From 10eaab3bb21a1b43e48822abdb5cae88ea3f5df7 Mon Sep 17 00:00:00 2001 From: Greg Gay Date: Tue, 20 Sep 2011 15:43:21 -0400 Subject: [PATCH] removed mods directory from the ATutor codebase --- mods/adobe_connect/README.txt | 39 - mods/adobe_connect/adobe_connect.gif | Bin 1411 -> 0 bytes mods/adobe_connect/index.php | 22 - mods/adobe_connect/index_admin.php | 112 - mods/adobe_connect/lib/ACConnection.php | 82 - mods/adobe_connect/lib/ACRoom.php | 159 - mods/adobe_connect/lib/ACUser.php | 124 - mods/adobe_connect/lib/lib.php | 90 - mods/adobe_connect/loader.php | 97 - mods/adobe_connect/module.css | 13 - mods/adobe_connect/module.php | 31 - mods/adobe_connect/module.sql | 43 - mods/adobe_connect/module.xml | 18 - mods/adobe_connect/module_cron.php | 15 - mods/adobe_connect/module_delete.php | 19 - mods/adobe_connect/module_install.php | 31 - mods/adobe_connect/module_uninstall.php | 26 - mods/announcement_subscription/module.php | 7 - mods/announcement_subscription/module.sql | 116 - mods/announcement_subscription/module.xml | 20 - .../module_install.php | 82 - .../module_uninstall.php | 31 - mods/announcement_subscription/readme.txt | 25 - mods/announcement_subscription/sendmail.php | 51 - .../side_menu.inc.php | 12 - mods/announcement_subscription/subscribe.php | 54 - .../subscribe_button.php | 15 - mods/assignment_dropbox/README | 25 - .../assignment_dropbox.inc.php | 81 - .../assignment_dropbox/assignment_dropbox.png | Bin 4929 -> 0 bytes .../assignment_dropbox_sm.png | Bin 465 -> 0 bytes mods/assignment_dropbox/flag.png | Bin 659 -> 0 bytes mods/assignment_dropbox/index.php | 396 - mods/assignment_dropbox/module.css | 15 - mods/assignment_dropbox/module.php | 44 - mods/assignment_dropbox/module.sql | 8 - mods/assignment_dropbox/module.xml | 19 - mods/assignment_dropbox/module_install.php | 52 - mods/assignment_dropbox/module_uninstall.php | 30 - mods/assignment_dropbox/sublinks.php | 62 - mods/atalker/ATalker-italian-voice-README.txt | 70 - mods/atalker/README_ATUTOR_MODULE | 212 - mods/atalker/admin/admin_index.php | 85 - mods/atalker/admin/admin_voice.php | 251 - mods/atalker/admin/admin_voice_files.php | 56 - mods/atalker/admin/admin_voice_html.php | 132 - mods/atalker/admin/play_voice.php | 38 - mods/atalker/admin_voice.php | 226 - mods/atalker/atalker_doc/1.0.voices.php | 21 - mods/atalker/atalker_doc/1.1.atalker.php | 21 - mods/atalker/atalkerlib.inc.php | 328 - mods/atalker/images/atalker.gif | Bin 2313 -> 0 bytes mods/atalker/images/atalker_sm.gif | Bin 1103 -> 0 bytes mods/atalker/index.php | 71 - mods/atalker/message_reader.php | 77 - mods/atalker/module.php | 53 - mods/atalker/module.sql | 177 - mods/atalker/module.xml | 19 - mods/atalker/module_install.php | 61 - mods/atalker/reader.html.php | 262 - mods/atalker/reader_controls.php | 85 - mods/atalker/sable_reader.php | 99 - mods/atalker/template_reader.php | 86 - mods/atalker/text_reader.php | 103 - mods/atsocial_iphone_app/.gitignore | 13 - mods/atsocial_iphone_app/.gitmodules | 3 - mods/atsocial_iphone_app/ATutor-Info.plist | 39 - .../ATutor.xcodeproj/project.pbxproj | 1215 --- mods/atsocial_iphone_app/ATutor_Prefix.pch | 18 - mods/atsocial_iphone_app/Activities.png | Bin 4627 -> 0 bytes .../Classes/ATutorAppDelegate.h | 34 - .../Classes/ATutorAppDelegate.m | 119 - .../Classes/ATutorHelper.h | 39 - .../Classes/ATutorHelper.m | 141 - .../Classes/ActivitiesViewController.h | 17 - .../Classes/ActivitiesViewController.m | 82 - .../Classes/CommonFunctions.h | 28 - .../Classes/CommonFunctions.m | 76 - mods/atsocial_iphone_app/Classes/Contact.h | 22 - mods/atsocial_iphone_app/Classes/Contact.m | 52 - .../Classes/ContactItemCell.h | 17 - .../Classes/ContactItemCell.m | 20 - .../Classes/ContactViewController.h | 21 - .../Classes/ContactViewController.m | 73 - .../Classes/ContactsDataSource.h | 17 - .../Classes/ContactsDataSource.m | 65 - .../Classes/ContactsViewController.h | 16 - .../Classes/ContactsViewController.m | 35 - .../Classes/GroupsViewController.h | 17 - .../Classes/GroupsViewController.m | 54 - .../Classes/LauncherViewController.h | 26 - .../Classes/LauncherViewController.m | 155 - mods/atsocial_iphone_app/Classes/OSConsumer.h | 34 - mods/atsocial_iphone_app/Classes/OSConsumer.m | 163 - mods/atsocial_iphone_app/Classes/OSProvider.h | 42 - mods/atsocial_iphone_app/Classes/OSProvider.m | 46 - .../Classes/QAWebController.h | 27 - .../Classes/QAWebController.m | 38 - mods/atsocial_iphone_app/Classes/StyleSheet.h | 16 - mods/atsocial_iphone_app/Classes/StyleSheet.m | 30 - mods/atsocial_iphone_app/Contacts.png | Bin 3560 -> 0 bytes mods/atsocial_iphone_app/Gadgets.png | Bin 5349 -> 0 bytes mods/atsocial_iphone_app/Groups.png | Bin 5209 -> 0 bytes .../IASKAppSettingsViewController.h | 59 - .../IASKAppSettingsViewController.m | 620 -- .../IASKSpecifierValuesViewController.h | 34 - .../IASKSpecifierValuesViewController.m | 142 - .../Models/IASKSettingsReader.h | 107 - .../Models/IASKSettingsReader.m | 157 - .../InAppSettingsKit/Models/IASKSpecifier.h | 52 - .../InAppSettingsKit/Models/IASKSpecifier.m | 208 - .../Views/IASKPSSliderSpecifierViewCell.h | 31 - .../Views/IASKPSSliderSpecifierViewCell.m | 66 - .../Views/IASKPSTextFieldSpecifierViewCell.h | 29 - .../Views/IASKPSTextFieldSpecifierViewCell.m | 51 - .../Views/IASKPSTitleValueSpecifierViewCell.h | 22 - .../Views/IASKPSTitleValueSpecifierViewCell.m | 54 - .../IASKPSToggleSwitchSpecifierViewCell.h | 29 - .../IASKPSToggleSwitchSpecifierViewCell.m | 46 - .../InAppSettingsKit/Views/IASKSlider.h | 26 - .../InAppSettingsKit/Views/IASKSlider.m | 29 - .../InAppSettingsKit/Views/IASKSwitch.h | 26 - .../InAppSettingsKit/Views/IASKSwitch.m | 30 - .../InAppSettingsKit/Views/IASKTextField.h | 26 - .../InAppSettingsKit/Views/IASKTextField.m | 29 - .../Xibs/IASKAppSettingsView.xib | 460 -- .../Xibs/IASKPSSliderSpecifierViewCell.xib | 449 -- .../Xibs/IASKPSTextFieldSpecifierViewCell.xib | 469 -- .../IASKPSToggleSwitchSpecifierViewCell.xib | 434 - .../Xibs/IASKSpecifierValuesView.xib | 408 - .../KeychainUtils/SFHFKeychainUtils.h | 41 - .../KeychainUtils/SFHFKeychainUtils.m | 390 - .../OAuth/Crypto/Base64Transcoder.c | 230 - .../OAuth/Crypto/Base64Transcoder.h | 36 - mods/atsocial_iphone_app/OAuth/Crypto/hmac.c | 86 - mods/atsocial_iphone_app/OAuth/Crypto/hmac.h | 31 - mods/atsocial_iphone_app/OAuth/Crypto/sha1.c | 169 - mods/atsocial_iphone_app/OAuth/Crypto/sha1.h | 12 - .../OAuth/Extensions/NSString+URLEncoding.h | 36 - .../OAuth/Extensions/NSString+URLEncoding.m | 63 - .../OAuth/OAAsynchronousDataFetcher.h | 44 - .../OAuth/OAAsynchronousDataFetcher.m | 131 - mods/atsocial_iphone_app/OAuth/OAConsumer.h | 41 - mods/atsocial_iphone_app/OAuth/OAConsumer.m | 52 - .../atsocial_iphone_app/OAuth/OADataFetcher.h | 38 - .../atsocial_iphone_app/OAuth/OADataFetcher.m | 64 - .../OAuth/OAMutableURLRequest.h | 77 - .../OAuth/OAMutableURLRequest.m | 218 - .../OAuth/OARequestParameter.h | 45 - .../OAuth/OARequestParameter.m | 70 - .../OAuth/OAServiceTicket.h | 43 - .../OAuth/OAServiceTicket.m | 51 - mods/atsocial_iphone_app/OAuth/OAToken.h | 39 - mods/atsocial_iphone_app/OAuth/OAToken.m | 82 - .../OAuth/OAToken_KeychainExtensions.h | 35 - .../OAuth/OAToken_KeychainExtensions.m | 63 - .../OAHMAC_SHA1SignatureProvider.h | 32 - .../OAHMAC_SHA1SignatureProvider.m | 57 - .../OAPlaintextSignatureProvider.h | 31 - .../OAPlaintextSignatureProvider.m | 43 - .../OASignatureProviding.h | 34 - mods/atsocial_iphone_app/README.markdown | 7 - .../Settings.bundle/Root.plist | 61 - .../Settings.bundle/en.lproj/Root.strings | Bin 546 -> 0 bytes .../TouchJSON/CDataScanner.h | 43 - .../TouchJSON/CDataScanner.m | 230 - .../Extensions/CDataScanner_Extensions.h | 16 - .../Extensions/CDataScanner_Extensions.m | 59 - .../Extensions/NSCharacterSet_Extensions.h | 15 - .../Extensions/NSCharacterSet_Extensions.m | 27 - .../Extensions/NSDictionary_JSONExtensions.h | 15 - .../Extensions/NSDictionary_JSONExtensions.m | 20 - .../TouchJSON/JSON/CJSONDeserializer.h | 19 - .../TouchJSON/JSON/CJSONDeserializer.m | 31 - .../TouchJSON/JSON/CJSONScanner.h | 26 - .../TouchJSON/JSON/CJSONScanner.m | 435 - .../TouchJSON/JSON/CJSONSerializer.h | 24 - .../TouchJSON/JSON/CJSONSerializer.m | 163 - mods/atsocial_iphone_app/main.m | 17 - mods/atutor_opencaps/README | 179 - mods/atutor_opencaps/doc/index.html | 0 mods/atutor_opencaps/flowplayer/LICENSE.txt | 721 -- mods/atutor_opencaps/flowplayer/README.txt | 302 - .../flowplayer/flowplayer-3.2.2.min.js | 24 - .../flowplayer/flowplayer-3.2.2.swf | Bin 115213 -> 0 bytes .../flowplayer/flowplayer.audio-3.2.0.swf | Bin 3150 -> 0 bytes .../flowplayer/flowplayer.captions-3.2.1.swf | Bin 8327 -> 0 bytes .../flowplayer/flowplayer.content-3.2.0.swf | Bin 4301 -> 0 bytes .../flowplayer/flowplayer.controls-3.2.1.swf | Bin 35736 -> 0 bytes mods/atutor_opencaps/flowplayer/index.html | 0 mods/atutor_opencaps/images/AtOpenCaps.png | Bin 34419 -> 0 bytes mods/atutor_opencaps/images/index.html | 0 mods/atutor_opencaps/images/poster.jpg | Bin 20035 -> 0 bytes mods/atutor_opencaps/include/atoc.js | 88 - mods/atutor_opencaps/include/basic.js | 31 - .../include/classes/ATOC_Debug.php | 52 - .../include/classes/ATOC_Json.php | 46 - .../include/classes/ATOC_ProjectManager.php | 326 - .../include/classes/ATOC_ServerFiles.php | 65 - mods/atutor_opencaps/include/config.inc.php | 54 - mods/atutor_opencaps/include/index.html | 0 mods/atutor_opencaps/include/vitals.inc.php | 134 - mods/atutor_opencaps/index.php | 418 - mods/atutor_opencaps/index_admin.php | 23 - mods/atutor_opencaps/index_instructor.php | 16 - mods/atutor_opencaps/module.css | 47 - mods/atutor_opencaps/module.php | 90 - mods/atutor_opencaps/module.sql | 77 - mods/atutor_opencaps/module.xml | 20 - mods/atutor_opencaps/module_install.php | 80 - mods/atutor_opencaps/module_uninstall.php | 49 - .../opencaps/conversion_service/about.txt | 26 - .../conversion_service/imported/index.html | 0 .../conversion_service/imported/noname.JSON | 1 - .../conversion_service/imported/noname.srt | 12 - .../conversion_service/imported/noname.txt | 19 - .../classes/ccformats/cc_DFXP_format.php | 282 - .../classes/ccformats/cc_DvdStl_format.php | 119 - .../classes/ccformats/cc_JSONcc_format.php | 113 - .../classes/ccformats/cc_MPlayer_format.php | 110 - .../classes/ccformats/cc_MicroDvd_format.php | 171 - .../classes/ccformats/cc_QTSMIL_format.php | 150 - .../classes/ccformats/cc_QTtext_format.php | 517 -- .../classes/ccformats/cc_RealText_format.php | 122 - .../classes/ccformats/cc_Sami_format.php | 227 - .../classes/ccformats/cc_Scc_format.php | 149 - .../classes/ccformats/cc_SubRipSrt_format.php | 204 - .../classes/ccformats/cc_SubViewer_format.php | 117 - .../include/classes/ccformats/index.html | 0 .../classes/core_CaptionCollection_class.php | 120 - .../classes/core_CaptionFormat_class.php | 69 - .../include/classes/core_Caption_class.php | 156 - .../include/classes/core_CcService_class.php | 57 - .../classes/core_ConversionManager_class.php | 246 - .../include/classes/core_XmlTag.php | 162 - .../include/classes/core_XmlTagCollection.php | 38 - .../include/classes/core_XmlTagTrace.php | 242 - .../classes/core_XmlTagTraceManager.php | 174 - .../include/classes/index.html | 0 .../classes/static_CcUtilVital_class.php | 61 - .../include/classes/static_TimeUtil_class.php | 186 - .../classes/static_TxtFileTools_class.php | 107 - .../conversion_service/include/config.inc.php | 41 - .../conversion_service/include/index.html | 0 .../opencaps/conversion_service/index.php | 71 - mods/atutor_opencaps/opencaps/editor.php | 123 - mods/atutor_opencaps/opencaps/error_log | 1 - mods/atutor_opencaps/opencaps/export.php | 77 - mods/atutor_opencaps/opencaps/help.php | 25 - .../opencaps/images/application_edit.png | Bin 703 -> 0 bytes .../opencaps/images/application_get.png | Bin 581 -> 0 bytes .../opencaps/images/application_put.png | Bin 585 -> 0 bytes .../opencaps/images/arrow_right.png | Bin 349 -> 0 bytes .../opencaps/images/asterisk_yellow.png | Bin 3212 -> 0 bytes .../opencaps/images/bullet_delete.png | Bin 308 -> 0 bytes .../opencaps/images/clip_leftedge.png | Bin 3085 -> 0 bytes .../opencaps/images/clip_next.png | Bin 3243 -> 0 bytes .../opencaps/images/clip_prev.png | Bin 3246 -> 0 bytes .../opencaps/images/clip_rightedge.png | Bin 3084 -> 0 bytes .../atutor_opencaps/opencaps/images/cross.png | Bin 655 -> 0 bytes .../opencaps/images/door_out.png | Bin 688 -> 0 bytes mods/atutor_opencaps/opencaps/images/end.png | Bin 2950 -> 0 bytes mods/atutor_opencaps/opencaps/images/ffwd.png | Bin 3353 -> 0 bytes .../atutor_opencaps/opencaps/images/ffwd2.png | Bin 3343 -> 0 bytes .../opencaps/images/index.html | 0 .../opencaps/images/last_start.png | Bin 3637 -> 0 bytes mods/atutor_opencaps/opencaps/images/logo.png | Bin 2148 -> 0 bytes .../opencaps/images/middlebar.png | Bin 2864 -> 0 bytes .../opencaps/images/page_gear.png | Bin 833 -> 0 bytes .../atutor_opencaps/opencaps/images/pause.png | Bin 3554 -> 0 bytes mods/atutor_opencaps/opencaps/images/play.png | Bin 3483 -> 0 bytes .../opencaps/images/pressplay.png | Bin 3397 -> 0 bytes .../opencaps/images/rewind.png | Bin 3355 -> 0 bytes .../opencaps/images/rewind2.png | Bin 3297 -> 0 bytes .../opencaps/images/slider-bg-1.png | Bin 204 -> 0 bytes .../opencaps/images/slider-bg-2.png | Bin 365 -> 0 bytes .../opencaps/images/slider-handle-ghost.gif | Bin 959 -> 0 bytes .../opencaps/images/slider-handle.gif | Bin 176 -> 0 bytes .../atutor_opencaps/opencaps/images/start.png | Bin 2940 -> 0 bytes .../opencaps/include/basic_header.inc.php | 66 - .../classes/captionCollection_class.php | 125 - .../include/classes/caption_class.php | 27 - .../opencaps/include/classes/clip_class.php | 65 - .../opencaps/include/classes/db_class.php | 90 - .../opencaps/include/classes/index.html | 0 .../include/classes/project_class.php | 503 -- .../include/classes/system_OcAtutor_class.php | 37 - .../opencaps/include/classes/system_class.php | 328 - .../opencaps/include/classes/time_class.php | 209 - .../opencaps/include/classes/user_class.php | 125 - .../opencaps/include/config.inc.php | 48 - .../opencaps/include/footer.inc.php | 30 - .../opencaps/include/header.inc.php | 99 - .../opencaps/include/index.html | 0 .../opencaps/include/matterhorn.inc.php | 61 - .../opencaps/include/vitals.inc.php | 140 - .../opencaps/include/workflow.php | 94 - mods/atutor_opencaps/opencaps/index.php | 54 - .../opencaps/install/config_template.php | 44 - .../opencaps/install/index.html | 0 .../opencaps/install/oc_schema.sql | 31 - .../opencaps/js/AC_QuickTime.js | 1 - mods/atutor_opencaps/opencaps/js/editor.js | 883 --- mods/atutor_opencaps/opencaps/js/export.js | 21 - mods/atutor_opencaps/opencaps/js/index.html | 0 .../opencaps/js/jquery/GPL-LICENSE.txt | 278 - .../opencaps/js/jquery/MIT-LICENSE.txt | 20 - .../opencaps/js/jquery/jARIA.js | 1 - .../opencaps/js/jquery/jquery-1.2.3.js | 1 - .../opencaps/js/jquery/jquery-1.2.6.js | 3549 --------- .../opencaps/js/jquery/jquery-1.3.2.min.js | 19 - .../opencaps/js/jquery/jquery.dimensions.js | 1 - .../js/jquery/jquery.keyboard-a11y.js | 1 - .../opencaps/js/jquery/jquery.tabindex.js | 1 - .../opencaps/js/jquery/ui.base.js | 1 - .../opencaps/js/jquery/ui.core.js | 519 -- .../opencaps/js/jquery/ui.dialog.js | 1 - .../opencaps/js/jquery/ui.draggable.js | 1 - .../opencaps/js/jquery/ui.droppable.js | 1 - .../opencaps/js/jquery/ui.slider.js | 558 -- .../atutor_opencaps/opencaps/js/json/json2.js | 476 -- mods/atutor_opencaps/opencaps/js/preview.js | 86 - mods/atutor_opencaps/opencaps/js/settings.js | 25 - mods/atutor_opencaps/opencaps/js/start.js | 155 - .../opencaps/js/start_remote.js | 99 - mods/atutor_opencaps/opencaps/js/utils.js | 182 - mods/atutor_opencaps/opencaps/license.txt | 76 - mods/atutor_opencaps/opencaps/loadmedia.php | 66 - mods/atutor_opencaps/opencaps/login.php | 60 - mods/atutor_opencaps/opencaps/logout.php | 32 - mods/atutor_opencaps/opencaps/preview.php | 45 - .../opencaps.json | 1 - .../opencaps.json | 1 - .../opencaps/projects/index.html | 11 - .../opencaps/projects/layouts/smil_0.mov | 1 - .../opencaps/projects/layouts/smil_1.mov | 1 - .../opencaps/projects/layouts/smil_2.mov | 1 - .../opencaps/projects/opencaps.json | 1 - .../opencaps/projects/player_template.php | 106 - mods/atutor_opencaps/opencaps/register.php | 125 - .../opencaps/scripts/install.sh | 44 - .../opencaps/scripts/install_remote_only.sh | 35 - mods/atutor_opencaps/opencaps/settings.php | 79 - mods/atutor_opencaps/opencaps/start.php | 155 - .../atutor_opencaps/opencaps/start_remote.php | 64 - mods/atutor_opencaps/opencaps/styles.css | 459 -- mods/atutor_opencaps/opencaps/styles_ff.css | 5 - mods/atutor_opencaps/opencaps/styles_ie.css | 34 - .../opencaps/styles_public.css | 109 - mods/atutor_opencaps/player.php | 144 - mods/atutor_opencaps/service.php | 100 - mods/atutor_opencaps/service_test.php | 53 - mods/basiclti/ModuleCallbacks.class.php | 65 - mods/basiclti/README.txt | 161 - mods/basiclti/TODO.txt | 13 - mods/basiclti/basiclti.jpg | Bin 1827 -> 0 bytes mods/basiclti/content_tool_action.js | 29 - mods/basiclti/images/basiclti-icon.png | Bin 5271 -> 0 bytes mods/basiclti/include/constants.inc.php | 7 - mods/basiclti/index.php | 12 - mods/basiclti/index_admin.php | 59 - mods/basiclti/index_instructor.php | 63 - mods/basiclti/launch/TrivialStore.php | 45 - mods/basiclti/launch/ims-blti/LICENSE.txt | 22 - mods/basiclti/launch/ims-blti/OAuth.php | 808 -- mods/basiclti/launch/ims-blti/blti.php | 325 - mods/basiclti/launch/ims-blti/blti_util.php | 225 - mods/basiclti/launch/launch.php | 120 - mods/basiclti/launch/loadrows.php | 65 - mods/basiclti/launch/service.php | 336 - mods/basiclti/lib/at_form_util.php | 336 - mods/basiclti/module.css | 11 - mods/basiclti/module.php | 90 - mods/basiclti/module.sql | 130 - mods/basiclti/module.xml | 19 - mods/basiclti/module_backup.php | 69 - mods/basiclti/module_delete.php | 21 - mods/basiclti/module_install.php | 65 - mods/basiclti/module_uninstall.php | 45 - mods/basiclti/tool/admin_create.php | 55 - mods/basiclti/tool/admin_delete.php | 51 - mods/basiclti/tool/admin_edit.php | 90 - mods/basiclti/tool/admin_view.php | 43 - mods/basiclti/tool/content_edit.php | 213 - mods/basiclti/tool/forms.php | 88 - mods/basiclti/tool/instructor_create.php | 60 - mods/basiclti/tool/instructor_delete.php | 52 - mods/basiclti/tool/instructor_edit.php | 76 - mods/basiclti/tool/instructor_view.php | 49 - mods/calendar/README_ATUTOR_MODULE | 89 - mods/calendar/admin_cal.php | 180 - mods/calendar/calendar.gif | Bin 2062 -> 0 bytes mods/calendar/index.php | 41 - mods/calendar/index_admin.php | 41 - mods/calendar/module.css | 152 - mods/calendar/module.php | 72 - mods/calendar/module.sql | 30 - mods/calendar/module.xml | 19 - mods/calendar/module_install.php | 62 - mods/calendar/side_menu.inc.php | 48 - mods/calendar/sync_cal.php | 76 - mods/ccnet/ccnet.php | 67 - mods/ccnet/ccnet_logo.jpg | Bin 1355 -> 0 bytes mods/ccnet/index.php | 28 - mods/ccnet/module.php | 38 - mods/ccnet/module.sql | 13 - mods/ccnet/module.xml | 19 - mods/ccnet/module_install.php | 62 - mods/ccnet/module_uninstall.php | 31 - mods/certificate/README | 14 - mods/certificate/certificate.gif | Bin 2163 -> 0 bytes mods/certificate/certificate_create.php | 245 - mods/certificate/certificate_delete.php | 66 - mods/certificate/certificate_edit.php | 321 - mods/certificate/common.inc.php | 157 - mods/certificate/default_certificate.pdf | Bin 526128 -> 0 bytes .../default_certificate.pdf.fields | 18 - .../default_certificate_for_fraser_health.pdf | Bin 525683 -> 0 bytes mods/certificate/get_adobe_reader.gif | Bin 1953 -> 0 bytes mods/certificate/index.php | 135 - mods/certificate/index_instructor.php | 115 - mods/certificate/module.css | 11 - mods/certificate/module.php | 81 - mods/certificate/module.sql | 52 - mods/certificate/module.xml | 19 - mods/certificate/module_install.php | 66 - mods/certificate/module_uninstall.php | 45 - mods/certificate/open_certificate.php | 55 - mods/certify/README | 18 - mods/certify/certify.css | 32 - mods/certify/certify.gif | Bin 2163 -> 0 bytes mods/certify/certify_certificate.php | 163 - mods/certify/certify_delete.php | 82 - mods/certify/certify_functions.php | 88 - mods/certify/certify_student_status.php | 140 - mods/certify/certify_tests.php | 167 - mods/certify/default_certificate.pdf | Bin 526128 -> 0 bytes mods/certify/download_certificate.php | 124 - mods/certify/download_certificate.php.bak | 125 - mods/certify/index.php | 92 - mods/certify/index_instructor.php | 100 - mods/certify/module.php | 95 - mods/certify/module.sql | 35 - mods/certify/module.xml | 19 - mods/certify/module_delete.php | 32 - mods/certify/module_install.php | 71 - mods/certify/module_uninstall.php | 44 - mods/certify/test.pdf | Bin 526128 -> 0 bytes mods/clean_file_storage/README | 3 - .../clean_file_storage/clean_file_storage.jpg | Bin 1827 -> 0 bytes mods/clean_file_storage/index.php | 12 - mods/clean_file_storage/index_admin.php | 74 - mods/clean_file_storage/module.css | 11 - mods/clean_file_storage/module.php | 24 - mods/clean_file_storage/module.sql | 11 - mods/clean_file_storage/module.xml | 22 - mods/clean_file_storage/module_install.php | 67 - mods/clean_file_storage/module_uninstall.php | 44 - mods/cmap/README | 19 - mods/cmap/cmap_logo.jpg | Bin 1428 -> 0 bytes mods/cmap/index.php | 29 - mods/cmap/index_admin.php | 76 - mods/cmap/index_instructor.php | 30 - mods/cmap/module.php | 73 - mods/cmap/module.sql | 15 - mods/cmap/module.xml | 19 - mods/cmap/module_install.php | 26 - mods/cmap/module_uninstall.php | 31 - mods/cpref_switch/ajax_save.php | 88 - mods/cpref_switch/module.css | 23 - mods/cpref_switch/module.inc.php | 16 - mods/cpref_switch/module.php | 21 - mods/cpref_switch/module.sql | 3 - mods/cpref_switch/module.xml | 19 - mods/cpref_switch/module_install.php | 64 - mods/cpref_switch/module_uninstall.php | 27 - mods/cpref_switch/side_menu.inc.php | 119 - mods/disclaimer/README | 20 - mods/disclaimer/common.inc.php | 43 - mods/disclaimer/disclaimer.png | Bin 6514 -> 0 bytes mods/disclaimer/disclaimer_supplement.zip | Bin 7851 -> 0 bytes mods/disclaimer/module.php | 37 - mods/disclaimer/module.sql | 13 - mods/disclaimer/module.xml | 19 - mods/disclaimer/module_install.php | 52 - mods/disclaimer/module_uninstall.php | 30 - mods/disclaimer/tac_edit.php | 117 - mods/disclaimer/terms_and_conditions.php | 58 - mods/disclaimer/terms_and_conditions.tmpl.php | 77 - mods/ecomm/datetimepicker.js | 487 -- mods/ecomm/error_beanstream.php | 28 - mods/ecomm/failure_beanstream.php | 38 - mods/ecomm/images/cal.gif | Bin 127 -> 0 bytes mods/ecomm/images/mc_42x27.gif | Bin 2000 -> 0 bytes mods/ecomm/images/visa_42x27.gif | Bin 1493 -> 0 bytes mods/ecomm/include/payments.lib.php | 684 -- mods/ecomm/index.php | 87 - mods/ecomm/index_admin.php | 195 - mods/ecomm/index_admin_approve.php | 96 - mods/ecomm/index_instructor.php | 121 - mods/ecomm/invoice.php | 79 - mods/ecomm/module.php | 60 - mods/ecomm/module.sql | 140 - mods/ecomm/module.xml | 19 - mods/ecomm/module_install.php | 51 - mods/ecomm/module_uninstall.php | 26 - mods/ecomm/payment.php | 102 - mods/ecomm/payments.png | Bin 6525 -> 0 bytes mods/ecomm/payments_admin.php | 96 - mods/ecomm/payments_export_csv.php | 52 - mods/ecomm/readme | 135 - mods/ecomm/response_ipn.php | 73 - mods/ecomm/response_paypal_user.php | 26 - mods/ecomm/response_user.php | 11 - mods/ecomm/success_beanstream.php | 37 - mods/elluminate/elluminate.php | 75 - mods/elluminate/elluminate_logo.gif | Bin 1917 -> 0 bytes mods/elluminate/index.php | 57 - mods/elluminate/module.css | 24 - mods/elluminate/module.php | 48 - mods/elluminate/module.sql | 16 - mods/elluminate/module.xml | 19 - mods/elluminate/module_install.php | 25 - mods/elluminate/module_uninstall.php | 31 - mods/elluminate/readme | 20 - mods/elluminate/side_menu.inc.php | 33 - mods/epresence/epresence_logo.gif | Bin 529 -> 0 bytes mods/epresence/index.php | 17 - mods/epresence/index_admin.php | 58 - mods/epresence/index_instructor.php | 15 - mods/epresence/module.php | 54 - mods/epresence/module.sql | 10 - mods/epresence/module.xml | 19 - mods/epresence/module_install.php | 25 - mods/epresence/module_uninstall.php | 26 - mods/fha_refresher/index.php | 111 - mods/fha_refresher/module.php | 23 - mods/fha_refresher/module.sql | 38 - mods/fha_refresher/module.xml | 19 - mods/fha_refresher/module_cron.php | 49 - mods/fha_refresher/module_delete.php | 17 - mods/fha_refresher/module_install.php | 16 - mods/fha_student_tools/icon.gif | Bin 373 -> 0 bytes mods/fha_student_tools/index.php | 36 - mods/fha_student_tools/instructor_index.php | 134 - mods/fha_student_tools/module.php | 23 - mods/fha_student_tools/module.sql | 10 - mods/fha_student_tools/module.xml | 19 - mods/fha_student_tools/module_delete.php | 17 - mods/fha_student_tools/module_install.php | 16 - mods/flowplayer/LICENSE.txt | 721 -- mods/flowplayer/README.txt | 222 - mods/flowplayer/flowplayer-3.1.2.min.js | 24 - mods/flowplayer/flowplayer-3.1.2.swf | Bin 107779 -> 0 bytes mods/flowplayer/flowplayer.controls-3.1.2.swf | Bin 26349 -> 0 bytes mods/flowplayer/module.php | 20 - mods/flowplayer/module.sql | 1 - mods/flowplayer/module.xml | 19 - mods/flowplayer/module_format_content.php | 67 - mods/flowplayer/module_install.php | 24 - mods/flowplayer/module_uninstall.php | 44 - mods/google_calendar/get_google_user.php | 55 - mods/google_calendar/google_cal.gif | Bin 2455 -> 0 bytes mods/google_calendar/google_prefs.php | 161 - mods/google_calendar/index.php | 40 - mods/google_calendar/index_admin.php | 38 - mods/google_calendar/index_instructor.php | 38 - mods/google_calendar/index_mystart.php | 43 - mods/google_calendar/module.php | 50 - mods/google_calendar/module.sql | 37 - mods/google_calendar/module.xml | 19 - mods/google_calendar/module_install.php | 68 - mods/google_calendar/module_uninstall.php | 26 - mods/google_calendar/readme | 14 - mods/google_calendar/side_menu.inc.php | 22 - mods/google_talk/google_talk.png | Bin 9774 -> 0 bytes mods/google_talk/index.php | 12 - mods/google_talk/module.php | 68 - mods/google_talk/module.sql | 5 - mods/google_talk/module.xml | 19 - mods/google_talk/module_install.php | 67 - mods/google_talk/module_uninstall.php | 26 - mods/gradebook/README | 51 - mods/gradebook/edit_marks.php | 421 - mods/gradebook/grade_scale.php | 186 - mods/gradebook/grade_scale_add.php | 17 - mods/gradebook/grade_scale_delete.php | 66 - mods/gradebook/grade_scale_edit.php | 17 - mods/gradebook/gradebook.png | Bin 1911 -> 0 bytes mods/gradebook/gradebook_add_tests.php | 305 - mods/gradebook/gradebook_delete_tests.php | 77 - mods/gradebook/gradebook_edit_tests.php | 195 - mods/gradebook/gradebook_tests.php | 129 - .../html/grade_scale_add_edit.inc.php | 227 - .../import_export_external_marks.php | 277 - mods/gradebook/lib/gradebook.inc.php | 489 -- mods/gradebook/module.php | 100 - mods/gradebook/module.sql | 108 - mods/gradebook/module.xml | 19 - mods/gradebook/module_install.php | 67 - mods/gradebook/my_gradebook.php | 131 - mods/gradebook/update_gradebook.php | 294 - mods/gradebook/verify_list.php | 201 - mods/gradebook/verify_tests.php | 225 - mods/hello_world/ModuleCallbacks.class.php | 27 - mods/hello_world/content_tool_action.js | 28 - mods/hello_world/hello_world.jpg | Bin 1827 -> 0 bytes mods/hello_world/index.php | 12 - mods/hello_world/index_admin.php | 10 - mods/hello_world/index_instructor.php | 10 - mods/hello_world/index_mystart.php | 13 - mods/hello_world/index_public.php | 15 - mods/hello_world/module.css | 11 - mods/hello_world/module.php | 110 - mods/hello_world/module.sql | 12 - mods/hello_world/module.xml | 19 - mods/hello_world/module_backup.php | 18 - mods/hello_world/module_cron.php | 13 - mods/hello_world/module_delete.php | 21 - mods/hello_world/module_format_content.php | 21 - mods/hello_world/module_install.php | 67 - mods/hello_world/module_news.php | 18 - mods/hello_world/module_uninstall.php | 44 - mods/hello_world/side_menu.inc.php | 13 - mods/hello_world/sublinks.php | 34 - mods/job_board/README | 138 - mods/job_board/admin/categories.php | 65 - mods/job_board/admin/edit_employer.php | 90 - mods/job_board/admin/edit_post.php | 89 - mods/job_board/admin/employers.php | 34 - mods/job_board/admin/preferences.php | 40 - mods/job_board/admin/view_post.php | 56 - mods/job_board/confirm.php | 42 - mods/job_board/employer/add_new_post.php | 93 - mods/job_board/employer/edit_post.php | 98 - mods/job_board/employer/home.php | 63 - mods/job_board/employer/login.php | 48 - mods/job_board/employer/logout.php | 23 - mods/job_board/employer/password_reminder.php | 167 - mods/job_board/employer/profile.php | 87 - mods/job_board/employer/registration.php | 91 - mods/job_board/employer/view_post.php | 64 - mods/job_board/images/bookmark.png | Bin 459 -> 0 bytes mods/job_board/images/jb_icon.png | Bin 6864 -> 0 bytes mods/job_board/images/jb_icon_tiny.png | Bin 3700 -> 0 bytes .../include/classes/Employer.class.php | 158 - mods/job_board/include/classes/Job.class.php | 642 -- mods/job_board/include/constants.inc.php | 32 - .../include/html/admin/jb_categories.tmpl.php | 88 - .../html/admin/jb_edit_employer.tmpl.php | 83 - .../include/html/admin/jb_edit_post.tmpl.php | 77 - .../include/html/admin/jb_employers.tmpl.php | 43 - .../include/html/admin/jb_index.tmpl.php | 49 - .../html/admin/jb_preferences.tmpl.php | 16 - .../html/employer/jb_add_new_post.tmpl.php | 67 - .../html/employer/jb_edit_post.tmpl.php | 73 - .../html/employer/jb_employer_header.tmpl.php | 10 - .../include/html/employer/jb_home.tmpl.php | 48 - .../include/html/employer/jb_login.tmpl.php | 28 - .../include/html/employer/jb_profile.tmpl.php | 73 - .../html/employer/jb_registration.tmpl.php | 79 - .../html/employer/password_change.tmpl.php | 62 - .../html/jb_advance_search_table.tmpl.php | 35 - mods/job_board/include/html/jb_index.tmpl.php | 58 - .../include/html/jb_subscribe.tmpl.php | 16 - .../include/html/jb_view_post.tmpl.php | 38 - mods/job_board/include/jb_add_to_cart.inc.php | 46 - mods/job_board/include/js/edit.js | 48 - mods/job_board/index.php | 135 - mods/job_board/index_admin.php | 54 - mods/job_board/module.css | 111 - mods/job_board/module.php | 125 - mods/job_board/module.sql | 160 - mods/job_board/module.xml | 19 - mods/job_board/module_install.php | 80 - mods/job_board/module_news.php | 41 - mods/job_board/module_uninstall.php | 49 - mods/job_board/sublinks.php | 40 - mods/job_board/subscribe.php | 47 - mods/job_board/view_post.php | 43 - mods/joomla_atutor/atutor/index_mambo.php | 74 - mods/joomla_atutor/com_atutor.zip | Bin 5067 -> 0 bytes mods/joomla_atutor/install.txt | 18 - mods/ldap/admin/config_ldap.php | 255 - mods/ldap/admin/ldap_auth_log.php | 115 - mods/ldap/admin/ldap_lib.php | 236 - mods/ldap/atutor.ldap.mod.struct.sql | 115 - mods/ldap/atutor.ldap.mod.tar.gz | Bin 214444 -> 0 bytes mods/ldap/include/lib/menu_pages.php | 424 - mods/ldap/include/lib/pk.pem | 9 - mods/ldap/include/lib/rsa.inc.php | 105 - mods/ldap/jscripts/jqgrid/jquery.jqGrid.js | 63 - mods/ldap/jscripts/jqgrid/jquery.js | 11 - mods/ldap/jscripts/jqgrid/js/grid.base.js | 1465 ---- mods/ldap/jscripts/jqgrid/js/grid.celledit.js | 406 - mods/ldap/jscripts/jqgrid/js/grid.common.js | 215 - mods/ldap/jscripts/jqgrid/js/grid.custom.js | 407 - mods/ldap/jscripts/jqgrid/js/grid.formedit.js | 906 --- .../ldap/jscripts/jqgrid/js/grid.inlinedit.js | 184 - .../ldap/jscripts/jqgrid/js/grid.locale-bg.js | 71 - .../ldap/jscripts/jqgrid/js/grid.locale-en.js | 71 - .../ldap/jscripts/jqgrid/js/grid.locale-it.js | 70 - mods/ldap/jscripts/jqgrid/js/grid.postext.js | 64 - .../jscripts/jqgrid/js/grid.setcolumns.js | 78 - mods/ldap/jscripts/jqgrid/js/grid.subgrid.js | 148 - .../ldap/jscripts/jqgrid/js/grid.tbltogrid.js | 105 - mods/ldap/jscripts/jqgrid/js/grid.treegrid.js | 322 - mods/ldap/jscripts/jqgrid/js/jqDnR.js | 28 - mods/ldap/jscripts/jqgrid/js/jqModal.js | 69 - .../jscripts/jqgrid/js/min/grid.base-min.js | 221 - .../jqgrid/js/min/grid.celledit-min.js | 54 - .../jscripts/jqgrid/js/min/grid.common-min.js | 34 - .../jscripts/jqgrid/js/min/grid.custom-min.js | 60 - .../jqgrid/js/min/grid.formedit-min.js | 105 - .../jqgrid/js/min/grid.inlinedit-min.js | 26 - .../jqgrid/js/min/grid.locale-bg-min.js | 12 - .../jqgrid/js/min/grid.locale-en-min.js | 10 - .../jqgrid/js/min/grid.locale-it-min.js | 10 - .../jqgrid/js/min/grid.postext-min.js | 20 - .../jqgrid/js/min/grid.setcolumns-min.js | 19 - .../jqgrid/js/min/grid.subgrid-min.js | 20 - .../jqgrid/js/min/grid.tbltogrid-min.js | 17 - .../jqgrid/js/min/grid.treegrid-min.js | 42 - .../jscripts/jqgrid/js/packall/grid.pack.js | 9 - .../jscripts/jqgrid/js/packed/grid.base.js | 9 - .../jqgrid/js/packed/grid.celledit.js | 1 - .../jscripts/jqgrid/js/packed/grid.common.js | 1 - .../jscripts/jqgrid/js/packed/grid.custom.js | 1 - .../jqgrid/js/packed/grid.formedit.js | 1 - .../jqgrid/js/packed/grid.inlinedit.js | 1 - .../jqgrid/js/packed/grid.locale-bg.js | 12 - .../jqgrid/js/packed/grid.locale-en.js | 10 - .../jqgrid/js/packed/grid.locale-it.js | 10 - .../jscripts/jqgrid/js/packed/grid.postext.js | 1 - .../jqgrid/js/packed/grid.setcolumns.js | 1 - .../jscripts/jqgrid/js/packed/grid.subgrid.js | 1 - .../jqgrid/js/packed/grid.tbltogrid.js | 1 - .../jqgrid/js/packed/grid.treegrid.js | 1 - .../jscripts/jqgrid/themes/basic/grid.css | 436 - .../jqgrid/themes/basic/images/cd_run.gif | Bin 1025 -> 0 bytes .../jqgrid/themes/basic/images/dirty.gif | Bin 832 -> 0 bytes .../jqgrid/themes/basic/images/down.gif | Bin 309 -> 0 bytes .../jqgrid/themes/basic/images/find.gif | Bin 986 -> 0 bytes .../jqgrid/themes/basic/images/first.gif | Bin 925 -> 0 bytes .../jqgrid/themes/basic/images/folder.png | Bin 229 -> 0 bytes .../themes/basic/images/grid-blue-ft.gif | Bin 821 -> 0 bytes .../themes/basic/images/grid-blue-hd.gif | Bin 821 -> 0 bytes .../jqgrid/themes/basic/images/headerbg.gif | Bin 87 -> 0 bytes .../jqgrid/themes/basic/images/headerleft.gif | Bin 425 -> 0 bytes .../themes/basic/images/headerright.gif | Bin 87 -> 0 bytes .../jqgrid/themes/basic/images/ico-close.gif | Bin 957 -> 0 bytes .../jqgrid/themes/basic/images/last.gif | Bin 923 -> 0 bytes .../jqgrid/themes/basic/images/line3.gif | Bin 70 -> 0 bytes .../jqgrid/themes/basic/images/minus.gif | Bin 85 -> 0 bytes .../jqgrid/themes/basic/images/next.gif | Bin 875 -> 0 bytes .../jqgrid/themes/basic/images/nochild.gif | Bin 66 -> 0 bytes .../jqgrid/themes/basic/images/off-first.gif | Bin 925 -> 0 bytes .../jqgrid/themes/basic/images/off-last.gif | Bin 923 -> 0 bytes .../jqgrid/themes/basic/images/off-next.gif | Bin 875 -> 0 bytes .../jqgrid/themes/basic/images/off-prev.gif | Bin 879 -> 0 bytes .../jqgrid/themes/basic/images/plus.gif | Bin 89 -> 0 bytes .../jqgrid/themes/basic/images/prev.gif | Bin 879 -> 0 bytes .../jqgrid/themes/basic/images/refresh.gif | Bin 581 -> 0 bytes .../jqgrid/themes/basic/images/resize.gif | Bin 862 -> 0 bytes .../jqgrid/themes/basic/images/row_add.gif | Bin 635 -> 0 bytes .../jqgrid/themes/basic/images/row_delete.gif | Bin 634 -> 0 bytes .../jqgrid/themes/basic/images/row_edit.gif | Bin 996 -> 0 bytes .../jqgrid/themes/basic/images/sort_asc.gif | Bin 830 -> 0 bytes .../jqgrid/themes/basic/images/sort_desc.gif | Bin 833 -> 0 bytes .../jqgrid/themes/basic/images/spacer.gif | Bin 43 -> 0 bytes .../themes/basic/images/tab_close-on.gif | Bin 351 -> 0 bytes .../jqgrid/themes/basic/images/tree_leaf.gif | Bin 134 -> 0 bytes .../jqgrid/themes/basic/images/tree_minus.gif | Bin 132 -> 0 bytes .../jqgrid/themes/basic/images/tree_plus.gif | Bin 138 -> 0 bytes .../jqgrid/themes/basic/images/up.gif | Bin 312 -> 0 bytes .../jscripts/jqgrid/themes/coffee/grid.css | 445 -- .../jqgrid/themes/coffee/images/cd_run.gif | Bin 1025 -> 0 bytes .../jqgrid/themes/coffee/images/dirty.gif | Bin 832 -> 0 bytes .../jqgrid/themes/coffee/images/down.gif | Bin 683 -> 0 bytes .../jqgrid/themes/coffee/images/find.gif | Bin 986 -> 0 bytes .../jqgrid/themes/coffee/images/first.gif | Bin 734 -> 0 bytes .../jqgrid/themes/coffee/images/folder.png | Bin 229 -> 0 bytes .../themes/coffee/images/grid-blue-ft.gif | Bin 165 -> 0 bytes .../themes/coffee/images/grid-blue-hd.gif | Bin 165 -> 0 bytes .../jqgrid/themes/coffee/images/headerbg.gif | Bin 105 -> 0 bytes .../themes/coffee/images/headerleft.gif | Bin 236 -> 0 bytes .../themes/coffee/images/headerright.gif | Bin 235 -> 0 bytes .../jqgrid/themes/coffee/images/ico-close.gif | Bin 854 -> 0 bytes .../jqgrid/themes/coffee/images/last.gif | Bin 737 -> 0 bytes .../jqgrid/themes/coffee/images/line3.gif | Bin 70 -> 0 bytes .../jqgrid/themes/coffee/images/minus.gif | Bin 85 -> 0 bytes .../jqgrid/themes/coffee/images/next.gif | Bin 483 -> 0 bytes .../jqgrid/themes/coffee/images/nochild.gif | Bin 66 -> 0 bytes .../jqgrid/themes/coffee/images/off-first.gif | Bin 483 -> 0 bytes .../jqgrid/themes/coffee/images/off-last.gif | Bin 485 -> 0 bytes .../jqgrid/themes/coffee/images/off-next.gif | Bin 476 -> 0 bytes .../jqgrid/themes/coffee/images/off-prev.gif | Bin 479 -> 0 bytes .../jqgrid/themes/coffee/images/plus.gif | Bin 89 -> 0 bytes .../jqgrid/themes/coffee/images/prev.gif | Bin 483 -> 0 bytes .../jqgrid/themes/coffee/images/refresh.gif | Bin 581 -> 0 bytes .../jqgrid/themes/coffee/images/resize.gif | Bin 862 -> 0 bytes .../jqgrid/themes/coffee/images/row_add.gif | Bin 635 -> 0 bytes .../themes/coffee/images/row_delete.gif | Bin 634 -> 0 bytes .../jqgrid/themes/coffee/images/row_edit.gif | Bin 996 -> 0 bytes .../jqgrid/themes/coffee/images/sort_asc.gif | Bin 114 -> 0 bytes .../jqgrid/themes/coffee/images/sort_desc.gif | Bin 113 -> 0 bytes .../jqgrid/themes/coffee/images/spacer.gif | Bin 43 -> 0 bytes .../themes/coffee/images/tab_close-on.gif | Bin 351 -> 0 bytes .../jqgrid/themes/coffee/images/tree_leaf.gif | Bin 134 -> 0 bytes .../themes/coffee/images/tree_minus.gif | Bin 132 -> 0 bytes .../jqgrid/themes/coffee/images/tree_plus.gif | Bin 138 -> 0 bytes .../jqgrid/themes/coffee/images/up.gif | Bin 673 -> 0 bytes .../jscripts/jqgrid/themes/green/grid.css | 446 -- .../jqgrid/themes/green/images/cd_run.gif | Bin 1025 -> 0 bytes .../jqgrid/themes/green/images/dirty.gif | Bin 832 -> 0 bytes .../jqgrid/themes/green/images/down.gif | Bin 734 -> 0 bytes .../jqgrid/themes/green/images/find.gif | Bin 986 -> 0 bytes .../jqgrid/themes/green/images/first.gif | Bin 763 -> 0 bytes .../jqgrid/themes/green/images/folder.png | Bin 229 -> 0 bytes .../themes/green/images/grid-blue-ft.gif | Bin 165 -> 0 bytes .../themes/green/images/grid-blue-hd.gif | Bin 165 -> 0 bytes .../jqgrid/themes/green/images/headerbg.gif | Bin 105 -> 0 bytes .../jqgrid/themes/green/images/headerleft.gif | Bin 236 -> 0 bytes .../themes/green/images/headerright.gif | Bin 235 -> 0 bytes .../jqgrid/themes/green/images/ico-close.gif | Bin 854 -> 0 bytes .../jqgrid/themes/green/images/last.gif | Bin 760 -> 0 bytes .../jqgrid/themes/green/images/leaf.gif | Bin 203 -> 0 bytes .../jqgrid/themes/green/images/line3.gif | Bin 70 -> 0 bytes .../jqgrid/themes/green/images/minus.gif | Bin 85 -> 0 bytes .../jqgrid/themes/green/images/next.gif | Bin 1177 -> 0 bytes .../jqgrid/themes/green/images/nochild.gif | Bin 66 -> 0 bytes .../jqgrid/themes/green/images/off-first.gif | Bin 763 -> 0 bytes .../jqgrid/themes/green/images/off-last.gif | Bin 760 -> 0 bytes .../jqgrid/themes/green/images/off-next.gif | Bin 1177 -> 0 bytes .../jqgrid/themes/green/images/off-prev.gif | Bin 1175 -> 0 bytes .../jqgrid/themes/green/images/plus.gif | Bin 89 -> 0 bytes .../jqgrid/themes/green/images/prev.gif | Bin 1175 -> 0 bytes .../jqgrid/themes/green/images/refresh.gif | Bin 581 -> 0 bytes .../jqgrid/themes/green/images/resize.gif | Bin 862 -> 0 bytes .../jqgrid/themes/green/images/row_add.gif | Bin 635 -> 0 bytes .../jqgrid/themes/green/images/row_delete.gif | Bin 634 -> 0 bytes .../jqgrid/themes/green/images/row_edit.gif | Bin 996 -> 0 bytes .../jqgrid/themes/green/images/sort_asc.gif | Bin 71 -> 0 bytes .../jqgrid/themes/green/images/sort_desc.gif | Bin 55 -> 0 bytes .../jqgrid/themes/green/images/spacer.gif | Bin 43 -> 0 bytes .../themes/green/images/tab_close-on.gif | Bin 351 -> 0 bytes .../jqgrid/themes/green/images/tree_leaf.gif | Bin 134 -> 0 bytes .../jqgrid/themes/green/images/tree_minus.gif | Bin 132 -> 0 bytes .../jqgrid/themes/green/images/tree_plus.gif | Bin 138 -> 0 bytes .../jqgrid/themes/green/images/up.gif | Bin 735 -> 0 bytes mods/ldap/jscripts/jqgrid/themes/jqModal.css | 31 - .../ldap/jscripts/jqgrid/themes/sand/grid.css | 448 -- .../jqgrid/themes/sand/images/cd_run.gif | Bin 1025 -> 0 bytes .../jqgrid/themes/sand/images/dirty.gif | Bin 832 -> 0 bytes .../jqgrid/themes/sand/images/down.gif | Bin 379 -> 0 bytes .../jqgrid/themes/sand/images/find.gif | Bin 986 -> 0 bytes .../jqgrid/themes/sand/images/first.gif | Bin 399 -> 0 bytes .../jqgrid/themes/sand/images/folder.png | Bin 229 -> 0 bytes .../themes/sand/images/grid-blue-ft.gif | Bin 165 -> 0 bytes .../themes/sand/images/grid-blue-hd.gif | Bin 165 -> 0 bytes .../jqgrid/themes/sand/images/headerbg.gif | Bin 105 -> 0 bytes .../jqgrid/themes/sand/images/headerleft.gif | Bin 197 -> 0 bytes .../jqgrid/themes/sand/images/headerright.gif | Bin 258 -> 0 bytes .../jqgrid/themes/sand/images/ico-close.gif | Bin 957 -> 0 bytes .../jqgrid/themes/sand/images/last.gif | Bin 398 -> 0 bytes .../jqgrid/themes/sand/images/line3.gif | Bin 70 -> 0 bytes .../jqgrid/themes/sand/images/minus.gif | Bin 85 -> 0 bytes .../jqgrid/themes/sand/images/next.gif | Bin 392 -> 0 bytes .../jqgrid/themes/sand/images/nochild.gif | Bin 66 -> 0 bytes .../jqgrid/themes/sand/images/off-first.gif | Bin 399 -> 0 bytes .../jqgrid/themes/sand/images/off-last.gif | Bin 398 -> 0 bytes .../jqgrid/themes/sand/images/off-next.gif | Bin 392 -> 0 bytes .../jqgrid/themes/sand/images/off-prev.gif | Bin 389 -> 0 bytes .../jqgrid/themes/sand/images/plus.gif | Bin 89 -> 0 bytes .../jqgrid/themes/sand/images/prev.gif | Bin 389 -> 0 bytes .../jqgrid/themes/sand/images/refresh.gif | Bin 581 -> 0 bytes .../jqgrid/themes/sand/images/resize.gif | Bin 862 -> 0 bytes .../jqgrid/themes/sand/images/row_add.gif | Bin 635 -> 0 bytes .../jqgrid/themes/sand/images/row_delete.gif | Bin 634 -> 0 bytes .../jqgrid/themes/sand/images/row_edit.gif | Bin 996 -> 0 bytes .../jqgrid/themes/sand/images/sort_asc.gif | Bin 56 -> 0 bytes .../jqgrid/themes/sand/images/sort_desc.gif | Bin 55 -> 0 bytes .../jqgrid/themes/sand/images/spacer.gif | Bin 43 -> 0 bytes .../themes/sand/images/tab_close-on.gif | Bin 351 -> 0 bytes .../jqgrid/themes/sand/images/tree_leaf.gif | Bin 134 -> 0 bytes .../jqgrid/themes/sand/images/tree_minus.gif | Bin 132 -> 0 bytes .../jqgrid/themes/sand/images/tree_plus.gif | Bin 138 -> 0 bytes .../jscripts/jqgrid/themes/sand/images/up.gif | Bin 382 -> 0 bytes mods/ldap/login.php | 227 - mods/ldap/readme.txt | 142 - mods/ldap/rsa/base64.js | 71 - mods/ldap/rsa/jsbn.js | 559 -- mods/ldap/rsa/prng4.js | 45 - mods/ldap/rsa/rng.js | 68 - mods/ldap/rsa/rsa.js | 96 - mods/ldap/themes/default/login.tmpl.php | 78 - mods/mahara/README | 82 - mods/mahara/cookie.php | 38 - mods/mahara/index.php | 109 - mods/mahara/index_admin.php | 162 - mods/mahara/mahara.gif | Bin 1883 -> 0 bytes mods/mahara/mahara_login.php | 199 - mods/mahara/module.php | 52 - mods/mahara/module.sql | 21 - mods/mahara/module.xml | 19 - mods/mahara/module_delete.php | 35 - mods/mahara/module_install.php | 67 - mods/mahara/module_uninstall.php | 26 - mods/mahara/new_account.php | 244 - mods/mahara/new_account_admin.php | 281 - mods/marratech/index.php | 13 - mods/marratech/marratech.php | 70 - mods/marratech/marratech_logo.jpg | Bin 1350 -> 0 bytes mods/marratech/module.php | 38 - mods/marratech/module.sql | 12 - mods/marratech/module.xml | 19 - mods/marratech/module_install.php | 25 - mods/marratech/readme | 21 - .../Auth_viaMySQL/Auth_viaMySQL.php | 105 - .../Auth_viaMySQL/CacheTimer_viaMySQL.php | 36 - mods/mediawiki/MySQL_Auth/MySQLActiveUser.php | 48 - mods/mediawiki/README | 96 - mods/mediawiki/index.php | 26 - mods/mediawiki/index_admin.php | 48 - mods/mediawiki/index_instructor.php | 18 - mods/mediawiki/index_mystart.php | 25 - mods/mediawiki/index_public.php | 26 - mods/mediawiki/module.css | 5 - mods/mediawiki/module.php | 89 - mods/mediawiki/module.sql | 13 - mods/mediawiki/module.xml | 19 - mods/mediawiki/module_delete.php | 21 - mods/mediawiki/module_install.php | 67 - mods/mediawiki/module_news.php | 38 - mods/mediawiki/module_uninstall.php | 44 - mods/mediawiki/mw_config.php | 13 - mods/mediawiki/mw_connect.php | 25 - mods/mediawiki/mw_icon_sm.png | Bin 1040 -> 0 bytes mods/mediawiki/mw_logo.png | Bin 6777 -> 0 bytes mods/mediawiki/side_menu.inc.php | 15 - mods/mediawiki/sublinks.php | 36 - mods/merlot/README | 28 - mods/merlot/add_to_links.php | 148 - .../classes/MerlotResultParser.class.php | 135 - mods/merlot/index.php | 134 - mods/merlot/index_admin.php | 71 - mods/merlot/merlot.gif | Bin 2041 -> 0 bytes mods/merlot/merlot.js | 1805 ----- mods/merlot/merlot_adv.php | 172 - mods/merlot/merlot_rest.php | 130 - mods/merlot/merlot_soap.php | 115 - mods/merlot/merlotlogo.gif | Bin 4762 -> 0 bytes mods/merlot/module.css | 230 - mods/merlot/module.php | 43 - mods/merlot/module.sql | 48 - mods/merlot/module.xml | 23 - mods/merlot/module_install.php | 66 - mods/merlot/module_uninstall.php | 26 - mods/openmeetings/TODO.txt | 42 - mods/openmeetings/add_group_meetings.php | 141 - mods/openmeetings/html/course_meeting.inc.php | 43 - mods/openmeetings/html/create_room.inc.php | 44 - mods/openmeetings/html/create_room.tmpl.php | 81 - mods/openmeetings/html/edit_room.inc.php | 28 - mods/openmeetings/html/group_meeting.inc.php | 48 - mods/openmeetings/html/update_room.inc.php | 41 - mods/openmeetings/index.php | 57 - mods/openmeetings/lib/SOAP_openmeetings.php | 238 - mods/openmeetings/lib/nusoap.php | 7024 ----------------- mods/openmeetings/lib/openmeetings.class.php | 243 - mods/openmeetings/lib/openmeetings.inc.php | 61 - mods/openmeetings/module.css | 17 - mods/openmeetings/module.php | 59 - mods/openmeetings/module.sql | 66 - mods/openmeetings/module.xml | 19 - mods/openmeetings/module_install.php | 46 - mods/openmeetings/module_uninstall.php | 26 - mods/openmeetings/openmeetings.php | 82 - mods/openmeetings/openmeetings_delete.php | 65 - mods/openmeetings/openmeetings_group.php | 60 - mods/openmeetings/openmeetings_instructor.php | 122 - mods/openmeetings/openmeetings_logo.png | Bin 15745 -> 0 bytes mods/openmeetings/readme | 61 - mods/openmeetings/view_meetings.php | 60 - mods/patcher/README | 52 - mods/patcher/classes/Patch.class.php | 732 -- mods/patcher/classes/PatchCreator.class.php | 386 - .../patcher/classes/PatchListParser.class.php | 128 - mods/patcher/classes/PatchParser.class.php | 139 - mods/patcher/include/common.inc.php | 132 - mods/patcher/include/json.inc.php | 71 - .../include/patch_xml_template.inc.php | 44 - mods/patcher/index_admin.php | 424 - mods/patcher/module.css | 11 - mods/patcher/module.php | 43 - mods/patcher/module.sql | 145 - mods/patcher/module.xml | 19 - mods/patcher/module_install.php | 67 - mods/patcher/myown_patches.php | 99 - mods/patcher/patch_create.php | 23 - mods/patcher/patch_creator.php | 134 - mods/patcher/patch_delete.php | 71 - mods/patcher/patch_edit.php | 42 - mods/patcher/patch_edit_interface.tmpl.php | 349 - mods/patcher/sample_patch.xml | 50 - mods/patcher/sample_patch_list.xml | 23 - mods/patcher/xml_special_chars.txt | 5 - mods/pdf_converter/README | 27 - mods/pdf_converter/class.ezpdf.php | 1555 ---- mods/pdf_converter/class.pdf.php | 3077 -------- mods/pdf_converter/font/courier.php | 7 - mods/pdf_converter/font/helvetica.php | 15 - mods/pdf_converter/font/helveticab.php | 15 - mods/pdf_converter/font/helveticabi.php | 15 - mods/pdf_converter/font/helveticai.php | 15 - mods/pdf_converter/font/makefont/cp1250.map | 251 - mods/pdf_converter/font/makefont/cp1251.map | 255 - mods/pdf_converter/font/makefont/cp1252.map | 251 - mods/pdf_converter/font/makefont/cp1253.map | 239 - mods/pdf_converter/font/makefont/cp1254.map | 249 - mods/pdf_converter/font/makefont/cp1255.map | 233 - mods/pdf_converter/font/makefont/cp1257.map | 244 - mods/pdf_converter/font/makefont/cp1258.map | 247 - mods/pdf_converter/font/makefont/cp874.map | 225 - .../font/makefont/iso-8859-1.map | 256 - .../font/makefont/iso-8859-11.map | 248 - .../font/makefont/iso-8859-15.map | 256 - .../font/makefont/iso-8859-16.map | 256 - .../font/makefont/iso-8859-2.map | 256 - .../font/makefont/iso-8859-4.map | 256 - .../font/makefont/iso-8859-5.map | 256 - .../font/makefont/iso-8859-7.map | 250 - .../font/makefont/iso-8859-9.map | 256 - mods/pdf_converter/font/makefont/koi8-r.map | 256 - mods/pdf_converter/font/makefont/koi8-u.map | 256 - mods/pdf_converter/font/makefont/makefont.php | 416 - mods/pdf_converter/font/symbol.php | 15 - mods/pdf_converter/font/times.php | 15 - mods/pdf_converter/font/timesb.php | 15 - mods/pdf_converter/font/timesbi.php | 15 - mods/pdf_converter/font/timesi.php | 15 - mods/pdf_converter/font/zapfdingbats.php | 15 - mods/pdf_converter/fpdf.css | 23 - mods/pdf_converter/fpdf.php | 1647 ---- mods/pdf_converter/index.php | 12 - mods/pdf_converter/module.php | 26 - mods/pdf_converter/module.sql | 4 - mods/pdf_converter/module.xml | 20 - mods/pdf_converter/module_install.php | 67 - mods/pdf_converter/module_uninstall.php | 31 - mods/pdf_converter/muestra_pdf.txt | 3 - mods/pdf_converter/pdf.php | 212 - mods/pdf_converter/pdf_converter.php | 127 - mods/pdf_converter/pdf_icon.jpg | Bin 1095 -> 0 bytes mods/pdf_converter/side_menu.inc.php | 19 - mods/photo_album/HTML/Template/IT.php | 990 --- mods/photo_album/HTML/Template/ITX.php | 809 -- mods/photo_album/HTML/Template/IT_Error.php | 51 - mods/photo_album/README.txt | 50 - .../Template/admin_comment_list.tpl.php | 75 - .../photo_album/Template/admin_config.tpl.php | 15 - .../Template/admin_image_list.tpl.php | 91 - .../Template/delete_confirm.tpl.php | 32 - mods/photo_album/Template/file_upload.tpl.php | 33 - mods/photo_album/Template/form.tpl.php | 48 - mods/photo_album/Template/index.tpl.php | 75 - mods/photo_album/Template/index.tpl.php.bak | 44 - mods/photo_album/Template/index_admin.tpl.php | 18 - .../Template/instructor_comment.tpl.php | 76 - .../Template/instructor_config.tpl.php | 15 - .../Template/instructor_image.tpl.php | 93 - mods/photo_album/Template/my_comment.tpl.php | 44 - mods/photo_album/Template/my_photo.tpl.php | 48 - mods/photo_album/Template/result.tpl.php | 20 - mods/photo_album/Template/view.tpl.php | 81 - mods/photo_album/admin_comment_list.php | 173 - mods/photo_album/admin_config.php | 68 - mods/photo_album/admin_image_list.php | 181 - .../classes/image_upload.class.php | 256 - mods/photo_album/classes/pa.class.php | 157 - .../classes/pa_admin_comment.class.php | 180 - .../classes/pa_admin_image.class.php | 178 - mods/photo_album/classes/pa_index.class.php | 118 - .../classes/pa_mycomment.class.php | 141 - mods/photo_album/classes/pa_mypic.class.php | 140 - mods/photo_album/classes/pa_view.class.php | 111 - .../classes/phpThumb_1.7.2/cache/index.php | 4 - .../phpThumb_1.7.2/cache/source/index.php | 4 - .../docs/phpthumb.changelog.txt | 1137 --- .../phpThumb_1.7.2/docs/phpthumb.faq.txt | 280 - .../phpThumb_1.7.2/docs/phpthumb.license.txt | 340 - .../phpThumb_1.7.2/docs/phpthumb.readme.txt | 549 -- .../classes/phpThumb_1.7.2/fonts/readme.txt | 5 - .../classes/phpThumb_1.7.2/images/readme.txt | 4 - .../classes/phpThumb_1.7.2/index.php | 3 - .../phpThumb.config.php.default | 242 - .../classes/phpThumb_1.7.2/phpThumb.php | 601 -- .../classes/phpThumb_1.7.2/phpthumb.bmp.php | 874 -- .../classes/phpThumb_1.7.2/phpthumb.class.php | 3433 -------- .../phpThumb_1.7.2/phpthumb.filters.php | 1266 --- .../phpThumb_1.7.2/phpthumb.functions.php | 757 -- .../classes/phpThumb_1.7.2/phpthumb.gif.php | 1168 --- .../classes/phpThumb_1.7.2/phpthumb.ico.php | 119 - .../phpThumb_1.7.2/phpthumb.unsharp.php | 162 - mods/photo_album/define.php | 105 - .../component-templates/css/Lightbox.css | 111 - .../component-templates/html/Lightbox.html | 383 - .../component-templates/images/Banana.jpg | Bin 1708 -> 0 bytes .../component-templates/images/Blackberry.jpg | Bin 4241 -> 0 bytes .../component-templates/images/Cherry.jpg | Bin 3359 -> 0 bytes .../images/Dragonfruit.jpg | Bin 4353 -> 0 bytes .../fluid/component-templates/images/Fig.jpg | Bin 4568 -> 0 bytes .../component-templates/images/Grapes.jpg | Bin 5185 -> 0 bytes .../component-templates/images/Kiwano.jpg | Bin 2611 -> 0 bytes .../fluid/component-templates/images/Kiwi.jpg | Bin 3216 -> 0 bytes .../component-templates/images/Kumquat.jpg | Bin 3428 -> 0 bytes .../component-templates/images/Lemon.jpg | Bin 2330 -> 0 bytes .../component-templates/images/Mangosteen.jpg | Bin 3637 -> 0 bytes .../component-templates/images/Orange.jpg | Bin 4029 -> 0 bytes .../component-templates/images/RedApple.jpg | Bin 2482 -> 0 bytes .../component-templates/images/Tamarillo.jpg | Bin 2535 -> 0 bytes .../component-templates/js/fluid/Fluid.js | 136 - .../component-templates/js/fluid/Lightbox.js | 15 - .../component-templates/js/fluid/Reorderer.js | 945 --- .../js/jquery.tabindex/LICENSE.txt | 307 - .../js/jquery.tabindex/jquery.tabindex.js | 52 - .../js/jquery.ui-1.0/GPL-LICENSE.txt | 278 - .../js/jquery.ui-1.0/MIT-LICENSE.txt | 20 - .../js/jquery.ui-1.0/jquery.dimensions.js | 116 - .../js/jquery.ui-1.0/themes/dark/dark.css | 11 - .../jquery.ui-1.0/themes/dark/dark.form.css | 192 - .../jquery.ui-1.0/themes/dark/dark.form.png | Bin 12308 -> 0 bytes .../jquery.ui-1.0/themes/dark/dark.menu.css | 9 - .../jquery.ui-1.0/themes/dark/dark.modal.css | 93 - .../jquery.ui-1.0/themes/dark/dark.tabs.css | 73 - .../jquery.ui-1.0/themes/dark/dark.tree.css | 61 - .../themes/flora/flora.accordion.css | 12 - .../jquery.ui-1.0/themes/flora/flora.all.css | 9 - .../themes/flora/flora.calendar.css | 167 - .../js/jquery.ui-1.0/themes/flora/flora.css | 2 - .../themes/flora/flora.dialog.css | 86 - .../jquery.ui-1.0/themes/flora/flora.menu.css | 8 - .../themes/flora/flora.resizable.css | 20 - .../themes/flora/flora.shadow.css | 33 - .../themes/flora/flora.slider.css | 8 - .../themes/flora/flora.tablesorter.css | 40 - .../jquery.ui-1.0/themes/flora/flora.tabs.css | 80 - .../themes/flora/i/accordion-left-act.png | Bin 249 -> 0 bytes .../themes/flora/i/accordion-left-over.png | Bin 174 -> 0 bytes .../themes/flora/i/accordion-left.png | Bin 174 -> 0 bytes .../themes/flora/i/accordion-middle-act.png | Bin 148 -> 0 bytes .../themes/flora/i/accordion-middle-over.png | Bin 122 -> 0 bytes .../themes/flora/i/accordion-middle.png | Bin 122 -> 0 bytes .../themes/flora/i/accordion-right-act.png | Bin 245 -> 0 bytes .../themes/flora/i/accordion-right-over.png | Bin 177 -> 0 bytes .../themes/flora/i/accordion-right.png | Bin 177 -> 0 bytes .../js/jquery.ui-1.0/themes/flora/i/asc.gif | Bin 54 -> 0 bytes .../js/jquery.ui-1.0/themes/flora/i/bg.gif | Bin 64 -> 0 bytes .../js/jquery.ui-1.0/themes/flora/i/desc.gif | Bin 54 -> 0 bytes .../jquery.ui-1.0/themes/flora/i/dialog-e.gif | Bin 440 -> 0 bytes .../jquery.ui-1.0/themes/flora/i/dialog-n.gif | Bin 569 -> 0 bytes .../themes/flora/i/dialog-ne.gif | Bin 353 -> 0 bytes .../themes/flora/i/dialog-nw.gif | Bin 353 -> 0 bytes .../jquery.ui-1.0/themes/flora/i/dialog-s.gif | Bin 434 -> 0 bytes .../themes/flora/i/dialog-se.gif | Bin 175 -> 0 bytes .../themes/flora/i/dialog-sw.gif | Bin 175 -> 0 bytes .../themes/flora/i/dialog-title.gif | Bin 238 -> 0 bytes .../flora/i/dialog-titlebar-close-hover.png | Bin 2927 -> 0 bytes .../themes/flora/i/dialog-titlebar-close.png | Bin 2880 -> 0 bytes .../jquery.ui-1.0/themes/flora/i/dialog-w.gif | Bin 437 -> 0 bytes .../themes/flora/i/menu-submenu.gif | Bin 93 -> 0 bytes .../themes/flora/i/resizable-e.gif | Bin 338 -> 0 bytes .../themes/flora/i/resizable-n.gif | Bin 341 -> 0 bytes .../themes/flora/i/resizable-ne.gif | Bin 124 -> 0 bytes .../themes/flora/i/resizable-nw.gif | Bin 91 -> 0 bytes .../themes/flora/i/resizable-s.gif | Bin 341 -> 0 bytes .../themes/flora/i/resizable-se.gif | Bin 120 -> 0 bytes .../themes/flora/i/resizable-sw.gif | Bin 175 -> 0 bytes .../themes/flora/i/resizable-w.gif | Bin 339 -> 0 bytes .../jquery.ui-1.0/themes/flora/i/shadow.png | Bin 3977 -> 0 bytes .../themes/flora/i/slider-bg-1.png | Bin 204 -> 0 bytes .../themes/flora/i/slider-bg-2.png | Bin 326 -> 0 bytes .../themes/flora/i/slider-handle.gif | Bin 176 -> 0 bytes .../js/jquery.ui-1.0/themes/flora/i/tabs.gif | Bin 377 -> 0 bytes .../js/jquery.ui-1.0/themes/light/light.css | 11 - .../jquery.ui-1.0/themes/light/light.form.css | 45 - .../jquery.ui-1.0/themes/light/light.menu.css | 8 - .../themes/light/light.modal.css | 91 - .../jquery.ui-1.0/themes/light/light.tabs.css | 71 - .../jquery.ui-1.0/themes/light/light.tree.css | 61 - .../js/jquery.ui-1.0/ui.accordion.js | 246 - .../js/jquery.ui-1.0/ui.calendar.js | 871 -- .../js/jquery.ui-1.0/ui.dialog.js | 133 - .../js/jquery.ui-1.0/ui.draggable.ext.js | 259 - .../js/jquery.ui-1.0/ui.draggable.js | 182 - .../js/jquery.ui-1.0/ui.droppable.ext.js | 25 - .../js/jquery.ui-1.0/ui.droppable.js | 201 - .../js/jquery.ui-1.0/ui.magnifier.js | 191 - .../js/jquery.ui-1.0/ui.mouse.js | 253 - .../js/jquery.ui-1.0/ui.resizable.js | 304 - .../js/jquery.ui-1.0/ui.selectable.js | 116 - .../js/jquery.ui-1.0/ui.shadow.js | 87 - .../js/jquery.ui-1.0/ui.slider.js | 294 - .../js/jquery.ui-1.0/ui.sortable.js | 263 - .../js/jquery.ui-1.0/ui.tablesorter.js | 808 -- .../js/jquery.ui-1.0/ui.tabs.js | 445 -- .../js/jquery/GPL-LICENSE.txt | 278 - .../js/jquery/MIT-LICENSE.txt | 20 - .../js/jquery/jquery-1.2.1.js | 2992 ------- mods/photo_album/get_pa.php | 254 - mods/photo_album/handler/add_begin.php | 138 - mods/photo_album/handler/delete.php | 92 - mods/photo_album/handler/delete_begin.php | 119 - mods/photo_album/handler/edit_begin.php | 166 - mods/photo_album/handler/fat.js | 91 - mods/photo_album/handler/file_upload.php | 117 - mods/photo_album/handler/store.php | 268 - mods/photo_album/include/data_func.php | 699 -- mods/photo_album/include/general_func.php | 279 - mods/photo_album/index.php | 235 - mods/photo_album/index_admin.php | 66 - mods/photo_album/instructor_comment.php | 171 - mods/photo_album/instructor_config.php | 67 - mods/photo_album/instructor_image.php | 183 - mods/photo_album/module.css | 342 - mods/photo_album/module.php | 176 - mods/photo_album/module.sql | 212 - mods/photo_album/module.xml | 19 - mods/photo_album/module_delete.php | 35 - mods/photo_album/module_install.php | 111 - mods/photo_album/module_uninstall.php | 64 - mods/photo_album/my_comment.php | 156 - mods/photo_album/my_photo.php | 156 - mods/photo_album/skins/pa_first.gif | Bin 118 -> 0 bytes mods/photo_album/skins/pa_first.png | Bin 29906 -> 0 bytes mods/photo_album/skins/pa_last.gif | Bin 106 -> 0 bytes mods/photo_album/skins/pa_last.png | Bin 28083 -> 0 bytes mods/photo_album/skins/pa_next.gif | Bin 84 -> 0 bytes mods/photo_album/skins/pa_next.png | Bin 28513 -> 0 bytes mods/photo_album/skins/pa_prev.gif | Bin 80 -> 0 bytes mods/photo_album/skins/pa_prev.png | Bin 27892 -> 0 bytes mods/photo_album/skins/pa_tool_icon.gif | Bin 1390 -> 0 bytes mods/photo_album/skins/pa_tool_icon.png | Bin 46615 -> 0 bytes mods/photo_album/skins/photo_logo.jpg | Bin 4899 -> 0 bytes mods/photo_album/skins/photo_logo.png | Bin 56781 -> 0 bytes mods/photo_album/skins/swatch_green.jpg | Bin 289 -> 0 bytes mods/photo_album/skins/swatch_green.png | Bin 29409 -> 0 bytes mods/photo_album/skins/swatch_yellow.jpg | Bin 290 -> 0 bytes mods/photo_album/skins/swatch_yellow.png | Bin 27000 -> 0 bytes mods/photo_album/view.php | 173 - mods/photos/addComment.php | 54 - mods/photos/admin/preferences.php | 39 - mods/photos/albums.php | 177 - mods/photos/course_albums.php | 47 - mods/photos/create_album.php | 74 - mods/photos/delete_album.php | 63 - mods/photos/delete_comment.php | 88 - mods/photos/delete_photo.php | 72 - mods/photos/edit_album.php | 86 - mods/photos/edit_comment.php | 46 - mods/photos/edit_photos.php | 143 - mods/photos/get_photo.php | 103 - mods/photos/images/loading.gif | Bin 1849 -> 0 bytes mods/photos/images/next.png | Bin 5946 -> 0 bytes mods/photos/images/no.png | Bin 465 -> 0 bytes mods/photos/images/photo_gallery.png | Bin 7430 -> 0 bytes mods/photos/images/prev.png | Bin 5895 -> 0 bytes mods/photos/images/search_bg.png | Bin 3290 -> 0 bytes mods/photos/images/search_icon.png | Bin 3443 -> 0 bytes mods/photos/include/ajaxupload.js | 711 -- .../include/classes/AjaxMessage.class.php | 87 - .../include/classes/PhotoAlbum.class.php | 702 -- .../include/classes/SimpleImage.class.php | 86 - mods/photos/include/constants.inc.php | 48 - .../include/html/admin/pa_index.tmpl.php | 49 - .../html/admin/pa_preferences.tmpl.php | 12 - mods/photos/include/html/pa_albums.tmpl.php | 336 - .../include/html/pa_create_album.tmpl.php | 34 - .../include/html/pa_edit_album.tmpl.php | 35 - .../include/html/pa_edit_photos.tmpl.php | 34 - mods/photos/include/html/pa_index.tmpl.php | 77 - .../include/html/pa_organize_photos.tmpl.php | 28 - mods/photos/include/html/pa_photo.tmpl.php | 181 - mods/photos/include/html/pa_search.tmpl.php | 167 - mods/photos/include/imageReorderer.js | 57 - mods/photos/include/lib.inc.php | 158 - mods/photos/include/upload.js | 46 - mods/photos/index.php | 49 - mods/photos/index_admin.php | 75 - mods/photos/module.css | 327 - mods/photos/module.php | 148 - mods/photos/module.sql | 131 - mods/photos/module.xml | 19 - mods/photos/module_install.php | 117 - mods/photos/module_uninstall.php | 49 - mods/photos/photo.php | 89 - mods/photos/profile_album.php | 75 - mods/photos/remove_uploaded_photo.php | 44 - mods/photos/search.php | 49 - mods/photos/shared_albums.php | 46 - mods/photos/sublinks.php | 84 - mods/phpdoc/PHPDoc/README | 22 - .../phpdoc/PHPDoc/accessor/PhpdocAccessor.php | 77 - .../PHPDoc/accessor/PhpdocClassAccessor.php | 239 - .../accessor/PhpdocDocumentAccessor.php | 249 - .../PHPDoc/accessor/PhpdocIndexAccessor.php | 359 - .../PHPDoc/accessor/PhpdocModuleAccessor.php | 35 - .../PHPDoc/accessor/PhpdocWarningAccessor.php | 89 - .../phpdoc/PHPDoc/analyser/PhpdocAnalyser.php | 361 - .../PHPDoc/analyser/PhpdocClassAnalyser.php | 553 -- .../PHPDoc/analyser/PhpdocModuleAnalyser.php | 366 - mods/phpdoc/PHPDoc/apidoc/empty.html | 14 - mods/phpdoc/PHPDoc/apidoc/index2.html | 22 - mods/phpdoc/PHPDoc/apidoc/keep/empty.html | 14 - mods/phpdoc/PHPDoc/apidoc/keep/index2.html | 22 - mods/phpdoc/PHPDoc/apidoc/keep/phpdoc.css | 89 - mods/phpdoc/PHPDoc/apidoc/keep/phpdoc.dtd | 146 - mods/phpdoc/PHPDoc/apidoc/phpdoc.css | 89 - mods/phpdoc/PHPDoc/apidoc/phpdoc.dtd | 146 - mods/phpdoc/PHPDoc/core/Phpdoc.php | 238 - mods/phpdoc/PHPDoc/core/PhpdocArgvHandler.php | 161 - mods/phpdoc/PHPDoc/core/PhpdocObject.php | 187 - .../phpdoc/PHPDoc/core/PhpdocSetupHandler.php | 217 - mods/phpdoc/PHPDoc/exceptions/PhpdocError.php | 126 - .../PHPDoc/filehandler/PhpdocFileHandler.php | 209 - mods/phpdoc/PHPDoc/index.php | 70 - mods/phpdoc/PHPDoc/indexer/PhpdocIndexer.php | 196 - .../PHPDoc/parser/PhpdocClassParser.php | 128 - .../PHPDoc/parser/PhpdocConstantParser.php | 109 - .../PHPDoc/parser/PhpdocFunctionParser.php | 137 - .../PHPDoc/parser/PhpdocModuleParser.php | 141 - mods/phpdoc/PHPDoc/parser/PhpdocParser.php | 450 -- .../phpdoc/PHPDoc/parser/PhpdocParserCore.php | 661 -- .../PHPDoc/parser/PhpdocParserRegExp.php | 492 -- .../phpdoc/PHPDoc/parser/PhpdocParserTags.php | 739 -- mods/phpdoc/PHPDoc/parser/PhpdocUseParser.php | 74 - .../PHPDoc/parser/PhpdocVariableParser.php | 127 - mods/phpdoc/PHPDoc/prepend.php | 71 - mods/phpdoc/PHPDoc/redist/IT.php | 654 -- mods/phpdoc/PHPDoc/redist/ITX.php | 293 - .../PHPDoc/renderer/PhpdocRendererObject.php | 21 - mods/phpdoc/PHPDoc/renderer/html/CVS/Entries | 8 - .../PHPDoc/renderer/html/CVS/Repository | 1 - mods/phpdoc/PHPDoc/renderer/html/CVS/Root | 1 - .../renderer/html/PhpdocHTMLClassRenderer.php | 392 - .../html/PhpdocHTMLDocumentRenderer.php | 743 -- .../renderer/html/PhpdocHTMLIndexRenderer.php | 457 -- .../html/PhpdocHTMLModuleRenderer.php | 95 - .../renderer/html/PhpdocHTMLRenderer.php | 78 - .../html/PhpdocHTMLRendererManager.php | 99 - .../html/PhpdocHTMLWarningRenderer.php | 88 - .../renderer/html/templates/CVS/Entries | 12 - .../renderer/html/templates/CVS/Repository | 1 - .../PHPDoc/renderer/html/templates/CVS/Root | 1 - .../PHPDoc/renderer/html/templates/class.html | 598 -- .../renderer/html/templates/classtree.html | 64 - .../renderer/html/templates/elementlist.html | 65 - .../templates/frame_packageelementlist.html | 47 - .../html/templates/frame_packagelist.html | 23 - .../renderer/html/templates/module.html | 445 -- .../renderer/html/templates/modulegroup.html | 64 - .../renderer/html/templates/packagelist.html | 106 - .../PHPDoc/renderer/html/templates/phpdoc.css | 92 - .../renderer/html/templates/warnings.html | 85 - .../renderer/html/templates/xmlfiles.html | 63 - mods/phpdoc/PHPDoc/warning/PhpdocWarning.php | 66 - .../xmlexporter/PhpdocXMLClassExporter.php | 181 - .../xmlexporter/PhpdocXMLDocumentExporter.php | 420 - .../PHPDoc/xmlexporter/PhpdocXMLExporter.php | 142 - .../xmlexporter/PhpdocXMLIndexExporter.php | 192 - .../xmlexporter/PhpdocXMLModuleExporter.php | 51 - .../xmlexporter/PhpdocXMLWarningExporter.php | 49 - .../PHPDoc/xmlreader/PhpdocXMLReader.php | 225 - .../PHPDoc/xmlwriter/PhpdocXMLWriter.php | 175 - mods/phpdoc/index.php | 12 - mods/phpdoc/index_admin.php | 14 - mods/phpdoc/module.css | 11 - mods/phpdoc/module.php | 69 - mods/phpdoc/module.sql | 4 - mods/phpdoc/module.xml | 19 - mods/phpdoc/module_install.php | 75 - mods/phpdoc2/PhpDocumentor/Authors | 23 - mods/phpdoc2/PhpDocumentor/ChangeLog | 9 - mods/phpdoc2/PhpDocumentor/FAQ | 187 - mods/phpdoc2/PhpDocumentor/INSTALL | 81 - mods/phpdoc2/PhpDocumentor/LICENSE | 145 - mods/phpdoc2/PhpDocumentor/README | 198 - mods/phpdoc2/PhpDocumentor/Release-1.4.1 | 101 - mods/phpdoc2/PhpDocumentor/index.html | 1 - .../media/images/earthli/abstract_class.png | Bin 28596 -> 0 bytes .../media/images/earthli/abstract_method.png | Bin 38234 -> 0 bytes .../images/earthli/abstract_private_class.png | Bin 31125 -> 0 bytes .../earthli/abstract_private_method.png | Bin 42186 -> 0 bytes .../media/images/earthli/class.png | Bin 34105 -> 0 bytes .../media/images/earthli/class_folder.png | Bin 38077 -> 0 bytes .../media/images/earthli/constant.png | Bin 38498 -> 0 bytes .../images/earthli/constructor_method.png | Bin 38542 -> 0 bytes .../images/earthli/destructor_method.png | Bin 42499 -> 0 bytes .../media/images/earthli/file.png | Bin 34390 -> 0 bytes .../media/images/earthli/folder.png | Bin 31458 -> 0 bytes .../media/images/earthli/function.png | Bin 36141 -> 0 bytes .../media/images/earthli/function_folder.png | Bin 38913 -> 0 bytes .../media/images/earthli/global.png | Bin 39189 -> 0 bytes .../media/images/earthli/index.png | Bin 28309 -> 0 bytes .../media/images/earthli/lock.png | Bin 36030 -> 0 bytes .../media/images/earthli/method.png | Bin 38359 -> 0 bytes .../media/images/earthli/next_button.png | Bin 29828 -> 0 bytes .../media/images/earthli/package.png | Bin 37982 -> 0 bytes .../media/images/earthli/package_folder.png | Bin 37583 -> 0 bytes .../media/images/earthli/previous_button.png | Bin 29797 -> 0 bytes .../media/images/earthli/private_class.png | Bin 39677 -> 0 bytes .../media/images/earthli/private_method.png | Bin 42420 -> 0 bytes .../media/images/earthli/private_variable.png | Bin 44500 -> 0 bytes .../media/images/earthli/tutorial.png | Bin 37266 -> 0 bytes .../media/images/earthli/tutorial_folder.png | Bin 39800 -> 0 bytes .../media/images/earthli/variable.png | Bin 40250 -> 0 bytes mods/phpdoc2/PhpDocumentor/new_phpdoc.php | 33 - mods/phpdoc2/PhpDocumentor/pear-phpdoc | 41 - mods/phpdoc2/PhpDocumentor/phpDocumentor.ini | 122 - .../PhpDocumentor/phpDocumentor/Classes.inc | 1356 ---- .../PhpDocumentor/phpDocumentor/Converter.inc | 5441 ------------- .../HTML/frames/HTMLframesConverter.inc | 1914 ----- .../frames/templates/DOM/earthli/options.ini | 577 -- .../DOM/earthli/templates/basicindex.tpl | 57 - .../templates/DOM/earthli/templates/blank.tpl | 13 - .../templates/DOM/earthli/templates/class.tpl | 444 -- .../DOM/earthli/templates/classtrees.tpl | 19 - .../templates/DOM/earthli/templates/const.tpl | 18 - .../DOM/earthli/templates/define.tpl | 25 - .../DOM/earthli/templates/docblock.tpl | 14 - .../DOM/earthli/templates/elementindex.tpl | 12 - .../DOM/earthli/templates/errors.tpl | 21 - .../DOM/earthli/templates/examplesource.tpl | 6 - .../DOM/earthli/templates/filesource.tpl | 8 - .../DOM/earthli/templates/footer.tpl | 8 - .../DOM/earthli/templates/function.tpl | 44 - .../DOM/earthli/templates/global.tpl | 27 - .../DOM/earthli/templates/header.tpl | 95 - .../DOM/earthli/templates/include.tpl | 17 - .../templates/DOM/earthli/templates/index.tpl | 24 - .../DOM/earthli/templates/left_frame.tpl | 250 - .../DOM/earthli/templates/media/banner.css | 32 - .../templates/media/images/AbstractClass.png | Bin 620 -> 0 bytes .../media/images/AbstractClass_logo.png | Bin 1232 -> 0 bytes .../templates/media/images/AbstractMethod.png | Bin 696 -> 0 bytes .../media/images/AbstractPrivateClass.png | Bin 848 -> 0 bytes .../images/AbstractPrivateClass_logo.png | Bin 1615 -> 0 bytes .../media/images/AbstractPrivateMethod.png | Bin 874 -> 0 bytes .../earthli/templates/media/images/Class.png | Bin 570 -> 0 bytes .../templates/media/images/Class_logo.png | Bin 1600 -> 0 bytes .../templates/media/images/Constant.png | Bin 752 -> 0 bytes .../templates/media/images/Constructor.png | Bin 865 -> 0 bytes .../templates/media/images/Destructor.png | Bin 956 -> 0 bytes .../templates/media/images/Function.png | Bin 596 -> 0 bytes .../earthli/templates/media/images/Global.png | Bin 712 -> 0 bytes .../DOM/earthli/templates/media/images/I.png | Bin 148 -> 0 bytes .../earthli/templates/media/images/Index.png | Bin 584 -> 0 bytes .../templates/media/images/Interface.png | Bin 1083 -> 0 bytes .../templates/media/images/Interface_logo.png | Bin 1600 -> 0 bytes .../DOM/earthli/templates/media/images/L.png | Bin 153 -> 0 bytes .../earthli/templates/media/images/Lminus.png | Bin 219 -> 0 bytes .../earthli/templates/media/images/Lplus.png | Bin 224 -> 0 bytes .../earthli/templates/media/images/Method.png | Bin 661 -> 0 bytes .../earthli/templates/media/images/Page.png | Bin 592 -> 0 bytes .../templates/media/images/Page_logo.png | Bin 1369 -> 0 bytes .../templates/media/images/PrivateClass.png | Bin 790 -> 0 bytes .../media/images/PrivateClass_logo.png | Bin 1836 -> 0 bytes .../templates/media/images/PrivateMethod.png | Bin 918 -> 0 bytes .../media/images/PrivateVariable.png | Bin 772 -> 0 bytes .../templates/media/images/StaticMethod.png | Bin 661 -> 0 bytes .../templates/media/images/StaticVariable.png | Bin 688 -> 0 bytes .../DOM/earthli/templates/media/images/T.png | Bin 152 -> 0 bytes .../earthli/templates/media/images/Tminus.png | Bin 207 -> 0 bytes .../earthli/templates/media/images/Tplus.png | Bin 222 -> 0 bytes .../templates/media/images/Variable.png | Bin 688 -> 0 bytes .../earthli/templates/media/images/blank.png | Bin 144 -> 0 bytes .../templates/media/images/class_folder.png | Bin 633 -> 0 bytes .../earthli/templates/media/images/empty.png | Bin 90 -> 0 bytes .../earthli/templates/media/images/file.png | Bin 462 -> 0 bytes .../earthli/templates/media/images/folder.png | Bin 492 -> 0 bytes .../media/images/function_folder.png | Bin 605 -> 0 bytes .../earthli/templates/media/images/minus.gif | Bin 54 -> 0 bytes .../templates/media/images/next_button.png | Bin 657 -> 0 bytes .../media/images/next_button_disabled.png | Bin 543 -> 0 bytes .../templates/media/images/package.png | Bin 668 -> 0 bytes .../templates/media/images/package_folder.png | Bin 564 -> 0 bytes .../earthli/templates/media/images/plus.gif | Bin 56 -> 0 bytes .../media/images/previous_button.png | Bin 644 -> 0 bytes .../media/images/previous_button_disabled.png | Bin 541 -> 0 bytes .../media/images/private_class_logo.png | Bin 1836 -> 0 bytes .../templates/media/images/tutorial.png | Bin 431 -> 0 bytes .../media/images/tutorial_folder.png | Bin 572 -> 0 bytes .../templates/media/images/up_button.png | Bin 668 -> 0 bytes .../earthli/templates/media/lib/classTree.js | 454 -- .../earthli/templates/media/stylesheet.css | 181 - .../DOM/earthli/templates/method.tpl | 151 - .../templates/DOM/earthli/templates/page.tpl | 214 - .../DOM/earthli/templates/pkgelementindex.tpl | 17 - .../templates/DOM/earthli/templates/ric.tpl | 6 - .../DOM/earthli/templates/todolist.tpl | 14 - .../DOM/earthli/templates/top_frame.tpl | 45 - .../DOM/earthli/templates/tutorial.tpl | 13 - .../DOM/earthli/templates/tutorial_nav.tpl | 41 - .../DOM/earthli/templates/tutorial_toc.tpl | 39 - .../DOM/earthli/templates/tutorial_tree.tpl | 9 - .../templates/DOM/earthli/templates/var.tpl | 94 - .../HTML/frames/templates/earthli/options.ini | 576 -- .../earthli/templates/basicindex.tpl | 57 - .../templates/earthli/templates/blank.tpl | 13 - .../templates/earthli/templates/class.tpl | 437 - .../earthli/templates/classtrees.tpl | 19 - .../templates/earthli/templates/const.tpl | 18 - .../templates/earthli/templates/define.tpl | 25 - .../templates/earthli/templates/docblock.tpl | 14 - .../earthli/templates/elementindex.tpl | 12 - .../templates/earthli/templates/errors.tpl | 21 - .../earthli/templates/examplesource.tpl | 6 - .../earthli/templates/filesource.tpl | 8 - .../templates/earthli/templates/footer.tpl | 8 - .../templates/earthli/templates/function.tpl | 44 - .../templates/earthli/templates/global.tpl | 27 - .../templates/earthli/templates/header.tpl | 12 - .../templates/earthli/templates/include.tpl | 17 - .../templates/earthli/templates/index.tpl | 24 - .../earthli/templates/left_frame.tpl | 159 - .../earthli/templates/media/banner.css | 33 - .../templates/media/images/AbstractClass.png | Bin 620 -> 0 bytes .../media/images/AbstractClass_logo.png | Bin 1232 -> 0 bytes .../templates/media/images/AbstractMethod.png | Bin 696 -> 0 bytes .../media/images/AbstractPrivateClass.png | Bin 848 -> 0 bytes .../images/AbstractPrivateClass_logo.png | Bin 1615 -> 0 bytes .../media/images/AbstractPrivateMethod.png | Bin 874 -> 0 bytes .../earthli/templates/media/images/Class.png | Bin 570 -> 0 bytes .../templates/media/images/Class_logo.png | Bin 1600 -> 0 bytes .../templates/media/images/Constant.png | Bin 752 -> 0 bytes .../templates/media/images/Constructor.png | Bin 865 -> 0 bytes .../templates/media/images/Destructor.png | Bin 956 -> 0 bytes .../templates/media/images/Function.png | Bin 596 -> 0 bytes .../earthli/templates/media/images/Global.png | Bin 712 -> 0 bytes .../earthli/templates/media/images/I.png | Bin 148 -> 0 bytes .../earthli/templates/media/images/Index.png | Bin 584 -> 0 bytes .../templates/media/images/Interface.png | Bin 1083 -> 0 bytes .../templates/media/images/Interface_logo.png | Bin 1600 -> 0 bytes .../earthli/templates/media/images/L.png | Bin 153 -> 0 bytes .../earthli/templates/media/images/Lminus.png | Bin 219 -> 0 bytes .../earthli/templates/media/images/Lplus.png | Bin 224 -> 0 bytes .../earthli/templates/media/images/Method.png | Bin 661 -> 0 bytes .../earthli/templates/media/images/Page.png | Bin 592 -> 0 bytes .../templates/media/images/Page_logo.png | Bin 1369 -> 0 bytes .../templates/media/images/PrivateClass.png | Bin 790 -> 0 bytes .../media/images/PrivateClass_logo.png | Bin 1836 -> 0 bytes .../templates/media/images/PrivateMethod.png | Bin 918 -> 0 bytes .../media/images/PrivateVariable.png | Bin 772 -> 0 bytes .../templates/media/images/StaticMethod.png | Bin 661 -> 0 bytes .../templates/media/images/StaticVariable.png | Bin 688 -> 0 bytes .../earthli/templates/media/images/T.png | Bin 152 -> 0 bytes .../earthli/templates/media/images/Tminus.png | Bin 207 -> 0 bytes .../earthli/templates/media/images/Tplus.png | Bin 222 -> 0 bytes .../templates/media/images/Variable.png | Bin 688 -> 0 bytes .../earthli/templates/media/images/blank.png | Bin 144 -> 0 bytes .../templates/media/images/class_folder.png | Bin 633 -> 0 bytes .../earthli/templates/media/images/empty.png | Bin 90 -> 0 bytes .../earthli/templates/media/images/file.png | Bin 462 -> 0 bytes .../earthli/templates/media/images/folder.png | Bin 492 -> 0 bytes .../media/images/function_folder.png | Bin 605 -> 0 bytes .../templates/media/images/next_button.png | Bin 657 -> 0 bytes .../media/images/next_button_disabled.png | Bin 543 -> 0 bytes .../templates/media/images/package.png | Bin 668 -> 0 bytes .../templates/media/images/package_folder.png | Bin 564 -> 0 bytes .../media/images/previous_button.png | Bin 644 -> 0 bytes .../media/images/previous_button_disabled.png | Bin 541 -> 0 bytes .../media/images/private_class_logo.png | Bin 1836 -> 0 bytes .../templates/media/images/tutorial.png | Bin 431 -> 0 bytes .../media/images/tutorial_folder.png | Bin 572 -> 0 bytes .../templates/media/images/up_button.png | Bin 668 -> 0 bytes .../earthli/templates/media/stylesheet.css | 146 - .../templates/earthli/templates/method.tpl | 151 - .../templates/earthli/templates/page.tpl | 214 - .../earthli/templates/pkgelementindex.tpl | 17 - .../templates/earthli/templates/ric.tpl | 6 - .../templates/earthli/templates/todolist.tpl | 14 - .../templates/earthli/templates/top_frame.tpl | 45 - .../templates/earthli/templates/tutorial.tpl | 13 - .../earthli/templates/tutorial_nav.tpl | 41 - .../earthli/templates/tutorial_toc.tpl | 39 - .../earthli/templates/tutorial_tree.tpl | 6 - .../templates/earthli/templates/var.tpl | 94 - .../PhpDocumentor/phpDocumentor/DescHTML.inc | 423 - .../phpDocumentor/DocBlockTags.inc | 1078 --- .../PhpDocumentor/phpDocumentor/Errors.inc | 1172 --- .../phpDocumentor/EventStack.inc | 98 - .../phpDocumentor/HighlightParser.inc | 2603 ------ .../phpDocumentor/InlineTags.inc | 869 -- .../phpDocumentor/IntermediateParser.inc | 1940 ----- .../PhpDocumentor/phpDocumentor/Io.inc | 992 --- .../phpDocumentor/LinkClasses.inc | 220 - .../phpDocumentor/PackagePageElements.inc | 405 - .../PhpDocumentor/phpDocumentor/Parser.inc | 3252 -------- .../phpDocumentor/ParserData.inc | 789 -- .../phpDocumentor/ParserDescCleanup.inc | 1486 ---- .../phpDocumentor/ParserDocBlock.inc | 1225 --- .../phpDocumentor/ParserElements.inc | 2288 ------ .../phpDocumentor/ProceduralPages.inc | 1067 --- .../PhpDocumentor/phpDocumentor/Publisher.inc | 110 - .../PhpDocumentor/phpDocumentor/Setup.inc.php | 970 --- .../phpDocumentor/Smarty-2.6.0/BUGS | 7 - .../phpDocumentor/Smarty-2.6.0/COPYING.lib | 458 -- .../phpDocumentor/Smarty-2.6.0/ChangeLog | 5421 ------------- .../phpDocumentor/Smarty-2.6.0/FAQ | 284 - .../phpDocumentor/Smarty-2.6.0/INSTALL | 29 - .../phpDocumentor/Smarty-2.6.0/NEWS | 733 -- .../phpDocumentor/Smarty-2.6.0/README | 80 - .../phpDocumentor/Smarty-2.6.0/RELEASE_NOTES | 423 - .../phpDocumentor/Smarty-2.6.0/TODO | 12 - .../Smarty-2.6.0/libs/Config_File.class.php | 365 - .../Smarty-2.6.0/libs/Smarty.class.php | 2010 ----- .../libs/Smarty_Compiler.class.php | 2123 ----- .../core/core.assemble_plugin_filepath.php | 62 - .../core/core.assign_smarty_interface.php | 43 - .../libs/core/core.create_dir_structure.php | 79 - .../libs/core/core.display_debug_console.php | 60 - .../libs/core/core.get_include_path.php | 44 - .../libs/core/core.get_microtime.php | 23 - .../libs/core/core.get_php_resource.php | 80 - .../Smarty-2.6.0/libs/core/core.is_secure.php | 59 - .../libs/core/core.is_trusted.php | 50 - .../libs/core/core.load_plugins.php | 125 - .../libs/core/core.load_resource_plugin.php | 74 - .../libs/core/core.process_cached_inserts.php | 71 - .../core/core.process_compiled_include.php | 32 - .../libs/core/core.read_cache_file.php | 111 - .../Smarty-2.6.0/libs/core/core.rm_auto.php | 71 - .../Smarty-2.6.0/libs/core/core.rmdir.php | 55 - .../libs/core/core.run_insert_handler.php | 71 - .../libs/core/core.smarty_include_php.php | 50 - .../libs/core/core.write_cache_file.php | 73 - .../libs/core/core.write_compiled_include.php | 59 - .../core/core.write_compiled_resource.php | 37 - .../libs/core/core.write_file.php | 48 - .../phpDocumentor/Smarty-2.6.0/libs/debug.tpl | 64 - .../Smarty-2.6.0/libs/plugins/block.strip.php | 35 - .../libs/plugins/block.textformat.php | 83 - .../libs/plugins/function.assign.php | 38 - .../plugins/function.assign_debug_info.php | 39 - .../libs/plugins/function.config_load.php | 130 - .../libs/plugins/function.counter.php | 88 - .../libs/plugins/function.cycle.php | 119 - .../libs/plugins/function.debug.php | 35 - .../libs/plugins/function.eval.php | 48 - .../libs/plugins/function.fetch.php | 217 - .../libs/plugins/function.html_checkboxes.php | 135 - .../libs/plugins/function.html_image.php | 143 - .../libs/plugins/function.html_options.php | 118 - .../libs/plugins/function.html_radios.php | 138 - .../plugins/function.html_select_date.php | 243 - .../plugins/function.html_select_time.php | 163 - .../libs/plugins/function.html_table.php | 113 - .../libs/plugins/function.mailto.php | 140 - .../libs/plugins/function.math.php | 82 - .../libs/plugins/function.popup.php | 87 - .../libs/plugins/function.popup_init.php | 39 - .../libs/plugins/function.var_dump.php | 20 - .../libs/plugins/modifier.capitalize.php | 25 - .../libs/plugins/modifier.cat.php | 33 - .../plugins/modifier.count_characters.php | 31 - .../plugins/modifier.count_paragraphs.php | 28 - .../libs/plugins/modifier.count_sentences.php | 28 - .../libs/plugins/modifier.count_words.php | 32 - .../libs/plugins/modifier.date_format.php | 43 - .../libs/plugins/modifier.debug_print_var.php | 57 - .../libs/plugins/modifier.default.php | 31 - .../libs/plugins/modifier.escape.php | 63 - .../libs/plugins/modifier.htmlentities.php | 18 - .../libs/plugins/modifier.indent.php | 27 - .../libs/plugins/modifier.lower.php | 25 - .../libs/plugins/modifier.nl2br.php | 35 - .../libs/plugins/modifier.rawurlencode.php | 18 - .../libs/plugins/modifier.regex_replace.php | 29 - .../libs/plugins/modifier.replace.php | 29 - .../libs/plugins/modifier.spacify.php | 29 - .../libs/plugins/modifier.string_format.php | 28 - .../libs/plugins/modifier.strip.php | 33 - .../libs/plugins/modifier.strip_tags.php | 31 - .../libs/plugins/modifier.truncate.php | 43 - .../libs/plugins/modifier.upper.php | 25 - .../libs/plugins/modifier.wordwrap.php | 28 - .../plugins/outputfilter.trimwhitespace.php | 75 - .../plugins/shared.escape_special_chars.php | 30 - .../libs/plugins/shared.make_timestamp.php | 43 - .../Smarty-2.6.0/misc/smarty_icon.README | 6 - .../Smarty-2.6.0/misc/smarty_icon.gif | Bin 1102 -> 0 bytes .../phpDocumentor/TutorialHighlightParser.inc | 620 -- .../phpDocumentor/WordParser.inc | 365 - .../phpDocumentor/XMLpackagePageParser.inc | 644 -- .../PhpDocumentor/phpDocumentor/clone.inc.php | 53 - .../phpDocumentor/clone5.inc.php | 54 - .../phpDocumentor/common.inc.php | 313 - .../phpDocumentor/find_phpdoc.php | 49 - .../phpDocumentor/phpDocumentorTParser.inc | 2946 ------- .../phpDocumentorTWordParser.inc | 384 - .../PhpDocumentor/phpDocumentor/phpdoc.inc | 66 - mods/phpdoc2/PhpDocumentor/phpdoc | 63 - mods/phpdoc2/PhpDocumentor/phpdoc.php | 32 - .../phpdoc2/PhpDocumentor/poweredbyphpdoc.gif | Bin 1363 -> 0 bytes .../phpdoc2/PhpDocumentor/scripts/add_cvs.php | 153 - .../PhpDocumentor/scripts/create_examples.php | 70 - .../scripts/create_package.xml.php | 158 - mods/phpdoc2/PhpDocumentor/scripts/makedoc.sh | 94 - .../PhpDocumentor/scripts/tokenizer_test.php | 59 - mods/phpdoc2/api_install.php | 101 - mods/phpdoc2/apidoc/index.html | 1 - mods/phpdoc2/include/classes/index.html | 1 - .../include/classes/phpdoc2_images.class.php | 114 - mods/phpdoc2/include/index.html | 1 - mods/phpdoc2/index.php | 12 - mods/phpdoc2/index_admin.php | 29 - mods/phpdoc2/module.css | 53 - mods/phpdoc2/module.php | 29 - mods/phpdoc2/module.sql | 5 - mods/phpdoc2/module.xml | 19 - mods/phpdoc2/module_install.php | 66 - mods/phpdoc2/module_uninstall.php | 45 - mods/phpmyadmin/module.php | 21 - mods/phpmyadmin/module.sql | 12 - mods/phpmyadmin/module.xml | 19 - mods/phpmyadmin/module_install.php | 25 - mods/phpmyadmin/module_uninstall.php | 21 - mods/phpmyadmin/phpmyadmin.php | 71 - mods/plog/README_ATUTOR_MODULE | 28 - mods/plog/admin_plog.php | 129 - mods/plog/index.php | 62 - mods/plog/index_admin.php | 40 - mods/plog/index_instructor.php | 75 - mods/plog/module.css | 188 - mods/plog/module.php | 81 - mods/plog/module.sql | 34 - mods/plog/module.xml | 19 - mods/plog/module_install.php | 48 - mods/plog/plog_logo.gif | Bin 1604 -> 0 bytes mods/plog/side_menu.inc.php | 38 - mods/plog/sync_plog.php | 202 - mods/plog/sync_plog11.php | 236 - mods/pnATutor/ATutor/index_pn.php | 100 - mods/pnATutor/pnadmin.php | 246 - mods/pnATutor/pnblocks/courses.php | 184 - mods/pnATutor/pndocs/credits.txt | 10 - mods/pnATutor/pndocs/license.txt | 346 - mods/pnATutor/pndocs/readme.txt | 21 - mods/pnATutor/pnincludes/overlib.js | 1315 --- mods/pnATutor/pnincludes/overlib_mini.js | 328 - mods/pnATutor/pnincludes/overlib_power.gif | Bin 1963 -> 0 bytes mods/pnATutor/pninit.php | 79 - mods/pnATutor/pnlang/eng/admin.php | 21 - mods/pnATutor/pnlang/eng/courses.php | 8 - .../pntemplates/pnATutor_block_courses.htm | 26 - .../pnATutor_block_courses_modify.htm | 44 - mods/pnATutor/pnuser.php | 147 - mods/pnATutor/pnversion.php | 18 - mods/scorm_packages/delete.php | 75 - mods/scorm_packages/import.php | 111 - mods/scorm_packages/index.php | 64 - mods/scorm_packages/lib.inc.php | 89 - mods/scorm_packages/module.php | 40 - mods/scorm_packages/module.sql | 75 - mods/scorm_packages/module.xml | 19 - mods/scorm_packages/module_install.php | 26 - mods/scorm_packages/module_uninstall.php | 35 - mods/scorm_packages/packages/index.php | 45 - mods/scorm_packages/packages/preferences.php | 115 - .../scorm_packages/possible_module_backup.php | 65 - .../scorm-1.2/images/active.png | Bin 499 -> 0 bytes .../scorm_packages/scorm-1.2/images/asset.png | Bin 453 -> 0 bytes .../scorm-1.2/images/browsed.png | Bin 505 -> 0 bytes mods/scorm_packages/scorm-1.2/images/busy.png | Bin 499 -> 0 bytes .../scorm-1.2/images/completed.png | Bin 505 -> 0 bytes .../scorm-1.2/images/failed.png | Bin 206 -> 0 bytes .../scorm-1.2/images/incomplete.png | Bin 538 -> 0 bytes .../scorm-1.2/images/not-attempted.png | Bin 532 -> 0 bytes .../scorm-1.2/images/passed.png | Bin 232 -> 0 bytes mods/scorm_packages/scorm-1.2/import.php | 489 -- .../scorm-1.2/java/ATutorApiAdapterApplet.jar | Bin 3574 -> 0 bytes .../java/ATutorApiAdapterApplet.java | 313 - .../java/PfPLMS-API-adapter-core.jar | Bin 17318 -> 0 bytes mods/scorm_packages/scorm-1.2/java/gnu.jar | Bin 24398 -> 0 bytes .../scorm_packages/scorm-1.2/learner_view.php | 45 - mods/scorm_packages/scorm-1.2/lib.inc.php | 253 - mods/scorm_packages/scorm-1.2/read.php | 106 - mods/scorm_packages/scorm-1.2/settings.php | 121 - mods/scorm_packages/scorm-1.2/view.inc.php | 399 - mods/scorm_packages/scorm-1.2/view.php | 426 - mods/scorm_packages/scorm-1.2/write.php | 59 - mods/scorm_packages/settings.php | 65 - mods/social/README | 97 - mods/social/activities.php | 31 - mods/social/admin/delete_applications.php | 45 - mods/social/applications.php | 131 - mods/social/basic_profile.php | 149 - mods/social/connections.php | 143 - mods/social/edit_profile.php | 236 - mods/social/groups/create.php | 177 - mods/social/groups/delete.php | 53 - mods/social/groups/delete_message.php | 56 - mods/social/groups/edit.php | 197 - mods/social/groups/get_sgroup_logo.php | 70 - mods/social/groups/index.php | 57 - mods/social/groups/invitation_handler.php | 132 - mods/social/groups/invite.php | 68 - mods/social/groups/join.php | 80 - mods/social/groups/list.php | 91 - mods/social/groups/search.php | 77 - mods/social/groups/view.php | 76 - mods/social/html/activities.tmpl.php | 34 - .../html/admin/delete_applications.tmpl.php | 40 - .../social/html/application_settings.tmpl.php | 63 - mods/social/html/applications.tmpl.php | 103 - mods/social/html/basic_profile.tmpl.php | 128 - mods/social/html/connections.tmpl.php | 107 - mods/social/html/edit_profile.tmpl.php | 99 - .../edit_profile/edit_additional.tmpl.php | 26 - .../html/edit_profile/edit_education.tmpl.php | 56 - .../html/edit_profile/edit_position.tmpl.php | 44 - .../html/edit_profile/edit_websites.tmpl.php | 29 - mods/social/html/friend_list.tmpl.php | 35 - mods/social/html/index_public.tmpl.php | 71 - .../html/individual_application.tmpl.php | 16 - mods/social/html/notifications.tmpl.php | 78 - mods/social/html/profile_picture.html.php | 213 - mods/social/html/pubmenu.tmpl.php | 12 - .../html/settings/account_settings.tmpl.php | 10 - .../settings/application_settings.tmpl.php | 26 - .../html/settings/privacy_settings.tmpl.php | 144 - .../html/settings/settings_menu.tmpl.php | 6 - mods/social/html/sgroup_create.tmpl.php | 38 - mods/social/html/sgroup_edit.tmpl.php | 93 - mods/social/html/sgroup_invite.tmpl.php | 47 - mods/social/html/sgroup_list.tmpl.php | 61 - mods/social/html/sgroup_search.tmpl.php | 51 - mods/social/html/sgroup_view.tmpl.php | 136 - mods/social/html/sgroups.tmpl.php | 37 - mods/social/html/sprofile.tmpl.php | 214 - mods/social/html/tiny_applications.tmpl.php | 35 - mods/social/html/tiny_sgroups.tmpl.php | 36 - mods/social/images/b_drop.png | Bin 311 -> 0 bytes mods/social/images/check_icon.gif | Bin 564 -> 0 bytes mods/social/images/check_icon.jpg | Bin 4147 -> 0 bytes mods/social/images/check_icon.png | Bin 4349 -> 0 bytes mods/social/images/edit_profile.gif | Bin 232 -> 0 bytes mods/social/images/icon-settings.png | Bin 326 -> 0 bytes mods/social/images/nophoto.gif | Bin 193 -> 0 bytes mods/social/images/placelogo.gif | Bin 1035 -> 0 bytes mods/social/images/placelogo.png | Bin 3854 -> 0 bytes mods/social/images/plus_icon.gif | Bin 997 -> 0 bytes mods/social/images/plus_icon.jpg | Bin 458 -> 0 bytes mods/social/images/social.jpg | Bin 2603 -> 0 bytes mods/social/index.php | 165 - mods/social/index_admin.php | 49 - mods/social/index_instructor.php | 23 - mods/social/index_mystart.php | 19 - mods/social/index_public.php | 127 - mods/social/lib/BasicBlobCrypter.php | 130 - mods/social/lib/BasicSecurityToken.php | 160 - mods/social/lib/BlobCrypter.php | 53 - mods/social/lib/Crypto.php | 123 - mods/social/lib/SecurityToken.php | 70 - .../lib/Shindig/ATutorActivityService.php | 75 - .../lib/Shindig/ATutorAppDataService.php | 74 - mods/social/lib/Shindig/ATutorDbFetcher.php | 812 -- .../lib/Shindig/ATutorMessagesService.php | 20 - .../lib/Shindig/ATutorPersonService.php | 78 - mods/social/lib/Shindig/ATutorService.php | 121 - mods/social/lib/Shindig/README | 4 - mods/social/lib/classes/Activity.class.php | 151 - mods/social/lib/classes/Application.class.php | 398 - .../social/lib/classes/Applications.class.php | 120 - mods/social/lib/classes/Member.class.php | 478 -- .../PrivacyController.class.php | 162 - .../PrivacyControl/PrivacyObject.class.php | 92 - .../PrivacyControl/SetPrivacyControl.php | 60 - .../SocialGroups/SocialGroup.class.php | 485 -- .../SocialGroups/SocialGroups.class.php | 250 - mods/social/lib/constants.inc.php | 64 - mods/social/lib/friends.inc.php | 656 -- mods/social/lib/js/container.js | 89 - mods/social/lib/js/jquery-1.3.2.js | 4376 ---------- mods/social/lib/js/jquery.all.js | 19 - mods/social/lib/js/livesearch.js | 40 - mods/social/lib/js/myContainer.bak | 146 - mods/social/lib/js/myContainer.js | 146 - mods/social/lib/js/myContainer_shindig.js | 146 - mods/social/lib/js/myContainer_shindig2.js | 146 - mods/social/lib/profile_menu.inc.php | 6 - mods/social/module.css | 97 - mods/social/module.php | 147 - mods/social/module.sql | 423 - mods/social/module.xml | 23 - mods/social/module_backup.php | 33 - mods/social/module_delete.php | 34 - mods/social/module_install.php | 78 - mods/social/module_uninstall.php | 49 - mods/social/privacy_settings.php | 46 - mods/social/profile_picture.php | 19 - mods/social/set_prefs.php | 47 - mods/social/settings.php | 83 - mods/social/side_menu.inc.php | 75 - mods/social/sprofile.php | 108 - mods/terms_and_conditions/module.php | 25 - mods/terms_and_conditions/module.sql | 7 - mods/terms_and_conditions/module.xml | 19 - mods/terms_and_conditions/module_install.php | 52 - .../terms_and_conditions/module_uninstall.php | 30 - mods/terms_and_conditions/tac_edit.php | 112 - .../terms_and_conditions.php | 23 - .../terms_and_conditions.tmpl.php | 63 - mods/tle/assembler.php | 58 - mods/tle/home-tle_search.gif | Bin 1906 -> 0 bytes mods/tle/import.php | 122 - mods/tle/index.php | 56 - mods/tle/index_admin.php | 58 - mods/tle/index_student.php | 56 - mods/tle/module.php | 31 - mods/tle/module.sql | 12 - mods/tle/module.xml | 19 - mods/tle/module_install.php | 20 - mods/tle/module_uninstall.php | 26 - mods/tle/readme_tle.txt | 22 - mods/twitter/Twitter.php | 25 - mods/twitter/index.php | 37 - mods/twitter/module.php | 48 - mods/twitter/module.sql | 3 - mods/twitter/module.xml | 19 - mods/twitter/module_uninstall.php | 26 - mods/twitter/twitter.png | Bin 5273 -> 0 bytes mods/userplane/README | 29 - mods/userplane/index.php | 12 - mods/userplane/index_admin.php | 67 - mods/userplane/module.css | 12 - mods/userplane/module.php | 47 - mods/userplane/module.sql | 10 - mods/userplane/module.xml | 19 - mods/userplane/module_install.php | 30 - mods/userplane/module_uninstall.php | 26 - mods/userplane/side_menu.inc.php | 14 - mods/userplane/userplane.jpg | Bin 1804 -> 0 bytes mods/utf8conv/index.php | 12 - mods/utf8conv/index_admin.php | 21 - mods/utf8conv/index_instructor.php | 21 - mods/utf8conv/module.php | 37 - mods/utf8conv/module.sql | 4 - mods/utf8conv/module.xml | 40 - mods/utf8conv/module_install.php | 67 - mods/utf8conv/module_uninstall.php | 31 - mods/utf8conv/readDir.php | 148 - mods/utf8conv/utf8conv.php | 442 -- mods/wiki/LICENSE | 36 - mods/wiki/README_ATUTOR_MODULE | 30 - mods/wiki/config.php | 123 - mods/wiki/doc/Acronyms | 112 - mods/wiki/doc/AdminTasksSql | 114 - mods/wiki/doc/CHANGES | 464 -- mods/wiki/doc/CREDITS | 107 - mods/wiki/doc/ConfigSettings | 851 -- mods/wiki/doc/FAQ | 116 - mods/wiki/doc/INSTALL | 28 - mods/wiki/doc/INTERNALS | 1135 --- mods/wiki/doc/LinkSpammers | 248 - mods/wiki/doc/MagicFields | 15 - mods/wiki/doc/NicerUrls | 124 - mods/wiki/doc/NoticeMessages | 5 - mods/wiki/doc/PluginMetaFiles | 259 - mods/wiki/doc/ProtectedMode | 578 -- mods/wiki/doc/README | 1388 ---- mods/wiki/doc/README.de | 858 -- mods/wiki/doc/README.fragments | 642 -- mods/wiki/doc/README.plugins | 2240 ------ mods/wiki/doc/ReadOnlyWiki | 87 - mods/wiki/doc/SetupTool | 116 - mods/wiki/doc/UPGRADE | 7 - mods/wiki/doc/WikiXmlRpc | 172 - mods/wiki/ewiki.php | 3981 ---------- mods/wiki/fragments/404finder.php | 86 - mods/wiki/fragments/binary.php | 27 - mods/wiki/fragments/blocks/README | 2 - mods/wiki/fragments/blocks/calendar.php | 13 - mods/wiki/fragments/blocks/editsidetext.php | 10 - mods/wiki/fragments/blocks/intpages.php | 19 - mods/wiki/fragments/blocks/mainmenu.php | 22 - mods/wiki/fragments/blocks/news.php | 59 - mods/wiki/fragments/blocks/printhint.php | 20 - mods/wiki/fragments/blocks/search.php | 19 - mods/wiki/fragments/css.php | 35 - mods/wiki/fragments/css/PlugInstall.css | 48 - mods/wiki/fragments/css/README | 31 - mods/wiki/fragments/css/UserRegistry.css | 31 - mods/wiki/fragments/css/WikiNavBarStyle.css | 60 - mods/wiki/fragments/css/WikiSetupWizard.css | 5 - mods/wiki/fragments/css/calendar.css | 54 - mods/wiki/fragments/css/core.css | 137 - mods/wiki/fragments/css/forum.css | 24 - mods/wiki/fragments/force_lang_de.php | 50 - mods/wiki/fragments/funcs/README | 5 - mods/wiki/fragments/funcs/auth.php | 53 - mods/wiki/fragments/funcs/save_newest_pages | 32 - mods/wiki/fragments/funcs/wiki_format.inc | 291 - mods/wiki/fragments/head/core.php | 17 - mods/wiki/fragments/head/meta.php | 51 - mods/wiki/fragments/htaccess | 25 - mods/wiki/fragments/ini.php | 85 - mods/wiki/fragments/js/pngbehaviour.htc | 55 - .../fragments/parent-cms/nuke_mod_wiki_index | 58 - mods/wiki/fragments/patches/README | 14 - mods/wiki/fragments/patches/auth_ldap.patch | 148 - mods/wiki/fragments/patches/binarystoredirect | 37 - mods/wiki/fragments/patches/clickableimages | 27 - mods/wiki/fragments/patches/nowikiwords | 9 - mods/wiki/fragments/patches/old_php_compat.pl | 49 - mods/wiki/fragments/patches/uploadedfilenames | 18 - mods/wiki/fragments/rss.php | 27 - mods/wiki/fragments/site_prot.php | 171 - .../fragments/strike_register_globals.php | 49 - .../fragments/strip_wonderful_slashes.php | 49 - mods/wiki/fragments/zero_pagerank.php | 34 - mods/wiki/index.php | 60 - mods/wiki/index_admin.php | 10 - mods/wiki/index_instructor.php | 11 - mods/wiki/init-pages/ATutorWiki | 15 - mods/wiki/init-pages/CamelCase | 7 - mods/wiki/init-pages/CreatePages | 13 - mods/wiki/init-pages/EditThisPage | 9 - mods/wiki/init-pages/ErfurtWiki | 16 - mods/wiki/init-pages/ExtendedWikiMarkup | 180 - mods/wiki/init-pages/FormattingOptions | 18 - mods/wiki/init-pages/FrontPage | 16 - mods/wiki/init-pages/HyperLink | 6 - mods/wiki/init-pages/HyperTextMarkupLanguage | 7 - mods/wiki/init-pages/ImageUploading | 10 - mods/wiki/init-pages/WikiHowto | 10 - mods/wiki/init-pages/WikiMarkup | 74 - mods/wiki/init-pages/WikiWikiWeb | 8 - mods/wiki/init-pages/WikiWord | 31 - mods/wiki/init-pages/WorldWideWeb | 4 - mods/wiki/module.css | 225 - mods/wiki/module.php | 32 - mods/wiki/module.sql | 3 - mods/wiki/module.xml | 19 - mods/wiki/module_delete.php | 21 - mods/wiki/module_install.php | 65 - mods/wiki/module_uninstall.php | 26 - mods/wiki/page.php | 74 - mods/wiki/plugins/.htaccess | 2 - mods/wiki/plugins/action/calendarlist.meta | 7 - mods/wiki/plugins/action/calendarlist.php | 37 - mods/wiki/plugins/action/diff.meta | 7 - mods/wiki/plugins/action/diff.php | 86 - mods/wiki/plugins/action/diff_gnu.meta | 6 - mods/wiki/plugins/action/diff_gnu.php | 76 - .../plugins/action/diff_gnu_safemode.meta | 7 - .../wiki/plugins/action/diff_gnu_safemode.php | 99 - mods/wiki/plugins/action/email_page.meta | 7 - mods/wiki/plugins/action/email_page.php | 258 - mods/wiki/plugins/action/extract.meta | 7 - mods/wiki/plugins/action/extract.php | 99 - mods/wiki/plugins/action/htm.meta | 6 - mods/wiki/plugins/action/htm.php | 13 - mods/wiki/plugins/action/info_qdiff.meta | 7 - mods/wiki/plugins/action/info_qdiff.php | 50 - mods/wiki/plugins/action/like_pages.meta | 7 - mods/wiki/plugins/action/like_pages.php | 37 - mods/wiki/plugins/action/manpage.meta | 7 - mods/wiki/plugins/action/manpage.php | 144 - mods/wiki/plugins/action/raw.meta | 7 - mods/wiki/plugins/action/raw.php | 25 - mods/wiki/plugins/action/relatedchanges.meta | 7 - mods/wiki/plugins/action/relatedchanges.php | 18 - mods/wiki/plugins/action/rss.meta | 7 - mods/wiki/plugins/action/rss.php | 48 - mods/wiki/plugins/action/translation.meta | 7 - mods/wiki/plugins/action/translation.php | 185 - mods/wiki/plugins/action/verdiff.meta | 7 - mods/wiki/plugins/action/verdiff.php | 63 - mods/wiki/plugins/admin/admintrigger.php | 21 - mods/wiki/plugins/admin/control.meta | 7 - mods/wiki/plugins/admin/control.php | 278 - .../plugins/admin/page_searchandreplace.meta | 8 - .../plugins/admin/page_searchandreplace.php | 175 - mods/wiki/plugins/admin/page_searchcache.meta | 7 - mods/wiki/plugins/admin/page_searchcache.php | 90 - .../plugins/appearance/fancy_list_dict.meta | 7 - .../plugins/appearance/fancy_list_dict.php | 55 - .../wiki/plugins/appearance/listpages_br.meta | 7 - mods/wiki/plugins/appearance/listpages_br.php | 16 - .../plugins/appearance/listpages_tbl.meta | 7 - .../wiki/plugins/appearance/listpages_tbl.php | 22 - .../wiki/plugins/appearance/listpages_ul.meta | 7 - mods/wiki/plugins/appearance/listpages_ul.php | 21 - .../plugins/appearance/title_calendar.meta | 7 - .../plugins/appearance/title_calendar.php | 78 - mods/wiki/plugins/auth-liveuser/LGPL.txt | 504 -- mods/wiki/plugins/auth-liveuser/PACKAGE.txt | 1 - mods/wiki/plugins/auth-liveuser/README | 206 - .../plugins/auth-liveuser/auth_liveuser.meta | 7 - .../plugins/auth-liveuser/auth_liveuser.php | 509 -- .../auth-liveuser/liveuser_addusers_gui.meta | 5 - .../auth-liveuser/liveuser_addusers_gui.php | 146 - .../plugins/auth-liveuser/liveuser_aux.meta | 5 - .../plugins/auth-liveuser/liveuser_aux.php | 601 -- .../plugins/auth-liveuser/liveuser_conf.meta | 5 - .../plugins/auth-liveuser/liveuser_conf.php | 150 - .../auth-liveuser/liveuser_perms_gui.meta | 5 - .../auth-liveuser/liveuser_perms_gui.php | 279 - .../auth-liveuser/liveuser_prefs_gui.meta | 5 - .../auth-liveuser/liveuser_prefs_gui.php | 155 - .../auth-liveuser/liveuser_rights_gui.meta | 5 - .../auth-liveuser/liveuser_rights_gui.php | 158 - .../plugins/auth-liveuser/liveuser_setup.meta | 5 - .../plugins/auth-liveuser/liveuser_setup.php | 217 - .../auth-liveuser/liveuser_setup_prefs.meta | 5 - .../auth-liveuser/liveuser_setup_prefs.php | 107 - .../auth-liveuser/liveuser_users_gui.meta | 5 - .../auth-liveuser/liveuser_users_gui.php | 557 -- .../plugins/auth-liveuser/passdict-wget.sh | 3 - .../plugins/auth-liveuser/perm_liveuser.meta | 5 - .../plugins/auth-liveuser/perm_liveuser.php | 386 - .../plugins/auth-liveuser/pref_liveuser.meta | 5 - .../plugins/auth-liveuser/pref_liveuser.php | 254 - .../auth-liveuser/session_ip_verifier.meta | 7 - .../auth-liveuser/session_ip_verifier.php | 23 - mods/wiki/plugins/auth/auth_method_form.meta | 8 - mods/wiki/plugins/auth/auth_method_form.php | 93 - mods/wiki/plugins/auth/auth_method_http.meta | 9 - mods/wiki/plugins/auth/auth_method_http.php | 81 - mods/wiki/plugins/auth/auth_perm_old.meta | 10 - mods/wiki/plugins/auth/auth_perm_old.php | 53 - mods/wiki/plugins/auth/auth_perm_ring.meta | 7 - mods/wiki/plugins/auth/auth_perm_ring.php | 68 - mods/wiki/plugins/auth/auth_perm_unix.meta | 12 - mods/wiki/plugins/auth/auth_perm_unix.php | 502 -- mods/wiki/plugins/auth/auth_phplib.meta | 10 - mods/wiki/plugins/auth/auth_phplib.php | 305 - mods/wiki/plugins/auth/password_locks.meta | 10 - mods/wiki/plugins/auth/password_locks.php | 119 - mods/wiki/plugins/auth/userdb_anonymous.meta | 10 - mods/wiki/plugins/auth/userdb_anonymous.php | 64 - mods/wiki/plugins/auth/userdb_array.meta | 7 - mods/wiki/plugins/auth/userdb_array.php | 42 - mods/wiki/plugins/auth/userdb_sql.meta | 7 - mods/wiki/plugins/auth/userdb_sql.php | 83 - .../plugins/auth/userdb_systempasswd.meta | 9 - .../wiki/plugins/auth/userdb_systempasswd.php | 83 - .../plugins/auth/userdb_userregistry.meta | 11 - .../wiki/plugins/auth/userdb_userregistry.php | 279 - mods/wiki/plugins/auth/userdb_xprofile.meta | 10 - mods/wiki/plugins/auth/userdb_xprofile.php | 45 - mods/wiki/plugins/auth/users_ldap.meta | 12 - mods/wiki/plugins/auth/users_ldap.php | 48 - mods/wiki/plugins/auth/you.meta | 12 - mods/wiki/plugins/auth/you.php | 37 - mods/wiki/plugins/aview/aedit_authorname.meta | 1 - mods/wiki/plugins/aview/aedit_authorname.php | 1 - .../plugins/aview/aedit_deletebutton.js.meta | 1 - .../plugins/aview/aedit_deletebutton.js.php | 1 - mods/wiki/plugins/aview/aedit_log.meta | 1 - mods/wiki/plugins/aview/aedit_log.php | 1 - mods/wiki/plugins/aview/aedit_pageimage.meta | 1 - mods/wiki/plugins/aview/aedit_pageimage.php | 1 - mods/wiki/plugins/aview/aedit_templates.meta | 1 - mods/wiki/plugins/aview/aedit_templates.php | 1 - mods/wiki/plugins/aview/backlinks.meta | 7 - mods/wiki/plugins/aview/backlinks.php | 24 - mods/wiki/plugins/aview/blog.meta | 7 - mods/wiki/plugins/aview/blog.php | 40 - mods/wiki/plugins/aview/control2.meta | 10 - mods/wiki/plugins/aview/control2.php | 53 - mods/wiki/plugins/aview/downloadlist.meta | 7 - mods/wiki/plugins/aview/downloadlist.php | 55 - mods/wiki/plugins/aview/fpage_copyright.meta | 7 - mods/wiki/plugins/aview/fpage_copyright.php | 21 - mods/wiki/plugins/aview/fpage_logo.meta | 8 - mods/wiki/plugins/aview/fpage_logo.php | 17 - mods/wiki/plugins/aview/imgappend.meta | 7 - mods/wiki/plugins/aview/imgappend.php | 124 - mods/wiki/plugins/aview/linktree.meta | 9 - mods/wiki/plugins/aview/linktree.php | 150 - mods/wiki/plugins/aview/pagetrail.meta | 7 - mods/wiki/plugins/aview/pagetrail.php | 43 - mods/wiki/plugins/aview/piclogocntrl.meta | 8 - mods/wiki/plugins/aview/piclogocntrl.php | 93 - mods/wiki/plugins/aview/posts.meta | 7 - mods/wiki/plugins/aview/posts.php | 196 - mods/wiki/plugins/aview/subpages.meta | 7 - mods/wiki/plugins/aview/subpages.php | 24 - mods/wiki/plugins/aview/threads.meta | 8 - mods/wiki/plugins/aview/threads.php | 77 - mods/wiki/plugins/aview/toc.meta | 9 - mods/wiki/plugins/aview/toc.php | 76 - mods/wiki/plugins/core.meta | 32 - mods/wiki/plugins/db/any.meta | 10 - mods/wiki/plugins/db/any.php | 480 -- mods/wiki/plugins/db/binary_store.meta | 12 - mods/wiki/plugins/db/binary_store.php | 88 - mods/wiki/plugins/db/dba.meta | 10 - mods/wiki/plugins/db/dba.php | 212 - mods/wiki/plugins/db/dzf2.meta | 12 - mods/wiki/plugins/db/dzf2.php | 311 - mods/wiki/plugins/db/ext_multi.meta | 9 - mods/wiki/plugins/db/ext_multi.php | 109 - mods/wiki/plugins/db/ext_subwiki.meta | 9 - mods/wiki/plugins/db/ext_subwiki.php | 121 - mods/wiki/plugins/db/fast_files.meta | 5 - mods/wiki/plugins/db/fast_files.php | 9 - mods/wiki/plugins/db/flat_files.meta | 10 - mods/wiki/plugins/db/flat_files.php | 264 - mods/wiki/plugins/db/mysql.meta | 8 - mods/wiki/plugins/db/oldapi.meta | 6 - mods/wiki/plugins/db/oldapi.php | 67 - mods/wiki/plugins/db/phpwiki13.meta | 9 - mods/wiki/plugins/db/phpwiki13.php | 260 - mods/wiki/plugins/db/read_pmwiki1.meta | 11 - mods/wiki/plugins/db/read_pmwiki1.php | 261 - mods/wiki/plugins/db/rpc.meta | 9 - mods/wiki/plugins/db/rpc.php | 66 - mods/wiki/plugins/db/zip.meta | 9 - mods/wiki/plugins/db/zip.php | 151 - mods/wiki/plugins/debug/verbose.meta | 7 - mods/wiki/plugins/debug/warn_utf8.meta | 7 - mods/wiki/plugins/debug/warn_utf8.php | 33 - mods/wiki/plugins/debug/xerror.meta | 6 - mods/wiki/plugins/debug/xerror.php | 50 - mods/wiki/plugins/edit/authorname.meta | 7 - mods/wiki/plugins/edit/authorname.php | 42 - mods/wiki/plugins/edit/deletebutton.js.meta | 7 - mods/wiki/plugins/edit/deletebutton.js.php | 26 - mods/wiki/plugins/edit/flags.meta | 7 - mods/wiki/plugins/edit/flags.php | 44 - mods/wiki/plugins/edit/helptext.meta | 7 - mods/wiki/plugins/edit/helptext.php | 26 - mods/wiki/plugins/edit/limitlinks.meta | 9 - mods/wiki/plugins/edit/limitlinks.php | 39 - mods/wiki/plugins/edit/lock.meta | 7 - mods/wiki/plugins/edit/lock.php | 71 - mods/wiki/plugins/edit/log.meta | 7 - mods/wiki/plugins/edit/log.php | 37 - mods/wiki/plugins/edit/minor.meta | 7 - mods/wiki/plugins/edit/minor.php | 27 - mods/wiki/plugins/edit/msg.meta | 7 - mods/wiki/plugins/edit/msg.php | 18 - mods/wiki/plugins/edit/pageimage.meta | 6 - mods/wiki/plugins/edit/pageimage.php | 101 - mods/wiki/plugins/edit/plog.meta | 6 - mods/wiki/plugins/edit/requirespassword.meta | 9 - mods/wiki/plugins/edit/requirespassword.php | 26 - mods/wiki/plugins/edit/spam_block.meta | 9 - mods/wiki/plugins/edit/spam_block.php | 109 - mods/wiki/plugins/edit/spam_deface.meta | 10 - mods/wiki/plugins/edit/spam_deface.php | 77 - mods/wiki/plugins/edit/templates.meta | 7 - mods/wiki/plugins/edit/templates.php | 54 - mods/wiki/plugins/edit/upload.meta | 6 - mods/wiki/plugins/edit/warn.meta | 7 - mods/wiki/plugins/edit/warn.php | 49 - mods/wiki/plugins/email_protect.meta | 12 - mods/wiki/plugins/email_protect.php | 329 - mods/wiki/plugins/feature/anacron.meta | 10 - mods/wiki/plugins/feature/anacron.php | 43 - mods/wiki/plugins/feature/announcements.meta | 8 - mods/wiki/plugins/feature/announcements.php | 64 - mods/wiki/plugins/feature/appendcomments.meta | 9 - mods/wiki/plugins/feature/appendcomments.php | 109 - mods/wiki/plugins/feature/appendonly.meta | 7 - mods/wiki/plugins/feature/appendonly.php | 69 - mods/wiki/plugins/feature/appendwrite.meta | 9 - mods/wiki/plugins/feature/appendwrite.php | 112 - .../wiki/plugins/feature/fset_actionurls.meta | 9 - mods/wiki/plugins/feature/fset_actionurls.php | 5 - mods/wiki/plugins/feature/imgfile_naming.meta | 7 - mods/wiki/plugins/feature/imgfile_naming.php | 70 - mods/wiki/plugins/feature/imgresize_gd.meta | 9 - mods/wiki/plugins/feature/imgresize_gd.php | 126 - mods/wiki/plugins/feature/imgresize_gd2.meta | 15 - mods/wiki/plugins/feature/imgresize_gd2.php | 351 - .../plugins/feature/imgresize_magick.meta | 7 - .../wiki/plugins/feature/imgresize_magick.php | 66 - mods/wiki/plugins/feature/pingback.meta | 10 - mods/wiki/plugins/feature/pingback.php | 198 - mods/wiki/plugins/feature/refererlog.meta | 9 - mods/wiki/plugins/feature/refererlog.php | 166 - mods/wiki/plugins/feature/spellcheck.meta | 1 - mods/wiki/plugins/feature/spellcheck.php | 3 - mods/wiki/plugins/feature/spellcheck2.meta | 1 - mods/wiki/plugins/feature/spellcheck2.php | 3 - mods/wiki/plugins/feature/xpi.meta | 9 - mods/wiki/plugins/feature/xpi.php | 424 - mods/wiki/plugins/feature/xpi0.meta | 8 - mods/wiki/plugins/feature/xpi0.php | 55 - mods/wiki/plugins/filter/f_fixhtml.meta | 9 - mods/wiki/plugins/filter/f_fixhtml.php | 172 - mods/wiki/plugins/filter/f_msiepng.meta | 9 - mods/wiki/plugins/filter/f_msiepng.php | 31 - mods/wiki/plugins/filter/f_tidy.meta | 3 - mods/wiki/plugins/filter/fun_chef.meta | 7 - mods/wiki/plugins/filter/fun_chef.php | 77 - .../wiki/plugins/filter/fun_screamomatic.meta | 7 - mods/wiki/plugins/filter/fun_screamomatic.php | 39 - mods/wiki/plugins/filter/fun_upsidedown.meta | 7 - mods/wiki/plugins/filter/fun_upsidedown.php | 80 - mods/wiki/plugins/filter/fun_wella.meta | 7 - mods/wiki/plugins/filter/fun_wella.php | 47 - .../wiki/plugins/filter/search_highlight.meta | 7 - mods/wiki/plugins/filter/search_highlight.php | 101 - mods/wiki/plugins/init.php | 123 - mods/wiki/plugins/input_trimming.meta | 9 - mods/wiki/plugins/input_trimming.php | 217 - mods/wiki/plugins/interwiki/editable.meta | 7 - mods/wiki/plugins/interwiki/editable.php | 108 - mods/wiki/plugins/interwiki/intermap.meta | 6 - mods/wiki/plugins/interwiki/intermap.php | 113 - mods/wiki/plugins/interwiki/intermaptxt.meta | 6 - mods/wiki/plugins/interwiki/intermaptxt.php | 18 - mods/wiki/plugins/interwiki/linkdb.meta | 0 mods/wiki/plugins/interwiki/metadb-wget.sh | 20 - mods/wiki/plugins/interwiki/metadb.meta | 8 - mods/wiki/plugins/interwiki/metadb.php | 73 - mods/wiki/plugins/interwiki/metawiki.meta | 0 mods/wiki/plugins/interwiki/near.meta | 7 - mods/wiki/plugins/interwiki/near.php | 41 - mods/wiki/plugins/interwiki/neighbor.meta | 7 - mods/wiki/plugins/interwiki/neighbor.php | 37 - mods/wiki/plugins/interwiki/sisterpages.meta | 9 - mods/wiki/plugins/interwiki/sisterpages.php | 49 - .../wiki/plugins/interwiki/virtualsister.meta | 7 - mods/wiki/plugins/interwiki/virtualsister.php | 44 - mods/wiki/plugins/interwiki/walking.meta | 7 - mods/wiki/plugins/interwiki/walking.php | 22 - mods/wiki/plugins/jump.meta | 8 - mods/wiki/plugins/jump.php | 106 - mods/wiki/plugins/lib/COLLEGE.ttf | Bin 5896 -> 0 bytes mods/wiki/plugins/lib/cache.meta | 13 - mods/wiki/plugins/lib/cache.php | 136 - mods/wiki/plugins/lib/captcha.meta | 8 - mods/wiki/plugins/lib/captcha.php | 280 - mods/wiki/plugins/lib/fakedba.meta | 6 - mods/wiki/plugins/lib/fakedba.php | 61 - mods/wiki/plugins/lib/fakezlib.meta | 6 - mods/wiki/plugins/lib/fakezlib.php | 35 - mods/wiki/plugins/lib/feed.meta | 11 - mods/wiki/plugins/lib/feed.php | 440 -- mods/wiki/plugins/lib/feedparse.meta | 8 - mods/wiki/plugins/lib/feedparse.php | 120 - mods/wiki/plugins/lib/fix.meta | 7 - mods/wiki/plugins/lib/fix.php | 49 - mods/wiki/plugins/lib/gzdecode.meta | 5 - mods/wiki/plugins/lib/http.meta | 9 - mods/wiki/plugins/lib/http.php | 623 -- mods/wiki/plugins/lib/http_cache.meta | 7 - mods/wiki/plugins/lib/http_cache.php | 51 - mods/wiki/plugins/lib/js.meta | 6 - mods/wiki/plugins/lib/libxprofile.meta | 8 - mods/wiki/plugins/lib/libxprofile.php | 148 - mods/wiki/plugins/lib/mime_magic.meta | 7 - mods/wiki/plugins/lib/mime_magic.php | 560 -- mods/wiki/plugins/lib/minidav.meta | 7 - mods/wiki/plugins/lib/minidav.php | 729 -- mods/wiki/plugins/lib/navbar.meta | 10 - mods/wiki/plugins/lib/navbar.php | 305 - mods/wiki/plugins/lib/opensearch.meta | 8 - mods/wiki/plugins/lib/opensearch.php | 194 - mods/wiki/plugins/lib/page_delegator.meta | 7 - mods/wiki/plugins/lib/page_delegator.php | 40 - mods/wiki/plugins/lib/phprequest.meta | 6 - mods/wiki/plugins/lib/phprequest.php | 52 - mods/wiki/plugins/lib/phprpc.meta | 7 - mods/wiki/plugins/lib/phprpc.php | 165 - mods/wiki/plugins/lib/pluginmetadata.meta | 6 - mods/wiki/plugins/lib/pluginmetadata.php | 201 - mods/wiki/plugins/lib/protmode.meta | 7 - mods/wiki/plugins/lib/protmode.php | 49 - mods/wiki/plugins/lib/save_storevars.meta | 7 - mods/wiki/plugins/lib/save_storevars.php | 35 - mods/wiki/plugins/lib/shutdown.meta | 7 - mods/wiki/plugins/lib/shutdown.php | 29 - mods/wiki/plugins/lib/spamblock_whois.meta | 7 - mods/wiki/plugins/lib/spamblock_whois.php | 35 - mods/wiki/plugins/lib/speed.meta | 6 - mods/wiki/plugins/lib/speed.php | 89 - mods/wiki/plugins/lib/subpagelist.meta | 4 - mods/wiki/plugins/lib/subpagelist.php | 30 - mods/wiki/plugins/lib/sync.meta | 6 - mods/wiki/plugins/lib/sync.php | 117 - mods/wiki/plugins/lib/upgrade.meta | 11 - mods/wiki/plugins/lib/upgrade.php | 1594 ---- mods/wiki/plugins/lib/uservars_pages.meta | 7 - mods/wiki/plugins/lib/uservars_pages.php | 301 - mods/wiki/plugins/lib/webdav.meta | 10 - mods/wiki/plugins/lib/webdav.php | 263 - mods/wiki/plugins/lib/wikiapi.meta | 6 - mods/wiki/plugins/lib/wikiapi.php | 185 - mods/wiki/plugins/lib/wikinews.php | 12 - mods/wiki/plugins/lib/xml.meta | 7 - mods/wiki/plugins/lib/xml.php | 309 - mods/wiki/plugins/lib/xmlrpc.meta | 10 - mods/wiki/plugins/lib/xmlrpc.php | 1148 --- mods/wiki/plugins/linking/a_nofollow.meta | 7 - mods/wiki/plugins/linking/a_nofollow.php | 19 - mods/wiki/plugins/linking/autolinkext.meta | 6 - mods/wiki/plugins/linking/autolinking.meta | 9 - mods/wiki/plugins/linking/autolinking.php | 115 - mods/wiki/plugins/linking/deadly_hidden.meta | 7 - mods/wiki/plugins/linking/deadly_hidden.php | 18 - .../wiki/plugins/linking/instanturl_find.meta | 7 - mods/wiki/plugins/linking/instanturl_find.php | 41 - mods/wiki/plugins/linking/instanturls.meta | 7 - mods/wiki/plugins/linking/instanturls.php | 72 - mods/wiki/plugins/linking/link_css.meta | 7 - mods/wiki/plugins/linking/link_css.php | 43 - mods/wiki/plugins/linking/link_icons.meta | 12 - mods/wiki/plugins/linking/link_icons.php | 75 - .../plugins/linking/link_target_blank.meta | 7 - .../plugins/linking/link_target_blank.php | 20 - mods/wiki/plugins/linking/linkdatabase.meta | 7 - mods/wiki/plugins/linking/linkdatabase.php | 132 - mods/wiki/plugins/linking/linkexcerpts.meta | 7 - mods/wiki/plugins/linking/linkexcerpts.php | 43 - mods/wiki/plugins/linking/new_nofollow.meta | 7 - mods/wiki/plugins/linking/new_nofollow.php | 50 - mods/wiki/plugins/linking/plural.meta | 7 - mods/wiki/plugins/linking/plural.php | 106 - mods/wiki/plugins/linking/selfbacklinks.meta | 7 - mods/wiki/plugins/linking/selfbacklinks.php | 15 - mods/wiki/plugins/linking/selfmetawiki.meta | 7 - mods/wiki/plugins/linking/selfmetawiki.php | 14 - mods/wiki/plugins/linking/selfsearch.meta | 7 - mods/wiki/plugins/linking/selfsearch.php | 14 - mods/wiki/plugins/linking/shortwiki.meta | 7 - mods/wiki/plugins/linking/shortwiki.php | 24 - mods/wiki/plugins/linking/targets.meta | 7 - mods/wiki/plugins/linking/targets.php | 38 - mods/wiki/plugins/linking/tcn.meta | 11 - mods/wiki/plugins/linking/tcn.php | 117 - mods/wiki/plugins/linking/titlefix.meta | 7 - mods/wiki/plugins/linking/titlefix.php | 39 - mods/wiki/plugins/linking/xfn.meta | 7 - mods/wiki/plugins/linking/xfn.php | 43 - mods/wiki/plugins/linking/zero_pagerank.meta | 10 - mods/wiki/plugins/linking/zero_pagerank.php | 61 - mods/wiki/plugins/markup/1emphasis.meta | 7 - mods/wiki/plugins/markup/1emphasis.php | 15 - mods/wiki/plugins/markup/abbr.meta | 7 - mods/wiki/plugins/markup/abbr.php | 49 - mods/wiki/plugins/markup/asciitbl.meta | 7 - mods/wiki/plugins/markup/asciitbl.php | 76 - mods/wiki/plugins/markup/bbcode.meta | 7 - mods/wiki/plugins/markup/bbcode.php | 45 - mods/wiki/plugins/markup/braceabbr.meta | 7 - mods/wiki/plugins/markup/braceabbr.php | 20 - mods/wiki/plugins/markup/complextbl.meta | 7 - mods/wiki/plugins/markup/complextbl.php | 58 - mods/wiki/plugins/markup/css.meta | 11 - mods/wiki/plugins/markup/css.php | 129 - mods/wiki/plugins/markup/css_singleat.meta | 8 - mods/wiki/plugins/markup/css_singleat.php | 26 - mods/wiki/plugins/markup/definitionlinks.meta | 7 - mods/wiki/plugins/markup/definitionlinks.php | 25 - .../plugins/markup/fix_source_mangling.meta | 7 - .../plugins/markup/fix_source_mangling.php | 44 - mods/wiki/plugins/markup/footnotes.meta | 7 - mods/wiki/plugins/markup/footnotes.php | 61 - mods/wiki/plugins/markup/htmltable.meta | 7 - mods/wiki/plugins/markup/htmltable.php | 58 - mods/wiki/plugins/markup/miki.meta | 6 - mods/wiki/plugins/markup/miki.php | 11 - mods/wiki/plugins/markup/naturallists.meta | 7 - mods/wiki/plugins/markup/naturallists.php | 28 - mods/wiki/plugins/markup/phpwiki.meta | 7 - mods/wiki/plugins/markup/phpwiki.php | 17 - mods/wiki/plugins/markup/rendering_null.meta | 7 - mods/wiki/plugins/markup/rendering_null.php | 34 - mods/wiki/plugins/markup/rescuehtml.meta | 7 - mods/wiki/plugins/markup/rescuehtml.php | 44 - mods/wiki/plugins/markup/sfwiki.meta | 7 - mods/wiki/plugins/markup/sfwiki.php | 32 - mods/wiki/plugins/markup/smilies.meta | 10 - mods/wiki/plugins/markup/smilies.php | 106 - mods/wiki/plugins/markup/table_colspan.meta | 7 - mods/wiki/plugins/markup/table_colspan.php | 23 - mods/wiki/plugins/markup/table_rowspan.meta | 7 - mods/wiki/plugins/markup/table_rowspan.php | 23 - mods/wiki/plugins/markup/tex.meta | 12 - mods/wiki/plugins/markup/tex.php | 72 - mods/wiki/plugins/markup/timestamp.meta | 6 - mods/wiki/plugins/markup/timestamp.php | 31 - mods/wiki/plugins/markup/update_format.meta | 7 - mods/wiki/plugins/markup/update_format.php | 44 - mods/wiki/plugins/markup/usemod.meta | 7 - mods/wiki/plugins/markup/usemod.php | 46 - mods/wiki/plugins/meta.bin | 157 - mods/wiki/plugins/meta/block_chinese.meta | 7 - mods/wiki/plugins/meta/block_chinese.php | 60 - mods/wiki/plugins/meta/builtincategories.meta | 9 - mods/wiki/plugins/meta/builtincategories.php | 81 - mods/wiki/plugins/meta/f_title.meta | 7 - mods/wiki/plugins/meta/f_title.php | 16 - mods/wiki/plugins/meta/meta.meta | 7 - mods/wiki/plugins/meta/meta.php | 93 - .../plugins/meta/page_pagecategories.meta | 0 mods/wiki/plugins/meta/relative_links.meta | 0 mods/wiki/plugins/meta/search_categories.meta | 0 mods/wiki/plugins/module/calendar.meta | 11 - mods/wiki/plugins/module/calendar.php | 236 - mods/wiki/plugins/module/collectuserdata.meta | 7 - mods/wiki/plugins/module/collectuserdata.php | 48 - mods/wiki/plugins/module/downloads.meta | 12 - mods/wiki/plugins/module/downloads.php | 368 - mods/wiki/plugins/module/fset_blog.meta | 6 - mods/wiki/plugins/module/fset_blog.php | 10 - mods/wiki/plugins/module/tour.meta | 7 - mods/wiki/plugins/module/tour.php | 53 - mods/wiki/plugins/module/uservars_gui.meta | 7 - mods/wiki/plugins/module/uservars_gui.php | 337 - mods/wiki/plugins/mpi/mpi+cdml.meta | 7 - mods/wiki/plugins/mpi/mpi+cdml.php | 31 - mods/wiki/plugins/mpi/mpi+moin.meta | 7 - mods/wiki/plugins/mpi/mpi+moin.php | 28 - mods/wiki/plugins/mpi/mpi.meta | 9 - mods/wiki/plugins/mpi/mpi.php | 140 - mods/wiki/plugins/mpi/mpi_addcomment.meta | 3 - mods/wiki/plugins/mpi/mpi_addcomment.php | 4 - mods/wiki/plugins/mpi/mpi_addlink.meta | 6 - mods/wiki/plugins/mpi/mpi_addlink.php | 71 - mods/wiki/plugins/mpi/mpi_backlinks.meta | 6 - mods/wiki/plugins/mpi/mpi_backlinks.php | 19 - mods/wiki/plugins/mpi/mpi_backtree.meta | 6 - mods/wiki/plugins/mpi/mpi_backtree.php | 52 - mods/wiki/plugins/mpi/mpi_blog.meta | 6 - mods/wiki/plugins/mpi/mpi_blog.php | 171 - mods/wiki/plugins/mpi/mpi_bugreport.meta | 6 - mods/wiki/plugins/mpi/mpi_bugreport.php | 151 - mods/wiki/plugins/mpi/mpi_bugreportstate.meta | 6 - mods/wiki/plugins/mpi/mpi_bugreportstate.php | 72 - mods/wiki/plugins/mpi/mpi_embed.meta | 6 - mods/wiki/plugins/mpi/mpi_embed.php | 51 - mods/wiki/plugins/mpi/mpi_fallback.meta | 5 - mods/wiki/plugins/mpi/mpi_fallback.php | 32 - mods/wiki/plugins/mpi/mpi_farinclude.meta | 6 - mods/wiki/plugins/mpi/mpi_farinclude.php | 63 - mods/wiki/plugins/mpi/mpi_honeypot.meta | 6 - mods/wiki/plugins/mpi/mpi_honeypot.php | 20 - mods/wiki/plugins/mpi/mpi_inlineframe.meta | 6 - mods/wiki/plugins/mpi/mpi_inlineframe.php | 35 - mods/wiki/plugins/mpi/mpi_insert.meta | 8 - mods/wiki/plugins/mpi/mpi_insert.php | 85 - mods/wiki/plugins/mpi/mpi_localsitemap.meta | 6 - mods/wiki/plugins/mpi/mpi_localsitemap.php | 53 - mods/wiki/plugins/mpi/mpi_multimedia.meta | 6 - mods/wiki/plugins/mpi/mpi_multimedia.php | 54 - mods/wiki/plugins/mpi/mpi_phpwiki.meta | 6 - mods/wiki/plugins/mpi/mpi_phpwiki.php | 56 - mods/wiki/plugins/mpi/mpi_redirectlinks.meta | 5 - mods/wiki/plugins/mpi/mpi_redirectlinks.php | 31 - mods/wiki/plugins/mpi/mpi_registerspam.meta | 6 - mods/wiki/plugins/mpi/mpi_registerspam.php | 64 - mods/wiki/plugins/mpi/mpi_removedlinks.meta | 5 - mods/wiki/plugins/mpi/mpi_removedlinks.php | 38 - mods/wiki/plugins/mpi/mpi_settitle.meta | 6 - mods/wiki/plugins/mpi/mpi_settitle.php | 25 - mods/wiki/plugins/mpi/mpi_sparsetable.meta | 6 - mods/wiki/plugins/mpi/mpi_sparsetable.php | 100 - mods/wiki/plugins/mpi/mpi_survey.meta | 6 - mods/wiki/plugins/mpi/mpi_survey.php | 152 - mods/wiki/plugins/mpi/mpi_syndicate.meta | 6 - mods/wiki/plugins/mpi/mpi_syndicate.php | 37 - mods/wiki/plugins/mpi/mpi_tableeditor.meta | 6 - mods/wiki/plugins/mpi/mpi_tableeditor.php | 160 - mods/wiki/plugins/mpi/mpi_wikiscript.meta | 6 - mods/wiki/plugins/mpi/off/mpi_brainfuck.php | 150 - mods/wiki/plugins/mpi/off/mpi_sqlquery.php | 67 - mods/wiki/plugins/notify.meta | 8 - mods/wiki/plugins/notify.php | 254 - mods/wiki/plugins/old/alias.meta | 7 - mods/wiki/plugins/old/alias.php | 40 - mods/wiki/plugins/old/markup_code.meta | 7 - mods/wiki/plugins/old/markup_code.php | 51 - mods/wiki/plugins/old/markup_html.meta | 7 - mods/wiki/plugins/old/markup_html.php | 17 - mods/wiki/plugins/old/markup_paragraphs.meta | 7 - mods/wiki/plugins/old/markup_paragraphs.php | 25 - mods/wiki/plugins/page/README.meta | 7 - mods/wiki/plugins/page/README.php | 191 - mods/wiki/plugins/page/aboutplugins.meta | 7 - mods/wiki/plugins/page/aboutplugins.php | 87 - mods/wiki/plugins/page/addnewpage.meta | 7 - mods/wiki/plugins/page/addnewpage.php | 84 - mods/wiki/plugins/page/createnewpage.meta | 7 - mods/wiki/plugins/page/createnewpage.php | 31 - mods/wiki/plugins/page/ewikilog.meta | 7 - mods/wiki/plugins/page/ewikilog.php | 28 - mods/wiki/plugins/page/extractall.meta | 9 - mods/wiki/plugins/page/extractall.php | 142 - mods/wiki/plugins/page/fortune.meta | 7 - mods/wiki/plugins/page/fortune.php | 23 - mods/wiki/plugins/page/hitcounter.meta | 7 - mods/wiki/plugins/page/hitcounter.php | 40 - mods/wiki/plugins/page/imagegallery.meta | 10 - mods/wiki/plugins/page/imagegallery.php | 145 - mods/wiki/plugins/page/interwikimap.meta | 7 - mods/wiki/plugins/page/interwikimap.php | 26 - mods/wiki/plugins/page/minidump.meta | 8 - mods/wiki/plugins/page/minidump.php | 183 - mods/wiki/plugins/page/orphanedpages.meta | 9 - mods/wiki/plugins/page/orphanedpages.php | 65 - mods/wiki/plugins/page/pageindex.meta | 6 - mods/wiki/plugins/page/pageindex.php | 5 - mods/wiki/plugins/page/phpinfo.meta | 7 - mods/wiki/plugins/page/phpinfo.php | 21 - mods/wiki/plugins/page/powersearch.meta | 9 - mods/wiki/plugins/page/powersearch.php | 144 - mods/wiki/plugins/page/randompage.meta | 9 - mods/wiki/plugins/page/randompage.php | 39 - mods/wiki/plugins/page/recentchanges.meta | 9 - mods/wiki/plugins/page/recentchanges.php | 222 - mods/wiki/plugins/page/scandisk.meta | 7 - mods/wiki/plugins/page/scandisk.php | 68 - mods/wiki/plugins/page/since_updates.meta | 9 - mods/wiki/plugins/page/since_updates.php | 45 - mods/wiki/plugins/page/sitemap.meta | 10 - mods/wiki/plugins/page/sitemap.php | 238 - mods/wiki/plugins/page/textupload.meta | 11 - mods/wiki/plugins/page/textupload.php | 872 -- mods/wiki/plugins/page/wantedpages.meta | 7 - mods/wiki/plugins/page/wantedpages.php | 51 - mods/wiki/plugins/page/weekdiff.meta | 2 - mods/wiki/plugins/page/wikidump.meta | 7 - mods/wiki/plugins/page/wikidump.php | 342 - mods/wiki/plugins/page/wikidump2.meta | 11 - mods/wiki/plugins/page/wikidump2.php | 456 -- mods/wiki/plugins/page/wikinews.meta | 7 - mods/wiki/plugins/page/wikinews.php | 110 - mods/wiki/plugins/page/wikiuserlogin.meta | 7 - mods/wiki/plugins/page/wikiuserlogin.php | 51 - mods/wiki/plugins/page/wordindex.meta | 9 - mods/wiki/plugins/page/wordindex.php | 62 - mods/wiki/plugins/passwd_expire.php | 13 - mods/wiki/plugins/patchsaving.meta | 8 - mods/wiki/plugins/patchsaving.php | 88 - mods/wiki/plugins/pluginloader.meta | 8 - mods/wiki/plugins/pluginloader.php | 168 - mods/wiki/plugins/spages.meta | 11 - mods/wiki/plugins/spages.php | 175 - mods/wiki/plugins/spam/antibot_captcha.meta | 7 - mods/wiki/plugins/spam/antibot_captcha.php | 39 - mods/wiki/plugins/spam/antibot_checkbox.meta | 8 - mods/wiki/plugins/spam/antibot_checkbox.php | 34 - mods/wiki/plugins/spam/antibot_delay.meta | 7 - mods/wiki/plugins/spam/antibot_delay.php | 41 - mods/wiki/plugins/spam/cookieusers.meta | 7 - mods/wiki/plugins/spam/cookieusers.php | 33 - mods/wiki/plugins/spam/limitlinks.ln | 3 - mods/wiki/plugins/spam/watchonly.meta | 7 - mods/wiki/plugins/spam/watchonly.php | 35 - mods/wiki/plugins/sql/arrowadmin.meta | 10 - mods/wiki/plugins/sql/arrowadmin.php | 232 - mods/wiki/plugins/user/dbpref.meta | 6 - mods/wiki/plugins/user/dbpref.php | 9 - mods/wiki/plugins/user/sessionpref.meta | 6 - mods/wiki/plugins/user/sessionpref.php | 9 - mods/wiki/side_menu.inc.php | 13 - mods/wiki/spages/AbandonedPages.php | 8 - mods/wiki/spages/HitCounter.php | 28 - mods/wiki/spages/LeastPopular.php | 8 - mods/wiki/spages/LinkLessPages.php | 28 - mods/wiki/spages/OrphanedPages.php | 52 - mods/wiki/spages/PageLinks.php | 31 - mods/wiki/spages/PageRefs.php | 39 - mods/wiki/spages/PageSize.php | 31 - mods/wiki/spages/WantedPages.php | 41 - mods/wiki/spages/WordIndex.php | 46 - mods/wiki/tlogo.png | Bin 2072 -> 0 bytes mods/wiki/tools/cron.d/HOWTO | 174 - mods/wiki/tools/cron.d/S01env.php | 15 - mods/wiki/tools/cron.d/S01textplainout.php | 14 - mods/wiki/tools/cron.d/S10config.php | 42 - mods/wiki/tools/cron.d/S11defaults.php | 18 - mods/wiki/tools/cron.d/S16nohup.php | 11 - mods/wiki/tools/cron.d/S17anacron.php | 44 - mods/wiki/tools/cron.d/S18lock.php | 37 - mods/wiki/tools/cron.d/S20__start__.php | 4 - mods/wiki/tools/cron.d/S30__hourly__.php | 22 - mods/wiki/tools/cron.d/S35mail2wiki.php | 194 - mods/wiki/tools/cron.d/S50__daily__.php | 19 - mods/wiki/tools/cron.d/S53sync.php | 51 - mods/wiki/tools/cron.d/S56gagalinks.php | 63 - mods/wiki/tools/cron.d/S61keptpages.php | 11 - mods/wiki/tools/cron.d/S63deletedpage.php | 77 - mods/wiki/tools/cron.d/S64trashcan.php | 70 - mods/wiki/tools/cron.d/S67versionholes.php | 75 - mods/wiki/tools/cron.d/S70__weekly__.php | 19 - mods/wiki/tools/cron.d/S77metadb.php | 0 mods/wiki/tools/cron.d/S80recentnotify.php | 108 - mods/wiki/tools/cron.d/S81weekdiff.php | 0 mods/wiki/tools/cron.d/S90__monthly__.php | 16 - mods/wiki/tools/cron.d/S92binbackup.php | 60 - mods/wiki/tools/cron.d/S92mimebackup.php | 103 - mods/wiki/tools/cron.d/S93checklinks.php | 0 mods/wiki/tools/cron.d/S99__end__.php | 0 mods/wiki/tools/cron.d/Z17anacron.php | 26 - mods/wiki/tools/cron.d/Z18unlock.php | 10 - mods/wiki/tools/cron.d/index.php | 109 - mods/wiki/tools/cron.d/run-parts.php | 77 - mods/wiki/tools/ewikictl | 812 -- mods/wiki/tools/ewikictl.bat | 13 - mods/wiki/tools/index.html | 259 - mods/wiki/tools/mergeplugins | 27 - mods/wiki/tools/metacache | 40 - mods/wiki/tools/mkhuge | 88 - mods/wiki/tools/mkpageplugin | 107 - mods/wiki/tools/mkpluginmap | 120 - mods/wiki/tools/mkxpi | 93 - mods/wiki/tools/setup | 815 -- mods/wiki/tools/setup.dat | 1 - mods/wiki/tools/t_backup.php | 92 - mods/wiki/tools/t_checklinks.php | 116 - mods/wiki/tools/t_commander/80x25.css | 129 - mods/wiki/tools/t_commander/action.php | 334 - mods/wiki/tools/t_commander/commandline.php | 15 - mods/wiki/tools/t_commander/edit.php | 232 - mods/wiki/tools/t_commander/filemenu.php | 71 - mods/wiki/tools/t_commander/index.html | 185 - mods/wiki/tools/t_commander/info.php | 79 - mods/wiki/tools/t_commander/keymenu.php | 35 - mods/wiki/tools/t_commander/list.php | 59 - mods/wiki/tools/t_commander/list_vers.php | 51 - mods/wiki/tools/t_commander/t_config.php | 39 - mods/wiki/tools/t_config.css | 57 - mods/wiki/tools/t_config.php | 68 - mods/wiki/tools/t_control.php | 38 - mods/wiki/tools/t_convertdb.php | 424 - mods/wiki/tools/t_ewikictl.php | 311 - mods/wiki/tools/t_flags.php | 101 - mods/wiki/tools/t_holes.php | 112 - mods/wiki/tools/t_remove.php | 148 - mods/wiki/tools/t_restore.php | 107 - mods/wiki/tools/t_revert.php | 119 - mods/wiki/tools/t_searchandreplace.php | 29 - mods/wiki/tools/t_setupwiz.php | 682 -- mods/wiki/tools/t_sync.php | 195 - mods/wiki/tools/t_textinsert.php | 149 - mods/wiki/tools/t_textupload.php | 29 - mods/wiki/tools/t_transfer.php | 149 - mods/wiki/tools/upgrade-r101d | 44 - mods/wiki/tools/whiptail | Bin 21292 -> 0 bytes mods/wiki/tools/wiki2html | 123 - mods/wiki/tools/xt_searchcache_staticf.php | 100 - mods/wiki/tools/xt_sysinfo.php | 54 - mods/wiki/wiki.css | 37 - mods/wiki/z.php | 106 - mods/wordpress/README | 28 - mods/wordpress/index.php | 18 - mods/wordpress/index_admin.php | 46 - mods/wordpress/index_instructor.php | 13 - mods/wordpress/index_mystart.php | 15 - mods/wordpress/index_public.php | 17 - mods/wordpress/module.css | 15 - mods/wordpress/module.php | 84 - mods/wordpress/module.sql | 30 - mods/wordpress/module.xml | 19 - mods/wordpress/module_delete.php | 21 - mods/wordpress/module_install.php | 67 - mods/wordpress/module_news.php | 43 - mods/wordpress/module_uninstall.php | 44 - mods/wordpress/sublinks.php | 36 - mods/wordpress/wordpress_icon_sm.png | Bin 1089 -> 0 bytes mods/wordpress/wordpress_logo.png | Bin 5886 -> 0 bytes mods/wordpress/wp_config.php | 13 - mods/wordpress/wp_connect.php | 25 - .../ext_db_auth.php | 536 -- .../readme.txt | 70 - 2774 files changed, 294330 deletions(-) delete mode 100755 mods/adobe_connect/README.txt delete mode 100755 mods/adobe_connect/adobe_connect.gif delete mode 100755 mods/adobe_connect/index.php delete mode 100755 mods/adobe_connect/index_admin.php delete mode 100755 mods/adobe_connect/lib/ACConnection.php delete mode 100755 mods/adobe_connect/lib/ACRoom.php delete mode 100755 mods/adobe_connect/lib/ACUser.php delete mode 100755 mods/adobe_connect/lib/lib.php delete mode 100755 mods/adobe_connect/loader.php delete mode 100755 mods/adobe_connect/module.css delete mode 100755 mods/adobe_connect/module.php delete mode 100755 mods/adobe_connect/module.sql delete mode 100755 mods/adobe_connect/module.xml delete mode 100755 mods/adobe_connect/module_cron.php delete mode 100755 mods/adobe_connect/module_delete.php delete mode 100755 mods/adobe_connect/module_install.php delete mode 100755 mods/adobe_connect/module_uninstall.php delete mode 100755 mods/announcement_subscription/module.php delete mode 100755 mods/announcement_subscription/module.sql delete mode 100755 mods/announcement_subscription/module.xml delete mode 100755 mods/announcement_subscription/module_install.php delete mode 100644 mods/announcement_subscription/module_uninstall.php delete mode 100755 mods/announcement_subscription/readme.txt delete mode 100755 mods/announcement_subscription/sendmail.php delete mode 100755 mods/announcement_subscription/side_menu.inc.php delete mode 100755 mods/announcement_subscription/subscribe.php delete mode 100755 mods/announcement_subscription/subscribe_button.php delete mode 100644 mods/assignment_dropbox/README delete mode 100644 mods/assignment_dropbox/assignment_dropbox.inc.php delete mode 100644 mods/assignment_dropbox/assignment_dropbox.png delete mode 100644 mods/assignment_dropbox/assignment_dropbox_sm.png delete mode 100644 mods/assignment_dropbox/flag.png delete mode 100644 mods/assignment_dropbox/index.php delete mode 100644 mods/assignment_dropbox/module.css delete mode 100644 mods/assignment_dropbox/module.php delete mode 100644 mods/assignment_dropbox/module.sql delete mode 100644 mods/assignment_dropbox/module.xml delete mode 100644 mods/assignment_dropbox/module_install.php delete mode 100644 mods/assignment_dropbox/module_uninstall.php delete mode 100644 mods/assignment_dropbox/sublinks.php delete mode 100644 mods/atalker/ATalker-italian-voice-README.txt delete mode 100644 mods/atalker/README_ATUTOR_MODULE delete mode 100644 mods/atalker/admin/admin_index.php delete mode 100644 mods/atalker/admin/admin_voice.php delete mode 100644 mods/atalker/admin/admin_voice_files.php delete mode 100644 mods/atalker/admin/admin_voice_html.php delete mode 100644 mods/atalker/admin/play_voice.php delete mode 100644 mods/atalker/admin_voice.php delete mode 100644 mods/atalker/atalker_doc/1.0.voices.php delete mode 100644 mods/atalker/atalker_doc/1.1.atalker.php delete mode 100644 mods/atalker/atalkerlib.inc.php delete mode 100644 mods/atalker/images/atalker.gif delete mode 100644 mods/atalker/images/atalker_sm.gif delete mode 100644 mods/atalker/index.php delete mode 100644 mods/atalker/message_reader.php delete mode 100644 mods/atalker/module.php delete mode 100644 mods/atalker/module.sql delete mode 100644 mods/atalker/module.xml delete mode 100644 mods/atalker/module_install.php delete mode 100644 mods/atalker/reader.html.php delete mode 100644 mods/atalker/reader_controls.php delete mode 100644 mods/atalker/sable_reader.php delete mode 100644 mods/atalker/template_reader.php delete mode 100644 mods/atalker/text_reader.php delete mode 100644 mods/atsocial_iphone_app/.gitignore delete mode 100644 mods/atsocial_iphone_app/.gitmodules delete mode 100644 mods/atsocial_iphone_app/ATutor-Info.plist delete mode 100755 mods/atsocial_iphone_app/ATutor.xcodeproj/project.pbxproj delete mode 100644 mods/atsocial_iphone_app/ATutor_Prefix.pch delete mode 100644 mods/atsocial_iphone_app/Activities.png delete mode 100644 mods/atsocial_iphone_app/Classes/ATutorAppDelegate.h delete mode 100644 mods/atsocial_iphone_app/Classes/ATutorAppDelegate.m delete mode 100644 mods/atsocial_iphone_app/Classes/ATutorHelper.h delete mode 100644 mods/atsocial_iphone_app/Classes/ATutorHelper.m delete mode 100644 mods/atsocial_iphone_app/Classes/ActivitiesViewController.h delete mode 100644 mods/atsocial_iphone_app/Classes/ActivitiesViewController.m delete mode 100644 mods/atsocial_iphone_app/Classes/CommonFunctions.h delete mode 100644 mods/atsocial_iphone_app/Classes/CommonFunctions.m delete mode 100644 mods/atsocial_iphone_app/Classes/Contact.h delete mode 100644 mods/atsocial_iphone_app/Classes/Contact.m delete mode 100644 mods/atsocial_iphone_app/Classes/ContactItemCell.h delete mode 100644 mods/atsocial_iphone_app/Classes/ContactItemCell.m delete mode 100644 mods/atsocial_iphone_app/Classes/ContactViewController.h delete mode 100644 mods/atsocial_iphone_app/Classes/ContactViewController.m delete mode 100644 mods/atsocial_iphone_app/Classes/ContactsDataSource.h delete mode 100644 mods/atsocial_iphone_app/Classes/ContactsDataSource.m delete mode 100644 mods/atsocial_iphone_app/Classes/ContactsViewController.h delete mode 100644 mods/atsocial_iphone_app/Classes/ContactsViewController.m delete mode 100644 mods/atsocial_iphone_app/Classes/GroupsViewController.h delete mode 100644 mods/atsocial_iphone_app/Classes/GroupsViewController.m delete mode 100644 mods/atsocial_iphone_app/Classes/LauncherViewController.h delete mode 100644 mods/atsocial_iphone_app/Classes/LauncherViewController.m delete mode 100644 mods/atsocial_iphone_app/Classes/OSConsumer.h delete mode 100644 mods/atsocial_iphone_app/Classes/OSConsumer.m delete mode 100644 mods/atsocial_iphone_app/Classes/OSProvider.h delete mode 100644 mods/atsocial_iphone_app/Classes/OSProvider.m delete mode 100644 mods/atsocial_iphone_app/Classes/QAWebController.h delete mode 100644 mods/atsocial_iphone_app/Classes/QAWebController.m delete mode 100644 mods/atsocial_iphone_app/Classes/StyleSheet.h delete mode 100644 mods/atsocial_iphone_app/Classes/StyleSheet.m delete mode 100644 mods/atsocial_iphone_app/Contacts.png delete mode 100644 mods/atsocial_iphone_app/Gadgets.png delete mode 100644 mods/atsocial_iphone_app/Groups.png delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKAppSettingsViewController.h delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.h delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSettingsReader.h delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSettingsReader.m delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSpecifier.h delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSpecifier.m delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.h delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.m delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.h delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.m delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTitleValueSpecifierViewCell.h delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTitleValueSpecifierViewCell.m delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSToggleSwitchSpecifierViewCell.h delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSToggleSwitchSpecifierViewCell.m delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSlider.h delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSlider.m delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSwitch.h delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSwitch.m delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKTextField.h delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKTextField.m delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKAppSettingsView.xib delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKPSSliderSpecifierViewCell.xib delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKPSTextFieldSpecifierViewCell.xib delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKPSToggleSwitchSpecifierViewCell.xib delete mode 100644 mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKSpecifierValuesView.xib delete mode 100755 mods/atsocial_iphone_app/KeychainUtils/SFHFKeychainUtils.h delete mode 100755 mods/atsocial_iphone_app/KeychainUtils/SFHFKeychainUtils.m delete mode 100644 mods/atsocial_iphone_app/OAuth/Crypto/Base64Transcoder.c delete mode 100644 mods/atsocial_iphone_app/OAuth/Crypto/Base64Transcoder.h delete mode 100644 mods/atsocial_iphone_app/OAuth/Crypto/hmac.c delete mode 100644 mods/atsocial_iphone_app/OAuth/Crypto/hmac.h delete mode 100644 mods/atsocial_iphone_app/OAuth/Crypto/sha1.c delete mode 100644 mods/atsocial_iphone_app/OAuth/Crypto/sha1.h delete mode 100644 mods/atsocial_iphone_app/OAuth/Extensions/NSString+URLEncoding.h delete mode 100644 mods/atsocial_iphone_app/OAuth/Extensions/NSString+URLEncoding.m delete mode 100644 mods/atsocial_iphone_app/OAuth/OAAsynchronousDataFetcher.h delete mode 100644 mods/atsocial_iphone_app/OAuth/OAAsynchronousDataFetcher.m delete mode 100644 mods/atsocial_iphone_app/OAuth/OAConsumer.h delete mode 100644 mods/atsocial_iphone_app/OAuth/OAConsumer.m delete mode 100644 mods/atsocial_iphone_app/OAuth/OADataFetcher.h delete mode 100644 mods/atsocial_iphone_app/OAuth/OADataFetcher.m delete mode 100644 mods/atsocial_iphone_app/OAuth/OAMutableURLRequest.h delete mode 100644 mods/atsocial_iphone_app/OAuth/OAMutableURLRequest.m delete mode 100644 mods/atsocial_iphone_app/OAuth/OARequestParameter.h delete mode 100644 mods/atsocial_iphone_app/OAuth/OARequestParameter.m delete mode 100644 mods/atsocial_iphone_app/OAuth/OAServiceTicket.h delete mode 100644 mods/atsocial_iphone_app/OAuth/OAServiceTicket.m delete mode 100644 mods/atsocial_iphone_app/OAuth/OAToken.h delete mode 100644 mods/atsocial_iphone_app/OAuth/OAToken.m delete mode 100755 mods/atsocial_iphone_app/OAuth/OAToken_KeychainExtensions.h delete mode 100755 mods/atsocial_iphone_app/OAuth/OAToken_KeychainExtensions.m delete mode 100644 mods/atsocial_iphone_app/OAuth/Signature Providers/OAHMAC_SHA1SignatureProvider.h delete mode 100644 mods/atsocial_iphone_app/OAuth/Signature Providers/OAHMAC_SHA1SignatureProvider.m delete mode 100644 mods/atsocial_iphone_app/OAuth/Signature Providers/OAPlaintextSignatureProvider.h delete mode 100644 mods/atsocial_iphone_app/OAuth/Signature Providers/OAPlaintextSignatureProvider.m delete mode 100644 mods/atsocial_iphone_app/OAuth/Signature Providers/OASignatureProviding.h delete mode 100644 mods/atsocial_iphone_app/README.markdown delete mode 100644 mods/atsocial_iphone_app/Settings.bundle/Root.plist delete mode 100644 mods/atsocial_iphone_app/Settings.bundle/en.lproj/Root.strings delete mode 100755 mods/atsocial_iphone_app/TouchJSON/CDataScanner.h delete mode 100755 mods/atsocial_iphone_app/TouchJSON/CDataScanner.m delete mode 100755 mods/atsocial_iphone_app/TouchJSON/Extensions/CDataScanner_Extensions.h delete mode 100755 mods/atsocial_iphone_app/TouchJSON/Extensions/CDataScanner_Extensions.m delete mode 100755 mods/atsocial_iphone_app/TouchJSON/Extensions/NSCharacterSet_Extensions.h delete mode 100755 mods/atsocial_iphone_app/TouchJSON/Extensions/NSCharacterSet_Extensions.m delete mode 100755 mods/atsocial_iphone_app/TouchJSON/Extensions/NSDictionary_JSONExtensions.h delete mode 100755 mods/atsocial_iphone_app/TouchJSON/Extensions/NSDictionary_JSONExtensions.m delete mode 100755 mods/atsocial_iphone_app/TouchJSON/JSON/CJSONDeserializer.h delete mode 100755 mods/atsocial_iphone_app/TouchJSON/JSON/CJSONDeserializer.m delete mode 100755 mods/atsocial_iphone_app/TouchJSON/JSON/CJSONScanner.h delete mode 100755 mods/atsocial_iphone_app/TouchJSON/JSON/CJSONScanner.m delete mode 100755 mods/atsocial_iphone_app/TouchJSON/JSON/CJSONSerializer.h delete mode 100755 mods/atsocial_iphone_app/TouchJSON/JSON/CJSONSerializer.m delete mode 100644 mods/atsocial_iphone_app/main.m delete mode 100755 mods/atutor_opencaps/README delete mode 100755 mods/atutor_opencaps/doc/index.html delete mode 100755 mods/atutor_opencaps/flowplayer/LICENSE.txt delete mode 100755 mods/atutor_opencaps/flowplayer/README.txt delete mode 100755 mods/atutor_opencaps/flowplayer/flowplayer-3.2.2.min.js delete mode 100755 mods/atutor_opencaps/flowplayer/flowplayer-3.2.2.swf delete mode 100755 mods/atutor_opencaps/flowplayer/flowplayer.audio-3.2.0.swf delete mode 100755 mods/atutor_opencaps/flowplayer/flowplayer.captions-3.2.1.swf delete mode 100755 mods/atutor_opencaps/flowplayer/flowplayer.content-3.2.0.swf delete mode 100755 mods/atutor_opencaps/flowplayer/flowplayer.controls-3.2.1.swf delete mode 100755 mods/atutor_opencaps/flowplayer/index.html delete mode 100755 mods/atutor_opencaps/images/AtOpenCaps.png delete mode 100755 mods/atutor_opencaps/images/index.html delete mode 100755 mods/atutor_opencaps/images/poster.jpg delete mode 100755 mods/atutor_opencaps/include/atoc.js delete mode 100755 mods/atutor_opencaps/include/basic.js delete mode 100755 mods/atutor_opencaps/include/classes/ATOC_Debug.php delete mode 100755 mods/atutor_opencaps/include/classes/ATOC_Json.php delete mode 100755 mods/atutor_opencaps/include/classes/ATOC_ProjectManager.php delete mode 100755 mods/atutor_opencaps/include/classes/ATOC_ServerFiles.php delete mode 100755 mods/atutor_opencaps/include/config.inc.php delete mode 100755 mods/atutor_opencaps/include/index.html delete mode 100755 mods/atutor_opencaps/include/vitals.inc.php delete mode 100755 mods/atutor_opencaps/index.php delete mode 100755 mods/atutor_opencaps/index_admin.php delete mode 100755 mods/atutor_opencaps/index_instructor.php delete mode 100755 mods/atutor_opencaps/module.css delete mode 100755 mods/atutor_opencaps/module.php delete mode 100755 mods/atutor_opencaps/module.sql delete mode 100755 mods/atutor_opencaps/module.xml delete mode 100755 mods/atutor_opencaps/module_install.php delete mode 100755 mods/atutor_opencaps/module_uninstall.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/about.txt delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/imported/index.html delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/imported/noname.JSON delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/imported/noname.srt delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/imported/noname.txt delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_DFXP_format.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_DvdStl_format.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_JSONcc_format.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_MPlayer_format.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_MicroDvd_format.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_QTSMIL_format.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_QTtext_format.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_RealText_format.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_Sami_format.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_Scc_format.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_SubRipSrt_format.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_SubViewer_format.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/index.html delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_CaptionCollection_class.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_CaptionFormat_class.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_Caption_class.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_CcService_class.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_ConversionManager_class.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTag.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTagCollection.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTagTrace.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTagTraceManager.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/index.html delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/static_CcUtilVital_class.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/static_TimeUtil_class.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/classes/static_TxtFileTools_class.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/config.inc.php delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/include/index.html delete mode 100755 mods/atutor_opencaps/opencaps/conversion_service/index.php delete mode 100755 mods/atutor_opencaps/opencaps/editor.php delete mode 100755 mods/atutor_opencaps/opencaps/error_log delete mode 100755 mods/atutor_opencaps/opencaps/export.php delete mode 100755 mods/atutor_opencaps/opencaps/help.php delete mode 100755 mods/atutor_opencaps/opencaps/images/application_edit.png delete mode 100755 mods/atutor_opencaps/opencaps/images/application_get.png delete mode 100755 mods/atutor_opencaps/opencaps/images/application_put.png delete mode 100755 mods/atutor_opencaps/opencaps/images/arrow_right.png delete mode 100755 mods/atutor_opencaps/opencaps/images/asterisk_yellow.png delete mode 100755 mods/atutor_opencaps/opencaps/images/bullet_delete.png delete mode 100755 mods/atutor_opencaps/opencaps/images/clip_leftedge.png delete mode 100755 mods/atutor_opencaps/opencaps/images/clip_next.png delete mode 100755 mods/atutor_opencaps/opencaps/images/clip_prev.png delete mode 100755 mods/atutor_opencaps/opencaps/images/clip_rightedge.png delete mode 100755 mods/atutor_opencaps/opencaps/images/cross.png delete mode 100755 mods/atutor_opencaps/opencaps/images/door_out.png delete mode 100755 mods/atutor_opencaps/opencaps/images/end.png delete mode 100755 mods/atutor_opencaps/opencaps/images/ffwd.png delete mode 100755 mods/atutor_opencaps/opencaps/images/ffwd2.png delete mode 100755 mods/atutor_opencaps/opencaps/images/index.html delete mode 100755 mods/atutor_opencaps/opencaps/images/last_start.png delete mode 100755 mods/atutor_opencaps/opencaps/images/logo.png delete mode 100755 mods/atutor_opencaps/opencaps/images/middlebar.png delete mode 100755 mods/atutor_opencaps/opencaps/images/page_gear.png delete mode 100755 mods/atutor_opencaps/opencaps/images/pause.png delete mode 100755 mods/atutor_opencaps/opencaps/images/play.png delete mode 100755 mods/atutor_opencaps/opencaps/images/pressplay.png delete mode 100755 mods/atutor_opencaps/opencaps/images/rewind.png delete mode 100755 mods/atutor_opencaps/opencaps/images/rewind2.png delete mode 100755 mods/atutor_opencaps/opencaps/images/slider-bg-1.png delete mode 100755 mods/atutor_opencaps/opencaps/images/slider-bg-2.png delete mode 100755 mods/atutor_opencaps/opencaps/images/slider-handle-ghost.gif delete mode 100755 mods/atutor_opencaps/opencaps/images/slider-handle.gif delete mode 100755 mods/atutor_opencaps/opencaps/images/start.png delete mode 100755 mods/atutor_opencaps/opencaps/include/basic_header.inc.php delete mode 100755 mods/atutor_opencaps/opencaps/include/classes/captionCollection_class.php delete mode 100755 mods/atutor_opencaps/opencaps/include/classes/caption_class.php delete mode 100755 mods/atutor_opencaps/opencaps/include/classes/clip_class.php delete mode 100755 mods/atutor_opencaps/opencaps/include/classes/db_class.php delete mode 100755 mods/atutor_opencaps/opencaps/include/classes/index.html delete mode 100755 mods/atutor_opencaps/opencaps/include/classes/project_class.php delete mode 100755 mods/atutor_opencaps/opencaps/include/classes/system_OcAtutor_class.php delete mode 100755 mods/atutor_opencaps/opencaps/include/classes/system_class.php delete mode 100755 mods/atutor_opencaps/opencaps/include/classes/time_class.php delete mode 100755 mods/atutor_opencaps/opencaps/include/classes/user_class.php delete mode 100755 mods/atutor_opencaps/opencaps/include/config.inc.php delete mode 100755 mods/atutor_opencaps/opencaps/include/footer.inc.php delete mode 100755 mods/atutor_opencaps/opencaps/include/header.inc.php delete mode 100755 mods/atutor_opencaps/opencaps/include/index.html delete mode 100755 mods/atutor_opencaps/opencaps/include/matterhorn.inc.php delete mode 100755 mods/atutor_opencaps/opencaps/include/vitals.inc.php delete mode 100755 mods/atutor_opencaps/opencaps/include/workflow.php delete mode 100755 mods/atutor_opencaps/opencaps/index.php delete mode 100755 mods/atutor_opencaps/opencaps/install/config_template.php delete mode 100755 mods/atutor_opencaps/opencaps/install/index.html delete mode 100755 mods/atutor_opencaps/opencaps/install/oc_schema.sql delete mode 100755 mods/atutor_opencaps/opencaps/js/AC_QuickTime.js delete mode 100755 mods/atutor_opencaps/opencaps/js/editor.js delete mode 100755 mods/atutor_opencaps/opencaps/js/export.js delete mode 100755 mods/atutor_opencaps/opencaps/js/index.html delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/GPL-LICENSE.txt delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/MIT-LICENSE.txt delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/jARIA.js delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/jquery-1.2.3.js delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/jquery-1.2.6.js delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/jquery-1.3.2.min.js delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/jquery.dimensions.js delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/jquery.keyboard-a11y.js delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/jquery.tabindex.js delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/ui.base.js delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/ui.core.js delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/ui.dialog.js delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/ui.draggable.js delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/ui.droppable.js delete mode 100755 mods/atutor_opencaps/opencaps/js/jquery/ui.slider.js delete mode 100755 mods/atutor_opencaps/opencaps/js/json/json2.js delete mode 100755 mods/atutor_opencaps/opencaps/js/preview.js delete mode 100755 mods/atutor_opencaps/opencaps/js/settings.js delete mode 100755 mods/atutor_opencaps/opencaps/js/start.js delete mode 100755 mods/atutor_opencaps/opencaps/js/start_remote.js delete mode 100755 mods/atutor_opencaps/opencaps/js/utils.js delete mode 100755 mods/atutor_opencaps/opencaps/license.txt delete mode 100755 mods/atutor_opencaps/opencaps/loadmedia.php delete mode 100755 mods/atutor_opencaps/opencaps/login.php delete mode 100755 mods/atutor_opencaps/opencaps/logout.php delete mode 100755 mods/atutor_opencaps/opencaps/preview.php delete mode 100755 mods/atutor_opencaps/opencaps/projects/12-d0679f0984ba38ffc572d0d9718091d37059d5b6/opencaps.json delete mode 100755 mods/atutor_opencaps/opencaps/projects/3-d0679f0984ba38ffc572d0d9718091d37059d5b6/opencaps.json delete mode 100755 mods/atutor_opencaps/opencaps/projects/index.html delete mode 100755 mods/atutor_opencaps/opencaps/projects/layouts/smil_0.mov delete mode 100755 mods/atutor_opencaps/opencaps/projects/layouts/smil_1.mov delete mode 100755 mods/atutor_opencaps/opencaps/projects/layouts/smil_2.mov delete mode 100755 mods/atutor_opencaps/opencaps/projects/opencaps.json delete mode 100755 mods/atutor_opencaps/opencaps/projects/player_template.php delete mode 100755 mods/atutor_opencaps/opencaps/register.php delete mode 100755 mods/atutor_opencaps/opencaps/scripts/install.sh delete mode 100755 mods/atutor_opencaps/opencaps/scripts/install_remote_only.sh delete mode 100755 mods/atutor_opencaps/opencaps/settings.php delete mode 100755 mods/atutor_opencaps/opencaps/start.php delete mode 100755 mods/atutor_opencaps/opencaps/start_remote.php delete mode 100755 mods/atutor_opencaps/opencaps/styles.css delete mode 100755 mods/atutor_opencaps/opencaps/styles_ff.css delete mode 100755 mods/atutor_opencaps/opencaps/styles_ie.css delete mode 100755 mods/atutor_opencaps/opencaps/styles_public.css delete mode 100755 mods/atutor_opencaps/player.php delete mode 100755 mods/atutor_opencaps/service.php delete mode 100755 mods/atutor_opencaps/service_test.php delete mode 100644 mods/basiclti/ModuleCallbacks.class.php delete mode 100644 mods/basiclti/README.txt delete mode 100644 mods/basiclti/TODO.txt delete mode 100644 mods/basiclti/basiclti.jpg delete mode 100644 mods/basiclti/content_tool_action.js delete mode 100644 mods/basiclti/images/basiclti-icon.png delete mode 100644 mods/basiclti/include/constants.inc.php delete mode 100644 mods/basiclti/index.php delete mode 100644 mods/basiclti/index_admin.php delete mode 100644 mods/basiclti/index_instructor.php delete mode 100644 mods/basiclti/launch/TrivialStore.php delete mode 100644 mods/basiclti/launch/ims-blti/LICENSE.txt delete mode 100644 mods/basiclti/launch/ims-blti/OAuth.php delete mode 100644 mods/basiclti/launch/ims-blti/blti.php delete mode 100644 mods/basiclti/launch/ims-blti/blti_util.php delete mode 100644 mods/basiclti/launch/launch.php delete mode 100644 mods/basiclti/launch/loadrows.php delete mode 100644 mods/basiclti/launch/service.php delete mode 100644 mods/basiclti/lib/at_form_util.php delete mode 100644 mods/basiclti/module.css delete mode 100644 mods/basiclti/module.php delete mode 100644 mods/basiclti/module.sql delete mode 100644 mods/basiclti/module.xml delete mode 100644 mods/basiclti/module_backup.php delete mode 100644 mods/basiclti/module_delete.php delete mode 100644 mods/basiclti/module_install.php delete mode 100644 mods/basiclti/module_uninstall.php delete mode 100644 mods/basiclti/tool/admin_create.php delete mode 100644 mods/basiclti/tool/admin_delete.php delete mode 100644 mods/basiclti/tool/admin_edit.php delete mode 100644 mods/basiclti/tool/admin_view.php delete mode 100644 mods/basiclti/tool/content_edit.php delete mode 100644 mods/basiclti/tool/forms.php delete mode 100644 mods/basiclti/tool/instructor_create.php delete mode 100644 mods/basiclti/tool/instructor_delete.php delete mode 100644 mods/basiclti/tool/instructor_edit.php delete mode 100644 mods/basiclti/tool/instructor_view.php delete mode 100644 mods/calendar/README_ATUTOR_MODULE delete mode 100644 mods/calendar/admin_cal.php delete mode 100644 mods/calendar/calendar.gif delete mode 100644 mods/calendar/index.php delete mode 100644 mods/calendar/index_admin.php delete mode 100644 mods/calendar/module.css delete mode 100644 mods/calendar/module.php delete mode 100644 mods/calendar/module.sql delete mode 100644 mods/calendar/module.xml delete mode 100644 mods/calendar/module_install.php delete mode 100644 mods/calendar/side_menu.inc.php delete mode 100644 mods/calendar/sync_cal.php delete mode 100644 mods/ccnet/ccnet.php delete mode 100644 mods/ccnet/ccnet_logo.jpg delete mode 100644 mods/ccnet/index.php delete mode 100644 mods/ccnet/module.php delete mode 100644 mods/ccnet/module.sql delete mode 100644 mods/ccnet/module.xml delete mode 100644 mods/ccnet/module_install.php delete mode 100644 mods/ccnet/module_uninstall.php delete mode 100644 mods/certificate/README delete mode 100644 mods/certificate/certificate.gif delete mode 100644 mods/certificate/certificate_create.php delete mode 100644 mods/certificate/certificate_delete.php delete mode 100644 mods/certificate/certificate_edit.php delete mode 100644 mods/certificate/common.inc.php delete mode 100644 mods/certificate/default_certificate.pdf delete mode 100644 mods/certificate/default_certificate.pdf.fields delete mode 100644 mods/certificate/default_certificate_for_fraser_health.pdf delete mode 100644 mods/certificate/get_adobe_reader.gif delete mode 100644 mods/certificate/index.php delete mode 100644 mods/certificate/index_instructor.php delete mode 100644 mods/certificate/module.css delete mode 100644 mods/certificate/module.php delete mode 100644 mods/certificate/module.sql delete mode 100644 mods/certificate/module.xml delete mode 100644 mods/certificate/module_install.php delete mode 100644 mods/certificate/module_uninstall.php delete mode 100644 mods/certificate/open_certificate.php delete mode 100644 mods/certify/README delete mode 100644 mods/certify/certify.css delete mode 100644 mods/certify/certify.gif delete mode 100644 mods/certify/certify_certificate.php delete mode 100644 mods/certify/certify_delete.php delete mode 100644 mods/certify/certify_functions.php delete mode 100644 mods/certify/certify_student_status.php delete mode 100644 mods/certify/certify_tests.php delete mode 100644 mods/certify/default_certificate.pdf delete mode 100644 mods/certify/download_certificate.php delete mode 100644 mods/certify/download_certificate.php.bak delete mode 100644 mods/certify/index.php delete mode 100644 mods/certify/index_instructor.php delete mode 100644 mods/certify/module.php delete mode 100644 mods/certify/module.sql delete mode 100644 mods/certify/module.xml delete mode 100644 mods/certify/module_delete.php delete mode 100644 mods/certify/module_install.php delete mode 100644 mods/certify/module_uninstall.php delete mode 100644 mods/certify/test.pdf delete mode 100644 mods/clean_file_storage/README delete mode 100644 mods/clean_file_storage/clean_file_storage.jpg delete mode 100644 mods/clean_file_storage/index.php delete mode 100644 mods/clean_file_storage/index_admin.php delete mode 100644 mods/clean_file_storage/module.css delete mode 100644 mods/clean_file_storage/module.php delete mode 100644 mods/clean_file_storage/module.sql delete mode 100644 mods/clean_file_storage/module.xml delete mode 100644 mods/clean_file_storage/module_install.php delete mode 100644 mods/clean_file_storage/module_uninstall.php delete mode 100644 mods/cmap/README delete mode 100644 mods/cmap/cmap_logo.jpg delete mode 100644 mods/cmap/index.php delete mode 100644 mods/cmap/index_admin.php delete mode 100644 mods/cmap/index_instructor.php delete mode 100644 mods/cmap/module.php delete mode 100644 mods/cmap/module.sql delete mode 100644 mods/cmap/module.xml delete mode 100644 mods/cmap/module_install.php delete mode 100644 mods/cmap/module_uninstall.php delete mode 100644 mods/cpref_switch/ajax_save.php delete mode 100644 mods/cpref_switch/module.css delete mode 100644 mods/cpref_switch/module.inc.php delete mode 100644 mods/cpref_switch/module.php delete mode 100644 mods/cpref_switch/module.sql delete mode 100644 mods/cpref_switch/module.xml delete mode 100644 mods/cpref_switch/module_install.php delete mode 100644 mods/cpref_switch/module_uninstall.php delete mode 100644 mods/cpref_switch/side_menu.inc.php delete mode 100644 mods/disclaimer/README delete mode 100644 mods/disclaimer/common.inc.php delete mode 100644 mods/disclaimer/disclaimer.png delete mode 100644 mods/disclaimer/disclaimer_supplement.zip delete mode 100644 mods/disclaimer/module.php delete mode 100644 mods/disclaimer/module.sql delete mode 100644 mods/disclaimer/module.xml delete mode 100644 mods/disclaimer/module_install.php delete mode 100644 mods/disclaimer/module_uninstall.php delete mode 100644 mods/disclaimer/tac_edit.php delete mode 100644 mods/disclaimer/terms_and_conditions.php delete mode 100644 mods/disclaimer/terms_and_conditions.tmpl.php delete mode 100644 mods/ecomm/datetimepicker.js delete mode 100644 mods/ecomm/error_beanstream.php delete mode 100644 mods/ecomm/failure_beanstream.php delete mode 100644 mods/ecomm/images/cal.gif delete mode 100644 mods/ecomm/images/mc_42x27.gif delete mode 100644 mods/ecomm/images/visa_42x27.gif delete mode 100644 mods/ecomm/include/payments.lib.php delete mode 100644 mods/ecomm/index.php delete mode 100644 mods/ecomm/index_admin.php delete mode 100644 mods/ecomm/index_admin_approve.php delete mode 100644 mods/ecomm/index_instructor.php delete mode 100644 mods/ecomm/invoice.php delete mode 100644 mods/ecomm/module.php delete mode 100644 mods/ecomm/module.sql delete mode 100644 mods/ecomm/module.xml delete mode 100644 mods/ecomm/module_install.php delete mode 100644 mods/ecomm/module_uninstall.php delete mode 100644 mods/ecomm/payment.php delete mode 100644 mods/ecomm/payments.png delete mode 100644 mods/ecomm/payments_admin.php delete mode 100644 mods/ecomm/payments_export_csv.php delete mode 100644 mods/ecomm/readme delete mode 100644 mods/ecomm/response_ipn.php delete mode 100644 mods/ecomm/response_paypal_user.php delete mode 100644 mods/ecomm/response_user.php delete mode 100644 mods/ecomm/success_beanstream.php delete mode 100644 mods/elluminate/elluminate.php delete mode 100644 mods/elluminate/elluminate_logo.gif delete mode 100644 mods/elluminate/index.php delete mode 100644 mods/elluminate/module.css delete mode 100644 mods/elluminate/module.php delete mode 100644 mods/elluminate/module.sql delete mode 100644 mods/elluminate/module.xml delete mode 100644 mods/elluminate/module_install.php delete mode 100644 mods/elluminate/module_uninstall.php delete mode 100644 mods/elluminate/readme delete mode 100644 mods/elluminate/side_menu.inc.php delete mode 100644 mods/epresence/epresence_logo.gif delete mode 100644 mods/epresence/index.php delete mode 100644 mods/epresence/index_admin.php delete mode 100644 mods/epresence/index_instructor.php delete mode 100644 mods/epresence/module.php delete mode 100644 mods/epresence/module.sql delete mode 100644 mods/epresence/module.xml delete mode 100644 mods/epresence/module_install.php delete mode 100644 mods/epresence/module_uninstall.php delete mode 100644 mods/fha_refresher/index.php delete mode 100644 mods/fha_refresher/module.php delete mode 100644 mods/fha_refresher/module.sql delete mode 100644 mods/fha_refresher/module.xml delete mode 100644 mods/fha_refresher/module_cron.php delete mode 100644 mods/fha_refresher/module_delete.php delete mode 100644 mods/fha_refresher/module_install.php delete mode 100644 mods/fha_student_tools/icon.gif delete mode 100644 mods/fha_student_tools/index.php delete mode 100644 mods/fha_student_tools/instructor_index.php delete mode 100644 mods/fha_student_tools/module.php delete mode 100644 mods/fha_student_tools/module.sql delete mode 100644 mods/fha_student_tools/module.xml delete mode 100644 mods/fha_student_tools/module_delete.php delete mode 100644 mods/fha_student_tools/module_install.php delete mode 100644 mods/flowplayer/LICENSE.txt delete mode 100644 mods/flowplayer/README.txt delete mode 100644 mods/flowplayer/flowplayer-3.1.2.min.js delete mode 100644 mods/flowplayer/flowplayer-3.1.2.swf delete mode 100644 mods/flowplayer/flowplayer.controls-3.1.2.swf delete mode 100644 mods/flowplayer/module.php delete mode 100644 mods/flowplayer/module.sql delete mode 100644 mods/flowplayer/module.xml delete mode 100644 mods/flowplayer/module_format_content.php delete mode 100644 mods/flowplayer/module_install.php delete mode 100644 mods/flowplayer/module_uninstall.php delete mode 100644 mods/google_calendar/get_google_user.php delete mode 100644 mods/google_calendar/google_cal.gif delete mode 100644 mods/google_calendar/google_prefs.php delete mode 100644 mods/google_calendar/index.php delete mode 100644 mods/google_calendar/index_admin.php delete mode 100644 mods/google_calendar/index_instructor.php delete mode 100644 mods/google_calendar/index_mystart.php delete mode 100644 mods/google_calendar/module.php delete mode 100644 mods/google_calendar/module.sql delete mode 100644 mods/google_calendar/module.xml delete mode 100644 mods/google_calendar/module_install.php delete mode 100644 mods/google_calendar/module_uninstall.php delete mode 100644 mods/google_calendar/readme delete mode 100644 mods/google_calendar/side_menu.inc.php delete mode 100644 mods/google_talk/google_talk.png delete mode 100644 mods/google_talk/index.php delete mode 100644 mods/google_talk/module.php delete mode 100644 mods/google_talk/module.sql delete mode 100644 mods/google_talk/module.xml delete mode 100644 mods/google_talk/module_install.php delete mode 100644 mods/google_talk/module_uninstall.php delete mode 100644 mods/gradebook/README delete mode 100644 mods/gradebook/edit_marks.php delete mode 100644 mods/gradebook/grade_scale.php delete mode 100644 mods/gradebook/grade_scale_add.php delete mode 100644 mods/gradebook/grade_scale_delete.php delete mode 100644 mods/gradebook/grade_scale_edit.php delete mode 100644 mods/gradebook/gradebook.png delete mode 100644 mods/gradebook/gradebook_add_tests.php delete mode 100644 mods/gradebook/gradebook_delete_tests.php delete mode 100644 mods/gradebook/gradebook_edit_tests.php delete mode 100644 mods/gradebook/gradebook_tests.php delete mode 100644 mods/gradebook/html/grade_scale_add_edit.inc.php delete mode 100644 mods/gradebook/import_export_external_marks.php delete mode 100644 mods/gradebook/lib/gradebook.inc.php delete mode 100644 mods/gradebook/module.php delete mode 100644 mods/gradebook/module.sql delete mode 100644 mods/gradebook/module.xml delete mode 100644 mods/gradebook/module_install.php delete mode 100644 mods/gradebook/my_gradebook.php delete mode 100644 mods/gradebook/update_gradebook.php delete mode 100644 mods/gradebook/verify_list.php delete mode 100644 mods/gradebook/verify_tests.php delete mode 100644 mods/hello_world/ModuleCallbacks.class.php delete mode 100644 mods/hello_world/content_tool_action.js delete mode 100644 mods/hello_world/hello_world.jpg delete mode 100644 mods/hello_world/index.php delete mode 100644 mods/hello_world/index_admin.php delete mode 100644 mods/hello_world/index_instructor.php delete mode 100644 mods/hello_world/index_mystart.php delete mode 100644 mods/hello_world/index_public.php delete mode 100644 mods/hello_world/module.css delete mode 100644 mods/hello_world/module.php delete mode 100644 mods/hello_world/module.sql delete mode 100644 mods/hello_world/module.xml delete mode 100644 mods/hello_world/module_backup.php delete mode 100644 mods/hello_world/module_cron.php delete mode 100644 mods/hello_world/module_delete.php delete mode 100644 mods/hello_world/module_format_content.php delete mode 100644 mods/hello_world/module_install.php delete mode 100644 mods/hello_world/module_news.php delete mode 100644 mods/hello_world/module_uninstall.php delete mode 100644 mods/hello_world/side_menu.inc.php delete mode 100644 mods/hello_world/sublinks.php delete mode 100644 mods/job_board/README delete mode 100644 mods/job_board/admin/categories.php delete mode 100644 mods/job_board/admin/edit_employer.php delete mode 100644 mods/job_board/admin/edit_post.php delete mode 100644 mods/job_board/admin/employers.php delete mode 100644 mods/job_board/admin/preferences.php delete mode 100644 mods/job_board/admin/view_post.php delete mode 100644 mods/job_board/confirm.php delete mode 100644 mods/job_board/employer/add_new_post.php delete mode 100644 mods/job_board/employer/edit_post.php delete mode 100644 mods/job_board/employer/home.php delete mode 100644 mods/job_board/employer/login.php delete mode 100644 mods/job_board/employer/logout.php delete mode 100644 mods/job_board/employer/password_reminder.php delete mode 100644 mods/job_board/employer/profile.php delete mode 100644 mods/job_board/employer/registration.php delete mode 100644 mods/job_board/employer/view_post.php delete mode 100644 mods/job_board/images/bookmark.png delete mode 100644 mods/job_board/images/jb_icon.png delete mode 100644 mods/job_board/images/jb_icon_tiny.png delete mode 100644 mods/job_board/include/classes/Employer.class.php delete mode 100644 mods/job_board/include/classes/Job.class.php delete mode 100644 mods/job_board/include/constants.inc.php delete mode 100644 mods/job_board/include/html/admin/jb_categories.tmpl.php delete mode 100644 mods/job_board/include/html/admin/jb_edit_employer.tmpl.php delete mode 100644 mods/job_board/include/html/admin/jb_edit_post.tmpl.php delete mode 100644 mods/job_board/include/html/admin/jb_employers.tmpl.php delete mode 100644 mods/job_board/include/html/admin/jb_index.tmpl.php delete mode 100644 mods/job_board/include/html/admin/jb_preferences.tmpl.php delete mode 100644 mods/job_board/include/html/employer/jb_add_new_post.tmpl.php delete mode 100644 mods/job_board/include/html/employer/jb_edit_post.tmpl.php delete mode 100644 mods/job_board/include/html/employer/jb_employer_header.tmpl.php delete mode 100644 mods/job_board/include/html/employer/jb_home.tmpl.php delete mode 100644 mods/job_board/include/html/employer/jb_login.tmpl.php delete mode 100644 mods/job_board/include/html/employer/jb_profile.tmpl.php delete mode 100644 mods/job_board/include/html/employer/jb_registration.tmpl.php delete mode 100644 mods/job_board/include/html/employer/password_change.tmpl.php delete mode 100644 mods/job_board/include/html/jb_advance_search_table.tmpl.php delete mode 100644 mods/job_board/include/html/jb_index.tmpl.php delete mode 100644 mods/job_board/include/html/jb_subscribe.tmpl.php delete mode 100644 mods/job_board/include/html/jb_view_post.tmpl.php delete mode 100644 mods/job_board/include/jb_add_to_cart.inc.php delete mode 100644 mods/job_board/include/js/edit.js delete mode 100644 mods/job_board/index.php delete mode 100644 mods/job_board/index_admin.php delete mode 100644 mods/job_board/module.css delete mode 100644 mods/job_board/module.php delete mode 100644 mods/job_board/module.sql delete mode 100644 mods/job_board/module.xml delete mode 100644 mods/job_board/module_install.php delete mode 100644 mods/job_board/module_news.php delete mode 100644 mods/job_board/module_uninstall.php delete mode 100644 mods/job_board/sublinks.php delete mode 100644 mods/job_board/subscribe.php delete mode 100644 mods/job_board/view_post.php delete mode 100644 mods/joomla_atutor/atutor/index_mambo.php delete mode 100644 mods/joomla_atutor/com_atutor.zip delete mode 100644 mods/joomla_atutor/install.txt delete mode 100644 mods/ldap/admin/config_ldap.php delete mode 100644 mods/ldap/admin/ldap_auth_log.php delete mode 100644 mods/ldap/admin/ldap_lib.php delete mode 100755 mods/ldap/atutor.ldap.mod.struct.sql delete mode 100644 mods/ldap/atutor.ldap.mod.tar.gz delete mode 100644 mods/ldap/include/lib/menu_pages.php delete mode 100755 mods/ldap/include/lib/pk.pem delete mode 100644 mods/ldap/include/lib/rsa.inc.php delete mode 100644 mods/ldap/jscripts/jqgrid/jquery.jqGrid.js delete mode 100644 mods/ldap/jscripts/jqgrid/jquery.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.base.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.celledit.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.common.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.custom.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.formedit.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.inlinedit.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.locale-bg.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.locale-en.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.locale-it.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.postext.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.setcolumns.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.subgrid.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.tbltogrid.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/grid.treegrid.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/jqDnR.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/jqModal.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.base-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.celledit-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.common-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.custom-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.formedit-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.inlinedit-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.locale-bg-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.locale-en-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.locale-it-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.postext-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.setcolumns-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.subgrid-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.tbltogrid-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/min/grid.treegrid-min.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packall/grid.pack.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.base.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.celledit.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.common.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.custom.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.formedit.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.inlinedit.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.locale-bg.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.locale-en.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.locale-it.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.postext.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.setcolumns.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.subgrid.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.tbltogrid.js delete mode 100644 mods/ldap/jscripts/jqgrid/js/packed/grid.treegrid.js delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/grid.css delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/cd_run.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/dirty.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/down.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/find.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/first.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/folder.png delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/grid-blue-ft.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/grid-blue-hd.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/headerbg.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/headerleft.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/headerright.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/ico-close.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/last.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/line3.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/minus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/next.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/nochild.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/off-first.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/off-last.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/off-next.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/off-prev.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/plus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/prev.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/refresh.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/resize.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/row_add.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/row_delete.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/row_edit.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/sort_asc.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/sort_desc.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/spacer.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/tab_close-on.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/tree_leaf.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/tree_minus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/tree_plus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/basic/images/up.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/grid.css delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/cd_run.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/dirty.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/down.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/find.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/first.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/folder.png delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/grid-blue-ft.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/grid-blue-hd.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/headerbg.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/headerleft.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/headerright.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/ico-close.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/last.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/line3.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/minus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/next.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/nochild.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/off-first.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/off-last.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/off-next.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/off-prev.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/plus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/prev.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/refresh.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/resize.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/row_add.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/row_delete.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/row_edit.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/sort_asc.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/sort_desc.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/spacer.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/tab_close-on.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/tree_leaf.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/tree_minus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/tree_plus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/coffee/images/up.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/grid.css delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/cd_run.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/dirty.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/down.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/find.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/first.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/folder.png delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/grid-blue-ft.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/grid-blue-hd.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/headerbg.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/headerleft.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/headerright.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/ico-close.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/last.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/leaf.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/line3.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/minus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/next.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/nochild.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/off-first.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/off-last.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/off-next.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/off-prev.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/plus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/prev.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/refresh.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/resize.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/row_add.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/row_delete.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/row_edit.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/sort_asc.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/sort_desc.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/spacer.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/tab_close-on.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/tree_leaf.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/tree_minus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/tree_plus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/green/images/up.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/jqModal.css delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/grid.css delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/cd_run.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/dirty.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/down.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/find.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/first.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/folder.png delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/grid-blue-ft.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/grid-blue-hd.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/headerbg.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/headerleft.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/headerright.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/ico-close.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/last.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/line3.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/minus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/next.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/nochild.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/off-first.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/off-last.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/off-next.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/off-prev.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/plus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/prev.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/refresh.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/resize.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/row_add.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/row_delete.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/row_edit.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/sort_asc.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/sort_desc.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/spacer.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/tab_close-on.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/tree_leaf.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/tree_minus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/tree_plus.gif delete mode 100644 mods/ldap/jscripts/jqgrid/themes/sand/images/up.gif delete mode 100644 mods/ldap/login.php delete mode 100755 mods/ldap/readme.txt delete mode 100755 mods/ldap/rsa/base64.js delete mode 100755 mods/ldap/rsa/jsbn.js delete mode 100755 mods/ldap/rsa/prng4.js delete mode 100755 mods/ldap/rsa/rng.js delete mode 100755 mods/ldap/rsa/rsa.js delete mode 100755 mods/ldap/themes/default/login.tmpl.php delete mode 100644 mods/mahara/README delete mode 100644 mods/mahara/cookie.php delete mode 100644 mods/mahara/index.php delete mode 100644 mods/mahara/index_admin.php delete mode 100644 mods/mahara/mahara.gif delete mode 100644 mods/mahara/mahara_login.php delete mode 100644 mods/mahara/module.php delete mode 100644 mods/mahara/module.sql delete mode 100644 mods/mahara/module.xml delete mode 100644 mods/mahara/module_delete.php delete mode 100644 mods/mahara/module_install.php delete mode 100644 mods/mahara/module_uninstall.php delete mode 100644 mods/mahara/new_account.php delete mode 100644 mods/mahara/new_account_admin.php delete mode 100644 mods/marratech/index.php delete mode 100644 mods/marratech/marratech.php delete mode 100644 mods/marratech/marratech_logo.jpg delete mode 100644 mods/marratech/module.php delete mode 100644 mods/marratech/module.sql delete mode 100644 mods/marratech/module.xml delete mode 100644 mods/marratech/module_install.php delete mode 100644 mods/marratech/readme delete mode 100644 mods/mediawiki/MySQL_Auth/Auth_viaMySQL/Auth_viaMySQL.php delete mode 100644 mods/mediawiki/MySQL_Auth/Auth_viaMySQL/CacheTimer_viaMySQL.php delete mode 100644 mods/mediawiki/MySQL_Auth/MySQLActiveUser.php delete mode 100644 mods/mediawiki/README delete mode 100644 mods/mediawiki/index.php delete mode 100644 mods/mediawiki/index_admin.php delete mode 100644 mods/mediawiki/index_instructor.php delete mode 100644 mods/mediawiki/index_mystart.php delete mode 100644 mods/mediawiki/index_public.php delete mode 100644 mods/mediawiki/module.css delete mode 100644 mods/mediawiki/module.php delete mode 100644 mods/mediawiki/module.sql delete mode 100644 mods/mediawiki/module.xml delete mode 100644 mods/mediawiki/module_delete.php delete mode 100644 mods/mediawiki/module_install.php delete mode 100644 mods/mediawiki/module_news.php delete mode 100644 mods/mediawiki/module_uninstall.php delete mode 100644 mods/mediawiki/mw_config.php delete mode 100644 mods/mediawiki/mw_connect.php delete mode 100644 mods/mediawiki/mw_icon_sm.png delete mode 100644 mods/mediawiki/mw_logo.png delete mode 100644 mods/mediawiki/side_menu.inc.php delete mode 100644 mods/mediawiki/sublinks.php delete mode 100644 mods/merlot/README delete mode 100644 mods/merlot/add_to_links.php delete mode 100644 mods/merlot/classes/MerlotResultParser.class.php delete mode 100644 mods/merlot/index.php delete mode 100644 mods/merlot/index_admin.php delete mode 100644 mods/merlot/merlot.gif delete mode 100644 mods/merlot/merlot.js delete mode 100644 mods/merlot/merlot_adv.php delete mode 100644 mods/merlot/merlot_rest.php delete mode 100644 mods/merlot/merlot_soap.php delete mode 100644 mods/merlot/merlotlogo.gif delete mode 100644 mods/merlot/module.css delete mode 100644 mods/merlot/module.php delete mode 100644 mods/merlot/module.sql delete mode 100644 mods/merlot/module.xml delete mode 100644 mods/merlot/module_install.php delete mode 100644 mods/merlot/module_uninstall.php delete mode 100644 mods/openmeetings/TODO.txt delete mode 100644 mods/openmeetings/add_group_meetings.php delete mode 100644 mods/openmeetings/html/course_meeting.inc.php delete mode 100644 mods/openmeetings/html/create_room.inc.php delete mode 100644 mods/openmeetings/html/create_room.tmpl.php delete mode 100644 mods/openmeetings/html/edit_room.inc.php delete mode 100644 mods/openmeetings/html/group_meeting.inc.php delete mode 100644 mods/openmeetings/html/update_room.inc.php delete mode 100644 mods/openmeetings/index.php delete mode 100644 mods/openmeetings/lib/SOAP_openmeetings.php delete mode 100644 mods/openmeetings/lib/nusoap.php delete mode 100644 mods/openmeetings/lib/openmeetings.class.php delete mode 100644 mods/openmeetings/lib/openmeetings.inc.php delete mode 100644 mods/openmeetings/module.css delete mode 100644 mods/openmeetings/module.php delete mode 100644 mods/openmeetings/module.sql delete mode 100644 mods/openmeetings/module.xml delete mode 100644 mods/openmeetings/module_install.php delete mode 100644 mods/openmeetings/module_uninstall.php delete mode 100644 mods/openmeetings/openmeetings.php delete mode 100644 mods/openmeetings/openmeetings_delete.php delete mode 100644 mods/openmeetings/openmeetings_group.php delete mode 100644 mods/openmeetings/openmeetings_instructor.php delete mode 100644 mods/openmeetings/openmeetings_logo.png delete mode 100644 mods/openmeetings/readme delete mode 100644 mods/openmeetings/view_meetings.php delete mode 100644 mods/patcher/README delete mode 100644 mods/patcher/classes/Patch.class.php delete mode 100644 mods/patcher/classes/PatchCreator.class.php delete mode 100644 mods/patcher/classes/PatchListParser.class.php delete mode 100644 mods/patcher/classes/PatchParser.class.php delete mode 100644 mods/patcher/include/common.inc.php delete mode 100644 mods/patcher/include/json.inc.php delete mode 100644 mods/patcher/include/patch_xml_template.inc.php delete mode 100644 mods/patcher/index_admin.php delete mode 100644 mods/patcher/module.css delete mode 100644 mods/patcher/module.php delete mode 100644 mods/patcher/module.sql delete mode 100644 mods/patcher/module.xml delete mode 100644 mods/patcher/module_install.php delete mode 100644 mods/patcher/myown_patches.php delete mode 100644 mods/patcher/patch_create.php delete mode 100644 mods/patcher/patch_creator.php delete mode 100644 mods/patcher/patch_delete.php delete mode 100644 mods/patcher/patch_edit.php delete mode 100644 mods/patcher/patch_edit_interface.tmpl.php delete mode 100644 mods/patcher/sample_patch.xml delete mode 100644 mods/patcher/sample_patch_list.xml delete mode 100644 mods/patcher/xml_special_chars.txt delete mode 100644 mods/pdf_converter/README delete mode 100644 mods/pdf_converter/class.ezpdf.php delete mode 100644 mods/pdf_converter/class.pdf.php delete mode 100644 mods/pdf_converter/font/courier.php delete mode 100644 mods/pdf_converter/font/helvetica.php delete mode 100644 mods/pdf_converter/font/helveticab.php delete mode 100644 mods/pdf_converter/font/helveticabi.php delete mode 100644 mods/pdf_converter/font/helveticai.php delete mode 100644 mods/pdf_converter/font/makefont/cp1250.map delete mode 100644 mods/pdf_converter/font/makefont/cp1251.map delete mode 100644 mods/pdf_converter/font/makefont/cp1252.map delete mode 100644 mods/pdf_converter/font/makefont/cp1253.map delete mode 100644 mods/pdf_converter/font/makefont/cp1254.map delete mode 100644 mods/pdf_converter/font/makefont/cp1255.map delete mode 100644 mods/pdf_converter/font/makefont/cp1257.map delete mode 100644 mods/pdf_converter/font/makefont/cp1258.map delete mode 100644 mods/pdf_converter/font/makefont/cp874.map delete mode 100644 mods/pdf_converter/font/makefont/iso-8859-1.map delete mode 100644 mods/pdf_converter/font/makefont/iso-8859-11.map delete mode 100644 mods/pdf_converter/font/makefont/iso-8859-15.map delete mode 100644 mods/pdf_converter/font/makefont/iso-8859-16.map delete mode 100644 mods/pdf_converter/font/makefont/iso-8859-2.map delete mode 100644 mods/pdf_converter/font/makefont/iso-8859-4.map delete mode 100644 mods/pdf_converter/font/makefont/iso-8859-5.map delete mode 100644 mods/pdf_converter/font/makefont/iso-8859-7.map delete mode 100644 mods/pdf_converter/font/makefont/iso-8859-9.map delete mode 100644 mods/pdf_converter/font/makefont/koi8-r.map delete mode 100644 mods/pdf_converter/font/makefont/koi8-u.map delete mode 100644 mods/pdf_converter/font/makefont/makefont.php delete mode 100644 mods/pdf_converter/font/symbol.php delete mode 100644 mods/pdf_converter/font/times.php delete mode 100644 mods/pdf_converter/font/timesb.php delete mode 100644 mods/pdf_converter/font/timesbi.php delete mode 100644 mods/pdf_converter/font/timesi.php delete mode 100644 mods/pdf_converter/font/zapfdingbats.php delete mode 100644 mods/pdf_converter/fpdf.css delete mode 100644 mods/pdf_converter/fpdf.php delete mode 100644 mods/pdf_converter/index.php delete mode 100644 mods/pdf_converter/module.php delete mode 100644 mods/pdf_converter/module.sql delete mode 100644 mods/pdf_converter/module.xml delete mode 100644 mods/pdf_converter/module_install.php delete mode 100644 mods/pdf_converter/module_uninstall.php delete mode 100644 mods/pdf_converter/muestra_pdf.txt delete mode 100644 mods/pdf_converter/pdf.php delete mode 100644 mods/pdf_converter/pdf_converter.php delete mode 100644 mods/pdf_converter/pdf_icon.jpg delete mode 100644 mods/pdf_converter/side_menu.inc.php delete mode 100644 mods/photo_album/HTML/Template/IT.php delete mode 100644 mods/photo_album/HTML/Template/ITX.php delete mode 100644 mods/photo_album/HTML/Template/IT_Error.php delete mode 100644 mods/photo_album/README.txt delete mode 100644 mods/photo_album/Template/admin_comment_list.tpl.php delete mode 100644 mods/photo_album/Template/admin_config.tpl.php delete mode 100644 mods/photo_album/Template/admin_image_list.tpl.php delete mode 100644 mods/photo_album/Template/delete_confirm.tpl.php delete mode 100644 mods/photo_album/Template/file_upload.tpl.php delete mode 100644 mods/photo_album/Template/form.tpl.php delete mode 100644 mods/photo_album/Template/index.tpl.php delete mode 100644 mods/photo_album/Template/index.tpl.php.bak delete mode 100644 mods/photo_album/Template/index_admin.tpl.php delete mode 100644 mods/photo_album/Template/instructor_comment.tpl.php delete mode 100644 mods/photo_album/Template/instructor_config.tpl.php delete mode 100644 mods/photo_album/Template/instructor_image.tpl.php delete mode 100644 mods/photo_album/Template/my_comment.tpl.php delete mode 100644 mods/photo_album/Template/my_photo.tpl.php delete mode 100644 mods/photo_album/Template/result.tpl.php delete mode 100644 mods/photo_album/Template/view.tpl.php delete mode 100644 mods/photo_album/admin_comment_list.php delete mode 100644 mods/photo_album/admin_config.php delete mode 100644 mods/photo_album/admin_image_list.php delete mode 100644 mods/photo_album/classes/image_upload.class.php delete mode 100644 mods/photo_album/classes/pa.class.php delete mode 100644 mods/photo_album/classes/pa_admin_comment.class.php delete mode 100644 mods/photo_album/classes/pa_admin_image.class.php delete mode 100644 mods/photo_album/classes/pa_index.class.php delete mode 100644 mods/photo_album/classes/pa_mycomment.class.php delete mode 100644 mods/photo_album/classes/pa_mypic.class.php delete mode 100644 mods/photo_album/classes/pa_view.class.php delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/cache/index.php delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/cache/source/index.php delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.changelog.txt delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.faq.txt delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.license.txt delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.readme.txt delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/fonts/readme.txt delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/images/readme.txt delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/index.php delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/phpThumb.config.php.default delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/phpThumb.php delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/phpthumb.bmp.php delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/phpthumb.class.php delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/phpthumb.filters.php delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/phpthumb.functions.php delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/phpthumb.gif.php delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/phpthumb.ico.php delete mode 100644 mods/photo_album/classes/phpThumb_1.7.2/phpthumb.unsharp.php delete mode 100644 mods/photo_album/define.php delete mode 100644 mods/photo_album/fluid/component-templates/css/Lightbox.css delete mode 100644 mods/photo_album/fluid/component-templates/html/Lightbox.html delete mode 100644 mods/photo_album/fluid/component-templates/images/Banana.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/Blackberry.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/Cherry.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/Dragonfruit.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/Fig.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/Grapes.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/Kiwano.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/Kiwi.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/Kumquat.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/Lemon.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/Mangosteen.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/Orange.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/RedApple.jpg delete mode 100644 mods/photo_album/fluid/component-templates/images/Tamarillo.jpg delete mode 100644 mods/photo_album/fluid/component-templates/js/fluid/Fluid.js delete mode 100755 mods/photo_album/fluid/component-templates/js/fluid/Lightbox.js delete mode 100644 mods/photo_album/fluid/component-templates/js/fluid/Reorderer.js delete mode 100755 mods/photo_album/fluid/component-templates/js/jquery.tabindex/LICENSE.txt delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.tabindex/jquery.tabindex.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/GPL-LICENSE.txt delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/MIT-LICENSE.txt delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/jquery.dimensions.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.form.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.form.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.menu.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.modal.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.tabs.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.tree.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.accordion.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.all.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.calendar.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.dialog.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.menu.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.resizable.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.shadow.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.slider.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.tablesorter.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.tabs.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-left-act.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-left-over.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-left.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-middle-act.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-middle-over.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-middle.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-right-act.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-right-over.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-right.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/asc.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/bg.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/desc.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-e.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-n.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-ne.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-nw.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-s.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-se.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-sw.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-title.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-titlebar-close-hover.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-titlebar-close.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-w.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/menu-submenu.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-e.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-n.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-ne.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-nw.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-s.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-se.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-sw.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-w.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/shadow.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/slider-bg-1.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/slider-bg-2.png delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/slider-handle.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/tabs.gif delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.form.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.menu.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.modal.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.tabs.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.tree.css delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.accordion.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.calendar.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.dialog.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.draggable.ext.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.draggable.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.droppable.ext.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.droppable.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.magnifier.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.mouse.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.resizable.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.selectable.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.shadow.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.slider.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.sortable.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.tablesorter.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.tabs.js delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery/GPL-LICENSE.txt delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery/MIT-LICENSE.txt delete mode 100644 mods/photo_album/fluid/component-templates/js/jquery/jquery-1.2.1.js delete mode 100644 mods/photo_album/get_pa.php delete mode 100644 mods/photo_album/handler/add_begin.php delete mode 100644 mods/photo_album/handler/delete.php delete mode 100644 mods/photo_album/handler/delete_begin.php delete mode 100644 mods/photo_album/handler/edit_begin.php delete mode 100644 mods/photo_album/handler/fat.js delete mode 100644 mods/photo_album/handler/file_upload.php delete mode 100644 mods/photo_album/handler/store.php delete mode 100644 mods/photo_album/include/data_func.php delete mode 100644 mods/photo_album/include/general_func.php delete mode 100644 mods/photo_album/index.php delete mode 100644 mods/photo_album/index_admin.php delete mode 100644 mods/photo_album/instructor_comment.php delete mode 100644 mods/photo_album/instructor_config.php delete mode 100644 mods/photo_album/instructor_image.php delete mode 100644 mods/photo_album/module.css delete mode 100644 mods/photo_album/module.php delete mode 100644 mods/photo_album/module.sql delete mode 100644 mods/photo_album/module.xml delete mode 100644 mods/photo_album/module_delete.php delete mode 100644 mods/photo_album/module_install.php delete mode 100644 mods/photo_album/module_uninstall.php delete mode 100644 mods/photo_album/my_comment.php delete mode 100644 mods/photo_album/my_photo.php delete mode 100644 mods/photo_album/skins/pa_first.gif delete mode 100644 mods/photo_album/skins/pa_first.png delete mode 100644 mods/photo_album/skins/pa_last.gif delete mode 100644 mods/photo_album/skins/pa_last.png delete mode 100644 mods/photo_album/skins/pa_next.gif delete mode 100644 mods/photo_album/skins/pa_next.png delete mode 100644 mods/photo_album/skins/pa_prev.gif delete mode 100644 mods/photo_album/skins/pa_prev.png delete mode 100644 mods/photo_album/skins/pa_tool_icon.gif delete mode 100644 mods/photo_album/skins/pa_tool_icon.png delete mode 100644 mods/photo_album/skins/photo_logo.jpg delete mode 100644 mods/photo_album/skins/photo_logo.png delete mode 100644 mods/photo_album/skins/swatch_green.jpg delete mode 100644 mods/photo_album/skins/swatch_green.png delete mode 100644 mods/photo_album/skins/swatch_yellow.jpg delete mode 100644 mods/photo_album/skins/swatch_yellow.png delete mode 100644 mods/photo_album/view.php delete mode 100644 mods/photos/addComment.php delete mode 100644 mods/photos/admin/preferences.php delete mode 100644 mods/photos/albums.php delete mode 100644 mods/photos/course_albums.php delete mode 100644 mods/photos/create_album.php delete mode 100644 mods/photos/delete_album.php delete mode 100644 mods/photos/delete_comment.php delete mode 100644 mods/photos/delete_photo.php delete mode 100644 mods/photos/edit_album.php delete mode 100644 mods/photos/edit_comment.php delete mode 100644 mods/photos/edit_photos.php delete mode 100644 mods/photos/get_photo.php delete mode 100644 mods/photos/images/loading.gif delete mode 100644 mods/photos/images/next.png delete mode 100644 mods/photos/images/no.png delete mode 100644 mods/photos/images/photo_gallery.png delete mode 100644 mods/photos/images/prev.png delete mode 100644 mods/photos/images/search_bg.png delete mode 100644 mods/photos/images/search_icon.png delete mode 100644 mods/photos/include/ajaxupload.js delete mode 100644 mods/photos/include/classes/AjaxMessage.class.php delete mode 100644 mods/photos/include/classes/PhotoAlbum.class.php delete mode 100644 mods/photos/include/classes/SimpleImage.class.php delete mode 100644 mods/photos/include/constants.inc.php delete mode 100644 mods/photos/include/html/admin/pa_index.tmpl.php delete mode 100644 mods/photos/include/html/admin/pa_preferences.tmpl.php delete mode 100644 mods/photos/include/html/pa_albums.tmpl.php delete mode 100644 mods/photos/include/html/pa_create_album.tmpl.php delete mode 100644 mods/photos/include/html/pa_edit_album.tmpl.php delete mode 100644 mods/photos/include/html/pa_edit_photos.tmpl.php delete mode 100644 mods/photos/include/html/pa_index.tmpl.php delete mode 100644 mods/photos/include/html/pa_organize_photos.tmpl.php delete mode 100644 mods/photos/include/html/pa_photo.tmpl.php delete mode 100644 mods/photos/include/html/pa_search.tmpl.php delete mode 100644 mods/photos/include/imageReorderer.js delete mode 100644 mods/photos/include/lib.inc.php delete mode 100644 mods/photos/include/upload.js delete mode 100644 mods/photos/index.php delete mode 100644 mods/photos/index_admin.php delete mode 100644 mods/photos/module.css delete mode 100644 mods/photos/module.php delete mode 100644 mods/photos/module.sql delete mode 100644 mods/photos/module.xml delete mode 100644 mods/photos/module_install.php delete mode 100644 mods/photos/module_uninstall.php delete mode 100644 mods/photos/photo.php delete mode 100644 mods/photos/profile_album.php delete mode 100644 mods/photos/remove_uploaded_photo.php delete mode 100644 mods/photos/search.php delete mode 100644 mods/photos/shared_albums.php delete mode 100644 mods/photos/sublinks.php delete mode 100644 mods/phpdoc/PHPDoc/README delete mode 100644 mods/phpdoc/PHPDoc/accessor/PhpdocAccessor.php delete mode 100644 mods/phpdoc/PHPDoc/accessor/PhpdocClassAccessor.php delete mode 100644 mods/phpdoc/PHPDoc/accessor/PhpdocDocumentAccessor.php delete mode 100644 mods/phpdoc/PHPDoc/accessor/PhpdocIndexAccessor.php delete mode 100644 mods/phpdoc/PHPDoc/accessor/PhpdocModuleAccessor.php delete mode 100644 mods/phpdoc/PHPDoc/accessor/PhpdocWarningAccessor.php delete mode 100644 mods/phpdoc/PHPDoc/analyser/PhpdocAnalyser.php delete mode 100644 mods/phpdoc/PHPDoc/analyser/PhpdocClassAnalyser.php delete mode 100644 mods/phpdoc/PHPDoc/analyser/PhpdocModuleAnalyser.php delete mode 100755 mods/phpdoc/PHPDoc/apidoc/empty.html delete mode 100755 mods/phpdoc/PHPDoc/apidoc/index2.html delete mode 100755 mods/phpdoc/PHPDoc/apidoc/keep/empty.html delete mode 100755 mods/phpdoc/PHPDoc/apidoc/keep/index2.html delete mode 100755 mods/phpdoc/PHPDoc/apidoc/keep/phpdoc.css delete mode 100755 mods/phpdoc/PHPDoc/apidoc/keep/phpdoc.dtd delete mode 100755 mods/phpdoc/PHPDoc/apidoc/phpdoc.css delete mode 100755 mods/phpdoc/PHPDoc/apidoc/phpdoc.dtd delete mode 100644 mods/phpdoc/PHPDoc/core/Phpdoc.php delete mode 100644 mods/phpdoc/PHPDoc/core/PhpdocArgvHandler.php delete mode 100644 mods/phpdoc/PHPDoc/core/PhpdocObject.php delete mode 100644 mods/phpdoc/PHPDoc/core/PhpdocSetupHandler.php delete mode 100644 mods/phpdoc/PHPDoc/exceptions/PhpdocError.php delete mode 100644 mods/phpdoc/PHPDoc/filehandler/PhpdocFileHandler.php delete mode 100644 mods/phpdoc/PHPDoc/index.php delete mode 100644 mods/phpdoc/PHPDoc/indexer/PhpdocIndexer.php delete mode 100644 mods/phpdoc/PHPDoc/parser/PhpdocClassParser.php delete mode 100644 mods/phpdoc/PHPDoc/parser/PhpdocConstantParser.php delete mode 100644 mods/phpdoc/PHPDoc/parser/PhpdocFunctionParser.php delete mode 100644 mods/phpdoc/PHPDoc/parser/PhpdocModuleParser.php delete mode 100644 mods/phpdoc/PHPDoc/parser/PhpdocParser.php delete mode 100644 mods/phpdoc/PHPDoc/parser/PhpdocParserCore.php delete mode 100644 mods/phpdoc/PHPDoc/parser/PhpdocParserRegExp.php delete mode 100644 mods/phpdoc/PHPDoc/parser/PhpdocParserTags.php delete mode 100644 mods/phpdoc/PHPDoc/parser/PhpdocUseParser.php delete mode 100644 mods/phpdoc/PHPDoc/parser/PhpdocVariableParser.php delete mode 100644 mods/phpdoc/PHPDoc/prepend.php delete mode 100644 mods/phpdoc/PHPDoc/redist/IT.php delete mode 100644 mods/phpdoc/PHPDoc/redist/ITX.php delete mode 100644 mods/phpdoc/PHPDoc/renderer/PhpdocRendererObject.php delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/CVS/Entries delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/CVS/Repository delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/CVS/Root delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/PhpdocHTMLClassRenderer.php delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/PhpdocHTMLDocumentRenderer.php delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/PhpdocHTMLIndexRenderer.php delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/PhpdocHTMLModuleRenderer.php delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/PhpdocHTMLRenderer.php delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/PhpdocHTMLRendererManager.php delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/PhpdocHTMLWarningRenderer.php delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/CVS/Entries delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/CVS/Repository delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/CVS/Root delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/class.html delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/classtree.html delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/elementlist.html delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/frame_packageelementlist.html delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/frame_packagelist.html delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/module.html delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/modulegroup.html delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/packagelist.html delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/phpdoc.css delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/warnings.html delete mode 100644 mods/phpdoc/PHPDoc/renderer/html/templates/xmlfiles.html delete mode 100644 mods/phpdoc/PHPDoc/warning/PhpdocWarning.php delete mode 100644 mods/phpdoc/PHPDoc/xmlexporter/PhpdocXMLClassExporter.php delete mode 100644 mods/phpdoc/PHPDoc/xmlexporter/PhpdocXMLDocumentExporter.php delete mode 100644 mods/phpdoc/PHPDoc/xmlexporter/PhpdocXMLExporter.php delete mode 100644 mods/phpdoc/PHPDoc/xmlexporter/PhpdocXMLIndexExporter.php delete mode 100644 mods/phpdoc/PHPDoc/xmlexporter/PhpdocXMLModuleExporter.php delete mode 100644 mods/phpdoc/PHPDoc/xmlexporter/PhpdocXMLWarningExporter.php delete mode 100644 mods/phpdoc/PHPDoc/xmlreader/PhpdocXMLReader.php delete mode 100644 mods/phpdoc/PHPDoc/xmlwriter/PhpdocXMLWriter.php delete mode 100644 mods/phpdoc/index.php delete mode 100644 mods/phpdoc/index_admin.php delete mode 100644 mods/phpdoc/module.css delete mode 100644 mods/phpdoc/module.php delete mode 100644 mods/phpdoc/module.sql delete mode 100644 mods/phpdoc/module.xml delete mode 100644 mods/phpdoc/module_install.php delete mode 100644 mods/phpdoc2/PhpDocumentor/Authors delete mode 100644 mods/phpdoc2/PhpDocumentor/ChangeLog delete mode 100644 mods/phpdoc2/PhpDocumentor/FAQ delete mode 100644 mods/phpdoc2/PhpDocumentor/INSTALL delete mode 100644 mods/phpdoc2/PhpDocumentor/LICENSE delete mode 100644 mods/phpdoc2/PhpDocumentor/README delete mode 100644 mods/phpdoc2/PhpDocumentor/Release-1.4.1 delete mode 100644 mods/phpdoc2/PhpDocumentor/index.html delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/abstract_class.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/abstract_method.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/abstract_private_class.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/abstract_private_method.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/class.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/class_folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/constant.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/constructor_method.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/destructor_method.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/file.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/function.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/function_folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/global.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/index.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/lock.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/method.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/next_button.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/package.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/package_folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/previous_button.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/private_class.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/private_method.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/private_variable.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/tutorial.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/tutorial_folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/media/images/earthli/variable.png delete mode 100644 mods/phpdoc2/PhpDocumentor/new_phpdoc.php delete mode 100644 mods/phpdoc2/PhpDocumentor/pear-phpdoc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor.ini delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Classes.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converter.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/HTMLframesConverter.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/options.ini delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/basicindex.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/blank.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/class.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/classtrees.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/const.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/define.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/docblock.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/elementindex.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/errors.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/examplesource.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/filesource.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/footer.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/function.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/global.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/header.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/include.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/index.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/left_frame.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/banner.css delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/AbstractClass.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/AbstractClass_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/AbstractMethod.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/AbstractPrivateClass.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/AbstractPrivateClass_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/AbstractPrivateMethod.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Class.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Class_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Constant.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Constructor.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Destructor.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Function.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Global.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/I.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Index.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Interface.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Interface_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/L.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Lminus.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Lplus.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Method.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Page.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Page_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/PrivateClass.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/PrivateClass_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/PrivateMethod.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/PrivateVariable.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/StaticMethod.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/StaticVariable.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/T.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Tminus.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Tplus.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/Variable.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/blank.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/class_folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/empty.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/file.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/function_folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/minus.gif delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/next_button.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/next_button_disabled.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/package.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/package_folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/plus.gif delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/previous_button.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/previous_button_disabled.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/private_class_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/tutorial.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/tutorial_folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/images/up_button.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/lib/classTree.js delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/media/stylesheet.css delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/method.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/page.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/pkgelementindex.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/ric.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/todolist.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/top_frame.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/tutorial.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/tutorial_nav.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/tutorial_toc.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/tutorial_tree.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates/var.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/options.ini delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/basicindex.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/blank.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/class.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/classtrees.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/const.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/define.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/docblock.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/elementindex.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/errors.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/examplesource.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/filesource.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/footer.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/function.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/global.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/header.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/include.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/index.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/left_frame.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/banner.css delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/AbstractClass.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/AbstractClass_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/AbstractMethod.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/AbstractPrivateClass.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/AbstractPrivateClass_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/AbstractPrivateMethod.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Class.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Class_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Constant.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Constructor.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Destructor.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Function.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Global.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/I.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Index.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Interface.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Interface_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/L.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Lminus.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Lplus.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Method.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Page.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Page_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/PrivateClass.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/PrivateClass_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/PrivateMethod.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/PrivateVariable.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/StaticMethod.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/StaticVariable.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/T.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Tminus.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Tplus.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/Variable.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/blank.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/class_folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/empty.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/file.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/function_folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/next_button.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/next_button_disabled.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/package.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/package_folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/previous_button.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/previous_button_disabled.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/private_class_logo.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/tutorial.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/tutorial_folder.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/images/up_button.png delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/media/stylesheet.css delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/method.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/page.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/pkgelementindex.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/ric.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/todolist.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/top_frame.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/tutorial.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/tutorial_nav.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/tutorial_toc.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/tutorial_tree.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/earthli/templates/var.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/DescHTML.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/DocBlockTags.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Errors.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/EventStack.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/HighlightParser.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/InlineTags.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/IntermediateParser.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Io.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/LinkClasses.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/PackagePageElements.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Parser.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/ParserData.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/ParserDescCleanup.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/ParserDocBlock.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/ParserElements.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/ProceduralPages.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Publisher.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Setup.inc.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/BUGS delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/COPYING.lib delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/ChangeLog delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/FAQ delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/INSTALL delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/NEWS delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/README delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/RELEASE_NOTES delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/TODO delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Config_File.class.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Smarty.class.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Smarty_Compiler.class.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.assemble_plugin_filepath.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.assign_smarty_interface.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.create_dir_structure.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.display_debug_console.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_include_path.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_microtime.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_php_resource.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.is_secure.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.is_trusted.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.load_plugins.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.load_resource_plugin.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.process_cached_inserts.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.process_compiled_include.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.read_cache_file.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.rm_auto.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.rmdir.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.run_insert_handler.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.smarty_include_php.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_cache_file.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_compiled_include.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_compiled_resource.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_file.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/debug.tpl delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/block.strip.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/block.textformat.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.assign.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.assign_debug_info.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.config_load.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.counter.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.cycle.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.debug.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.eval.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.fetch.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_checkboxes.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_image.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_options.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_radios.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_select_date.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_select_time.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_table.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.mailto.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.math.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.popup.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.popup_init.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.var_dump.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.capitalize.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.cat.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_characters.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_paragraphs.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_sentences.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_words.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.date_format.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.debug_print_var.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.default.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.escape.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.htmlentities.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.indent.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.lower.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.nl2br.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.rawurlencode.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.regex_replace.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.replace.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.spacify.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.string_format.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.strip.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.strip_tags.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.truncate.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.upper.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.wordwrap.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/outputfilter.trimwhitespace.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/shared.escape_special_chars.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/shared.make_timestamp.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/misc/smarty_icon.README delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/Smarty-2.6.0/misc/smarty_icon.gif delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/TutorialHighlightParser.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/WordParser.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/XMLpackagePageParser.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/clone.inc.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/clone5.inc.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/common.inc.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/find_phpdoc.php delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/phpDocumentorTParser.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/phpDocumentorTWordParser.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpDocumentor/phpdoc.inc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpdoc delete mode 100644 mods/phpdoc2/PhpDocumentor/phpdoc.php delete mode 100644 mods/phpdoc2/PhpDocumentor/poweredbyphpdoc.gif delete mode 100644 mods/phpdoc2/PhpDocumentor/scripts/add_cvs.php delete mode 100644 mods/phpdoc2/PhpDocumentor/scripts/create_examples.php delete mode 100644 mods/phpdoc2/PhpDocumentor/scripts/create_package.xml.php delete mode 100644 mods/phpdoc2/PhpDocumentor/scripts/makedoc.sh delete mode 100644 mods/phpdoc2/PhpDocumentor/scripts/tokenizer_test.php delete mode 100644 mods/phpdoc2/api_install.php delete mode 100644 mods/phpdoc2/apidoc/index.html delete mode 100644 mods/phpdoc2/include/classes/index.html delete mode 100644 mods/phpdoc2/include/classes/phpdoc2_images.class.php delete mode 100644 mods/phpdoc2/include/index.html delete mode 100644 mods/phpdoc2/index.php delete mode 100644 mods/phpdoc2/index_admin.php delete mode 100644 mods/phpdoc2/module.css delete mode 100644 mods/phpdoc2/module.php delete mode 100644 mods/phpdoc2/module.sql delete mode 100644 mods/phpdoc2/module.xml delete mode 100644 mods/phpdoc2/module_install.php delete mode 100644 mods/phpdoc2/module_uninstall.php delete mode 100644 mods/phpmyadmin/module.php delete mode 100644 mods/phpmyadmin/module.sql delete mode 100644 mods/phpmyadmin/module.xml delete mode 100644 mods/phpmyadmin/module_install.php delete mode 100644 mods/phpmyadmin/module_uninstall.php delete mode 100644 mods/phpmyadmin/phpmyadmin.php delete mode 100644 mods/plog/README_ATUTOR_MODULE delete mode 100644 mods/plog/admin_plog.php delete mode 100644 mods/plog/index.php delete mode 100644 mods/plog/index_admin.php delete mode 100644 mods/plog/index_instructor.php delete mode 100644 mods/plog/module.css delete mode 100644 mods/plog/module.php delete mode 100644 mods/plog/module.sql delete mode 100644 mods/plog/module.xml delete mode 100644 mods/plog/module_install.php delete mode 100644 mods/plog/plog_logo.gif delete mode 100644 mods/plog/side_menu.inc.php delete mode 100644 mods/plog/sync_plog.php delete mode 100644 mods/plog/sync_plog11.php delete mode 100644 mods/pnATutor/ATutor/index_pn.php delete mode 100644 mods/pnATutor/pnadmin.php delete mode 100644 mods/pnATutor/pnblocks/courses.php delete mode 100644 mods/pnATutor/pndocs/credits.txt delete mode 100644 mods/pnATutor/pndocs/license.txt delete mode 100644 mods/pnATutor/pndocs/readme.txt delete mode 100644 mods/pnATutor/pnincludes/overlib.js delete mode 100644 mods/pnATutor/pnincludes/overlib_mini.js delete mode 100644 mods/pnATutor/pnincludes/overlib_power.gif delete mode 100644 mods/pnATutor/pninit.php delete mode 100644 mods/pnATutor/pnlang/eng/admin.php delete mode 100644 mods/pnATutor/pnlang/eng/courses.php delete mode 100644 mods/pnATutor/pntemplates/pnATutor_block_courses.htm delete mode 100644 mods/pnATutor/pntemplates/pnATutor_block_courses_modify.htm delete mode 100644 mods/pnATutor/pnuser.php delete mode 100644 mods/pnATutor/pnversion.php delete mode 100644 mods/scorm_packages/delete.php delete mode 100644 mods/scorm_packages/import.php delete mode 100644 mods/scorm_packages/index.php delete mode 100644 mods/scorm_packages/lib.inc.php delete mode 100644 mods/scorm_packages/module.php delete mode 100644 mods/scorm_packages/module.sql delete mode 100644 mods/scorm_packages/module.xml delete mode 100644 mods/scorm_packages/module_install.php delete mode 100644 mods/scorm_packages/module_uninstall.php delete mode 100644 mods/scorm_packages/packages/index.php delete mode 100644 mods/scorm_packages/packages/preferences.php delete mode 100644 mods/scorm_packages/possible_module_backup.php delete mode 100644 mods/scorm_packages/scorm-1.2/images/active.png delete mode 100644 mods/scorm_packages/scorm-1.2/images/asset.png delete mode 100644 mods/scorm_packages/scorm-1.2/images/browsed.png delete mode 100644 mods/scorm_packages/scorm-1.2/images/busy.png delete mode 100644 mods/scorm_packages/scorm-1.2/images/completed.png delete mode 100644 mods/scorm_packages/scorm-1.2/images/failed.png delete mode 100644 mods/scorm_packages/scorm-1.2/images/incomplete.png delete mode 100644 mods/scorm_packages/scorm-1.2/images/not-attempted.png delete mode 100644 mods/scorm_packages/scorm-1.2/images/passed.png delete mode 100644 mods/scorm_packages/scorm-1.2/import.php delete mode 100644 mods/scorm_packages/scorm-1.2/java/ATutorApiAdapterApplet.jar delete mode 100644 mods/scorm_packages/scorm-1.2/java/ATutorApiAdapterApplet.java delete mode 100644 mods/scorm_packages/scorm-1.2/java/PfPLMS-API-adapter-core.jar delete mode 100644 mods/scorm_packages/scorm-1.2/java/gnu.jar delete mode 100644 mods/scorm_packages/scorm-1.2/learner_view.php delete mode 100644 mods/scorm_packages/scorm-1.2/lib.inc.php delete mode 100644 mods/scorm_packages/scorm-1.2/read.php delete mode 100644 mods/scorm_packages/scorm-1.2/settings.php delete mode 100644 mods/scorm_packages/scorm-1.2/view.inc.php delete mode 100644 mods/scorm_packages/scorm-1.2/view.php delete mode 100644 mods/scorm_packages/scorm-1.2/write.php delete mode 100644 mods/scorm_packages/settings.php delete mode 100644 mods/social/README delete mode 100644 mods/social/activities.php delete mode 100644 mods/social/admin/delete_applications.php delete mode 100644 mods/social/applications.php delete mode 100644 mods/social/basic_profile.php delete mode 100644 mods/social/connections.php delete mode 100644 mods/social/edit_profile.php delete mode 100644 mods/social/groups/create.php delete mode 100644 mods/social/groups/delete.php delete mode 100644 mods/social/groups/delete_message.php delete mode 100644 mods/social/groups/edit.php delete mode 100644 mods/social/groups/get_sgroup_logo.php delete mode 100644 mods/social/groups/index.php delete mode 100644 mods/social/groups/invitation_handler.php delete mode 100644 mods/social/groups/invite.php delete mode 100644 mods/social/groups/join.php delete mode 100644 mods/social/groups/list.php delete mode 100644 mods/social/groups/search.php delete mode 100644 mods/social/groups/view.php delete mode 100644 mods/social/html/activities.tmpl.php delete mode 100644 mods/social/html/admin/delete_applications.tmpl.php delete mode 100644 mods/social/html/application_settings.tmpl.php delete mode 100644 mods/social/html/applications.tmpl.php delete mode 100644 mods/social/html/basic_profile.tmpl.php delete mode 100644 mods/social/html/connections.tmpl.php delete mode 100644 mods/social/html/edit_profile.tmpl.php delete mode 100644 mods/social/html/edit_profile/edit_additional.tmpl.php delete mode 100644 mods/social/html/edit_profile/edit_education.tmpl.php delete mode 100644 mods/social/html/edit_profile/edit_position.tmpl.php delete mode 100644 mods/social/html/edit_profile/edit_websites.tmpl.php delete mode 100644 mods/social/html/friend_list.tmpl.php delete mode 100644 mods/social/html/index_public.tmpl.php delete mode 100644 mods/social/html/individual_application.tmpl.php delete mode 100644 mods/social/html/notifications.tmpl.php delete mode 100644 mods/social/html/profile_picture.html.php delete mode 100644 mods/social/html/pubmenu.tmpl.php delete mode 100644 mods/social/html/settings/account_settings.tmpl.php delete mode 100644 mods/social/html/settings/application_settings.tmpl.php delete mode 100644 mods/social/html/settings/privacy_settings.tmpl.php delete mode 100644 mods/social/html/settings/settings_menu.tmpl.php delete mode 100644 mods/social/html/sgroup_create.tmpl.php delete mode 100644 mods/social/html/sgroup_edit.tmpl.php delete mode 100644 mods/social/html/sgroup_invite.tmpl.php delete mode 100644 mods/social/html/sgroup_list.tmpl.php delete mode 100644 mods/social/html/sgroup_search.tmpl.php delete mode 100644 mods/social/html/sgroup_view.tmpl.php delete mode 100644 mods/social/html/sgroups.tmpl.php delete mode 100644 mods/social/html/sprofile.tmpl.php delete mode 100644 mods/social/html/tiny_applications.tmpl.php delete mode 100644 mods/social/html/tiny_sgroups.tmpl.php delete mode 100644 mods/social/images/b_drop.png delete mode 100644 mods/social/images/check_icon.gif delete mode 100644 mods/social/images/check_icon.jpg delete mode 100644 mods/social/images/check_icon.png delete mode 100644 mods/social/images/edit_profile.gif delete mode 100644 mods/social/images/icon-settings.png delete mode 100644 mods/social/images/nophoto.gif delete mode 100644 mods/social/images/placelogo.gif delete mode 100644 mods/social/images/placelogo.png delete mode 100644 mods/social/images/plus_icon.gif delete mode 100644 mods/social/images/plus_icon.jpg delete mode 100644 mods/social/images/social.jpg delete mode 100644 mods/social/index.php delete mode 100644 mods/social/index_admin.php delete mode 100644 mods/social/index_instructor.php delete mode 100644 mods/social/index_mystart.php delete mode 100644 mods/social/index_public.php delete mode 100644 mods/social/lib/BasicBlobCrypter.php delete mode 100644 mods/social/lib/BasicSecurityToken.php delete mode 100644 mods/social/lib/BlobCrypter.php delete mode 100644 mods/social/lib/Crypto.php delete mode 100644 mods/social/lib/SecurityToken.php delete mode 100644 mods/social/lib/Shindig/ATutorActivityService.php delete mode 100644 mods/social/lib/Shindig/ATutorAppDataService.php delete mode 100644 mods/social/lib/Shindig/ATutorDbFetcher.php delete mode 100644 mods/social/lib/Shindig/ATutorMessagesService.php delete mode 100644 mods/social/lib/Shindig/ATutorPersonService.php delete mode 100644 mods/social/lib/Shindig/ATutorService.php delete mode 100644 mods/social/lib/Shindig/README delete mode 100644 mods/social/lib/classes/Activity.class.php delete mode 100644 mods/social/lib/classes/Application.class.php delete mode 100644 mods/social/lib/classes/Applications.class.php delete mode 100644 mods/social/lib/classes/Member.class.php delete mode 100644 mods/social/lib/classes/PrivacyControl/PrivacyController.class.php delete mode 100644 mods/social/lib/classes/PrivacyControl/PrivacyObject.class.php delete mode 100644 mods/social/lib/classes/PrivacyControl/SetPrivacyControl.php delete mode 100644 mods/social/lib/classes/SocialGroups/SocialGroup.class.php delete mode 100644 mods/social/lib/classes/SocialGroups/SocialGroups.class.php delete mode 100644 mods/social/lib/constants.inc.php delete mode 100644 mods/social/lib/friends.inc.php delete mode 100644 mods/social/lib/js/container.js delete mode 100644 mods/social/lib/js/jquery-1.3.2.js delete mode 100644 mods/social/lib/js/jquery.all.js delete mode 100644 mods/social/lib/js/livesearch.js delete mode 100644 mods/social/lib/js/myContainer.bak delete mode 100644 mods/social/lib/js/myContainer.js delete mode 100644 mods/social/lib/js/myContainer_shindig.js delete mode 100644 mods/social/lib/js/myContainer_shindig2.js delete mode 100644 mods/social/lib/profile_menu.inc.php delete mode 100644 mods/social/module.css delete mode 100644 mods/social/module.php delete mode 100644 mods/social/module.sql delete mode 100644 mods/social/module.xml delete mode 100644 mods/social/module_backup.php delete mode 100644 mods/social/module_delete.php delete mode 100644 mods/social/module_install.php delete mode 100644 mods/social/module_uninstall.php delete mode 100644 mods/social/privacy_settings.php delete mode 100644 mods/social/profile_picture.php delete mode 100644 mods/social/set_prefs.php delete mode 100644 mods/social/settings.php delete mode 100644 mods/social/side_menu.inc.php delete mode 100644 mods/social/sprofile.php delete mode 100644 mods/terms_and_conditions/module.php delete mode 100644 mods/terms_and_conditions/module.sql delete mode 100644 mods/terms_and_conditions/module.xml delete mode 100644 mods/terms_and_conditions/module_install.php delete mode 100644 mods/terms_and_conditions/module_uninstall.php delete mode 100644 mods/terms_and_conditions/tac_edit.php delete mode 100644 mods/terms_and_conditions/terms_and_conditions.php delete mode 100644 mods/terms_and_conditions/terms_and_conditions.tmpl.php delete mode 100644 mods/tle/assembler.php delete mode 100644 mods/tle/home-tle_search.gif delete mode 100644 mods/tle/import.php delete mode 100644 mods/tle/index.php delete mode 100644 mods/tle/index_admin.php delete mode 100644 mods/tle/index_student.php delete mode 100644 mods/tle/module.php delete mode 100644 mods/tle/module.sql delete mode 100644 mods/tle/module.xml delete mode 100644 mods/tle/module_install.php delete mode 100644 mods/tle/module_uninstall.php delete mode 100644 mods/tle/readme_tle.txt delete mode 100644 mods/twitter/Twitter.php delete mode 100755 mods/twitter/index.php delete mode 100755 mods/twitter/module.php delete mode 100644 mods/twitter/module.sql delete mode 100755 mods/twitter/module.xml delete mode 100644 mods/twitter/module_uninstall.php delete mode 100644 mods/twitter/twitter.png delete mode 100644 mods/userplane/README delete mode 100644 mods/userplane/index.php delete mode 100644 mods/userplane/index_admin.php delete mode 100644 mods/userplane/module.css delete mode 100644 mods/userplane/module.php delete mode 100644 mods/userplane/module.sql delete mode 100644 mods/userplane/module.xml delete mode 100644 mods/userplane/module_install.php delete mode 100644 mods/userplane/module_uninstall.php delete mode 100644 mods/userplane/side_menu.inc.php delete mode 100644 mods/userplane/userplane.jpg delete mode 100644 mods/utf8conv/index.php delete mode 100644 mods/utf8conv/index_admin.php delete mode 100644 mods/utf8conv/index_instructor.php delete mode 100644 mods/utf8conv/module.php delete mode 100644 mods/utf8conv/module.sql delete mode 100644 mods/utf8conv/module.xml delete mode 100644 mods/utf8conv/module_install.php delete mode 100644 mods/utf8conv/module_uninstall.php delete mode 100644 mods/utf8conv/readDir.php delete mode 100644 mods/utf8conv/utf8conv.php delete mode 100644 mods/wiki/LICENSE delete mode 100644 mods/wiki/README_ATUTOR_MODULE delete mode 100644 mods/wiki/config.php delete mode 100644 mods/wiki/doc/Acronyms delete mode 100644 mods/wiki/doc/AdminTasksSql delete mode 100644 mods/wiki/doc/CHANGES delete mode 100644 mods/wiki/doc/CREDITS delete mode 100644 mods/wiki/doc/ConfigSettings delete mode 100644 mods/wiki/doc/FAQ delete mode 100644 mods/wiki/doc/INSTALL delete mode 100644 mods/wiki/doc/INTERNALS delete mode 100644 mods/wiki/doc/LinkSpammers delete mode 100644 mods/wiki/doc/MagicFields delete mode 100644 mods/wiki/doc/NicerUrls delete mode 100644 mods/wiki/doc/NoticeMessages delete mode 100644 mods/wiki/doc/PluginMetaFiles delete mode 100644 mods/wiki/doc/ProtectedMode delete mode 100644 mods/wiki/doc/README delete mode 100644 mods/wiki/doc/README.de delete mode 100644 mods/wiki/doc/README.fragments delete mode 100644 mods/wiki/doc/README.plugins delete mode 100644 mods/wiki/doc/ReadOnlyWiki delete mode 100644 mods/wiki/doc/SetupTool delete mode 100644 mods/wiki/doc/UPGRADE delete mode 100644 mods/wiki/doc/WikiXmlRpc delete mode 100644 mods/wiki/ewiki.php delete mode 100644 mods/wiki/fragments/404finder.php delete mode 100644 mods/wiki/fragments/binary.php delete mode 100644 mods/wiki/fragments/blocks/README delete mode 100644 mods/wiki/fragments/blocks/calendar.php delete mode 100644 mods/wiki/fragments/blocks/editsidetext.php delete mode 100644 mods/wiki/fragments/blocks/intpages.php delete mode 100644 mods/wiki/fragments/blocks/mainmenu.php delete mode 100644 mods/wiki/fragments/blocks/news.php delete mode 100644 mods/wiki/fragments/blocks/printhint.php delete mode 100644 mods/wiki/fragments/blocks/search.php delete mode 100644 mods/wiki/fragments/css.php delete mode 100644 mods/wiki/fragments/css/PlugInstall.css delete mode 100644 mods/wiki/fragments/css/README delete mode 100644 mods/wiki/fragments/css/UserRegistry.css delete mode 100644 mods/wiki/fragments/css/WikiNavBarStyle.css delete mode 100644 mods/wiki/fragments/css/WikiSetupWizard.css delete mode 100644 mods/wiki/fragments/css/calendar.css delete mode 100644 mods/wiki/fragments/css/core.css delete mode 100644 mods/wiki/fragments/css/forum.css delete mode 100644 mods/wiki/fragments/force_lang_de.php delete mode 100644 mods/wiki/fragments/funcs/README delete mode 100644 mods/wiki/fragments/funcs/auth.php delete mode 100644 mods/wiki/fragments/funcs/save_newest_pages delete mode 100644 mods/wiki/fragments/funcs/wiki_format.inc delete mode 100644 mods/wiki/fragments/head/core.php delete mode 100644 mods/wiki/fragments/head/meta.php delete mode 100644 mods/wiki/fragments/htaccess delete mode 100644 mods/wiki/fragments/ini.php delete mode 100644 mods/wiki/fragments/js/pngbehaviour.htc delete mode 100644 mods/wiki/fragments/parent-cms/nuke_mod_wiki_index delete mode 100644 mods/wiki/fragments/patches/README delete mode 100644 mods/wiki/fragments/patches/auth_ldap.patch delete mode 100644 mods/wiki/fragments/patches/binarystoredirect delete mode 100644 mods/wiki/fragments/patches/clickableimages delete mode 100644 mods/wiki/fragments/patches/nowikiwords delete mode 100755 mods/wiki/fragments/patches/old_php_compat.pl delete mode 100644 mods/wiki/fragments/patches/uploadedfilenames delete mode 100644 mods/wiki/fragments/rss.php delete mode 100644 mods/wiki/fragments/site_prot.php delete mode 100644 mods/wiki/fragments/strike_register_globals.php delete mode 100644 mods/wiki/fragments/strip_wonderful_slashes.php delete mode 100644 mods/wiki/fragments/zero_pagerank.php delete mode 100644 mods/wiki/index.php delete mode 100644 mods/wiki/index_admin.php delete mode 100644 mods/wiki/index_instructor.php delete mode 100644 mods/wiki/init-pages/ATutorWiki delete mode 100644 mods/wiki/init-pages/CamelCase delete mode 100644 mods/wiki/init-pages/CreatePages delete mode 100644 mods/wiki/init-pages/EditThisPage delete mode 100644 mods/wiki/init-pages/ErfurtWiki delete mode 100644 mods/wiki/init-pages/ExtendedWikiMarkup delete mode 100644 mods/wiki/init-pages/FormattingOptions delete mode 100644 mods/wiki/init-pages/FrontPage delete mode 100644 mods/wiki/init-pages/HyperLink delete mode 100644 mods/wiki/init-pages/HyperTextMarkupLanguage delete mode 100644 mods/wiki/init-pages/ImageUploading delete mode 100644 mods/wiki/init-pages/WikiHowto delete mode 100644 mods/wiki/init-pages/WikiMarkup delete mode 100644 mods/wiki/init-pages/WikiWikiWeb delete mode 100644 mods/wiki/init-pages/WikiWord delete mode 100644 mods/wiki/init-pages/WorldWideWeb delete mode 100644 mods/wiki/module.css delete mode 100644 mods/wiki/module.php delete mode 100644 mods/wiki/module.sql delete mode 100644 mods/wiki/module.xml delete mode 100644 mods/wiki/module_delete.php delete mode 100644 mods/wiki/module_install.php delete mode 100644 mods/wiki/module_uninstall.php delete mode 100644 mods/wiki/page.php delete mode 100644 mods/wiki/plugins/.htaccess delete mode 100644 mods/wiki/plugins/action/calendarlist.meta delete mode 100644 mods/wiki/plugins/action/calendarlist.php delete mode 100644 mods/wiki/plugins/action/diff.meta delete mode 100644 mods/wiki/plugins/action/diff.php delete mode 100644 mods/wiki/plugins/action/diff_gnu.meta delete mode 100644 mods/wiki/plugins/action/diff_gnu.php delete mode 100644 mods/wiki/plugins/action/diff_gnu_safemode.meta delete mode 100644 mods/wiki/plugins/action/diff_gnu_safemode.php delete mode 100644 mods/wiki/plugins/action/email_page.meta delete mode 100644 mods/wiki/plugins/action/email_page.php delete mode 100644 mods/wiki/plugins/action/extract.meta delete mode 100644 mods/wiki/plugins/action/extract.php delete mode 100644 mods/wiki/plugins/action/htm.meta delete mode 100644 mods/wiki/plugins/action/htm.php delete mode 100644 mods/wiki/plugins/action/info_qdiff.meta delete mode 100644 mods/wiki/plugins/action/info_qdiff.php delete mode 100644 mods/wiki/plugins/action/like_pages.meta delete mode 100644 mods/wiki/plugins/action/like_pages.php delete mode 100644 mods/wiki/plugins/action/manpage.meta delete mode 100644 mods/wiki/plugins/action/manpage.php delete mode 100644 mods/wiki/plugins/action/raw.meta delete mode 100644 mods/wiki/plugins/action/raw.php delete mode 100644 mods/wiki/plugins/action/relatedchanges.meta delete mode 100644 mods/wiki/plugins/action/relatedchanges.php delete mode 100644 mods/wiki/plugins/action/rss.meta delete mode 100644 mods/wiki/plugins/action/rss.php delete mode 100644 mods/wiki/plugins/action/translation.meta delete mode 100644 mods/wiki/plugins/action/translation.php delete mode 100644 mods/wiki/plugins/action/verdiff.meta delete mode 100644 mods/wiki/plugins/action/verdiff.php delete mode 100644 mods/wiki/plugins/admin/admintrigger.php delete mode 100644 mods/wiki/plugins/admin/control.meta delete mode 100644 mods/wiki/plugins/admin/control.php delete mode 100644 mods/wiki/plugins/admin/page_searchandreplace.meta delete mode 100644 mods/wiki/plugins/admin/page_searchandreplace.php delete mode 100644 mods/wiki/plugins/admin/page_searchcache.meta delete mode 100644 mods/wiki/plugins/admin/page_searchcache.php delete mode 100644 mods/wiki/plugins/appearance/fancy_list_dict.meta delete mode 100644 mods/wiki/plugins/appearance/fancy_list_dict.php delete mode 100644 mods/wiki/plugins/appearance/listpages_br.meta delete mode 100644 mods/wiki/plugins/appearance/listpages_br.php delete mode 100644 mods/wiki/plugins/appearance/listpages_tbl.meta delete mode 100644 mods/wiki/plugins/appearance/listpages_tbl.php delete mode 100644 mods/wiki/plugins/appearance/listpages_ul.meta delete mode 100644 mods/wiki/plugins/appearance/listpages_ul.php delete mode 100644 mods/wiki/plugins/appearance/title_calendar.meta delete mode 100644 mods/wiki/plugins/appearance/title_calendar.php delete mode 100644 mods/wiki/plugins/auth-liveuser/LGPL.txt delete mode 100644 mods/wiki/plugins/auth-liveuser/PACKAGE.txt delete mode 100644 mods/wiki/plugins/auth-liveuser/README delete mode 100644 mods/wiki/plugins/auth-liveuser/auth_liveuser.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/auth_liveuser.php delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_addusers_gui.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_addusers_gui.php delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_aux.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_aux.php delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_conf.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_conf.php delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_perms_gui.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_perms_gui.php delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_prefs_gui.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_prefs_gui.php delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_rights_gui.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_rights_gui.php delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_setup.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_setup.php delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_setup_prefs.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_setup_prefs.php delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_users_gui.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/liveuser_users_gui.php delete mode 100755 mods/wiki/plugins/auth-liveuser/passdict-wget.sh delete mode 100644 mods/wiki/plugins/auth-liveuser/perm_liveuser.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/perm_liveuser.php delete mode 100644 mods/wiki/plugins/auth-liveuser/pref_liveuser.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/pref_liveuser.php delete mode 100644 mods/wiki/plugins/auth-liveuser/session_ip_verifier.meta delete mode 100644 mods/wiki/plugins/auth-liveuser/session_ip_verifier.php delete mode 100644 mods/wiki/plugins/auth/auth_method_form.meta delete mode 100644 mods/wiki/plugins/auth/auth_method_form.php delete mode 100644 mods/wiki/plugins/auth/auth_method_http.meta delete mode 100644 mods/wiki/plugins/auth/auth_method_http.php delete mode 100644 mods/wiki/plugins/auth/auth_perm_old.meta delete mode 100644 mods/wiki/plugins/auth/auth_perm_old.php delete mode 100644 mods/wiki/plugins/auth/auth_perm_ring.meta delete mode 100644 mods/wiki/plugins/auth/auth_perm_ring.php delete mode 100644 mods/wiki/plugins/auth/auth_perm_unix.meta delete mode 100644 mods/wiki/plugins/auth/auth_perm_unix.php delete mode 100644 mods/wiki/plugins/auth/auth_phplib.meta delete mode 100644 mods/wiki/plugins/auth/auth_phplib.php delete mode 100644 mods/wiki/plugins/auth/password_locks.meta delete mode 100644 mods/wiki/plugins/auth/password_locks.php delete mode 100644 mods/wiki/plugins/auth/userdb_anonymous.meta delete mode 100644 mods/wiki/plugins/auth/userdb_anonymous.php delete mode 100644 mods/wiki/plugins/auth/userdb_array.meta delete mode 100644 mods/wiki/plugins/auth/userdb_array.php delete mode 100644 mods/wiki/plugins/auth/userdb_sql.meta delete mode 100644 mods/wiki/plugins/auth/userdb_sql.php delete mode 100644 mods/wiki/plugins/auth/userdb_systempasswd.meta delete mode 100644 mods/wiki/plugins/auth/userdb_systempasswd.php delete mode 100644 mods/wiki/plugins/auth/userdb_userregistry.meta delete mode 100644 mods/wiki/plugins/auth/userdb_userregistry.php delete mode 100644 mods/wiki/plugins/auth/userdb_xprofile.meta delete mode 100644 mods/wiki/plugins/auth/userdb_xprofile.php delete mode 100644 mods/wiki/plugins/auth/users_ldap.meta delete mode 100644 mods/wiki/plugins/auth/users_ldap.php delete mode 100644 mods/wiki/plugins/auth/you.meta delete mode 100644 mods/wiki/plugins/auth/you.php delete mode 100644 mods/wiki/plugins/aview/aedit_authorname.meta delete mode 100644 mods/wiki/plugins/aview/aedit_authorname.php delete mode 100644 mods/wiki/plugins/aview/aedit_deletebutton.js.meta delete mode 100644 mods/wiki/plugins/aview/aedit_deletebutton.js.php delete mode 100644 mods/wiki/plugins/aview/aedit_log.meta delete mode 100644 mods/wiki/plugins/aview/aedit_log.php delete mode 100644 mods/wiki/plugins/aview/aedit_pageimage.meta delete mode 100644 mods/wiki/plugins/aview/aedit_pageimage.php delete mode 100644 mods/wiki/plugins/aview/aedit_templates.meta delete mode 100644 mods/wiki/plugins/aview/aedit_templates.php delete mode 100644 mods/wiki/plugins/aview/backlinks.meta delete mode 100644 mods/wiki/plugins/aview/backlinks.php delete mode 100644 mods/wiki/plugins/aview/blog.meta delete mode 100644 mods/wiki/plugins/aview/blog.php delete mode 100644 mods/wiki/plugins/aview/control2.meta delete mode 100644 mods/wiki/plugins/aview/control2.php delete mode 100644 mods/wiki/plugins/aview/downloadlist.meta delete mode 100644 mods/wiki/plugins/aview/downloadlist.php delete mode 100644 mods/wiki/plugins/aview/fpage_copyright.meta delete mode 100644 mods/wiki/plugins/aview/fpage_copyright.php delete mode 100644 mods/wiki/plugins/aview/fpage_logo.meta delete mode 100644 mods/wiki/plugins/aview/fpage_logo.php delete mode 100644 mods/wiki/plugins/aview/imgappend.meta delete mode 100644 mods/wiki/plugins/aview/imgappend.php delete mode 100644 mods/wiki/plugins/aview/linktree.meta delete mode 100644 mods/wiki/plugins/aview/linktree.php delete mode 100644 mods/wiki/plugins/aview/pagetrail.meta delete mode 100644 mods/wiki/plugins/aview/pagetrail.php delete mode 100644 mods/wiki/plugins/aview/piclogocntrl.meta delete mode 100644 mods/wiki/plugins/aview/piclogocntrl.php delete mode 100644 mods/wiki/plugins/aview/posts.meta delete mode 100644 mods/wiki/plugins/aview/posts.php delete mode 100644 mods/wiki/plugins/aview/subpages.meta delete mode 100644 mods/wiki/plugins/aview/subpages.php delete mode 100644 mods/wiki/plugins/aview/threads.meta delete mode 100644 mods/wiki/plugins/aview/threads.php delete mode 100644 mods/wiki/plugins/aview/toc.meta delete mode 100644 mods/wiki/plugins/aview/toc.php delete mode 100644 mods/wiki/plugins/core.meta delete mode 100644 mods/wiki/plugins/db/any.meta delete mode 100644 mods/wiki/plugins/db/any.php delete mode 100644 mods/wiki/plugins/db/binary_store.meta delete mode 100644 mods/wiki/plugins/db/binary_store.php delete mode 100644 mods/wiki/plugins/db/dba.meta delete mode 100644 mods/wiki/plugins/db/dba.php delete mode 100644 mods/wiki/plugins/db/dzf2.meta delete mode 100644 mods/wiki/plugins/db/dzf2.php delete mode 100644 mods/wiki/plugins/db/ext_multi.meta delete mode 100644 mods/wiki/plugins/db/ext_multi.php delete mode 100644 mods/wiki/plugins/db/ext_subwiki.meta delete mode 100644 mods/wiki/plugins/db/ext_subwiki.php delete mode 100644 mods/wiki/plugins/db/fast_files.meta delete mode 100644 mods/wiki/plugins/db/fast_files.php delete mode 100644 mods/wiki/plugins/db/flat_files.meta delete mode 100644 mods/wiki/plugins/db/flat_files.php delete mode 100644 mods/wiki/plugins/db/mysql.meta delete mode 100644 mods/wiki/plugins/db/oldapi.meta delete mode 100644 mods/wiki/plugins/db/oldapi.php delete mode 100644 mods/wiki/plugins/db/phpwiki13.meta delete mode 100644 mods/wiki/plugins/db/phpwiki13.php delete mode 100644 mods/wiki/plugins/db/read_pmwiki1.meta delete mode 100644 mods/wiki/plugins/db/read_pmwiki1.php delete mode 100644 mods/wiki/plugins/db/rpc.meta delete mode 100644 mods/wiki/plugins/db/rpc.php delete mode 100644 mods/wiki/plugins/db/zip.meta delete mode 100644 mods/wiki/plugins/db/zip.php delete mode 100644 mods/wiki/plugins/debug/verbose.meta delete mode 100644 mods/wiki/plugins/debug/warn_utf8.meta delete mode 100644 mods/wiki/plugins/debug/warn_utf8.php delete mode 100644 mods/wiki/plugins/debug/xerror.meta delete mode 100644 mods/wiki/plugins/debug/xerror.php delete mode 100644 mods/wiki/plugins/edit/authorname.meta delete mode 100644 mods/wiki/plugins/edit/authorname.php delete mode 100644 mods/wiki/plugins/edit/deletebutton.js.meta delete mode 100644 mods/wiki/plugins/edit/deletebutton.js.php delete mode 100644 mods/wiki/plugins/edit/flags.meta delete mode 100644 mods/wiki/plugins/edit/flags.php delete mode 100644 mods/wiki/plugins/edit/helptext.meta delete mode 100644 mods/wiki/plugins/edit/helptext.php delete mode 100644 mods/wiki/plugins/edit/limitlinks.meta delete mode 100644 mods/wiki/plugins/edit/limitlinks.php delete mode 100644 mods/wiki/plugins/edit/lock.meta delete mode 100644 mods/wiki/plugins/edit/lock.php delete mode 100644 mods/wiki/plugins/edit/log.meta delete mode 100644 mods/wiki/plugins/edit/log.php delete mode 100644 mods/wiki/plugins/edit/minor.meta delete mode 100644 mods/wiki/plugins/edit/minor.php delete mode 100644 mods/wiki/plugins/edit/msg.meta delete mode 100644 mods/wiki/plugins/edit/msg.php delete mode 100644 mods/wiki/plugins/edit/pageimage.meta delete mode 100644 mods/wiki/plugins/edit/pageimage.php delete mode 100644 mods/wiki/plugins/edit/plog.meta delete mode 100644 mods/wiki/plugins/edit/requirespassword.meta delete mode 100644 mods/wiki/plugins/edit/requirespassword.php delete mode 100644 mods/wiki/plugins/edit/spam_block.meta delete mode 100644 mods/wiki/plugins/edit/spam_block.php delete mode 100644 mods/wiki/plugins/edit/spam_deface.meta delete mode 100644 mods/wiki/plugins/edit/spam_deface.php delete mode 100644 mods/wiki/plugins/edit/templates.meta delete mode 100644 mods/wiki/plugins/edit/templates.php delete mode 100644 mods/wiki/plugins/edit/upload.meta delete mode 100644 mods/wiki/plugins/edit/warn.meta delete mode 100644 mods/wiki/plugins/edit/warn.php delete mode 100644 mods/wiki/plugins/email_protect.meta delete mode 100644 mods/wiki/plugins/email_protect.php delete mode 100644 mods/wiki/plugins/feature/anacron.meta delete mode 100644 mods/wiki/plugins/feature/anacron.php delete mode 100644 mods/wiki/plugins/feature/announcements.meta delete mode 100644 mods/wiki/plugins/feature/announcements.php delete mode 100644 mods/wiki/plugins/feature/appendcomments.meta delete mode 100644 mods/wiki/plugins/feature/appendcomments.php delete mode 100644 mods/wiki/plugins/feature/appendonly.meta delete mode 100644 mods/wiki/plugins/feature/appendonly.php delete mode 100644 mods/wiki/plugins/feature/appendwrite.meta delete mode 100644 mods/wiki/plugins/feature/appendwrite.php delete mode 100644 mods/wiki/plugins/feature/fset_actionurls.meta delete mode 100644 mods/wiki/plugins/feature/fset_actionurls.php delete mode 100644 mods/wiki/plugins/feature/imgfile_naming.meta delete mode 100644 mods/wiki/plugins/feature/imgfile_naming.php delete mode 100644 mods/wiki/plugins/feature/imgresize_gd.meta delete mode 100644 mods/wiki/plugins/feature/imgresize_gd.php delete mode 100644 mods/wiki/plugins/feature/imgresize_gd2.meta delete mode 100644 mods/wiki/plugins/feature/imgresize_gd2.php delete mode 100644 mods/wiki/plugins/feature/imgresize_magick.meta delete mode 100644 mods/wiki/plugins/feature/imgresize_magick.php delete mode 100644 mods/wiki/plugins/feature/pingback.meta delete mode 100644 mods/wiki/plugins/feature/pingback.php delete mode 100644 mods/wiki/plugins/feature/refererlog.meta delete mode 100644 mods/wiki/plugins/feature/refererlog.php delete mode 100644 mods/wiki/plugins/feature/spellcheck.meta delete mode 100644 mods/wiki/plugins/feature/spellcheck.php delete mode 100644 mods/wiki/plugins/feature/spellcheck2.meta delete mode 100644 mods/wiki/plugins/feature/spellcheck2.php delete mode 100644 mods/wiki/plugins/feature/xpi.meta delete mode 100644 mods/wiki/plugins/feature/xpi.php delete mode 100644 mods/wiki/plugins/feature/xpi0.meta delete mode 100644 mods/wiki/plugins/feature/xpi0.php delete mode 100644 mods/wiki/plugins/filter/f_fixhtml.meta delete mode 100644 mods/wiki/plugins/filter/f_fixhtml.php delete mode 100644 mods/wiki/plugins/filter/f_msiepng.meta delete mode 100644 mods/wiki/plugins/filter/f_msiepng.php delete mode 100644 mods/wiki/plugins/filter/f_tidy.meta delete mode 100644 mods/wiki/plugins/filter/fun_chef.meta delete mode 100644 mods/wiki/plugins/filter/fun_chef.php delete mode 100644 mods/wiki/plugins/filter/fun_screamomatic.meta delete mode 100644 mods/wiki/plugins/filter/fun_screamomatic.php delete mode 100644 mods/wiki/plugins/filter/fun_upsidedown.meta delete mode 100644 mods/wiki/plugins/filter/fun_upsidedown.php delete mode 100644 mods/wiki/plugins/filter/fun_wella.meta delete mode 100644 mods/wiki/plugins/filter/fun_wella.php delete mode 100644 mods/wiki/plugins/filter/search_highlight.meta delete mode 100644 mods/wiki/plugins/filter/search_highlight.php delete mode 100644 mods/wiki/plugins/init.php delete mode 100644 mods/wiki/plugins/input_trimming.meta delete mode 100644 mods/wiki/plugins/input_trimming.php delete mode 100644 mods/wiki/plugins/interwiki/editable.meta delete mode 100644 mods/wiki/plugins/interwiki/editable.php delete mode 100644 mods/wiki/plugins/interwiki/intermap.meta delete mode 100644 mods/wiki/plugins/interwiki/intermap.php delete mode 100644 mods/wiki/plugins/interwiki/intermaptxt.meta delete mode 100644 mods/wiki/plugins/interwiki/intermaptxt.php delete mode 100644 mods/wiki/plugins/interwiki/linkdb.meta delete mode 100755 mods/wiki/plugins/interwiki/metadb-wget.sh delete mode 100644 mods/wiki/plugins/interwiki/metadb.meta delete mode 100644 mods/wiki/plugins/interwiki/metadb.php delete mode 100644 mods/wiki/plugins/interwiki/metawiki.meta delete mode 100644 mods/wiki/plugins/interwiki/near.meta delete mode 100644 mods/wiki/plugins/interwiki/near.php delete mode 100644 mods/wiki/plugins/interwiki/neighbor.meta delete mode 100644 mods/wiki/plugins/interwiki/neighbor.php delete mode 100644 mods/wiki/plugins/interwiki/sisterpages.meta delete mode 100644 mods/wiki/plugins/interwiki/sisterpages.php delete mode 100644 mods/wiki/plugins/interwiki/virtualsister.meta delete mode 100644 mods/wiki/plugins/interwiki/virtualsister.php delete mode 100644 mods/wiki/plugins/interwiki/walking.meta delete mode 100644 mods/wiki/plugins/interwiki/walking.php delete mode 100644 mods/wiki/plugins/jump.meta delete mode 100644 mods/wiki/plugins/jump.php delete mode 100644 mods/wiki/plugins/lib/COLLEGE.ttf delete mode 100644 mods/wiki/plugins/lib/cache.meta delete mode 100644 mods/wiki/plugins/lib/cache.php delete mode 100644 mods/wiki/plugins/lib/captcha.meta delete mode 100644 mods/wiki/plugins/lib/captcha.php delete mode 100644 mods/wiki/plugins/lib/fakedba.meta delete mode 100644 mods/wiki/plugins/lib/fakedba.php delete mode 100644 mods/wiki/plugins/lib/fakezlib.meta delete mode 100644 mods/wiki/plugins/lib/fakezlib.php delete mode 100644 mods/wiki/plugins/lib/feed.meta delete mode 100644 mods/wiki/plugins/lib/feed.php delete mode 100644 mods/wiki/plugins/lib/feedparse.meta delete mode 100644 mods/wiki/plugins/lib/feedparse.php delete mode 100644 mods/wiki/plugins/lib/fix.meta delete mode 100644 mods/wiki/plugins/lib/fix.php delete mode 100644 mods/wiki/plugins/lib/gzdecode.meta delete mode 100644 mods/wiki/plugins/lib/http.meta delete mode 100644 mods/wiki/plugins/lib/http.php delete mode 100644 mods/wiki/plugins/lib/http_cache.meta delete mode 100644 mods/wiki/plugins/lib/http_cache.php delete mode 100644 mods/wiki/plugins/lib/js.meta delete mode 100644 mods/wiki/plugins/lib/libxprofile.meta delete mode 100644 mods/wiki/plugins/lib/libxprofile.php delete mode 100644 mods/wiki/plugins/lib/mime_magic.meta delete mode 100644 mods/wiki/plugins/lib/mime_magic.php delete mode 100644 mods/wiki/plugins/lib/minidav.meta delete mode 100644 mods/wiki/plugins/lib/minidav.php delete mode 100644 mods/wiki/plugins/lib/navbar.meta delete mode 100644 mods/wiki/plugins/lib/navbar.php delete mode 100644 mods/wiki/plugins/lib/opensearch.meta delete mode 100644 mods/wiki/plugins/lib/opensearch.php delete mode 100644 mods/wiki/plugins/lib/page_delegator.meta delete mode 100644 mods/wiki/plugins/lib/page_delegator.php delete mode 100644 mods/wiki/plugins/lib/phprequest.meta delete mode 100644 mods/wiki/plugins/lib/phprequest.php delete mode 100644 mods/wiki/plugins/lib/phprpc.meta delete mode 100644 mods/wiki/plugins/lib/phprpc.php delete mode 100644 mods/wiki/plugins/lib/pluginmetadata.meta delete mode 100644 mods/wiki/plugins/lib/pluginmetadata.php delete mode 100644 mods/wiki/plugins/lib/protmode.meta delete mode 100644 mods/wiki/plugins/lib/protmode.php delete mode 100644 mods/wiki/plugins/lib/save_storevars.meta delete mode 100644 mods/wiki/plugins/lib/save_storevars.php delete mode 100644 mods/wiki/plugins/lib/shutdown.meta delete mode 100644 mods/wiki/plugins/lib/shutdown.php delete mode 100644 mods/wiki/plugins/lib/spamblock_whois.meta delete mode 100644 mods/wiki/plugins/lib/spamblock_whois.php delete mode 100644 mods/wiki/plugins/lib/speed.meta delete mode 100644 mods/wiki/plugins/lib/speed.php delete mode 100644 mods/wiki/plugins/lib/subpagelist.meta delete mode 100644 mods/wiki/plugins/lib/subpagelist.php delete mode 100644 mods/wiki/plugins/lib/sync.meta delete mode 100644 mods/wiki/plugins/lib/sync.php delete mode 100644 mods/wiki/plugins/lib/upgrade.meta delete mode 100644 mods/wiki/plugins/lib/upgrade.php delete mode 100644 mods/wiki/plugins/lib/uservars_pages.meta delete mode 100644 mods/wiki/plugins/lib/uservars_pages.php delete mode 100644 mods/wiki/plugins/lib/webdav.meta delete mode 100644 mods/wiki/plugins/lib/webdav.php delete mode 100644 mods/wiki/plugins/lib/wikiapi.meta delete mode 100644 mods/wiki/plugins/lib/wikiapi.php delete mode 100644 mods/wiki/plugins/lib/wikinews.php delete mode 100644 mods/wiki/plugins/lib/xml.meta delete mode 100644 mods/wiki/plugins/lib/xml.php delete mode 100644 mods/wiki/plugins/lib/xmlrpc.meta delete mode 100644 mods/wiki/plugins/lib/xmlrpc.php delete mode 100644 mods/wiki/plugins/linking/a_nofollow.meta delete mode 100644 mods/wiki/plugins/linking/a_nofollow.php delete mode 100644 mods/wiki/plugins/linking/autolinkext.meta delete mode 100644 mods/wiki/plugins/linking/autolinking.meta delete mode 100644 mods/wiki/plugins/linking/autolinking.php delete mode 100644 mods/wiki/plugins/linking/deadly_hidden.meta delete mode 100644 mods/wiki/plugins/linking/deadly_hidden.php delete mode 100644 mods/wiki/plugins/linking/instanturl_find.meta delete mode 100644 mods/wiki/plugins/linking/instanturl_find.php delete mode 100644 mods/wiki/plugins/linking/instanturls.meta delete mode 100644 mods/wiki/plugins/linking/instanturls.php delete mode 100644 mods/wiki/plugins/linking/link_css.meta delete mode 100644 mods/wiki/plugins/linking/link_css.php delete mode 100644 mods/wiki/plugins/linking/link_icons.meta delete mode 100644 mods/wiki/plugins/linking/link_icons.php delete mode 100644 mods/wiki/plugins/linking/link_target_blank.meta delete mode 100644 mods/wiki/plugins/linking/link_target_blank.php delete mode 100644 mods/wiki/plugins/linking/linkdatabase.meta delete mode 100644 mods/wiki/plugins/linking/linkdatabase.php delete mode 100644 mods/wiki/plugins/linking/linkexcerpts.meta delete mode 100644 mods/wiki/plugins/linking/linkexcerpts.php delete mode 100644 mods/wiki/plugins/linking/new_nofollow.meta delete mode 100644 mods/wiki/plugins/linking/new_nofollow.php delete mode 100644 mods/wiki/plugins/linking/plural.meta delete mode 100644 mods/wiki/plugins/linking/plural.php delete mode 100644 mods/wiki/plugins/linking/selfbacklinks.meta delete mode 100644 mods/wiki/plugins/linking/selfbacklinks.php delete mode 100644 mods/wiki/plugins/linking/selfmetawiki.meta delete mode 100644 mods/wiki/plugins/linking/selfmetawiki.php delete mode 100644 mods/wiki/plugins/linking/selfsearch.meta delete mode 100644 mods/wiki/plugins/linking/selfsearch.php delete mode 100644 mods/wiki/plugins/linking/shortwiki.meta delete mode 100644 mods/wiki/plugins/linking/shortwiki.php delete mode 100644 mods/wiki/plugins/linking/targets.meta delete mode 100644 mods/wiki/plugins/linking/targets.php delete mode 100644 mods/wiki/plugins/linking/tcn.meta delete mode 100644 mods/wiki/plugins/linking/tcn.php delete mode 100644 mods/wiki/plugins/linking/titlefix.meta delete mode 100644 mods/wiki/plugins/linking/titlefix.php delete mode 100644 mods/wiki/plugins/linking/xfn.meta delete mode 100644 mods/wiki/plugins/linking/xfn.php delete mode 100644 mods/wiki/plugins/linking/zero_pagerank.meta delete mode 100644 mods/wiki/plugins/linking/zero_pagerank.php delete mode 100644 mods/wiki/plugins/markup/1emphasis.meta delete mode 100644 mods/wiki/plugins/markup/1emphasis.php delete mode 100644 mods/wiki/plugins/markup/abbr.meta delete mode 100644 mods/wiki/plugins/markup/abbr.php delete mode 100644 mods/wiki/plugins/markup/asciitbl.meta delete mode 100644 mods/wiki/plugins/markup/asciitbl.php delete mode 100644 mods/wiki/plugins/markup/bbcode.meta delete mode 100644 mods/wiki/plugins/markup/bbcode.php delete mode 100644 mods/wiki/plugins/markup/braceabbr.meta delete mode 100644 mods/wiki/plugins/markup/braceabbr.php delete mode 100644 mods/wiki/plugins/markup/complextbl.meta delete mode 100644 mods/wiki/plugins/markup/complextbl.php delete mode 100644 mods/wiki/plugins/markup/css.meta delete mode 100644 mods/wiki/plugins/markup/css.php delete mode 100644 mods/wiki/plugins/markup/css_singleat.meta delete mode 100644 mods/wiki/plugins/markup/css_singleat.php delete mode 100644 mods/wiki/plugins/markup/definitionlinks.meta delete mode 100644 mods/wiki/plugins/markup/definitionlinks.php delete mode 100644 mods/wiki/plugins/markup/fix_source_mangling.meta delete mode 100644 mods/wiki/plugins/markup/fix_source_mangling.php delete mode 100644 mods/wiki/plugins/markup/footnotes.meta delete mode 100644 mods/wiki/plugins/markup/footnotes.php delete mode 100644 mods/wiki/plugins/markup/htmltable.meta delete mode 100644 mods/wiki/plugins/markup/htmltable.php delete mode 100644 mods/wiki/plugins/markup/miki.meta delete mode 100644 mods/wiki/plugins/markup/miki.php delete mode 100644 mods/wiki/plugins/markup/naturallists.meta delete mode 100644 mods/wiki/plugins/markup/naturallists.php delete mode 100644 mods/wiki/plugins/markup/phpwiki.meta delete mode 100644 mods/wiki/plugins/markup/phpwiki.php delete mode 100644 mods/wiki/plugins/markup/rendering_null.meta delete mode 100644 mods/wiki/plugins/markup/rendering_null.php delete mode 100644 mods/wiki/plugins/markup/rescuehtml.meta delete mode 100644 mods/wiki/plugins/markup/rescuehtml.php delete mode 100644 mods/wiki/plugins/markup/sfwiki.meta delete mode 100644 mods/wiki/plugins/markup/sfwiki.php delete mode 100644 mods/wiki/plugins/markup/smilies.meta delete mode 100644 mods/wiki/plugins/markup/smilies.php delete mode 100644 mods/wiki/plugins/markup/table_colspan.meta delete mode 100644 mods/wiki/plugins/markup/table_colspan.php delete mode 100644 mods/wiki/plugins/markup/table_rowspan.meta delete mode 100644 mods/wiki/plugins/markup/table_rowspan.php delete mode 100644 mods/wiki/plugins/markup/tex.meta delete mode 100644 mods/wiki/plugins/markup/tex.php delete mode 100644 mods/wiki/plugins/markup/timestamp.meta delete mode 100644 mods/wiki/plugins/markup/timestamp.php delete mode 100644 mods/wiki/plugins/markup/update_format.meta delete mode 100644 mods/wiki/plugins/markup/update_format.php delete mode 100644 mods/wiki/plugins/markup/usemod.meta delete mode 100644 mods/wiki/plugins/markup/usemod.php delete mode 100644 mods/wiki/plugins/meta.bin delete mode 100644 mods/wiki/plugins/meta/block_chinese.meta delete mode 100644 mods/wiki/plugins/meta/block_chinese.php delete mode 100644 mods/wiki/plugins/meta/builtincategories.meta delete mode 100644 mods/wiki/plugins/meta/builtincategories.php delete mode 100644 mods/wiki/plugins/meta/f_title.meta delete mode 100644 mods/wiki/plugins/meta/f_title.php delete mode 100644 mods/wiki/plugins/meta/meta.meta delete mode 100644 mods/wiki/plugins/meta/meta.php delete mode 100644 mods/wiki/plugins/meta/page_pagecategories.meta delete mode 100644 mods/wiki/plugins/meta/relative_links.meta delete mode 100644 mods/wiki/plugins/meta/search_categories.meta delete mode 100644 mods/wiki/plugins/module/calendar.meta delete mode 100644 mods/wiki/plugins/module/calendar.php delete mode 100644 mods/wiki/plugins/module/collectuserdata.meta delete mode 100644 mods/wiki/plugins/module/collectuserdata.php delete mode 100644 mods/wiki/plugins/module/downloads.meta delete mode 100644 mods/wiki/plugins/module/downloads.php delete mode 100644 mods/wiki/plugins/module/fset_blog.meta delete mode 100644 mods/wiki/plugins/module/fset_blog.php delete mode 100644 mods/wiki/plugins/module/tour.meta delete mode 100644 mods/wiki/plugins/module/tour.php delete mode 100644 mods/wiki/plugins/module/uservars_gui.meta delete mode 100644 mods/wiki/plugins/module/uservars_gui.php delete mode 100644 mods/wiki/plugins/mpi/mpi+cdml.meta delete mode 100644 mods/wiki/plugins/mpi/mpi+cdml.php delete mode 100644 mods/wiki/plugins/mpi/mpi+moin.meta delete mode 100644 mods/wiki/plugins/mpi/mpi+moin.php delete mode 100644 mods/wiki/plugins/mpi/mpi.meta delete mode 100644 mods/wiki/plugins/mpi/mpi.php delete mode 100644 mods/wiki/plugins/mpi/mpi_addcomment.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_addcomment.php delete mode 100644 mods/wiki/plugins/mpi/mpi_addlink.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_addlink.php delete mode 100644 mods/wiki/plugins/mpi/mpi_backlinks.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_backlinks.php delete mode 100644 mods/wiki/plugins/mpi/mpi_backtree.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_backtree.php delete mode 100644 mods/wiki/plugins/mpi/mpi_blog.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_blog.php delete mode 100644 mods/wiki/plugins/mpi/mpi_bugreport.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_bugreport.php delete mode 100644 mods/wiki/plugins/mpi/mpi_bugreportstate.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_bugreportstate.php delete mode 100644 mods/wiki/plugins/mpi/mpi_embed.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_embed.php delete mode 100644 mods/wiki/plugins/mpi/mpi_fallback.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_fallback.php delete mode 100644 mods/wiki/plugins/mpi/mpi_farinclude.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_farinclude.php delete mode 100644 mods/wiki/plugins/mpi/mpi_honeypot.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_honeypot.php delete mode 100644 mods/wiki/plugins/mpi/mpi_inlineframe.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_inlineframe.php delete mode 100644 mods/wiki/plugins/mpi/mpi_insert.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_insert.php delete mode 100644 mods/wiki/plugins/mpi/mpi_localsitemap.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_localsitemap.php delete mode 100644 mods/wiki/plugins/mpi/mpi_multimedia.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_multimedia.php delete mode 100644 mods/wiki/plugins/mpi/mpi_phpwiki.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_phpwiki.php delete mode 100644 mods/wiki/plugins/mpi/mpi_redirectlinks.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_redirectlinks.php delete mode 100644 mods/wiki/plugins/mpi/mpi_registerspam.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_registerspam.php delete mode 100644 mods/wiki/plugins/mpi/mpi_removedlinks.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_removedlinks.php delete mode 100644 mods/wiki/plugins/mpi/mpi_settitle.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_settitle.php delete mode 100644 mods/wiki/plugins/mpi/mpi_sparsetable.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_sparsetable.php delete mode 100644 mods/wiki/plugins/mpi/mpi_survey.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_survey.php delete mode 100644 mods/wiki/plugins/mpi/mpi_syndicate.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_syndicate.php delete mode 100644 mods/wiki/plugins/mpi/mpi_tableeditor.meta delete mode 100644 mods/wiki/plugins/mpi/mpi_tableeditor.php delete mode 100644 mods/wiki/plugins/mpi/mpi_wikiscript.meta delete mode 100644 mods/wiki/plugins/mpi/off/mpi_brainfuck.php delete mode 100644 mods/wiki/plugins/mpi/off/mpi_sqlquery.php delete mode 100644 mods/wiki/plugins/notify.meta delete mode 100644 mods/wiki/plugins/notify.php delete mode 100644 mods/wiki/plugins/old/alias.meta delete mode 100644 mods/wiki/plugins/old/alias.php delete mode 100644 mods/wiki/plugins/old/markup_code.meta delete mode 100644 mods/wiki/plugins/old/markup_code.php delete mode 100644 mods/wiki/plugins/old/markup_html.meta delete mode 100644 mods/wiki/plugins/old/markup_html.php delete mode 100644 mods/wiki/plugins/old/markup_paragraphs.meta delete mode 100644 mods/wiki/plugins/old/markup_paragraphs.php delete mode 100644 mods/wiki/plugins/page/README.meta delete mode 100644 mods/wiki/plugins/page/README.php delete mode 100644 mods/wiki/plugins/page/aboutplugins.meta delete mode 100644 mods/wiki/plugins/page/aboutplugins.php delete mode 100644 mods/wiki/plugins/page/addnewpage.meta delete mode 100644 mods/wiki/plugins/page/addnewpage.php delete mode 100644 mods/wiki/plugins/page/createnewpage.meta delete mode 100644 mods/wiki/plugins/page/createnewpage.php delete mode 100644 mods/wiki/plugins/page/ewikilog.meta delete mode 100644 mods/wiki/plugins/page/ewikilog.php delete mode 100644 mods/wiki/plugins/page/extractall.meta delete mode 100644 mods/wiki/plugins/page/extractall.php delete mode 100644 mods/wiki/plugins/page/fortune.meta delete mode 100644 mods/wiki/plugins/page/fortune.php delete mode 100644 mods/wiki/plugins/page/hitcounter.meta delete mode 100644 mods/wiki/plugins/page/hitcounter.php delete mode 100644 mods/wiki/plugins/page/imagegallery.meta delete mode 100644 mods/wiki/plugins/page/imagegallery.php delete mode 100644 mods/wiki/plugins/page/interwikimap.meta delete mode 100644 mods/wiki/plugins/page/interwikimap.php delete mode 100644 mods/wiki/plugins/page/minidump.meta delete mode 100644 mods/wiki/plugins/page/minidump.php delete mode 100644 mods/wiki/plugins/page/orphanedpages.meta delete mode 100644 mods/wiki/plugins/page/orphanedpages.php delete mode 100644 mods/wiki/plugins/page/pageindex.meta delete mode 100644 mods/wiki/plugins/page/pageindex.php delete mode 100644 mods/wiki/plugins/page/phpinfo.meta delete mode 100644 mods/wiki/plugins/page/phpinfo.php delete mode 100644 mods/wiki/plugins/page/powersearch.meta delete mode 100644 mods/wiki/plugins/page/powersearch.php delete mode 100644 mods/wiki/plugins/page/randompage.meta delete mode 100644 mods/wiki/plugins/page/randompage.php delete mode 100644 mods/wiki/plugins/page/recentchanges.meta delete mode 100644 mods/wiki/plugins/page/recentchanges.php delete mode 100644 mods/wiki/plugins/page/scandisk.meta delete mode 100644 mods/wiki/plugins/page/scandisk.php delete mode 100644 mods/wiki/plugins/page/since_updates.meta delete mode 100644 mods/wiki/plugins/page/since_updates.php delete mode 100644 mods/wiki/plugins/page/sitemap.meta delete mode 100644 mods/wiki/plugins/page/sitemap.php delete mode 100644 mods/wiki/plugins/page/textupload.meta delete mode 100644 mods/wiki/plugins/page/textupload.php delete mode 100644 mods/wiki/plugins/page/wantedpages.meta delete mode 100644 mods/wiki/plugins/page/wantedpages.php delete mode 100644 mods/wiki/plugins/page/weekdiff.meta delete mode 100644 mods/wiki/plugins/page/wikidump.meta delete mode 100644 mods/wiki/plugins/page/wikidump.php delete mode 100644 mods/wiki/plugins/page/wikidump2.meta delete mode 100644 mods/wiki/plugins/page/wikidump2.php delete mode 100644 mods/wiki/plugins/page/wikinews.meta delete mode 100644 mods/wiki/plugins/page/wikinews.php delete mode 100644 mods/wiki/plugins/page/wikiuserlogin.meta delete mode 100644 mods/wiki/plugins/page/wikiuserlogin.php delete mode 100644 mods/wiki/plugins/page/wordindex.meta delete mode 100644 mods/wiki/plugins/page/wordindex.php delete mode 100644 mods/wiki/plugins/passwd_expire.php delete mode 100644 mods/wiki/plugins/patchsaving.meta delete mode 100644 mods/wiki/plugins/patchsaving.php delete mode 100644 mods/wiki/plugins/pluginloader.meta delete mode 100644 mods/wiki/plugins/pluginloader.php delete mode 100644 mods/wiki/plugins/spages.meta delete mode 100644 mods/wiki/plugins/spages.php delete mode 100644 mods/wiki/plugins/spam/antibot_captcha.meta delete mode 100644 mods/wiki/plugins/spam/antibot_captcha.php delete mode 100644 mods/wiki/plugins/spam/antibot_checkbox.meta delete mode 100644 mods/wiki/plugins/spam/antibot_checkbox.php delete mode 100644 mods/wiki/plugins/spam/antibot_delay.meta delete mode 100644 mods/wiki/plugins/spam/antibot_delay.php delete mode 100644 mods/wiki/plugins/spam/cookieusers.meta delete mode 100644 mods/wiki/plugins/spam/cookieusers.php delete mode 100644 mods/wiki/plugins/spam/limitlinks.ln delete mode 100644 mods/wiki/plugins/spam/watchonly.meta delete mode 100644 mods/wiki/plugins/spam/watchonly.php delete mode 100644 mods/wiki/plugins/sql/arrowadmin.meta delete mode 100644 mods/wiki/plugins/sql/arrowadmin.php delete mode 100644 mods/wiki/plugins/user/dbpref.meta delete mode 100644 mods/wiki/plugins/user/dbpref.php delete mode 100644 mods/wiki/plugins/user/sessionpref.meta delete mode 100644 mods/wiki/plugins/user/sessionpref.php delete mode 100644 mods/wiki/side_menu.inc.php delete mode 100644 mods/wiki/spages/AbandonedPages.php delete mode 100644 mods/wiki/spages/HitCounter.php delete mode 100644 mods/wiki/spages/LeastPopular.php delete mode 100644 mods/wiki/spages/LinkLessPages.php delete mode 100644 mods/wiki/spages/OrphanedPages.php delete mode 100644 mods/wiki/spages/PageLinks.php delete mode 100644 mods/wiki/spages/PageRefs.php delete mode 100644 mods/wiki/spages/PageSize.php delete mode 100644 mods/wiki/spages/WantedPages.php delete mode 100644 mods/wiki/spages/WordIndex.php delete mode 100644 mods/wiki/tlogo.png delete mode 100644 mods/wiki/tools/cron.d/HOWTO delete mode 100644 mods/wiki/tools/cron.d/S01env.php delete mode 100644 mods/wiki/tools/cron.d/S01textplainout.php delete mode 100644 mods/wiki/tools/cron.d/S10config.php delete mode 100644 mods/wiki/tools/cron.d/S11defaults.php delete mode 100644 mods/wiki/tools/cron.d/S16nohup.php delete mode 100644 mods/wiki/tools/cron.d/S17anacron.php delete mode 100644 mods/wiki/tools/cron.d/S18lock.php delete mode 100644 mods/wiki/tools/cron.d/S20__start__.php delete mode 100644 mods/wiki/tools/cron.d/S30__hourly__.php delete mode 100644 mods/wiki/tools/cron.d/S35mail2wiki.php delete mode 100644 mods/wiki/tools/cron.d/S50__daily__.php delete mode 100644 mods/wiki/tools/cron.d/S53sync.php delete mode 100644 mods/wiki/tools/cron.d/S56gagalinks.php delete mode 100644 mods/wiki/tools/cron.d/S61keptpages.php delete mode 100644 mods/wiki/tools/cron.d/S63deletedpage.php delete mode 100644 mods/wiki/tools/cron.d/S64trashcan.php delete mode 100644 mods/wiki/tools/cron.d/S67versionholes.php delete mode 100644 mods/wiki/tools/cron.d/S70__weekly__.php delete mode 100644 mods/wiki/tools/cron.d/S77metadb.php delete mode 100644 mods/wiki/tools/cron.d/S80recentnotify.php delete mode 100644 mods/wiki/tools/cron.d/S81weekdiff.php delete mode 100644 mods/wiki/tools/cron.d/S90__monthly__.php delete mode 100644 mods/wiki/tools/cron.d/S92binbackup.php delete mode 100644 mods/wiki/tools/cron.d/S92mimebackup.php delete mode 100644 mods/wiki/tools/cron.d/S93checklinks.php delete mode 100644 mods/wiki/tools/cron.d/S99__end__.php delete mode 100644 mods/wiki/tools/cron.d/Z17anacron.php delete mode 100644 mods/wiki/tools/cron.d/Z18unlock.php delete mode 100644 mods/wiki/tools/cron.d/index.php delete mode 100644 mods/wiki/tools/cron.d/run-parts.php delete mode 100755 mods/wiki/tools/ewikictl delete mode 100755 mods/wiki/tools/ewikictl.bat delete mode 100644 mods/wiki/tools/index.html delete mode 100755 mods/wiki/tools/mergeplugins delete mode 100755 mods/wiki/tools/metacache delete mode 100755 mods/wiki/tools/mkhuge delete mode 100755 mods/wiki/tools/mkpageplugin delete mode 100755 mods/wiki/tools/mkpluginmap delete mode 100755 mods/wiki/tools/mkxpi delete mode 100755 mods/wiki/tools/setup delete mode 100644 mods/wiki/tools/setup.dat delete mode 100644 mods/wiki/tools/t_backup.php delete mode 100644 mods/wiki/tools/t_checklinks.php delete mode 100644 mods/wiki/tools/t_commander/80x25.css delete mode 100644 mods/wiki/tools/t_commander/action.php delete mode 100644 mods/wiki/tools/t_commander/commandline.php delete mode 100644 mods/wiki/tools/t_commander/edit.php delete mode 100644 mods/wiki/tools/t_commander/filemenu.php delete mode 100644 mods/wiki/tools/t_commander/index.html delete mode 100644 mods/wiki/tools/t_commander/info.php delete mode 100644 mods/wiki/tools/t_commander/keymenu.php delete mode 100644 mods/wiki/tools/t_commander/list.php delete mode 100644 mods/wiki/tools/t_commander/list_vers.php delete mode 100644 mods/wiki/tools/t_commander/t_config.php delete mode 100644 mods/wiki/tools/t_config.css delete mode 100644 mods/wiki/tools/t_config.php delete mode 100644 mods/wiki/tools/t_control.php delete mode 100644 mods/wiki/tools/t_convertdb.php delete mode 100644 mods/wiki/tools/t_ewikictl.php delete mode 100644 mods/wiki/tools/t_flags.php delete mode 100644 mods/wiki/tools/t_holes.php delete mode 100644 mods/wiki/tools/t_remove.php delete mode 100644 mods/wiki/tools/t_restore.php delete mode 100644 mods/wiki/tools/t_revert.php delete mode 100644 mods/wiki/tools/t_searchandreplace.php delete mode 100644 mods/wiki/tools/t_setupwiz.php delete mode 100644 mods/wiki/tools/t_sync.php delete mode 100644 mods/wiki/tools/t_textinsert.php delete mode 100644 mods/wiki/tools/t_textupload.php delete mode 100644 mods/wiki/tools/t_transfer.php delete mode 100755 mods/wiki/tools/upgrade-r101d delete mode 100755 mods/wiki/tools/whiptail delete mode 100755 mods/wiki/tools/wiki2html delete mode 100644 mods/wiki/tools/xt_searchcache_staticf.php delete mode 100644 mods/wiki/tools/xt_sysinfo.php delete mode 100644 mods/wiki/wiki.css delete mode 100644 mods/wiki/z.php delete mode 100644 mods/wordpress/README delete mode 100644 mods/wordpress/index.php delete mode 100644 mods/wordpress/index_admin.php delete mode 100644 mods/wordpress/index_instructor.php delete mode 100644 mods/wordpress/index_mystart.php delete mode 100644 mods/wordpress/index_public.php delete mode 100644 mods/wordpress/module.css delete mode 100644 mods/wordpress/module.php delete mode 100644 mods/wordpress/module.sql delete mode 100644 mods/wordpress/module.xml delete mode 100644 mods/wordpress/module_delete.php delete mode 100644 mods/wordpress/module_install.php delete mode 100644 mods/wordpress/module_news.php delete mode 100644 mods/wordpress/module_uninstall.php delete mode 100644 mods/wordpress/sublinks.php delete mode 100644 mods/wordpress/wordpress_icon_sm.png delete mode 100644 mods/wordpress/wordpress_logo.png delete mode 100644 mods/wordpress/wp_config.php delete mode 100644 mods/wordpress/wp_connect.php delete mode 100644 mods/wordpress/wp_plugin/external-database-authentication/ext_db_auth.php delete mode 100644 mods/wordpress/wp_plugin/external-database-authentication/readme.txt diff --git a/mods/adobe_connect/README.txt b/mods/adobe_connect/README.txt deleted file mode 100755 index 38895a0eb..000000000 --- a/mods/adobe_connect/README.txt +++ /dev/null @@ -1,39 +0,0 @@ - -Adobe Connect Integration - -------------------------------------------------------------------- - -Description - -This module allows ATutor to connect with an Adobe Connect Server with a Single Sign-On using Adobe Connect API and maintaining user roles. - -When a instructor makes the module avaiable, course enrolled users can access Adobe Connect without login, if they don't have an account on Adobe Connect Server the module creates an account to access, with ATutor login username and ATutor firstname and lastname. - -This module creates an Adobe Connect room foreach course where the module is avaiable. The first time a course user accesses Adobe Connect, the module search a room in Adobe Connect Server named $_SESSION["course_id"] and if it doesn't exists, creates it. - -------------------------------------------------------------------- - -Requirements - -- Atutor version > 1.6 -- Adobe Connect Server > 6 - -------------------------------------------------------------------- - -Installation - -- Login as an admin user, goto Modules -> Install modules, and select the zip file. -- On the admin menu, go to the Adobe Connect tab -- Config the Adobe Connect Server - .Host and port - .An Adobe Connect admin user login data - .The folder id where the course rooms should be created (adobe connect folder sco-id) -- Activate headers authentication on the Adobe Connect Server installation - .in INSTALLATIONPATH/appserv/conf/WEB-INF/web.xml uncomment HeaderAuthenticationFilter lines - .in INSTALLATIONPATH/custom.ini add HTTP_AUTH_HEADER=XXXXXX where XXXXXX is the admin password - .reboot Adobe Connect application - -------------------------------------------------------------------- - -I don't have any relation with Adobe, this module is based on a OnCampus University development. For commercial or server configuration support, contact Adobe. - diff --git a/mods/adobe_connect/adobe_connect.gif b/mods/adobe_connect/adobe_connect.gif deleted file mode 100755 index 3e84c216d1683faf642f40f2ec0f628270b9f6f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1411 zcmV-}1$_EPNk%w1VKM+R0M!5hjHR1>r<9wssms;TahQg?)XDw*{iC|Es=~Nsi+Q!o z!r$QG=;`VD`upVN=GWNS;o{=T%+1)@+V%DJ+}+;C$;#T?-0|`9#L~>|?(USWqtw;b z=jiC;g&ME$IQ>r`TF{uys!EB`rhB*^Yirl{QUR#_wVrV`TF_A#>n^h z`1berA^8LV00000EC2ui05SkF000L6K!c${EE5Y}vP2`sPRBGJ+}$nT-)U?tU5J|)RPaN95dewH82Dkxiy;JH!6U0uV9P;=X&s0Q+!TPJHQmdw2_VSa^K4+y z1LQ0kO@zab(>hqt9UcHS>;N*%eg++S!BE}}e0wonf;dv+8fGW=3H3Jf+`HBFp5Vnx zb?YGkAW%TtugmVtL5pxsVKfRNF2YRMe?Guhqyq5OmvZpMC)f<(S#Vzi`GtYQ1pR?@ z9cu$}hn9f{KBwS<4LTVA;Z3j!P(WE0dWYc*^=-)E1rFlyVR0eK(A0YuVt8PRC`cdy zeq;0)p>dZ9Fu+(mwe;6h7>QsX3J>hqfCD{_QQc(<07-%dgq%@GG;1(0%^NXkm}8Sf zI8er!D!^7HkQ!)Nh#Jwb(Mc@2iOFON4-nCTn;E2eSqMN9(B_+PG9afLbP|RmlMmpj zC!Y`$7XYA_5nySXX~4+|2XlU+XniP*nZgEnHUI;k890zxrIuc*X`GxQny7PPO3>&A zAEZD844ICgr3$SA5JIaOaA_!~oq9?uj<%+d!UwtT8bhyX3_z^4mI7d?oO61j>G(;ZB$^3*G=@B-FZrxL|D+EI=JA<@PY;@+#mx08rXigf;w)#LFb+`UcvIB3*Y+lts8B0jyj6VIk{ik zt^D#8h)}!q;D^7p=9|xqyzH}c?|lQIia&j*V4tnr|APiv$d*A>kC?gdp ROrZ)_$if!VL'; - -echo _AT("adobe_connect_text").'

'; -echo ''._AT("adobe_connect_access").''; - -echo ''; - - -require(AT_INCLUDE_PATH.'footer.inc.php'); - -?> diff --git a/mods/adobe_connect/index_admin.php b/mods/adobe_connect/index_admin.php deleted file mode 100755 index 6d9d77b5c..000000000 --- a/mods/adobe_connect/index_admin.php +++ /dev/null @@ -1,112 +0,0 @@ -adobe_connect_adminpass = $addslashes($_POST['adobe_connect_adminpass']); - $tmpconfig->adobe_connect_adminuser = $addslashes($_POST['adobe_connect_adminuser']); - $tmpconfig->adobe_connect_folderid = (int)$_POST['adobe_connect_folderid']; - $tmpconfig->adobe_connect_host = $addslashes($_POST['adobe_connect_host']); - $tmpconfig->adobe_connect_port = $addslashes($_POST['adobe_connect_port']); - - foreach ($tmpconfig as $value) { - if (empty($value)) { - $msg->addError('adobe_connect_fillall'); - } - } - - if (!$msg->containsErrors()) { - - $config = getAdobeConnectConfig(); - - $inserts = array(); - $updates = array(); - foreach ($tmpconfig as $name => $value) { - - if (!empty($config->$name)) { - $updates[] = " value = '$value' WHERE name = '$name'"; - } else { - - $inserts[] = " VALUES ('$name', '$value')"; - - } - } - - if (!empty($inserts)) { - - $insertsql = "INSERT INTO ".TABLE_PREFIX."config (name, value) "; - foreach ($inserts as $insert) { - $result = mysql_query($insertsql.$insert, $db); - if (!$result) { - die('db insert problem'); - } - } - } - - if (!empty($updates)) { - foreach ($updates as $update) { - $updatesql = "UPDATE ".TABLE_PREFIX."config SET "; - $result = mysql_query($updatesql.$update, $db); - if (!$result) { - die('db update problem'); - } - } - } - - if (!$msg->containsErrors()) { - $msg->addFeedback('adobe_connect_saved'); - } - - header('location: '.$_SERVER["php_self"]); - } -} - - -// print header -require (AT_INCLUDE_PATH.'header.inc.php'); - - -// get config -if (!empty($_POST['send'])) { - foreach ($tmpconfig as $name => $tmp) { - $acc->$name = $tmp; - } -} else if (!$acc = getAdobeConnectConfig()) { - $acc->adobe_connect_adminpass = ''; - $acc->adobe_connect_adminuser = ''; - $acc->adobe_connect_folderid = ''; - $acc->adobe_connect_host = ''; - $acc->adobe_connect_port = ''; -} - -// print form -echo '
'; -echo '
'; -foreach ($acc as $name => $value) { - echo '
'; - echo '
*
'; - echo '
'; - echo ''; - echo '
'; -} - -echo '
'; -echo ''; -echo '
'; -echo ''; - - -// print footer -require (AT_INCLUDE_PATH.'footer.inc.php'); - - -?> diff --git a/mods/adobe_connect/lib/ACConnection.php b/mods/adobe_connect/lib/ACConnection.php deleted file mode 100755 index ea3a54bf5..000000000 --- a/mods/adobe_connect/lib/ACConnection.php +++ /dev/null @@ -1,82 +0,0 @@ - $v) { - $this->$attribute = $cfg->$attribute; - } - - } - - - public function getACHost() { - return $this->adobe_connect_host; - } - - - public function getACPort() { - return $this->adobe_connect_port; - } - - - public function getAdminSession() { - - $fp = @fsockopen($this->adobe_connect_host, $this->adobe_connect_port); - if (!$fp) { - return false; - } - - $url = '/api/xml?action=login&external-auth=use'; - - fputs($fp, "GET ".$url." HTTP/1.0\r\n".$this->adobe_connect_adminpass.":".$this->adobe_connect_adminuser."\r\nHost: ".$this->adobe_connect_host."\r\n\r\n"); - - while ($line = fgets($fp)) { - if (strstr($line, "code=\"ok\"")) { - $response = 1; - break; - } - - if (preg_match('/BREEZESESSION=(.*)\;/', $line, $result)) { - $session = explode(';', $result[1]); - $sessionid = $session[0]; - } - } - fclose($fp); - - if (empty($response)) { - return false; - } - - return $sessionid; - } - - - public function checkResponse($socket, $source) { - - while ($line = fgets($socket)) { - if (strstr($line, "code=\"ok\"")) { - return true; - } - } - - return false; - } - - -} - -?> diff --git a/mods/adobe_connect/lib/ACRoom.php b/mods/adobe_connect/lib/ACRoom.php deleted file mode 100755 index 337623280..000000000 --- a/mods/adobe_connect/lib/ACRoom.php +++ /dev/null @@ -1,159 +0,0 @@ -adobe_connect_host, $this->adobe_connect_port); - if (!$fp) { - return false; - } - if ($this->checkRoom($sessionid, $roomname)) { - return false; - } - - $roomname = trim($roomname); - $url = "/api/xml?action=sco-update&name=$roomname&folder-id=".$this->adobe_connect_folderid."&type=meeting&session=$sessionid"; - fputs($fp, "GET ".$url." HTTP/1.0\r\nHost: ".$this->adobe_connect_host."\r\n\r\n"); - - while($line = fgets($fp)) { - - if (preg_match('/\ sco-id=\"([0-9]*)\"/', $line, $result)) { - $scoid = $result[1]; - } - } - fclose($fp); - - if (empty($scoid)) { - return false; - } - - return true; - } - - - public function deleteRoom($sessionid, $roomname) { - - if (!$scoid = $this->checkRoom($sessionid, $roomname)) { - return false; - } else { - - $fp = @fsockopen($this->adobe_connect_host, $this->adobe_connect_port); - if (!$fp) { - return false; - } - - $url = "/api/xml?action=sco-delete&sco-id=$scoid&session=$sessionid"; - fputs($fp, "GET ".$url." HTTP/1.0\r\nHost: ".$this->adobe_connect_host."\r\n\r\n"); - - $response = $this->checkResponse($fp, __FUNCTION__); - fclose($fp); - - return $response; - } - } - - - public function assignUser($sessionid, $username, $roomname, $role) { - - if (!$scoid = $this->checkRoom($sessionid, $roomname)) { - return false; - } - - $user = new ACUser(); - $principalid = $user->checkUser($sessionid, $username); - if (!$principalid) { - return false; - } - - switch ($role) { - case 'instructor': - $acrole = 'host'; - break; - case 'student': - $acrole = 'view'; - break; - default: - return false; - } - - return $this->assignAction($sessionid, $scoid, $principalid, $acrole); - } - - - public function assignAction($sessionid, $scoid, $principalid, $role) { - - $fp = @fsockopen($this->adobe_connect_host, $this->adobe_connect_port); - if (!$fp) { - return false; - } - - $url = "/api/xml?action=permissions-update&permission-id=$role&acl-id=$scoid&principal-id=$principalid&session=$sessionid"; - fputs($fp, "GET ".$url." HTTP/1.0\r\nHost: ".$this->adobe_connect_host."\r\n\r\n"); - - $response = $this->checkResponse($fp, __FUNCTION__); - fclose($fp); - - return $response; - } - - - public function getRoomUrl($sessionid, $scoid) { - - - $fp = @fsockopen($this->adobe_connect_host, $this->adobe_connect_port); - if (!$fp) { - return false; - } - - $url = "/api/xml?action=sco-info&sco-id=$scoid&session=$sessionid"; - fputs($fp, "GET ".$url." HTTP/1.0\r\nHost: ".$this->adobe_connect_host."\r\n\r\n"); - - while ($line = fgets($fp)) { - if (preg_match('@\\/([^/]+)@', $line, $result)) { - $roomurl = $result[1]; - } - } - fclose($fp); - - if (empty($roomurl)) { - return false; - } - - return $roomurl; - } - - - public function checkRoom($sessionid, $roomname) { - - $fp = @fsockopen($this->adobe_connect_host, $this->adobe_connect_port); - if (!$fp) { - return false; - } - - $url = "/api/xml?action=sco-expanded-contents&sco-id=".$this->adobe_connect_folderid."&filter-type=meeting&filter-name=$roomname&session=$sessionid"; - fputs($fp, "GET ".$url." HTTP/1.0\r\nHost: ".$this->adobe_connect_host."\r\n\r\n"); - - while($line = fgets($fp)) { - - if (preg_match('/\ sco-id=\"([0-9]*)\"/', $line, $result)) { - $scoid = $result[1]; - } - - } - fclose($fp); - - if (empty($scoid)) { - return false; - } - - return $scoid; - } - -} - -?> diff --git a/mods/adobe_connect/lib/ACUser.php b/mods/adobe_connect/lib/ACUser.php deleted file mode 100755 index a75b89fac..000000000 --- a/mods/adobe_connect/lib/ACUser.php +++ /dev/null @@ -1,124 +0,0 @@ -adobe_connect_host, $this->adobe_connect_port); - if (!$fp) { - return false; - } - - $url = '/api/xml?action=login&external-auth=use'; - - fputs($fp, "GET ".$url." HTTP/1.0\r\n".$this->adobe_connect_adminpass.":".$username."\r\nHost: ".$this->adobe_connect_host."\r\n\r\n"); - - while($line = fgets($fp)) { - - if (preg_match('/BREEZESESSION=(.*)\;/', $line, $result)) { - $session = explode(';', $result[1]); - $sessionid = $session[0]; - break; - } - - } - fclose($fp); - - if (empty($sessionid)) { - return false; - } - - return $sessionid; - } - - - public function createUser($sessionid, $username, $fname, $lname) { - - $fp = @fsockopen($this->adobe_connect_host, $this->adobe_connect_port); - if (!$fp) { - return false; - } - - if ($this->checkUser($sessionid, $username)) { - return false; - } - - if ($fname == '' OR $fname == false OR $fname == ' ') { return false;} - if ($lname == '' OR $lname == false OR $lname == ' ') { return false;} - if ($username == '' OR $username == false OR $username == ' ') { return false;} - if (strlen($fname) > 40) { return false;} - if (strlen($lname) > 40) { return false;} - if (strlen($username) > 40) { return false;} - $username = trim($username); - - $url = "/api/xml?action=principal-update&login=$username&first-name=$fname&has-children=0&last-name=$lname&type=user&session=$sessionid"; - fputs($fp, "GET ".$url." HTTP/1.0\r\nHost: ".$this->adobe_connect_host."\r\n\r\n"); - - while($line = fgets($fp)) { - if (preg_match('/\ principal-id=\"([0-9]*)\"/', $line, $result)) { - $principalid = $result[1]; - } - } - fclose($fp); - - if (empty($principalid)) { - return false; - } - - return true; - } - - - public function deleteUser($sessionid, $username) { - - if (!$principalid = $this->checkUser($sessionid, $username)) { - return false; - } else { - - $fp = @fsockopen($this->adobe_connect_host, $this->adobe_connect_port); - if (!$fp) { - return false; - } - - $url = "/api/xml?action=principals-delete&principal-id=$principalid&session=$sessionid"; - fputs($fp, "GET ".$url." HTTP/1.0\r\nHost: ".$this->adobe_connect_host."\r\n\r\n"); - - $response = $this->checkResponse($fp, __FUNCTION__); - fclose($fp); - return $response; - } - } - - - public function checkUser($sessionid, $username) { - - $fp = @fsockopen($this->adobe_connect_host, $this->adobe_connect_port); - if (!$fp) { - return false; - } - - $url = "/api/xml?action=principal-list&filter-login=$username&session=$sessionid"; - fputs($fp, "GET ".$url." HTTP/1.0\r\nHost: ".$this->adobe_connect_host."\r\n\r\n"); - - while($line = fgets($fp)) { - - if (preg_match('/\ principal-id=\"([0-9]*)\"/', $line, $result)) { - $principalid = $result[1]; - } - - } - fclose($fp); - - if (empty($principalid)) { - return false; - } - - return $principalid; - } - -} - -?> diff --git a/mods/adobe_connect/lib/lib.php b/mods/adobe_connect/lib/lib.php deleted file mode 100755 index 316164cd9..000000000 --- a/mods/adobe_connect/lib/lib.php +++ /dev/null @@ -1,90 +0,0 @@ -$name = $value; - } - } - - if (empty($data)) { - return false; - } - - return $data; - } - - - function getMemberData() { - - global $db; - - $memberid = $_SESSION['member_id']; - - $membersql = "SELECT member_id, login, first_name, second_name, last_name - FROM ".TABLE_PREFIX."members - WHERE member_id = '$memberid'"; - $members = mysql_query($membersql, $db); - - while ($member = @mysql_fetch_assoc($members)) { - $memberdata->member_id = $member["member_id"]; - $memberdata->login = $member["login"]; - $memberdata->first_name = $member["first_name"]; - $memberdata->second_name = $member["second_name"]; - $memberdata->last_name = $member["last_name"]; - } - - if (empty($memberdata)) { - return false; - } - - return $memberdata; - } - - - function getMemberCourseAssign() { - - global $db; - - $memberid = $_SESSION['member_id']; - $courseid = $_SESSION['course_id']; - - $assignsql = "SELECT privileges, role - FROM ".TABLE_PREFIX."course_enrollment - WHERE member_id = '$memberid' AND course_id = '$courseid' AND approved = 'y' - ORDER BY role ASC"; - $assigns = mysql_query($assignsql, $db); - - while ($assign = @mysql_fetch_assoc($assigns)) { - if ($assign['role'] == 'Instructor') { - $assigndata->role = strtolower($assign['role']); - } else { - $assigndata->role = 'student'; - } - $assigndata->privileges = $assign['privileges']; - } - - if (empty($assigndata)) { - return false; - } - - return $assigndata; - } - - -?> diff --git a/mods/adobe_connect/loader.php b/mods/adobe_connect/loader.php deleted file mode 100755 index 4dee995cf..000000000 --- a/mods/adobe_connect/loader.php +++ /dev/null @@ -1,97 +0,0 @@ -addError('adobe_connect_wrong_member_sess'); -} - -$assign = getMemberCourseAssign(); -if (!$assign) { - $msg->addError('adobe_connect_no_access'); -} - - -$acuser = new ACUser(); -$acroom = new ACRoom(); - - -// admin session -$xsid = $acuser->getAdminSession(); -if (!$xsid) { - $msg->addError('adobe_connect_not_connect'); - echo ''; - -} else { - - // room id - $scoid = $acroom->checkRoom($xsid, $courseid); - if (!$scoid) { - - // comprovar que l'usuari té accés al mòdul - - $createresult = $acroom->createRoom($xsid, $courseid); - if (!$createresult) { - $msg->addError('adobe_connect_not_create_room'); - } else { - $scoid = $acroom->checkRoom($xsid, $courseid); - if (!$scoid) { - $msg->addError('adobe_connect_not_roomid'); - } - } - } - - - // user session - $userexists = $acuser->checkUser($xsid, $member->login); - if (!$userexists) { - - $createresult = $acuser->createUser($xsid, $member->login, $member->first_name, $member->last_name); - if (!$createresult) { - $msg->addError('adobe_connect_not_create_user'); - } else { - $usid = $acuser->getUserSession($member->login); - if (!$usid) { - $msg->addError('adobe_connect_not_user_session'); - } - } - } else { - $usid = $acuser->getUserSession($member->login); - } - - - // redirect url - $roomurl = $acroom->getRoomUrl($usid, $scoid); - if (!$roomurl) { - - $createresult = $acroom->assignUser($xsid, $member->login, $courseid, $assign->role); - if (!$createresult) { - $msg->addError('adobe_connect_not_assign'); - } else { - $roomurl = $acroom->getRoomUrl($usid, $scoid); - if (!$roomurl) { - $msg->addError('adobe_connect_not_roomurl'); - } - } - } - -} - - -$url = 'http://'.$acroom->getACHost().'/'.$roomurl.'?session='.$usid; -header('location: '.$url); - -?> diff --git a/mods/adobe_connect/module.css b/mods/adobe_connect/module.css deleted file mode 100755 index 520593c58..000000000 --- a/mods/adobe_connect/module.css +++ /dev/null @@ -1,13 +0,0 @@ - -div#adobe_connect { - border: 1px solid #ccc; - padding: 10px; - width: 50%; - margin-right: auto; - margin-left: auto; - background-color: #efefef; - color: #444; - margin-top: 30px; - margin-bottom: 30px; - text-align: center; -} diff --git a/mods/adobe_connect/module.php b/mods/adobe_connect/module.php deleted file mode 100755 index b10c63bbe..000000000 --- a/mods/adobe_connect/module.php +++ /dev/null @@ -1,31 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_ADOBE_CONNECT', $this->getAdminPrivilege()); - - -$_student_tool = 'mods/adobe_connect/index.php'; - - -// admin -if (admin_authenticate(AT_ADMIN_PRIV_ADOBE_CONNECT, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/adobe_connect/index_admin.php'); - $this->_pages['mods/adobe_connect/index_admin.php']['title_var'] = 'adobe_connect'; - $this->_pages['mods/adobe_connect/index_admin.php']['parent'] = AT_NAV_ADMIN; -} - - -// course -> home -$this->_pages['mods/adobe_connect/index.php']['title_var'] = 'adobe_connect'; -$this->_pages['mods/adobe_connect/index.php']['img'] = 'mods/adobe_connect/adobe_connect.gif'; - - -?> diff --git a/mods/adobe_connect/module.sql b/mods/adobe_connect/module.sql deleted file mode 100755 index 675eac89d..000000000 --- a/mods/adobe_connect/module.sql +++ /dev/null @@ -1,43 +0,0 @@ -# sql file for adobe connect module - -INSERT INTO `language_text` VALUES ('en', '_module', 'adobe_connect', 'Adobe Connect', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_module', 'adobe_connect_title', 'Adobe Connect Integration', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_module', 'adobe_connect_text', 'To access the course Adobe Connect room click on the link below', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_module', 'adobe_connect_host', 'Adobe Connect Host', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_module', 'adobe_connect_port', 'Port', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_module', 'adobe_connect_adminuser', 'Admin username', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_module', 'adobe_connect_adminpass', 'Admin password', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_module', 'adobe_connect_folderid', 'Shared meetings folder Identifier', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_module', 'adobe_connect_access', 'Access Adobe Connect', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_adobe_connect_saved', 'Changes saved', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_adobe_connect_fillall', 'You should fill all config params', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_adobe_connect_wrong_member_sess', 'Wrong session member', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_adobe_connect_no_access', 'This course hasn\'t Adobe Connect access', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_adobe_connect_not_connect', 'Can\'t connect to Adobe Connect', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_adobe_connect_not_create_room', 'Can\'t create Adobe Connect room', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_adobe_connect_not_assign', 'Can\'t assign you to the course room', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_adobe_connect_not_roomid', 'Can\'t get Adobe Connect room id', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_adobe_connect_not_create_user', 'Can\'t create Adobe Connect user', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_adobe_connect_not_user_session', 'Can\'t start an user session', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_adobe_connect_not_roomurl', 'Can\'t get Adobe Connect room URL', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_module', 'adobe_connect', 'Adobe Connect', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_module', 'adobe_connect_title', 'Adobe Connect Integration', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_module', 'adobe_connect_text', 'Para acceder a la sala de Adobe Connect de este curs clica debajo', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_module', 'adobe_connect_host', 'Host del servidor de Adobe Connect', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_module', 'adobe_connect_port', 'Puerto', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_module', 'adobe_connect_adminuser', 'Usuario administrador de Adobe Connect Server', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_module', 'adobe_connect_adminpass', 'Password del usuario administrador', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_module', 'adobe_connect_folderid', 'Identificador de la carpeta donde crear las salas', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_module', 'adobe_connect_access', 'Acceder a Adobe Connect', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_msgs', 'AT_FEEDBACK_adobe_connect_saved', 'Cambios guardados', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_msgs', 'AT_ERROR_adobe_connect_fillall', 'Rellena todos los campos', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_msgs', 'AT_ERROR_adobe_connect_wrong_member_sess', 'Sesión de usuario incorrecta', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_msgs', 'AT_ERROR_adobe_connect_no_access', 'Este curso no tiene acceso a Adobe Connect', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_msgs', 'AT_ERROR_adobe_connect_not_connect', 'No se puede conectar al servidor de Adobe Connect', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_msgs', 'AT_ERROR_adobe_connect_not_create_room', 'No se puede crear la sala en Adobe Connect', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_msgs', 'AT_ERROR_adobe_connect_not_assign', 'No se te puede assignar a la sala de Adobe Connect', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_msgs', 'AT_ERROR_adobe_connect_not_roomid', 'No se puede obtener el id de la sala de Adobe Connect de este curso', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_msgs', 'AT_ERROR_adobe_connect_not_create_user', 'No se puede crear tu usuario en Adobe Connect', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_msgs', 'AT_ERROR_adobe_connect_not_user_session', 'No se puede iniciar sesión en Adobe Connect', NOW(), ''); -INSERT INTO `language_text` VALUES ('es-es', '_msgs', 'AT_ERROR_adobe_connect_not_roomurl', 'No se puede obtener la URL de la sala', NOW(), ''); - diff --git a/mods/adobe_connect/module.xml b/mods/adobe_connect/module.xml deleted file mode 100755 index 676d401af..000000000 --- a/mods/adobe_connect/module.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - Adobe Connect Integration - This module allows ATutor to connect with an Adobe Connect Server with a Single Sign-On using Adobe Connect API and maintaining user roles. - - - David Monllao - david.monllao@urv.cat - - - GPL - - 0.5 - 2010-10-25 - stable - This module needs an Adobe Connect Server, for commercial support contact Adobe - - diff --git a/mods/adobe_connect/module_cron.php b/mods/adobe_connect/module_cron.php deleted file mode 100755 index 2d1e3b867..000000000 --- a/mods/adobe_connect/module_cron.php +++ /dev/null @@ -1,15 +0,0 @@ - diff --git a/mods/adobe_connect/module_delete.php b/mods/adobe_connect/module_delete.php deleted file mode 100755 index 707e092f2..000000000 --- a/mods/adobe_connect/module_delete.php +++ /dev/null @@ -1,19 +0,0 @@ - diff --git a/mods/adobe_connect/module_install.php b/mods/adobe_connect/module_install.php deleted file mode 100755 index 1cb21d7fe..000000000 --- a/mods/adobe_connect/module_install.php +++ /dev/null @@ -1,31 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exists')); -//} else if (!is_writable($directory) && @chmod($directory, 0666)) { -} else if (!is_writable($directory) && @chmod($directory, 0777)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writable')); -} - - -// db -$sqlfilepath = dirname(__FILE__).'/module.sql'; -if (!$msg->containsErrors() && file_exists($sqlfilepath)) { - - require_once(AT_INCLUDE_PATH.'classes/sqlutility.class.php'); - $sqlUtility = & new SqlUtility(); - $sqlUtility->queryFromFile($sqlfilepath, TABLE_PREFIX); -} - - -?> diff --git a/mods/adobe_connect/module_uninstall.php b/mods/adobe_connect/module_uninstall.php deleted file mode 100755 index aec32b097..000000000 --- a/mods/adobe_connect/module_uninstall.php +++ /dev/null @@ -1,26 +0,0 @@ -addError(array('MODULE_UNINSTALL', ' '.$directory.' can\'t be removed')); - } - -} - -// db -$sqlfilepath = dirname(__FILE__).'/module.sql'; -if (!$msg->containsErrors() && file_exists($sqlfilepath)) { - - require_once(AT_INCLUDE_PATH.'classes/sqlutility.class.php'); - $sqlUtility = new SqlUtility(); - $sqlUtility->revertQueryFromFile($sqlfilepath, TABLE_PREFIX); -} - -?> diff --git a/mods/announcement_subscription/module.php b/mods/announcement_subscription/module.php deleted file mode 100755 index c01322310..000000000 --- a/mods/announcement_subscription/module.php +++ /dev/null @@ -1,7 +0,0 @@ -_stacks['announcement_subscription'] = array('title_var'=>'announcement_subscription', 'file'=>'mods/announcement_subscription/side_menu.inc.php'); -?> diff --git a/mods/announcement_subscription/module.sql b/mods/announcement_subscription/module.sql deleted file mode 100755 index 47f11f9d7..000000000 --- a/mods/announcement_subscription/module.sql +++ /dev/null @@ -1,116 +0,0 @@ -# -# sql file for announcement_subscription module -# - - -# Set up table for subscribers -CREATE TABLE `courses_members_subscription` ( - `member_id` MEDIUMINT NOT NULL , - `course_id` MEDIUMINT NOT NULL , - `subscribe` MEDIUMINT NULL DEFAULT '0', - PRIMARY KEY (member_id) -) TYPE=MyISAM; - - - -# Insert module specific language: -INSERT INTO `language_text` VALUES ('en', - '_module', - 'announcement_subscription', - 'Announcement Subscription', - NOW(), - 'Title'); - -INSERT INTO `language_text` VALUES ('en', - '_module', - 'announcement_subscribe_subject', - 'Course Announcement Subscription', - NOW(), - 'Announcement subscription mail subject'); - -INSERT INTO `language_text` VALUES ('en', - '_module', - 'announcement_subscribe_body', - '*DO NOT REPLY TO THIS MESSAGE* \n -You are now subscribed to the newsfeed in the ATutor course "%s". Login at: %s to view the course.', - NOW(), - 'New announcement mail body'); - -INSERT INTO `language_text` VALUES ('en', - '_module', - 'announcement_unsubscribe_body', - '*DO NOT REPLY TO THIS MESSAGE* \n -Your subscription to the newsfeed in the ATutor course "%s" has been cancelled. Login at: %s to view the course.', - NOW(), - 'New announcement mail body'); - -INSERT INTO `language_text` VALUES ('en', - '_module', - 'announcement_notify_subject', - 'New Course Announcement', - NOW(), - 'New announcement mail subject'); - -INSERT INTO `language_text` VALUES ('en', - '_module', - 'announcement_notify_body1', - '*DO NOT REPLY TO THIS MESSAGE* \n -A new announcement has been published in the ATutor course "%s". Login at: %s to view the course.', - NOW(), - 'New announcement mail body'); - -INSERT INTO `language_text` VALUES ('en', - '_module', - 'announcement_subscription_subscribe', - 'Subscribe', - NOW(), - 'Subscribe'); - -INSERT INTO `language_text` VALUES ('en', - '_module', - 'announcement_subscription_unsubscribe', - 'Unsubscribe', - NOW(), - 'Unsubscribe'); - -INSERT INTO `language_text` VALUES ('en', - '_msgs', - 'AT_INFOS_ANNOUNCEMENTSUB_ALREADYINSTALLED_ADDNEWS', - 'Module already installed in file /editor/add_news.php ', - NOW(), - 'Module installed warning'); - -INSERT INTO `language_text` VALUES ('en', - '_msgs', - 'AT_FEEDBACK_ANNOUNCEMENTSUB_INSTALL_ADDNEWS', - 'Changes made to file /editor/add_news.php ', - NOW(), - 'Module installed feedback'); - -INSERT INTO `language_text` VALUES ('en', - '_msgs', - 'AT_ERROR_ANNOUNCEMENTSUB_INSTALL_ADDNEWS', - 'Could not write to file /editor/add_news.php ', - NOW(), - 'Module install error'); - -INSERT INTO `language_text` VALUES ('en', - '_msgs', - 'AT_FEEDBACK_ANNOUNCEMENTSUB_SUBSCRIBE', - 'You have successfully subscribed to the announcement newsfeed for this course.', - NOW(), - 'Subscribed feedback message'); - -INSERT INTO `language_text` VALUES ('en', - '_msgs', - 'AT_ERROR_ANOUNCEMENTSUB_INSTALL_UNWRITE', - 'Cannot write to file /editor/add_news.php. Please make sure appropriate permissions are set for writing to this file.', - NOW(), - 'file unwritable error'); - -INSERT INTO `language_text` VALUES ('en', - '_msgs', - 'AT_FEEDBACK_ANNOUNCEMENTSUB_UNSUBSCRIBE', - 'You have successfully unsubscribed from the announcement newsfeed for this course.', - NOW(), - 'Unsubscribed feedback message'); diff --git a/mods/announcement_subscription/module.xml b/mods/announcement_subscription/module.xml deleted file mode 100755 index 154cdf784..000000000 --- a/mods/announcement_subscription/module.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - Course Announcement Subscription - This module, when enabled, allows users to subscribe to the newsfeed from course announcements, much like they subscribe to forum threads. - - - Gøran Berntsen - gorzan@gmail.com - - - - - - 1.2 - 2010-10-25 - Stable - Please note that this module makes changes to some of the ATutor core files on installation. - If you want a notification email to be sent to the user upon subscription/unsubscription, uncomment the appropriate lines in subscribe.php - - diff --git a/mods/announcement_subscription/module_install.php b/mods/announcement_subscription/module_install.php deleted file mode 100755 index d11b88aa2..000000000 --- a/mods/announcement_subscription/module_install.php +++ /dev/null @@ -1,82 +0,0 @@ -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); -} - -/****** - * The following core files are changed: - * - * editor/add_news.php: - * - */ - -/****** - * Open editor/add_news.php, check if changes need to be made, make them if neccessary - */ - -$installed=FALSE; -$needle = "if (!\$msg->containsErrors() && (!isset(\$_POST['setvisual']) || isset(\$_POST['submit']))) {"; -$changes = "\n\t/***** -\t* Added by announcement_subscription: Send mail to announcement subscribers -\t*/\n -\t \$subscriberMod =& \$moduleFactory->getModule('announcement_subscription'); -\t if (\$subscriberMod->isEnabled() && !\$subscriberMod->isMissing()) { -\t\t include_once(AT_MODULE_PATH . 'announcement_subscription/sendmail.php'); -\t } \n -\t/***** -\t* End announcement_subscription -\t*/ \n "; - - -$filename=('../../editor/add_news.php'); -if(!is_writable($filename)){ -$msg->addError('ANOUNCEMENTSUB_INSTALL_UNWRITE'); -}else{ - $data = file($filename); - foreach($data as $line){ - $newfile .= (strpos($line,$needle))? $line . "\n" . $changes . "\n": $line; - if(strpos($line,'announcement_subscription/sendmail.php')){ - $msg->addInfo('ANNOUNCEMENTSUB_ALREADYINSTALLED_ADDNEWS'); - $installed=TRUE; - } - } - - if (!$installed) { - $file = fopen('$filename','w'); - if(fwrite($file,$newfile)){ - $msg->addFeedback('ANNOUNCEMENTSUB_INSTALL_ADDNEWS'); - }else{ - $msg->addError('ANNOUNCEMENTSUB_INSTALL_ADDNEWS'); - } - fclose($file); - } -} - -?> diff --git a/mods/announcement_subscription/module_uninstall.php b/mods/announcement_subscription/module_uninstall.php deleted file mode 100644 index 52d8f8129..000000000 --- a/mods/announcement_subscription/module_uninstall.php +++ /dev/null @@ -1,31 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/announcement_subscription/readme.txt b/mods/announcement_subscription/readme.txt deleted file mode 100755 index 1bd3cf5ac..000000000 --- a/mods/announcement_subscription/readme.txt +++ /dev/null @@ -1,25 +0,0 @@ -This module installes the following into the file /editor/add_news.php: - - /***** - * Added by announcement_subscription: Send mail to announcement subscribers - */ - - $subscriberMod =& $moduleFactory->getModule('announcement_subscription'); - if ($subscriberMod->isEnabled() && !$subscriberMod->isMissing()) { - include_once(AT_MODULE_PATH . 'announcement_subscription/sendmail.php'); - } - - /***** - * End announcement_subscription - */ - -These lines are added immediately after the line - - if (!$msg->containsErrors() && (!isset($_POST['setvisual']) || isset($_POST['submit']))) { - -which should be around line 70 of the file. add_news.php needs to be writable for this module -to install properly - if the file is unwritable you will need to change the file permissions -before installing the mod. There are different ways to do this depending on the web server software, -please see the web server documentation for details. - -To learn more about file permissions, see http://en.wikipedia.org/wiki/Permissions diff --git a/mods/announcement_subscription/sendmail.php b/mods/announcement_subscription/sendmail.php deleted file mode 100755 index b20a3dcb9..000000000 --- a/mods/announcement_subscription/sendmail.php +++ /dev/null @@ -1,51 +0,0 @@ - $row['email'], 'full_name' => $row['first_name'] . ' '. $row['second_name'] . ' ' . $row['last_name'], 'member_id'=>$row['member_id']); - } - } - - - - // SEND MAIL - if ($subscriber_email_list) { - require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php'); - foreach ($subscriber_email_list as $subscriber){ - $mail = new ATutorMailer; - $mail->AddAddress($subscriber['email'], get_display_name($subscriber['member_id'])); - $body = _AT('announcement_notify_body1', $_SESSION['course_title'], 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['title']."\n"; - $body .= $_POST['body_text']."\n"; - $mail->FromName = $_config['site_name']; - $mail->From = $_config['contact_email']; - $mail->Subject = _AT('announcement_notify_subject'); - $mail->Body = $body; - - if(!$mail->Send()) { - $msg->addError('SENDING_ERROR'); - } - - unset($mail); - } - } - - - -?> diff --git a/mods/announcement_subscription/side_menu.inc.php b/mods/announcement_subscription/side_menu.inc.php deleted file mode 100755 index c33c36f38..000000000 --- a/mods/announcement_subscription/side_menu.inc.php +++ /dev/null @@ -1,12 +0,0 @@ -'.$sub_button.''; - - - $savant->assign('dropdown_contents', $box_content); - - $savant->assign('title', _AT('announcement_subscription')); - $savant->display('include/box.tmpl.php'); -?> diff --git a/mods/announcement_subscription/subscribe.php b/mods/announcement_subscription/subscribe.php deleted file mode 100755 index 57e50747d..000000000 --- a/mods/announcement_subscription/subscribe.php +++ /dev/null @@ -1,54 +0,0 @@ -AddAddress($user_email['email'], get_display_name($_SESSION['member_id'])); - $mail->FromName = $_config['site_name']; - $mail->From = $_config['contact_email']; - -// SUBSCRIBE OR UNSUBSCRIBE? TAKE APPROPRIATE ACTION - if ($_GET['a'] == "subscribe"){ - // CHECK FOR EXISTING TABLE ENTRY - $check = mysql_fetch_row(mysql_query("SELECT COUNT(*) FROM ".TABLE_PREFIX."courses_members_subscription WHERE course_id=".$_SESSION['course_id']." AND member_id=".$_SESSION['member_id'])); - if(empty($check[0])){ - $sql = "INSERT INTO ".TABLE_PREFIX."courses_members_subscription (member_id,course_id,subscribe) VALUES(".$_SESSION['member_id'].",".$_SESSION['course_id'].",'1')"; - } else { - $sql = "UPDATE ".TABLE_PREFIX."courses_members_subscription SET subscribe='1' WHERE course_id=".$_SESSION['course_id']." AND member_id=".$_SESSION['member_id']; - } - $mail->Subject = _AT('announcement_subscribe_subject'); - $body = _AT('announcement_subscribe_body', $_SESSION['course_title'], AT_BASE_HREF.'bounce.php?course='.$_SESSION['course_id']); - $msg->addFeedback('ANNOUNCEMENTSUB_SUBSCRIBE'); - }elseif ($_GET['a'] == "unsubscribe"){ - $sql = "UPDATE ".TABLE_PREFIX."courses_members_subscription SET subscribe='0' WHERE course_id=".$_SESSION['course_id']." AND member_id=".$_SESSION['member_id']; - $mail->Subject = _AT('announcement_subscribe_subject'); - $body = _AT('announcement_unsubscribe_body', $_SESSION['course_title'], AT_BASE_HREF.'bounce.php?course='.$_SESSION['course_id']); - $msg->addFeedback('ANNOUNCEMENTSUB_UNSUBSCRIBE'); - }else { - die("Error: action not defined"); - } - -// FIX SUBSCRIPTION IN DB - mysql_query($sql) or die(mysql_error()); - -// FINISH UP MAIL AND SHIP IT OFF - - $mail->Body = $body; - - // UNCOMMENT THE FOLLOWING 3 LINES IF YOU WANT ATUTOR TO SEND AN EMAIL TO THE USER WHEN THE USER SUBSCRIBES/UNSUBSCRIBES TO A NEWSFEED - //if(!$mail->Send()) { - // $msg->addError('SENDING_ERROR'); - //} - - unset($mail); - -// GO HOME - -header('Location: ../../index.php'); - -?> diff --git a/mods/announcement_subscription/subscribe_button.php b/mods/announcement_subscription/subscribe_button.php deleted file mode 100755 index 85fb2364b..000000000 --- a/mods/announcement_subscription/subscribe_button.php +++ /dev/null @@ -1,15 +0,0 @@ - diff --git a/mods/assignment_dropbox/README b/mods/assignment_dropbox/README deleted file mode 100644 index 7ddbcebc3..000000000 --- a/mods/assignment_dropbox/README +++ /dev/null @@ -1,25 +0,0 @@ -Assignment Dropbox README - -This module can be installed with ATutor for: -1) instructors to manage students' assignment submissions. -2) students to submit assignments. - -* How to install -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: - -unzip assignment_dropbox.zip - -2. Login to ATutor as the administrator and run Install Module under the Modules tab, select the Assignment Dropbox module, which should be listed as available to be installed when the module has been unzipped into the mods directory - -3. Once the module has been installed, and enabled, login as instructor, click on tab "Manage", the "Assignment Dropbox" is listed onlong with the Assignment Manager. Instructors make the Assignment Dropbox available to students through "Course Tools". - -* How to use Assignment Dropbox -1. for instructors - Assignment Dropbox provides the same functionality as assignment submission in the "File Storage" tool, but with fewer steps and with a more intuitive interface. As an extension of "File Storage", when instructors create an assignment for a group, this group must have "File Storage" enabled, otherwise, the students are not able to submit assignments via Assignment Dropbox. If the Assignment Dropbox module is installed, a drop box is setup automatically when an assignment is created for all students in a course. - -2. for students - Once the Assignment Dropbox has been turned on in Course Tools by the instructor, a link "Assignment Dropbox" is displayed either on the course home page or as a main navigation tab. The dropbox lists all the assignments that are assigned to the student viewing, up to the submission "cut off date" set in an assignment's properties (set under "Accept Late Submissions). The student can upload or delete assignment files up until the "due date", after which assignment submissions are locked and can no longer be modified by students. The Delete button is greyed out when the due date is passed. The Upload button remains available to students until the cut off date. \ No newline at end of file diff --git a/mods/assignment_dropbox/assignment_dropbox.inc.php b/mods/assignment_dropbox/assignment_dropbox.inc.php deleted file mode 100644 index 748725ff2..000000000 --- a/mods/assignment_dropbox/assignment_dropbox.inc.php +++ /dev/null @@ -1,81 +0,0 @@ - 0) RETURN true; - - // enrolled students can submit the assignments that assign to him/her - if ($_SESSION['member_id'] && $_SESSION['enroll']) { - // assignments that are assigned to all students - $sql = "SELECT count(*) cnt FROM ".TABLE_PREFIX."assignments - WHERE assignment_id = ".$owner_id." - AND assign_to=0 - AND course_id=".$_SESSION[course_id]; - $result = mysql_query($sql, $db); - $row = mysql_fetch_assoc($result); - - if ($row['cnt'] > 0) RETURN true; - - // assignments that are assigned to a group, - // and this group has "file storage" tool available - // and the student is in this group - $groups_list = implode(',',$_SESSION['groups']); // the groups that the student belongs to - $sql = "SELECT count(*) cnt - FROM ".TABLE_PREFIX."groups_types gt, ".TABLE_PREFIX."groups g, ".TABLE_PREFIX."assignments a - WHERE g.group_id in (".$groups_list.") - AND g.group_id in (SELECT group_id FROM ".TABLE_PREFIX."file_storage_groups) - AND g.type_id = gt.type_id - AND gt.course_id = $_SESSION[course_id] - AND gt.type_id = a.assign_to - AND a.assignment_id = ".$owner_id; - $result = mysql_query($sql, $db); - $row = mysql_fetch_assoc($result); - - if ($row['cnt'] > 0) RETURN true; - } - } - - return false; -} - -?> \ No newline at end of file diff --git a/mods/assignment_dropbox/assignment_dropbox.png b/mods/assignment_dropbox/assignment_dropbox.png deleted file mode 100644 index 62eb93848d97d08374beb390bcfd4558e6c1ac29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4929 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 diff --git a/mods/assignment_dropbox/assignment_dropbox_sm.png b/mods/assignment_dropbox/assignment_dropbox_sm.png deleted file mode 100644 index 47585a4ce745373f028821dff256f00b63dd9578..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 465 zcmV;?0WSWDP)$_nhLg+^h+lxv0G{W8>$+guHcY2e z>><+!IzS3VT+9r}^PCK0(;dfYdk9bzg*JiNPQb!*Z00rYS(yM$(>>@@?*vjQcv&o4 zAU~B~fyF&*CMs2fwY^K3J>bx{wFPu1*f~3g24V%P0 zYum_MwaLIW6Y*cb_p>Yu{vxd9|Azsy<~tAIf12UpM}PqU@>&L*YP+e;00000NkvXX Hu0mjf2F=9n diff --git a/mods/assignment_dropbox/flag.png b/mods/assignment_dropbox/flag.png deleted file mode 100644 index a64f45664182a14b97630613d0883d6d6601bf79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 659 zcmV;E0&M+>P);v&#=QHxwyiy(+-k^5Ht z15%5EAzZgD2y!d5%SA1MFfb?(vP@i9h+$?v9aG=@cyHc&r^Sp@7!rQrZocQ9bH3m2 zy@<$_Lb3Sz>66Dda-csB_Y5vv9~^#vxvzJ2XsChzzyS8fubuv`H?MM|{T&Y*FN}24 zKZIW>#Jk^CzRdJ>PUXKYPyTo}KYtr406Az*fPD{Kqm-Ij-`jiM?*6>hl&~Sc1)hiH zmvthHdb9H%#*(ofb53WLpLyjauM`wZ<=~W|CIqS#(Z)b)W2_5!vhx&eD5Hy>lQ3)(YEcw`VU22 tf#W!9sZ=U?)B$w`>2!KmL>7-a;5R98@H6MrYCiw~002ovPDHLkV1mN2A@%?O diff --git a/mods/assignment_dropbox/index.php b/mods/assignment_dropbox/index.php deleted file mode 100644 index f034c1693..000000000 --- a/mods/assignment_dropbox/index.php +++ /dev/null @@ -1,396 +0,0 @@ -addError('ACCESS_DENIED'); - header('Location: index.php'); - exit; -} - -// action - Upload -if (isset($_POST['upload']) && isset($_POST['owner_id'])) { - // 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.'mods/_standard/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 - (owner_type, owner_id, member_id, folder_id, - parent_file_id, date, num_comments, num_revisions, file_name, - file_size, description) - VALUES ($owner_type, $_POST[owner_id], $_SESSION[member_id], $_POST[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('ASSIGNMENT_HANDED_IN'); - header('Location: index.php'); - exit; - } else { - $msg->addError('FILE_NOT_SAVED'); - } - } - header('Location: index.php'); - exit; -} - -// action - Delete Files/Folders (pre-confirmation) -$files = array(); -foreach ($_POST as $name => $val) { - if (substr($name, 0, 5) == 'files') $files = $val; -} -if ($has_priv && isset($_POST['delete']) && is_array($files)) { - $hidden_vars = array(); - $hidden_vars['owner_id'] = $_REQUEST['owner_id']; - $file_list_to_print = ''; - $files = implode(',', $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=$_REQUEST[owner_id] ORDER BY file_name"; - $result = mysql_query($sql, $db); - while ($row = mysql_fetch_assoc($result)) { - $file_list_to_print .= '
  • '.htmlspecialchars($row['file_name']).'
  • '; - } - $msg->addConfirm(array('FILE_DELETE', $file_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 ($has_priv && isset($_POST['submit_yes'])) { - - // handle the delete - if (isset($_POST['files'])) { - $files = explode(',', $_POST['files']); - } - if (isset($files)) { - foreach ($files as $file) { - fs_delete_file($file, $owner_type, $_REQUEST['owner_id']); - } - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - } - - header('Location: index.php'); - exit; -} -// action - Cancel Delete -else if ($has_priv && isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - header('Location: index.php'); - exit; -} - -// display -$groups_list = implode(',',$_SESSION['groups']); - -$sql = ''; -if (authenticate(AT_PRIV_ASSIGNMENTS, AT_PRIV_RETURN)) { // instructor - $sql = "SELECT * FROM ".TABLE_PREFIX."assignments WHERE course_id=$_SESSION[course_id] ORDER BY title"; -} else { // students - if ($groups_list <> '') { - $sql = "(SELECT assignment_id, a.title, date_due, g.group_id - FROM ".TABLE_PREFIX."groups_types gt, ".TABLE_PREFIX."groups g, ".TABLE_PREFIX."assignments a - WHERE g.group_id in (".$groups_list.") - AND g.group_id in (SELECT group_id FROM ".TABLE_PREFIX."file_storage_groups) - AND g.type_id = gt.type_id - AND gt.course_id = $_SESSION[course_id] - AND gt.type_id = a.assign_to - AND (a.date_cutoff=0 OR UNIX_TIMESTAMP(a.date_cutoff) > ".time().")) - UNION - "; - } - $sql .= "(SELECT assignment_id, title, date_due, 0 - 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"; -} -$assignment_list_result = mysql_query($sql, $db); - -$_custom_css = $_base_path . 'mods/assignment_dropbox/module.css'; // use a custom stylesheet - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> -
    -'); - while ($assignment_row = mysql_fetch_assoc($assignment_list_result)) { - $owner_id = $assignment_row['assignment_id']; - - if ($assignment_row['group_id'] == 0) { - $folder_id = $_SESSION['member_id']; - } else { - $folder_id = $assignment_row['group_id']; - } - - // default sql for instructor: find all submitted assignments - $sql = "SELECT * FROM ".TABLE_PREFIX."files - WHERE owner_type=$owner_type - AND owner_id=$owner_id - AND parent_file_id=0"; - // students: find his own submitted assignments - if (!authenticate(AT_PRIV_ASSIGNMENTS, AT_PRIV_RETURN)) { - $sql .= " AND folder_id=$folder_id - ORDER BY date DESC, file_name, file_size"; - } - $result = mysql_query($sql, $db); -?> -
    -

    - - ';" class="floatleft"> - - - - - - - -
    - 0) { ?> - - -
    -


    - : -
    - - - -
    - - - - \ No newline at end of file diff --git a/mods/assignment_dropbox/module.css b/mods/assignment_dropbox/module.css deleted file mode 100644 index cce95ccd7..000000000 --- a/mods/assignment_dropbox/module.css +++ /dev/null @@ -1,15 +0,0 @@ -div.flagdiv { - float:left; - padding-left:0.5em; -} - -.floatleft { - float:left; -} - -div.assignment-detail { - -moz-border-radius:0.3em 0.3em 0.3em 0.3em; - background:none repeat scroll 0 0 #F7F7F7; - margin:1em 1em 2em 2em; - width:95%; -} \ No newline at end of file diff --git a/mods/assignment_dropbox/module.php b/mods/assignment_dropbox/module.php deleted file mode 100644 index cade9ae07..000000000 --- a/mods/assignment_dropbox/module.php +++ /dev/null @@ -1,44 +0,0 @@ -_list['assignment_dropbox'] = array('title_var'=>'assignment_dropbox','file'=>'mods/assignment_dropbox/sublinks.php'); - -/******* - * add the admin pages when needed. - */ -//if (admin_authenticate(AT_ADMIN_PRIV_assignment_dropbox, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { -// $this->_pages[AT_NAV_ADMIN] = array('mods/assignment_dropbox/index_admin.php'); -// $this->_pages['mods/assignment_dropbox/index_admin.php']['title_var'] = 'assignment_dropbox'; -// $this->_pages['mods/assignment_dropbox/index_admin.php']['parent'] = AT_NAV_ADMIN; -//} - -/******* - * student page. - */ -$this->_pages['mods/assignment_dropbox/index.php']['title_var'] = 'assignment_dropbox'; -$this->_pages['mods/assignment_dropbox/index.php']['icon'] = 'mods/assignment_dropbox/assignment_dropbox_sm.png'; -$this->_pages['mods/assignment_dropbox/index.php']['img'] = 'mods/assignment_dropbox/assignment_dropbox.png'; -$this->_pages['mods/assignment_dropbox/index.php']['text'] = _AT('assignment_dropbox_text'); -$this->_pages['mods/assignment_dropbox/index.php']['parent'] = 'mods/_standard/assignments/index_instructor.php'; - -$this->_pages['mods/_standard/assignments/index_instructor.php']['children'] = - array_merge(is_array($this->_pages['mods/_standard/assignments/index_instructor.php']['children']) ? $this->_pages['mods/_standard/assignments/index_instructor.php']['children'] : array(), array('mods/assignment_dropbox/index.php')); - -?> \ No newline at end of file diff --git a/mods/assignment_dropbox/module.sql b/mods/assignment_dropbox/module.sql deleted file mode 100644 index c299825c5..000000000 --- a/mods/assignment_dropbox/module.sql +++ /dev/null @@ -1,8 +0,0 @@ -# sql file for assignment dropbox module - -INSERT INTO `language_text` VALUES ('en', '_module','assignment_dropbox','Assignment Dropbox',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','assignment_dropbox_text','Submit assignments.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','flag_text','%s indicates files have been handed in.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','delete_text','Note: "Delete" button is only available before the assignment due date.',NOW(),''); - -UPDATE `language_text` SET TEXT='Assignments can be submitted using the Assignment Dropbox or through My Files in the File Storage tool. Assign an assignment to all students, or create a group and enable File Storage for that group, to add an assignment drop-box.' WHERE term='AT_INFOS_ASSIGNMENT_FS_SUBMISSIONS'; diff --git a/mods/assignment_dropbox/module.xml b/mods/assignment_dropbox/module.xml deleted file mode 100644 index e4ae0e51e..000000000 --- a/mods/assignment_dropbox/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Assignment Dropbox - This module provides a easy way for students to submit assignments and instructors to manage assignment submissions. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.2 - 2010-10-25 - stable - - - diff --git a/mods/assignment_dropbox/module_install.php b/mods/assignment_dropbox/module_install.php deleted file mode 100644 index 5c0944c56..000000000 --- a/mods/assignment_dropbox/module_install.php +++ /dev/null @@ -1,52 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/assignment_dropbox/module_uninstall.php b/mods/assignment_dropbox/module_uninstall.php deleted file mode 100644 index 0b7022e52..000000000 --- a/mods/assignment_dropbox/module_uninstall.php +++ /dev/null @@ -1,30 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/assignment_dropbox/sublinks.php b/mods/assignment_dropbox/sublinks.php deleted file mode 100644 index 93f0351d4..000000000 --- a/mods/assignment_dropbox/sublinks.php +++ /dev/null @@ -1,62 +0,0 @@ - '') { - $sql = "(SELECT a.title, date_due - FROM ".TABLE_PREFIX."groups_types gt, ".TABLE_PREFIX."groups g, ".TABLE_PREFIX."assignments a - WHERE g.group_id in (".$groups_list.") - AND g.group_id in (SELECT group_id FROM ".TABLE_PREFIX."file_storage_groups) - AND g.type_id = gt.type_id - AND gt.course_id = $_SESSION[course_id] - AND gt.type_id = a.assign_to - AND (a.date_cutoff=0 OR UNIX_TIMESTAMP(a.date_cutoff) > ".time().")) - UNION - "; - } - $sql .= "(SELECT 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 date_due DESC"; -} -$sql .= " LIMIT $link_limit"; -$result = mysql_query($sql, $db); - -if (mysql_num_rows($result) > 0) { - while ($row = mysql_fetch_assoc($result)) { - /**** - * SUBLINK_TEXT_LEN, VALIDATE_LENGTH_FOR_DISPLAY are defined in include/lib/constance.lib.inc - * SUBLINK_TEXT_LEN determins the maxium length of the string to be displayed on "detail view" box. - *****/ - $title = $row['title'] . ' ('._AT("due_date").': '.$row['date_due'].')'; - $list[] = ''. - $title .''; -// $list[] = ' SUBLINK_TEXT_LEN ? ' title="'.$row['value'].'"' : '') .'>'. -// validate_length($row['value'], SUBLINK_TEXT_LEN, VALIDATE_LENGTH_FOR_DISPLAY) .''; - } - return $list; -} else { - return 0; -} - -?> \ No newline at end of file diff --git a/mods/atalker/ATalker-italian-voice-README.txt b/mods/atalker/ATalker-italian-voice-README.txt deleted file mode 100644 index 6e90ace81..000000000 --- a/mods/atalker/ATalker-italian-voice-README.txt +++ /dev/null @@ -1,70 +0,0 @@ -THE ITALIAN VOICE FOR ATALKER (ATutor 1.5.1 pl2 - ATalker 0.1) - -Once You've completed the previous installations of Atalker, Atalker­_theme, FestivalTTS and Mbrola described on the official ATalker README: - -- install the italian language package from /packages dir inside the ATalker-it-addon.tar.gz archive; - -- Download the Italian-voices-package for Festival Text-to-Speech System at: - -http://www.pd.istc.cnr.it/Software/It-Festival/Italian-FESTIVAL.zip. - -The available Italian voices are in lp_diphone.zip and pc_diphone.zip sub-archives (female and male voices respectively); - -- unzip the "Italian" directory placed inside the above sub-archive lp_diphone.zip (or pc_diphone.zip) and copy in -[Festival-dir]/lib/voices/ (Where [Festival-dir] is your typical "/usr/share/festival/" directory); -- unzip the directory "ifd" placed inside the sub-archive "lex_ifd.zip" (it will generate the tree: festival/lib/dicts/ifd etc.) and - copy it in your own Festival dirtree ([Festival-dir]/lib/dicts/); -- unzip the directory "italian_scm" placed inside the sub-archive "italian_scm.zip" of Italian-Festival.zip -(it will generate the tree: festival/lib/italian_scm etc.) and copy it in -"/usr/lib/festival/" (or equivalent path on your system, not on [Festival-dir]/lib/dicts/); ; - -To avoid "SIOD ERROR: could not open file [...]/synthesis.scm", -modify the file: [Festival-dir]/lib/voices/italian/lp_diphone/festvox/lp_diphone.scm -at line 119 (substitute the term "libdir" with "datadir"). For male voice the lp_diphone directory changes in pc_diphone. - -To avoid "SIOD ERROR: unbound variable" during the setting-up of "lp_diphone" on interactive mode of Festival, -find the string "da noi" (line 120) on the file: [Festival-dir]/lib/voices/italian/lp_diphone/festvox/lp_diphone.scm -and rewrite the comment to a single line. - -NOTE: On the two steps above, the "lp_diphone" directory changes in the "pc_diphone" one for the male voice. - - - -SETTING UP MBROLA ITALIAN VOICES - -The available Italian voices are in lp_mbrola.zip and pc_mbrola.zip sub-archives (female and male voices respectively); - -Copy the directory "lp_mbrola" found in lp_mbrola_unix.zip (placed inside the archive "Italian-Festival.zip" cited above) -in [Festival-dir]/lib/voices/Italian/ (Where [Festival-dir] is your typical "/usr/share/festival/" directory); - -download the file (for the female voice) at: http://tcts.fpms.ac.be/synthesis/mbrola/dba/it4/it4-010926.zip -(http://tcts.fpms.ac.be/synthesis/mbrola/dba/it3/it3-010304.zip for the male voice) and unzip in [Festival-dir]/lib/voices/Italian/lp_mbrola/ (or pc_mbrola) - -NOTE: It's necessary moving the /it3 (or /it4) deflated directory [Festival-dir]/lib/voices/italian/lp_mbrola/ (or Pc_mbrola/). - -Change the term "libdir" with "datadir" in: -[Festival-dir]/lib/voices/italian/lp_mbrola/festvox/lp_mbrola.scm (line 106) (or in pc_mbrola.scm) -and rewrite the comment containing the term "moduli" (line 107) inside the same file on a single line, if it's on two. - -Create a symbolical link in /usr/sbin/mbrola to the /usr/local/bin/mbrola file (for Apache relative addressing). - - -PATCHING ATALKER - - -1) Please, BACKUP ATUTOR. - -2) unzip the files in the "ATutor" directory placed inside the ATalker-italian.zip archive on your own installed ATutor directory (create and deflate directory and files to the existing one "ATutor" dirtree); - - -3) Execute the queries placed in "sql" directory (placed in Atalker-italian.zip) (after having deleted the suitable records if necessary) on ATUTOR DB; - - - - - - - - - - diff --git a/mods/atalker/README_ATUTOR_MODULE b/mods/atalker/README_ATUTOR_MODULE deleted file mode 100644 index c7b57a1c0..000000000 --- a/mods/atalker/README_ATUTOR_MODULE +++ /dev/null @@ -1,212 +0,0 @@ -README for the ATutor 1.5.2 ATalker Module - -ATalker is a text-to-speech utility for reading text out loud over the Web with synthisized speech, available as an addon for ATutor. With the ATalker Theme installed, ATalker also provides an audio interface for ATutor, and reads feedback and error messages out loud. - -This version of ATalker (the second version) was developed on a Linux based system, but should, in theory, work on other systems that support the Festival Text-to-Speech system. It differd from the previous version on;y in that it include the ATutor module files. ATalker can currently produce English and Spanish voices. The potential for many other languages is available through the Mbrola project for those who would like to contribute. This version of ATalker is based on the Festival 1.4.3 Speech Synthesis System, though should function properly with Festival 2.0. - -1. Requirements - *Server - *Client - *Limitations -2. Installation and Integration with ATutor - *ATalker Install - *ATalker Integration -3. Using ATalker - *Students - *Instructors - *Administrators - ---------- - -**1 Requirements** (In addition to a working ATutor) -*Server*: - 1. Festival 1.4.3 or greater. Festival is a text-to-speech engine developed at the University of Edinburgh. Festival needs to be installed and functioning properly on your system before you attempt to install ATalker. - - Festival: - http://www.cstr.ed.ac.uk/projects/festival/ - - The ATalker reader will function with just the base Festival system, though it will only produce WAV audio files, which are very large, take a long time to download, and essentially make ATalker not very useful. You will want to install and MP3 or OGG encoder to convert WAV files to a more manageable size. MP3 or OGG files are about 1/10th the size of a WAV file. At least one of the following encoders should be installed on the system, and be available in the system's PATH variable (so it can be started from anywhere on the system). To determine if you have an encoder installed, type "lame", "oggenc, or "bladeenc" at the command prompt. If you get something other than "does not exists", chances are the encoder is installed. ATalker will try to determine which encoders are installed and automatically make those audio formats available. - - To create an audio interface for the ATalker theme, one of these encoders must be installed. WAV files are otherwise too large to be used for interface speech. - - 2. MP3 & OGG Audio Encoders (optional but reccommended) - 1. LAME MP3 encoder (Unix/Linux and Windows versions) - http://sourceforge.net/projects/lame/ - - 2. Bladeenc MP3 encoder (Unix/Linux, Mac, and Windows versions) - http://bladeenc.mp3.no/ - - 3. Oggenc OGG encoder (available through vorbis-tools for Unix/Linux and Windows) - http://www.vorbis.com/ - - 3. Mbrola Binary and Voices (optional additional voices) - http://tcts.fpms.ac.be/synthesis/mbrola.html - http://www.cstr.ed.ac.uk/projects/festival/mbrola.html - -*Client*: - A user's browser must be setup to read ATalker speech files. On Windows systems, default settings are often sufficeint, or when opening a speech file in a browser for the first time, users can choose which application to read the file with, and there after all such file will be read with that application. On Linux/Unix based systems it is sometimes necessary to configure browser helper applications to read these files. The mime types to add to the helper applications list are audio/wav, audio/x-ogg, and audio/x-mp3. - - The following are potential audio players that might be used to read ATalker audio files: - - Windows - IE - recommended: winamp (mp3,ogg,wav) - alternates: windows media player (mp3/wav) - Firefox - Quicktime for Windows. - Linux/Unix - Mozilla - recommended for 2.4 kernel: xmms (ogg/mp3/wav), mplayer (ogg/mp3/wav) - recomended for 2.6 kernel: mplayerplug-in for mozilla/netscape (ogg/mp3/wav), netscape-plugger(ogg/mp3/wav) - alternates: xmms - Opera - - -*Limitations and known issues*: - - The ATutor content directory must exists inside the ATutor installation. ATalker will not work with ATutor where the content/ directory exists outside the ATutor installation. - - Any current browser can be used to generate speech with ATalker, and when the appropriate helper application or plugin is installed, be used to read the files outloud. - - Linux mozilla users will require a version 2.6 kernel with a working version of ALSA (Advanced Linux Sound Architecture) installed, to take advantage of the *audio interface* features. All other features will function with 2.4 versions of the kernel (and earlier). The audio interface has been working on a Linux 2.6 system with the mplayerplug-in installed for Mozilla 1.7, but only for mp3 voice files. - - The audio interface works by default using Internet Explorer on Windows, and works with Netscape, Mozilla, Firefox, and Opera with the appropriate plugin installed (an audio player that plays mp3 or ogg files). - - Javascript is required for the popup ATalker, and for the audio interface reader, and some administrator voice manager functions. - - Though it is poreferable to create ogg files for the audio interface, in general mp3 files will be better supported across systems. - - Embed vs Object: Though we should be using the HTMLOBJECT element as the preferred method of preloading speech files, EMBED is still more broadly supported, so for now we have choosen to use the EMBED element. Support for the OBJECT element will come as it becomes more widely supported. - - Bandwidth: Unless you are on a T1 or higher network, you will likely notice that pages take longer to load when the ATutor theme is enabled. It will also take a little while to generate speech files. On DSL/Cable the delays are noticable, but not excessive. If you are using a modem, the ATalker theme, and using ATalker in general, is going to be slow. - - Server Power: The processing power of the server will also have an effect on the time it takes to generate new speech files. The speech generation process is still somewhat time consuming. Where speech files already exist, server processing power will not have much effect. Connection speed will. Creating and serving speech files works best with more cpu power, and with a faster internet connection speed. - - Where an error or feedback message is new, or contains dynamic information such as a file name of a file being deleted for example, ATalker will generate a new copy of the speech file, otherwise it will try to retrieve a copy of an existing speech file. When new files have to be generated, page loading speeds may not be as fast as usual. - - title, alt, input values: It is currently not possible to create interface voice files for language that appears within HTML attributed. In the future a parser will be developed to recognize attribute values, and handle speech files for those values without breaking the surrounding HTML. - -**2. Installation with ATutor 1.5.2** -(see: ATalker .01 for ATutor 1.5 and 1.5.1) - - Like most other ATutor modules, the source code of the module is unzipped into the ATutor/mods/ directory, then the module installer is run. If you plan on using the ATalker theme to add speech to the ATutor interface, see the section below for additional installation details - - ATalker Install: - - *Note*: For now ATalker will only function if the ATutor content/ directory is located inside your ATutor installation, and the AT_FORCE_GET_FILE constant is set to FALSE in include/config.inc.php. For future versions we will try to handle speech files so they can be located outside the ATutor installation, or in the MySQL database. - - 1. First upload the atutor_talker.0.2.tar.gz into the mods directory, then unzip the file. This will create a directory called "atalker" (i.e mods/atalker/) - - cd ATutor/mods/ - tar xzvf atalker.x.x.tar.gz - - 2. Login to ATutor as the admistrator and run the module installer. Select the Modules tab, choose Intall module, then select ATalker from the list of available not yet installed modules. Read through the Details then press Yes to confirm the installation - - 3. Enabled the ATalker module after it has been installed. - - ATalker should now be available as a TTS reader for students and instructors, and as a speech generation tool for Instructors and administrators. Read on if you want to add/create a speech enabled theme. - - -**3.Creating an ATalker Theme** - Optionally you can create an ATalker enabled theme, or download and install the Default ATalker theme with each of the following features already available (see below). - - A) Install the ATalker theme (the ATutor default theme with speech enabled), which includes mouseover/onfocus speech, and audio feadback and error messages. See atutor.ca for the most recent version of the ATalker theme. - - http://atutor.ca/atalker/downloads.php - (If you have installed the ATalker theme jump to Step 5 in section B below. If you are creating a new speech enabled theme, begin at Step 1) - - - AND/OR - - B) Create your own ATalker enabled theme. . - - 1. To create your own ATalker enabled theme, copy the following Javascript into the theme/theme_name/include/header.tmpl.php file near the Jump Menu to allow users to open ATalker into a new window and have it available while navigating through ATutor. - - - - Or. you can just insert a link somewhere in one of the other theme templates something like - - Open ATalker - - - - - 2. Add the reader Javascript to the theme header template themes/theme_name/include/header.tmpl.php. Place the following script in the head area of the HTMLin the file. - - - 3. Add the ATalker controls themes/theme_name/include/header.tmpl.php, immediately after the Global $msgs line near the bottom of the file, but before the $msg->printAll(); line. Like the following - - global $msg; - require(AT_INCLUDE_PATH."../mods/atalker/reader_controls.php"); - $msg->printAll(); - - - 4. Turn on ATalker by adding $atalker_on to the globals line at the top of themes/theme_name/include/header.tmpl.php, and assigning a value 1 "1" to it, as follows - - global $system_courses, $atalker_on; - $atalker_on = '1'; - - 5. Add the following lines to the _AT() function in include/lib/output.inc.php just before the last line "return $outString". This adds speech output from ATalker to the ATutor language output function, and collects a list of language items to preload. - - - require($_SERVER['DOCUMENT_ROOT'].$_base_path.'mods/atalker/template_reader.php'); - - - You will also need to add the $embed and $_base_path variables to the globals statement for the _AT() function in include/lib/output.inc.php, like so: - - global $_cache_template, $lang_et, $_rel_url, $_base_path, $embed; - - - You can create voice files using ATalker Administrator so ATutor interface feature will read outloud. You may want to manually create a list of language to generate speech for, then use the ATalker Administrator to create a voice for ATutor. See the administrator section in Using ATalker below. - - -**4. Using ATalker** - The ATalker addon provides speech output utilities for ATutor, for Students, Instructors, and Administrators: - -*Students* (and instructors and administrators): - ATalker includes a text reader that can be used to read text out loud, copied then pasted into the reader. ATalker also includes a SABLE/SSML reader that allows users to add their own text-to-speech markup to control various speech features such as pronunciation, volumn, emphasis, pitch etc. For more about these easy to learn markup language see the following links. The SABLE/SSML reader can also be used to read text that contains HTML (so the HTML is ignored). If available in the ATutor interface, ATalker has a popup version so it can be opened alongside ATutor as you navigate through courses. - - **Note that markup elements in the SABLE/SSML reader must be typed in uppercase fonts. See the following references for more about SABLE and SSML text-to-speech markup languages. - - SABLE Markup - http://www.bell-labs.com/project/tts/sable.html - - SSML Markup - http://www.w3.org/TR/speech-synthesis/ - - If the *ATalker Theme* is enabled, a mouse pointer, or the Tab key, can be used to read interface elements outloud when they recieve focus. Feedback and error messages will also be read outloud. - -*Instructors*: - Instructors and course members with ATalker privileges have the same features available to them as those described above for students, with the add ability to save files to the course content/ directory. A directory called "speech/" will be created to contain course speech files, and can be accessed through the course file manager. The Save tool can be used to generate audio files that can be linked into ATutor content pages, providing instructions, summaries, or perhaps audio copies of content pages etc. Using the SABLE/SSML reader TTS output can be formatted with markup to fine tune the audio output (see the references above). You could potentailly create TTS speech clips of two people talking, in different language, at different speeds, and different volumns, for example. The SABLE/SSML reader should be used to read text that contains HTML, otherwise the text reader will read the HTML tags along with the text. - - Instructors should use the MP3 or OGG audio formats for generating speech files. You may also generate files in WAV format, though they are very large, will take up a lot of space, and take a long time to download when students are listening to the files. MP3 is the more common format of the other two, supported by most current audio and multimedia application. OGG files are becoming more common, and are the preferred format. OGG is an open audio format that should be used where ever possible. - -*Administrators*: - If the ATalker theme has been installed, the system's administrator will want to generate voice files for ATutor so users can mouseover the interface to have it announced outloud. If the ATalker theme is not installed, then there isn't much to manage for an administrator, except the installation. - - Course size limits: - You may find that the *file size limits* placed on courses becomes a problem when instructors are generating lots of audio content, particularly if they save their content in WAV files. You might want to discourage using WAV files, and encourage using MP3 or OGG formats which are about 1/10th the size of WAV files. Set the following default values in include/config.inc.php to something larger. - - $MaxFileSize = 1048576; /* 1 MB */ - $MaxCourseSize = 10485760; /* 10 MB */ - - Also in course properties you can increase space available on a course by course basis. - - Generatong an Interface Voice: - Using the Manage ATutor Voice tool administrators can choose which interface items to make available with speech. If you choose to make the entire interface speech enabled, it can take a very long time to generate all the voice files. You may want to select a subset of interface items to add speech too, or generate speech files a few at a time. - - Use the text reader or the SABLE/SSML reader to adjust the voice to your liking. Then select the items from the list below the reader to generate their speech files. Voice items that contain HTML must be generated with the SABLE/SSML reader, otherwise the HTML will be read along with the text. You can also create other speech files that can be manually linked into the ATutor interface through theme templates to add various speech enhanced instructions, help,etc. - - Once your speech files are generated, they can be managed through the Voice Files tab in the ATalker Administrator - diff --git a/mods/atalker/admin/admin_index.php b/mods/atalker/admin/admin_index.php deleted file mode 100644 index d9a548b62..000000000 --- a/mods/atalker/admin/admin_index.php +++ /dev/null @@ -1,85 +0,0 @@ -addError($error); - -}else if ($_POST['type'] == "text"){ - - require(AT_INCLUDE_PATH.'../mods/atalker/text_reader.php'); - - }else if ($_POST['type'] == "sable"){ - - require(AT_INCLUDE_PATH.'../mods/atalker/sable_reader.php'); - } - -require_once(AT_INCLUDE_PATH.'../mods/atalker/admin/admin_voice.php'); - - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> - - \ No newline at end of file diff --git a/mods/atalker/admin/admin_voice.php b/mods/atalker/admin/admin_voice.php deleted file mode 100644 index fc23a4fc7..000000000 --- a/mods/atalker/admin/admin_voice.php +++ /dev/null @@ -1,251 +0,0 @@ -addError($error); - } - if(!$error){ - - foreach ($_POST['check'] as $lang_var){ - - $file_recieve = AT_SPEECH_URL.$lang_var.'.'.$_POST['file_type']; - $voice_file = AT_SPEECH_TEMPLATE_DIR.$lang_var.'.'.$_POST['file_type']; - - $sql = "SELECT * from ".TABLE_PREFIX."language_text WHERE language_code = '".$_SESSION['lang']."' AND term = '".$lang_var."'"; - $result = mysql_query($sql, $db); - $row = mysql_fetch_row($result); - - //remove markup from text input if not processed as SABLE formatted text - - if($_POST['type'] != "sable"){ - $row[3] = strip_tags($row[3]); - } - - if($_POST['file_type'] == "mp3"){ - - $file_out = AT_SPEECH_DIR.$lang_var.'.wav'; - - //If SABLE is being used, generate the SABLE markup as the input file - - - if($_POST['type'] == "sable"){ - - $file_in = AT_SPEECH_DIR.$lang_var.'.sable'; - $sable_out = ' - - - - - - - - '; - $sable_out .= $row[3]."."; - $sable_out .= ' - - - - - - '; - - - //write the SABLE file - $fp = fopen($file_in,'w'); - if (!$fp) { - echo _AT('AT_ERROR_TTS_NOT_CREATE_SABLE'); - exit; - } - fputs($fp, $sable_out); - fclose($fp); - $command = "text2wave $file_in -o $file_out -F 48000"; - }else{ - // If not SABLE being used, generate a standard scheme voice properties file and input text file. - $file_in = AT_SPEECH_DIR.$lang_var.'.txt'; - $scheme_out = AT_SPEECH_DIR.$now.'.scm'; - $file_props = "-mode --tts -eval ".$scheme_out; - - $fp = fopen($file_in,'w'); - if (!$fp) { - echo _AT('AT_ERROR_TTS_NOT_CREATE_TEXT'); - exit; - } - - fputs($fp, strip_tags($row[3]).'.'); - fclose($fp); - - $command = "text2wave $file_props $file_in -o $file_out -F 48000 -scale ".$_POST['volumn'].""; - } - - $file_out_mp3 = AT_SPEECH_DIR.$lang_var.'.mp3'; - - if(shell_exec('lame --longhelp')){ - $command2 = 'lame --quiet '.$file_out.' '. $file_out_mp3; - }else if (shell_exec('bladeenc -h')) { - $command2 = 'bladeenc -quiet '.$file_out.' '. $file_out_mp3; - } - - escapeshellcmd($command); - escapeshellcmd($command2); - passthru($command); - passthru($command2); - - if(file_exists(AT_SPEECH_TEMPLATE_DIR.$lang_var.'.ogg')){ - unlink(AT_SPEECH_TEMPLATE_DIR.$lang_var.'.ogg'); - } - - if(file_exists(AT_SPEECH_TEMPLATE_DIR.$lang_var.'.mp3')){ - unlink(AT_SPEECH_TEMPLATE_DIR.$lang_var.'.mp3'); - } - - if(copy($file_recieve, $voice_file)){ - $feedback = TTS_FILE_SAVED; - $msg->addFeedback($feedback); - }else{ - $error = TTS_FILE_SAVE_FAILED; - $msg->addError($error); - } - - - }else if($_POST['file_type'] == "ogg"){ - $file_out = AT_SPEECH_DIR.$lang_var.'.wav'; - - if($_POST['type'] == "sable"){ - $file_in = AT_SPEECH_DIR.$lang_var.'.sable'; - - $sable_out = ' - - - - - - - - '; - $sable_out .= $row[3]."."; - $sable_out .= ' - - - - - - '; - //write the SABLE file - $fp = fopen($file_in,'w'); - if (!$fp) { - echo _AT('AT_ERROR_TTS_NOT_CREATE_SABLE'); - exit; - } - - fputs($fp, $sable_out); - fclose($fp); - $command = "text2wave $file_in -o $file_out -F 48000"; - - } else{ - // If not SABLE being used, generate a standard scheme file and input text file. - $file_in = AT_SPEECH_DIR.$lang_var.'.txt'; - $scheme_out = AT_SPEECH_DIR.$now.'.scm'; - $file_props = "-mode --tts -eval ".$scheme_out; - - $fp = fopen($file_in,'w'); - if (!$fp) { - echo _AT('AT_ERROR_TTS_NOT_CREATE_TEXT'); - exit; - } - fputs($fp, $row[3].'.'); - fclose($fp); - $command = "text2wave $file_props $file_in -o $file_out -F 48000 -scale ".$_POST['volumn'].""; - } - - - $file_out_ogg = AT_SPEECH_DIR.$lang_var.'.ogg'; - $command2 = 'oggenc -quiet '.$file_out.' '. $file_out_ogg; - - escapeshellcmd($command); - escapeshellcmd($command2); - passthru($command); - passthru($command2); - - if(file_exists(AT_SPEECH_TEMPLATE_DIR.$lang_var.'.mp3')){ - unlink(AT_SPEECH_TEMPLATE_DIR.$lang_var.'.mp3'); - } - - if(file_exists(AT_SPEECH_TEMPLATE_DIR.$lang_var.'.ogg')){ - unlink(AT_SPEECH_TEMPLATE_DIR.$lang_var.'.ogg'); - } - - if(copy($file_recieve, $voice_file)){ - $feedback = TTS_FILE_SAVED; - $msg->addFeedback($feedback); - }else{ - $error = TTS_FILE_SAVE_FAILED; - $msg->addError($error); - } - - }else if($_POST['file_type'] == "wav"){ - $error = TTS_NO_WAV_ALLOWED; - $msg->addError($error); - } - } - - } - - }else if($_POST['remove'] && !$_GET['page']){ - - if(!$_POST['check']){ - - $error = array(TTS_FILES_REMOVED_CHECK); - $msg->addError($error); - - }else{ - - foreach ($_POST['check'] as $lang_var){ - if(file_exists(AT_SPEECH_TEMPLATE_DIR.$lang_var.".ogg")){ - - unlink(AT_SPEECH_TEMPLATE_DIR.$lang_var.".ogg"); - - }else if(file_exists(AT_SPEECH_TEMPLATE_DIR.$lang_var.".mp3")){ - - unlink(AT_SPEECH_TEMPLATE_DIR.$lang_var.".mp3"); - - }; - - } - - $feedback = array(TTS_FILES_REMOVED); - $msg->addFeedback($feedback); - - } - - } - -if($_GET['delete']){ - if(unlink(AT_SPEECH_TEMPLATE_DIR.$_GET['delete'])){ - $feedback = FILE_DELETED; - $msg->addFeedback($feedback); - }else{ - $error = TTS_FILE_DELETE_FAILED; - $msg->addError($error); - } - unset($_GET['delete']); -} -?> \ No newline at end of file diff --git a/mods/atalker/admin/admin_voice_files.php b/mods/atalker/admin/admin_voice_files.php deleted file mode 100644 index d1e7869fe..000000000 --- a/mods/atalker/admin/admin_voice_files.php +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - -
    -

    - - - - - -
    - '; - - while (false !== ($file = readdir($handle))) { - if($file != "." && $file !=".."){ - echo '
  • '.$file.' ('._AT('delete').')
  • '."\n"; - $files++; - } - } - if(!$files){ - echo _AT('no_files_found'); - - } - - echo ''; - - closedir($handle); - - } - ?> -
    -
    \ No newline at end of file diff --git a/mods/atalker/admin/admin_voice_html.php b/mods/atalker/admin/admin_voice_html.php deleted file mode 100644 index fc98968bc..000000000 --- a/mods/atalker/admin/admin_voice_html.php +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - -
    - - -
    - - -

    - - -

    - - - - - - - - - - - - 100){ - $chars = '('._AT(characters_total).' '.strlen($row['text']).')'; - $truncate = "..."; - } - echo ''."\n"; - $truncate = ""; - $chars = ''; - } - echo '
    : - - '.$p.' |'."\n"; - } - $p++; - } - - ?> - - -
     
    '.stripslashes(htmlspecialchars($row['text'])).'
    '; - ?> - -
    diff --git a/mods/atalker/admin/play_voice.php b/mods/atalker/admin/play_voice.php deleted file mode 100644 index d25ac5f21..000000000 --- a/mods/atalker/admin/play_voice.php +++ /dev/null @@ -1,38 +0,0 @@ - \ No newline at end of file diff --git a/mods/atalker/admin_voice.php b/mods/atalker/admin_voice.php deleted file mode 100644 index 99008d7e6..000000000 --- a/mods/atalker/admin_voice.php +++ /dev/null @@ -1,226 +0,0 @@ -addError($error); - } - } - if($_POST['file_type'] == "ogg"){ - - $command = 'oggenc --version'; - $command = escapeshellcmd($command); - - if(shell_exec($command) == ''){ - $error = "TTS_OGG_ENCODER"; - $msg->addError($error); - }else{ - $command2 = 'oggenc -quiet '.$file_out.' '. $file_out_ogg; - } - } - if(!$error){ - - foreach ($_POST['check'] as $lang_var){ - - $file_recieve = AT_SPEECH_URL.$lang_var.'.'.$_POST['file_type']; - $voice_file = AT_SPEECH_TEMPLATE_DIR.$lang_var.'.'.$_POST['file_type']; - - $sql = "SELECT * from ".TABLE_PREFIX."language_text WHERE language_code = '".$_SESSION['lang']."' AND term = '".$lang_var."'"; - $result = mysql_query($sql, $db); - $row = mysql_fetch_row($result); - - if($_POST['file_type'] == "mp3"){ - //$file_in = AT_SPEECH_DIR.$lang_var.'.sable'; - $file_out = AT_SPEECH_DIR.$lang_var.'.wav'; - //If SABLE is being used, generate the SBALE markup as the input file - if($_POST['type'] == "sable"){ - $file_in = AT_SPEECH_DIR.$lang_var.'.sable'; - $sable_out = ' - - - - - - - '; - $sable_out .= $row[3]."."; - $sable_out .= ' - - - - - - '; - //write the SABLE file - $fp = fopen($file_in,'w'); - if (!$fp) { - echo _AT(AT_ERROR_TTS__NOT_CREATE_SABLE); - exit; - } - fputs($fp, $sable_out); - fclose($fp); - $command = "text2wave $file_in -o $file_out -F 48000"; - }else{ - // If not SABLE being used, generate a standard scheme file and input text file. - $file_in = AT_SPEECH_DIR.$lang_var.'.txt'; - $scheme_out = AT_SPEECH_DIR.$now.'.scm'; - $file_props = "-mode --tts -eval ".AT_SPEECH_DIR.$now.".scm"; - $fp = fopen($file_in,'w'); - if (!$fp) { - echo _AT(AT_ERROR_TTS__NOT_CREATE_TEXT);echo 'Unable to create '.$name.' Text file.'; - exit; - } - fputs($fp, $row[3].'.'); - fclose($fp); - $command = "text2wave $file_props $file_in -o $file_out -F 48000 -scale ".$_POST['volumn'].""; - } - - - $file_out_mp3 = AT_SPEECH_DIR.$lang_var.'.mp3'; - - if(shell_exec('lame --longhelp')){ - $command2 = 'lame --quiet '.$file_out.' '. $file_out_mp3; - }else if (shell_exec('bladeenc -h')) { - $command2 = 'bladeenc -quiet '.$file_out.' '. $file_out_mp3; - } - escapeshellcmd($command); - escapeshellcmd($command2); - passthru($command); - passthru($command2); - - if(!copy($file_recieve, $voice_file)){ - $error = TTS_FILE_SAVE_FAILED; - $msg->addError($error); - } - - //gen_tts(); - - }else if($_POST['file_type'] == "ogg"){ - $file_out = AT_SPEECH_DIR.$lang_var.'.wav'; - - if($_POST['type'] == "sable"){ - $file_in = AT_SPEECH_DIR.$lang_var.'.sable'; - - $sable_out = ' - - - - - - - '; - $sable_out .= $row[3]."."; - $sable_out .= ' - - - - - - '; - //write the SABLE file - $fp = fopen($file_in,'w'); - if (!$fp) { - echo _AT(AT_ERROR_TTS__NOT_CREATE_SABLE); - exit; - } - - fputs($fp, $sable_out); - fclose($fp); - $command = "text2wave $file_in -o $file_out -F 48000"; - - } - - $file_props = "-mode --tts -eval ".AT_SPEECH_DIR.$now.".scm"; - $file_out_ogg = AT_SPEECH_DIR.$lang_var.'.ogg'; - $command2 = 'oggenc -quiet '.$file_out.' '. $file_out_ogg; - - escapeshellcmd($command); - escapeshellcmd($command2); - passthru($command); - passthru($command2); - - if(!copy($file_recieve, $voice_file)){ - $error = TTS_FILE_SAVE_FAILED; - $msg->addError($error); - } - - //gen_tts(); - - }else if($_POST['file_type'] == "wav"){ - $error = TTS_NO_WAV_ALLOWED; - $msg->addError($error); - } - } - - $feedback = array(TTS_VOICE_SAVED); - $msg->addFeedback($feedback); - } - -}else if($_POST['remove'] && !$_GET['page']){ - - if(!$_POST['check']){ - $error = array(TTS_FILES_REMOVED_CHECK); - $msg->addError($error); - }else{ - - foreach ($_POST['check'] as $lang_var){ - if(file_exists(AT_SPEECH_TEMPLATE_DIR.$lang_var.".ogg")){ - - unlink(AT_SPEECH_TEMPLATE_DIR.$lang_var.".ogg"); - - }else if(file_exists(AT_SPEECH_TEMPLATE_DIR.$lang_var.".mp3")){ - - unlink(AT_SPEECH_TEMPLATE_DIR.$lang_var.".mp3"); - - }; - - } - $feedback = array(TTS_FILES_REMOVED); - $msg->addFeedback($feedback); - - } - -} -?> \ No newline at end of file diff --git a/mods/atalker/atalker_doc/1.0.voices.php b/mods/atalker/atalker_doc/1.0.voices.php deleted file mode 100644 index bf5d26d3f..000000000 --- a/mods/atalker/atalker_doc/1.0.voices.php +++ /dev/null @@ -1,21 +0,0 @@ - - -

    1.0 ATalker Voices

    - -

    Administrators can use ATalker to create voices for ATutor....

    - - diff --git a/mods/atalker/atalker_doc/1.1.atalker.php b/mods/atalker/atalker_doc/1.1.atalker.php deleted file mode 100644 index f181aff77..000000000 --- a/mods/atalker/atalker_doc/1.1.atalker.php +++ /dev/null @@ -1,21 +0,0 @@ - - -

    1.1 Using ATalker

    - -

    Users can paste text and read it aloud. Instructors can can save speech to provide audio content. etc.

    - - diff --git a/mods/atalker/atalkerlib.inc.php b/mods/atalker/atalkerlib.inc.php deleted file mode 100644 index b944fe1bd..000000000 --- a/mods/atalker/atalkerlib.inc.php +++ /dev/null @@ -1,328 +0,0 @@ -addError($error); - } -} - -if($_GET['postdata']){ - $postdata = stripslashes($_GET['postdata']); - $_POST = unserialize($postdata); - - }else{ - - $postdata = serialize($_POST); -} - -// Garbage collector: delete tempfiles after $filelife seconds - function clean_tts_files(){ - //global AT_SPEECH_DIR; - $filelife = "1200"; //1200 seconds = 20 minutes - if ($handle = opendir(AT_SPEECH_DIR)){ - while (false !== ($file = readdir($handle))) { - $rawfile = split("\.", $file); - if($rawfile[0] != ''){ - $dir_files[$i] .= "$rawfile[0]\n"; - $this_now = time(); - if($this_now - $rawfile[0] > $filelife){ - unlink(AT_SPEECH_DIR.$file); - } - $i++; - } - } - } - } -clean_tts_files(); - -// Manage ATalker tabs and popup window - if ((isset($_REQUEST['popup'])) && ($_REQUEST['popup'] == TRUE)) { - $popup = TRUE; - $popup_win = "popup=1"; - } - - -// Read feedback messages out load - -/** -* Create scm file to pass to text2wave to define the voice, the volumn and the speed of the wave to build - @access private - @author Eura Ercolani - @return The complete path of the generated file -**/ - -function build_scm_file() -{ - global $db; - - //get voice info from the table AT_languages and AT_voices - $sql_command = "SELECT voice_name, voice_volumn, voice_speed FROM ".TABLE_PREFIX."languages, ".TABLE_PREFIX."voices WHERE language_code='"; - $sql_command .= $_SESSION[lang]."' AND ".TABLE_PREFIX."languages.voice_id = ".TABLE_PREFIX."voices.voice_id"; - $result = mysql_query($sql_command, $db); - $row = mysql_fetch_row($result); - $voice_name = $row[0]; //name of the voice to use - $volumn = $row[1]; //range value between 1(low) and 10 (high) - $speed = $row[2]; //range value between 0.6 (very fast) and 2.0 (very slow) - $scheme_file_txt .= "("; - $scheme_file_txt .= $voice_name; - $scheme_file_txt .= ")\n"; - $scheme_file_txt .= "("; - $scheme_file_txt .= "Parameter.set 'Duration_Stretch ".$speed; - $scheme_file_txt .= ")"; - - //Define the scm file name - $now = time(); - $scheme_file_name = AT_MSGS_DIR.$_SESSION[lang].DIRECTORY_SEPARATOR.$now.'.scm'; - //Open the file for output - $fp = fopen($scheme_file_name,'w'); - if (!$fp) - { - echo _AT(AT_ERROR_TTS__NOT_CREATE_SCHEME); - exit; - } - //Write into the file - fputs($fp, $scheme_file_txt); - fclose($fp); - - $voice_info[0] = $scheme_file_name; - $voice_info[1] = $volumn; - - return $voice_info; - -} - -/** -* Reads aloud error and feedback messages -* @ access public -* @param array $messages a list of messages sent to the $msg->printAll() function; -* @param array $vals a list of subistute (i.e.for %s within language) values for dynamic messages -* @author Greg Gay -*/ - - -function read_messages($messages, $vals){ - global $_base_href, $course_base_href, $msg, $play, $val, $db; - /* Modified by Eura Ercolani: mimetype support - BEGIN */ - - /* Modified by Eura Ercolani: mimetype support - END */ - foreach ($messages as $item){ - $sql = "SELECT * from ".TABLE_PREFIX."language_text WHERE language_code = '$_SESSION[lang]' AND term = '$item'"; - $result = mysql_query($sql, $db); - - while($row = mysql_fetch_row($result)){ - - /* Modified by Eura Ercolani: messages localization - BEGIN */ - //check to see if the folder exists.... - if(!is_dir(AT_MSGS_DIR.DIRECTORY_SEPARATOR.$_SESSION[lang]))//folder does not exists, I make it - mkdir(AT_MSGS_DIR.$_SESSION[lang]); - //$file_in = AT_MSGS_DIR.$row[2].'.txt'; - $file_in = AT_MSGS_DIR.$_SESSION[lang].DIRECTORY_SEPARATOR.$row[2].'.txt'; - //$file_out = AT_MSGS_DIR.$row[2].'.wav'; - $file_out = AT_MSGS_DIR.$_SESSION[lang].DIRECTORY_SEPARATOR.$row[2].'.wav'; - //$file_out_mp3 = AT_MSGS_DIR.$row[2].'.mp3'; - $file_out_mp3 = AT_MSGS_DIR.$_SESSION[lang].DIRECTORY_SEPARATOR.$row[2].'.mp3'; - //$file_recieve = AT_MSGS_URL.$row[2].'.mp3'; - $file_recieve = AT_MSGS_URL.$_SESSION[lang].DIRECTORY_SEPARATOR.$row[2].'.mp3'; - /* Modified by Eura Ercolani: messages localization - END */ - - if(file_exists($file_out_mp3)){ - - /* Modified by Eura Ercolani: mime type support - BEGIN */ - //echo ''; - echo ''; - /* Modified by Eura Ercolani: mime type support - END */ - - - }else{ - $fp = fopen($file_in,'w'); - - if (!$fp) { - echo AT_ERROR_TTS_NOT_CREATE_TEXT; - exit; - } - - $message = strip_tags($row[3]); - $message = str_replace("%s", $vals[$row[2]], $message); - fputs($fp, $message); - fclose($fp); - /* Modified by Eura Ercolani: voice setting - BEGIN */ - $voice_info = build_scm_file(); - $command = "text2wave ".$file_in." -o ".$file_out; - $command .= " -F 48000 -scale ".$voice_info[1]." -eval ".$voice_info[0]; - //$command = "text2wave $file_in -o $file_out -F 48000"; - /* Modified by Eura Ercolani: voice setting - BEGIN */ - - if(shell_exec('lame --longhelp')){ - - $command2 .= ' lame --quiet '.$file_out.' '. $file_out_mp3; - - }else if (shell_exec('bladeenc -h')) { - - $command2 .= ' bladeenc -quiet '.$file_out.' '. $file_out_mp3; - } - - escapeshellcmd($command); - escapeshellcmd($command2); - passthru($command); - - passthru($command2); - /* Modified by Eura Ercolani: mimetype support - BEGIN */ - //echo ''; - echo ''; - /* Modified by Eura Ercolani: mimetype support - END */ - unlink($file_in); - unlink($file_out); - /* Modified by Eura Ercolani: delete scm file - BEGIN */ - unlink($voice_info[0]); - /* Modified by Eura Ercolani: delete scm file - END */ - } - } - } -} - - -// List tabs for the ATalker -function get_atalker_tabs() { - //these are the _AT(x) variable names and their include file - $tabs[0] = array('text_reader', 'index.php', ''); - $tabs[1] = array('sable_reader', 'index.php', ''); - if($_SESSION['privileges'] == AT_ADMIN_PRIV_ADMIN){ - $tabs[2] = array('voice_files', 'index.php', ''); - } - -return $tabs; -} - - -// Check to see what encoders are available: currently supported encoders include: lame. bladeenc, oggenc - -function get_encoders(){ - global $select, $_POST; - - $command2 = 'bladeenc -h'; - $command2 = escapeshellcmd($command2); - $command3 = 'lame --version'; - $command3 = escapeshellcmd($command3); - if(shell_exec($command2) != '' || shell_exec($command3) != ''){ - echo ''; - } - - $command = 'oggenc --version'; - $command = escapeshellcmd($command); - if(shell_exec($command) != ''){ - echo ''; - } - -} - -// Send the user to the right place after each TTS action -function gen_tts(){ - global $_POST, $now, $file_recieve, $error, $postdata, $msg, $file_save, $filename, $tab, $voice_file, $lang_var, $messages; - //echo $voice_file; - //exit; - if(!$error && !$_GET['page']){ - if($_POST['download']){ - //unset($_POST['export']) - header('Content-type: audio/x-'.$_POST['file_type']); - header('Content-Disposition: attachment; filename="'.$now.'.'.$_POST['file_type']); - readfile($file_recieve); - - }else if($_POST['save']){ - $file_save = str_replace(" ", "_", $file_save); - - - if(@fopen($file_save, r)){ - $error= array(TTS_FILE_EXISTS, $filename); - $msg->addError($error); - }else{ - if(copy($file_recieve, $file_save)){ - $feedback = array(TTS_FILE_SAVED, $filename); - $msg->addFeedback($feedback); - }else{ - $error = array(TTS_FILE_SAVE_FAILED, $filename); - $msg->addError($error); - } - } - unset($_POST['save']); - }else if($_POST['export']){ - unset($_POST['export']); - header('Content-type: text/plain'); - header("Location:".AT_SPEECH_URL.$now.".sable"); - - }else{ - - //header('Content-type: audio/x-'.$_POST['file_type']); - header('Content-type: audio/x-'.$_POST['file_type']); - header("Location:".$file_recieve); - } - } -} - -?> diff --git a/mods/atalker/images/atalker.gif b/mods/atalker/images/atalker.gif deleted file mode 100644 index 821a6346ec72c19cc1203d667b955b7db36fba79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2313 zcmV+k3HJ6!Nk%w1VJ`qK0O$Vzab`9B{LS~xCE~dd;I>706^{WcK#< zxw*M?baYcjjQ{3Akakw??(Y2hbMeO>=)M)^ycMaFOM-%eFMeI)Gm)#SK_!1{r$M*z!T)U5Vp3qxR@8$*VoFXDZXD{rlzL<;X3^M ztFZ_O`srzli;M2X9@4B8tE;Qn*w~|sC+ff%d3kxp#>UFZ%I3TiFe|Od$jF(QnX|LA zvn3_!>gvwU&KDQF{QTOtt9OHSJGz=V(b3VNc6Rc~Bi`QLm6es-+uQ#B^UTc5uC1+W zWkl4})V#dB+}zy6#Kf7Fj*E0>vpG4}y;fFKOOle2r;#-O|7QQzE{u69uLTAE{*kmq zM16gIzrVkdjd`|DPs*np|NnyO#u%QSp1HBHV_ZSsv4r|LaBAuMV=6BIv#s zt*WZxx)$W*_z|oZ~x~({L(7nwhZ9l;Q#-4{QUg$^Yh%Y3IE?Z=DQR1%q8Ty6Vubv`Oqr;)Gnf; zqQ0FP{PU{*;YrM@9rW8y@yRUd%TS`3ao4vr*031Yu^0dU{`K+S$*@8H`eB)nY2?5# zy`eI3ZC;k_1$}kg@yU@*~`brT~B}1uPoKE zB%+^}sfmeiZDN##NLN=^nu&?pu@I1YCg#2z|Nng1+11^%4d1sFn2>SIz?1RLK)j?v z?&Q1T+pfx=pU1qCb76L9WnB8`nbXRl!h3subx{8P`}_O)$Hv0_(=MbmG^HdYz^SSF z&@Ar9EC2uhA^sIZa%Ew3Wn>_CX>@2HRA^-&M@dak03rDV0RRC104x9i001ulE&u=s z{s8|897wRBK}Hn-J7a2LSCJ#ue4<7&}Sh3>KLrdfk1@MBg zWkHRRW>JHd@4=@}AVrciY01(iJcy{cbm=HkCwA%<{VG+;CeDx}OP>6Rfdpw=2I>AUGM2MEJVaGn`(c=1p=1ltOXlu=^2HTX`-6`;~woe z`gAvL9_+oo`cZ2d#VvB$03*kkU82G}&x4@9kOd0}Ai#O)t*07VJjHR(MUp_ENfRxc zGeCYN)X>WrXJmuGe*q3iU4g%~$CFS8(I*B62Cy)|gf(2jL^D6)?XIETT91r~f`c^J$9-S^6W2be|#U4-!NKl6ovLJkwyfd&+cBqBox z3TPm^05R!#HG9ZD(9Mqej0`9o$ z?zfpjR53;lQ523C3|oxyg%V99!H*q`XW_*AW~`G*CfH|>^6s;aV*n9KXd?4*5O6^e zq_DgOuum&O|feaLggrSI+94wS!4^Mc)4d`%yL_nb!5qR1hav=ymMDU5&v%wJ9 z&#P zSV#gLIB6~SNV*zsg4L}VHX=J#WL0<0RaFzi2GQS diff --git a/mods/atalker/images/atalker_sm.gif b/mods/atalker/images/atalker_sm.gif deleted file mode 100644 index bbf40a91086761d3b6a49f8eb52505c0e6129607..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1103 zcmV-V1hD%@Nk%w1VG;lm0O$Vzab`9B{LS~xCE~dd;I>706^{WcK#< zxw*M?baYcjjQ{3Akakw??(Y2hbMeO>=)M)^ycMaFOM-%eFMeI)Gm)#SK_!1{r$M*z!T)U5Vp3qxR@8$*VoFXDZXD{rlzL<;X3^M ztFZ_O`srzli;M2X9@4B8tE;Qn*w~|sC+ff%d3kxp#>UFZ%I3TiFe|Od$jF(QnX|LA zvn3_!>gvwU&KDQF{QTOtt9OHSJGz=V(b3VNc6Rc~Bi`QLm6es-+uQ#B^UTc5uC1+W zWkl4})V#dB+}zy6#Kf7Fj*E0>vpG4}y;fFKOOle2r;#-O|7QQzE{u69uLTAE{*kmq zM16gIzrVkdjd`|DPs*np|NnyO#u%QSp1HBHV_ZSsv4r|LaBAuMV=6BIv#s zt*WZxx)$W*_z|oZ~x~({L(7nwhZ9l;Q#-4{QUg$^Yh%Y3IE?Z=DQR1%q8Ty6Vubv`Oqr;)Gnf; zqQ0FP{PU{*;YrM@9rW8y@yRUd%TS`3ao4vr*031Yu^0dU{`K+S$*@8H`eB)nY2?5# zy`eI3ZC;k_1$}kg@yU@*~`brT~B}1uPoKE zB%+^}sfmeiZDN##NLN=^nu&?pu@I1YCg#2z|Nng1+11^%4d1sFn2>SIz?1RLK)j?v z?&Q1T+pfx=pU1qCb76L9WnB8`nbXRl!h3subx{8P`}_O)$Hv0_(=MbmG^HdYz^SSF z&@Ar9EC2uhA^sIZa%Ew3Wn>_CX>@2HRA^-&M@dak03rDV0RRC104x9i000sI5&!@Q z{s8|89Qe;#st+sLSPDR}VI+3H9()3na1(}x{}@raB_tH77(FT_Pq zQl*NF26D==tHdA#3j|1b5Hi7|I0GTHU@-vO6a*u5y6JJrrzC+Wd=VG`B14`RId_I! z!Qh{xB%WAInpA^CBdkh8Quw#wi6>8E2Y@m=A}6MnYa#H^u#AOR8;8uIl`s#&KL~%S zDF6`2N&zEF=;j=?!4U;15eUgZGH1pN8;cm!lV{K*w2j%|l|q>( zbf83-addError($error); - -}else if ($_POST['type'] == "text"){ - require(AT_INCLUDE_PATH.'../mods/atalker/text_reader.php'); - -}else if ($_POST['type'] == "sable"){ - require(AT_INCLUDE_PATH.'../mods/atalker/sable_reader.php'); - -} - - - require (AT_INCLUDE_PATH.'header.inc.php'); - require ('reader.html.php'); - - require (AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/atalker/message_reader.php b/mods/atalker/message_reader.php deleted file mode 100644 index f64839471..000000000 --- a/mods/atalker/message_reader.php +++ /dev/null @@ -1,77 +0,0 @@ -base_href.'content/msgs/'); - - //See if the messages (msgs) directory exists and if it does, open it, otherwise create it, then open it - if(@!opendir(AT_MSGS_DIR)){ - mkdir(AT_MSGS_DIR, 0700); - } - - $i = '0'; - - if($_SESSION['message']['feedback'] != ''){ - foreach($_SESSION['message']['feedback'] as $var => $val){ - - if(is_array($val)){ - $messages[$i]= $val[0]; - $vals[$val[$i]] = $val[1]; - }else{ - $messages[$i] = $val; - } - $i++; - - } - } - - $i = '0'; - - if($_SESSION['message']['error'] != ''){ - foreach($_SESSION['message']['error'] as $var => $val){ - if(is_array($val)){ - $messages[$i]= $val[0]; - $vals[$val[$i]] = $val[1]; - }else{ - $messages[$i] = $val; - } - $i++; - } - } - - if($messages){ - if(!$vals){ - $vals = ''; - } - read_messages($messages, $vals); - $messages = ''; - } - } -} -?> \ No newline at end of file diff --git a/mods/atalker/module.php b/mods/atalker/module.php deleted file mode 100644 index 11113afad..000000000 --- a/mods/atalker/module.php +++ /dev/null @@ -1,53 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_ATALKER', $this->getAdminPrivilege()); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_student_tool = 'mods/atalker/index.php'; - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_HELLO_WORLD, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/atalker/admin/admin_index.php'); - $this->_pages['mods/atalker/admin/admin_index.php']['parent'] = AT_NAV_ADMIN; - $this->_pages['mods/atalker/admin/admin_index.php']['title_var'] = 'atalker'; -} - -/******* - * student and instructor page. - */ -$this->_pages['mods/atalker/index.php']['title_var'] = 'atalker'; -$this->_pages['mods/atalker/index.php']['img'] = 'mods/atalker/images/atalker.gif'; - - -/* Modified by Eura Ercolani: mimetype support - BEGIN */ - -if(isset($_POST['mp3HiddenMimeType'])) -{ - $_SESSION['mp3HiddenMimeType']=$_POST['mp3HiddenMimeType']; -} -/* Modified by Eura Ercolani: mimetype support - END */ -/* Modified by Eura Ercolani: introducing global variabiles - BEGIN */ -//ATutor root web folder -$_ATutor_home_path = '/home/eura/public_html/ATutor/'; - - -/* Modified by Eura Ercolani: introducing global variables - END */ - -?> \ No newline at end of file diff --git a/mods/atalker/module.sql b/mods/atalker/module.sql deleted file mode 100644 index 769e51475..000000000 --- a/mods/atalker/module.sql +++ /dev/null @@ -1,177 +0,0 @@ -# This file contains the language for the ATutor ATalker addon -# Translators can modify the language in field 4 of the VALUES statement with each INSERT command, and change the value in -# field 1 to that of the ISO-639 two letter language code. - - -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_FILE_EXISTS', 'File already exists. Delete the original file in the File Manager speech/ directory, or change the name of the new file before saving .','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_NOT_CREATE_SCHEME', 'Unable to create Scheme file.','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_MP3_ENCODER','No MP3encoder was found','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_OGG_ENCODER','No OGG encoder was found','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_NOT_CREATE_SABLE','Unable to create Sable file.','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_NOT_CREATE_TEXT)','Unable to create Text file.','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_FILE_SAVE_FAILED', 'Speech was not saved','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_NO_WAV_ALLOWED','WAV file can not be used to create interface language','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_FEEDBACK_TTS_VOICE_SAVED','Successfully saved voice file(s)','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_FEEDBACK_TTS_FILES_REMOVED_CHECK','You must select the checkboxes beside files to be removed)','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_FEEDBACK_TTS_FILES_REMOVED','Successfully removed selected file(s)','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_NO_CHOICE_MADE','You must check one or more language variables before selecting Create Voice','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_VOICE_FILE_DELETED','Successfully deletes voice file(s).','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_FILE_DELETE_FAILED','Delete voice files failed','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_FILE_CHARS','File names may only be made up of letters, numbers, and underscores.','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_ERROR_TTS_NO_TEXTIN','You must enter some text to read.','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_msgs','AT_FEEDBACK_TTS_FILE_SAVED','Successfully saved speech file(s). ','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','ATalker_administrator','ATalker Administrator','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','text_reader','Text Reader','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','sable_reader','SABLE/SSML Reader','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','voice_files','Voice File Manager','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','ATalker','ATalker','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','tts_file_names','Enter a file name, or save as the default file name','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','enter_some_text','Enter some text below:','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','play','Play','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','file_out_type','File Out Type:','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','voice','Voice','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','volumn','Volumn','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','speed','Speed','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','very_slow','very slow','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','slow','slow','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','medium','medium','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','fast','fast','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','very_fast','very fast','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','export_sable','Export SABLE','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','english','English','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','english2','English 2','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','spanish','Spanish','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','speaker','Speaker','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','male1','Male 1','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','male2','Male 2','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','male3','Male 3','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','male4','Male 4','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','female1','Female 1','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','highest','highest','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','high','high','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','low','low','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','lowest','lowest','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','pitch','Pitch','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','base','Base','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','middle','Middle','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','range','Range','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','largest','largest','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','large ','large','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','small','small','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','smallest','smallest','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','rate','Rate','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','fastest','fastest','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','slowest','slowest','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','loudest','loudest','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','loud','loud','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','quiet','quiet','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','enter_text_sable_ssml','Enter plain text, or text marked up with SABLE or SSML:','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','on1','On','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','off','Off','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','messages','Messages','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','manage_atutor_voice','Manage ATutor Voice','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','no_files_found','No voice files found','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','create_voice','Create Voice','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','remove_voice','Remove Voice','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','pages','Pages','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','variable','Variable','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','select_unselect','Select/Unselect','2005-09-02 12:17:53',''); -INSERT INTO `language_text` VALUES ('en','_module','characters_total','Characters Total:','2005-09-02 12:17:53',''); - - -## - -SET FOREIGN_KEY_CHECKS=0; -#---------------------------- -# Table structure for voices -#---------------------------- -CREATE TABLE `voices` ( - `voice_id` varchar(4) NOT NULL default '', - `voice_name` varchar(255) NOT NULL default '', - `voice_volumn` char(2) default NULL, - `voice_speed` char(3) default NULL, - PRIMARY KEY (`voice_id`) -) TYPE=MyISAM; -#---------------------------- -# Records for table voices -#---------------------------- - - -insert into voices values -('it01', 'voice_lp_mbrola', '1', '1.0'), -('en01', 'voice_kal_diphone', '1', '1.0'), -('it02', 'voice_pc_mbrola', '1', '1.0'); - -# The following Alter had to be removed because it broken languages -# other than Italian. -#ALTER TABLE languages ADD -# voice_id varchar(4) NULL; -# - - -insert into languages values -('en', 'iso-8859-1', 'ltr', 'en([-_][[:alpha:]]{2})?|english', 'English', 'English', 3, 'en01'), -INSERT INTO `language_text` VALUES ('it', 'iso-8859-1', 'ltr', 'it|italian', 'Italian', 'Italian', 3, 'it01'); - - - -INSERT INTO `language_text` VALUES ('it','_template', 'atalker_administrator', 'Configurazione di ATalker', '2005-12-09 00:42:17',''), -INSERT INTO `language_text` VALUES ('it','_template', 'text_reader', 'Lettore di testo', '2005-12-09 00:43:48', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'sable_reader', 'Lettore SABLE/SSML', '2005-12-09 00:44:16', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'voice_files', 'Gestore file vocali', '2005-12-09 00:45:30', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'atalker', 'ATalker', '2005-12-09 00:45:49', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'tts_file_names', 'Inserire un nome file, oppure salvare con il nome di default', '2005-12-09 00:46:35', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'enter_some_text', 'Inserire del testo qui sotto:', '2005-12-09 00:47:20', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'play', 'Avvia', '2005-12-09 00:47:43', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'file_out_type', 'Tipo del file di output:', '2005-12-09 00:48:09', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'voice', 'Voce', '2005-12-09 00:48:34', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'volumn', 'Volume', '2005-12-09 00:48:54', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'speed', 'Velocità', '2005-12-09 00:49:15', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'very_slow', 'molto lento', '2005-12-09 00:49:37', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'slow', 'lento', '2005-12-09 00:49:54', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'medium', 'medio', '2005-12-09 00:50:12', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'fast', 'veloce', '2005-12-09 00:50:32', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'very_fast', 'molto veloce', '2005-12-09 00:50:55', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'export_sable', 'Esporta in SABLE', '2005-12-09 00:51:28', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'english', 'Inglese', '2005-12-09 00:51:49', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'english2', 'Inglese 2', '2005-12-09 00:52:16', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'spanish', 'Spagnolo', '2005-12-09 00:52:42', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'speaker', 'Speaker', '2005-12-09 00:54:34', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'male1', 'Maschile 1', '2005-12-09 00:54:53', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'male2', 'Maschile 2', '2005-12-09 00:55:20', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'male3', 'Maschile 3', '2005-12-09 00:55:43', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'male4', 'Maschile 4', '2005-12-09 00:56:03', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'female1', 'Femminile 1', '2005-12-09 00:56:27', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'highest', 'altissimo', '2005-12-09 00:57:10', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'high', 'alto', '2005-12-09 00:57:30', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'low', 'basso', '2005-12-09 00:57:53', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'lowest', 'bassissimo', '2005-12-09 00:58:11', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'pitch', 'Tono', '2005-12-09 01:03:10', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'base', 'Base', '2005-12-09 01:03:29', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'middle', 'Medio', '2005-12-09 01:03:48', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'range', 'Intervallo', '2005-12-09 01:04:13', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'largest', 'larghissimo', '2005-12-09 01:04:45', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'large', 'largo', '2005-12-09 01:05:12', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'small', 'piccolo', '2005-12-09 01:05:38', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'smallest', 'piccolissimo', '2005-12-09 01:05:58', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'rate', 'Ritmo', '2005-12-09 01:06:33', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'fastest', 'velocissimo', '2005-12-09 01:06:52', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'slowest', 'lentissimo', '2005-12-09 01:07:12', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'loudest', 'fortissimo', '2005-12-09 01:08:48', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'loud', 'forte', '2005-12-09 01:09:24', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'quiet', 'tranquillo', '2005-12-09 01:09:46', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'enter_text_sable_ssml', 'Inserire del testo in chiaro o codificato secondo SABLE o SSML:', '2005-12-09 01:10:45', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'on1', 'Attiva', '2005-12-09 01:11:19', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'off', 'Disattiva', '2005-12-09 01:11:54', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'messages', 'Messaggi', '2005-12-09 01:12:13', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'manage_atutor_voice', 'Gestione voci in ATutor', '2005-12-09 01:13:15', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'no_files_found', 'Nessun file vocale trovato', '2005-12-09 01:13:40', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'create_voice', 'Crea File Vocale', '2005-12-09 01:14:06', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'remove_voice', 'Rimuovi File Vocale', '2005-12-09 01:14:48', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'pages', 'Pagine', '2005-12-09 01:15:04', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'variable', 'Variabile', '2005-12-09 01:15:23', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'select_unselect', 'Seleziona/Deseleziona', '2005-12-09 01:15:45', ''), -INSERT INTO `language_text` VALUES ('it','_template', 'characters_total', 'Caratteri Totali:', '2005-12-09 01:16:12', ''); - - - diff --git a/mods/atalker/module.xml b/mods/atalker/module.xml deleted file mode 100644 index b63aa2f14..000000000 --- a/mods/atalker/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - ATalker for ATutor - ATalker is based on the Festival Text-to-Speech system, which must be installed and functioning on the system prior to installing the ATalker module. See the README_ATUTOR_MODULE file in the ATalker top directory for complete installation instructions. - - - Greg Gay - info@atutor.ca - - - http://atutor.ca/atalker - GPL - - 0.2 - 2005-12-07 - experimental - You will like want to install an audio encoder or two, otherwise speech will be generated as WAV files, which are very large and take a long time to download. See the README_ATUTOR_MODULE file in the ATalaker mods directory for information about mp3 and ogg audio encoders. - - \ No newline at end of file diff --git a/mods/atalker/module_install.php b/mods/atalker/module_install.php deleted file mode 100644 index 60917dac3..000000000 --- a/mods/atalker/module_install.php +++ /dev/null @@ -1,61 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -// } else if (!is_writable($directory) && @chmod($directory, 0666)) { -// $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -// } - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/atalker/reader.html.php b/mods/atalker/reader.html.php deleted file mode 100644 index 87d9c1ac7..000000000 --- a/mods/atalker/reader.html.php +++ /dev/null @@ -1,262 +0,0 @@ - - - -
    - -
    - - - - - - - -
    - - - - - - - - - - - - - - -
    - - - - - -
    -
    -
    - -
    - - - - - - - -
    -
    - -
    - -
    - - -
    - - - - - - - - - - - - - - -
    - - - - - - -
    - -
    - - - - - - - - - - - - - -
    - - - -
    - - - - - - -
    - - - -
    -
    - -
    -
    - -
    - - -
    -
    - -
    - -
    -
    - -
    - - -
    - - \ No newline at end of file diff --git a/mods/atalker/reader_controls.php b/mods/atalker/reader_controls.php deleted file mode 100644 index 3aad4b690..000000000 --- a/mods/atalker/reader_controls.php +++ /dev/null @@ -1,85 +0,0 @@ -'; - //global $_rel_url; - $_rel_url_new = ltrim($_rel_url, "/"); - if($_REQUEST['cid']){ - - - } - - if($_rel_url == "/index.php"){ - - echo '('; - - }else{ - - echo '('; - } - - - if( $_SESSION['atalker_on'] == '1'){ - - echo ' '._AT('voice').' '._AT('on1').' / '._AT('off').' '; - - }else if(!$_SESSION['atalker_on']){ - - echo '( '._AT('voice').' '._AT('on1').' / '._AT('off').''; - - } - - if($_GET['messages_on'] == '1'){ - - $_SESSION['messages_on'] = '1'; - header("Location: ".$_SERVER['PHP_SELF']); - - - }else if($_GET['messages_on'] == '2'){ - - session_unregister('messages_on'); - header("Location: ".$_SERVER['PHP_SELF']); - - } - - if( $_SESSION['messages_on'] == '1'){ - - require(AT_INCLUDE_PATH."../mods/atalker/message_reader.php"); - echo ' -- '._AT('messages').' '._AT('on1').' / '._AT('off').' ) '; - - }else if(!$_SESSION['messages_on']){ - - echo ' -- '._AT('messages').' '._AT('on1').' / '._AT('off').' )'; - - } - - echo '
    '; -?> \ No newline at end of file diff --git a/mods/atalker/sable_reader.php b/mods/atalker/sable_reader.php deleted file mode 100644 index 068a6a47c..000000000 --- a/mods/atalker/sable_reader.php +++ /dev/null @@ -1,99 +0,0 @@ - 0){ - $file_save = AT_SPEECH_FILES_DIR.$_POST['filename']; - }else{ - $file_save = AT_SPEECH_TEMPLATE_DIR.$_POST['filename']; - } - }else{ - if($_SESSION['course_id'] > 0){ - $file_save = AT_SPEECH_FILES_DIR.$now.'.'.$_POST['file_type']; - }else{ - $file_save = AT_SPEECH_TEMPLATE_DIR.$now.'.'.$_POST['file_type']; - } - } - - - $file_in = AT_SPEECH_DIR.$now.'.sable'; - $file_out = AT_SPEECH_DIR.$now.'.wav'; - $file_out_mp3 = AT_SPEECH_DIR.$now.'.mp3'; - $file_out_ogg = AT_SPEECH_DIR.$now.'.ogg'; - $file_recieve = AT_SPEECH_URL.$now.'.'.$_POST['file_type']; - - - $postdata = serialize($_POST); - - if(!$_POST['create'] && !$_POST['remove']){ -$sable_out = ' - - - - - - - - '; - $sable_out .= stripslashes($_POST['textin']); - $sable_out .= ' - - - - - -'; - - //write the SABLE file - $fp = fopen($file_in,'w'); - if (!$fp) { - echo AT_ERROR_TTS_NOT_CREATE_SABLE; - exit; - } - fputs($fp, $sable_out); - fclose($fp); - - - if($_POST['file_type'] == "mp3"){ - $command = "text2wave $file_in -o $file_out -F 48000"; - if(shell_exec('lame --longhelp')){ - $command2 = 'lame --quiet '.$file_out.' '. $file_out_mp3; - }else if (shell_exec('bladeenc -h')) { - $command2 = 'bladeenc -quiet '.$file_out.' '. $file_out_mp3; - } - escapeshellcmd($command); - escapeshellcmd($command2); - passthru($command); - passthru($command2); - gen_tts(); - }else if($_POST['file_type'] == "ogg"){ - $command = "text2wave $file_in -o $file_out -F 48000"; - $command2 = 'oggenc -quiet '.$file_out.' '. $file_out_ogg; - escapeshellcmd($command); - escapeshellcmd($command2); - passthru($command); - passthru($command2); - gen_tts(); - - }else{ - $command = "text2wave $file_in -o $file_out -F 48000"; - escapeshellcmd($command); - passthru($command); - gen_tts(); - } -} - -?> \ No newline at end of file diff --git a/mods/atalker/template_reader.php b/mods/atalker/template_reader.php deleted file mode 100644 index 7c0121e84..000000000 --- a/mods/atalker/template_reader.php +++ /dev/null @@ -1,86 +0,0 @@ - '.$outString.''; - - }else if(file_exists(AT_SPEECH_TEMPLATE_DIR.$format.'.mp3')){ - - $outString =' '.$outString.''; - } - - }else{ - - // Mozilla browsers - if(file_exists(AT_SPEECH_TEMPLATE_DIR.$format.'.ogg')){ - /* Modified by Eura Ercolani: mimetype support - BEGIN */ - - //$outString =' '.$outString.''; - $outString =' '.$outString.''; - /* Modified by Eura Ercolani: mimetype support - END */ - - if(!$embed[$format]){ - - /* Modified by Eura Ercolani: mimetype support - BEGIN */ - //$embed[$format] =''."\n"; - - $embed[$format] =''."\n"; - /* Modified by Eura Ercolani: mimetype support - BEGIN */ - - $outString .= $embed[$format]; - } - - }else if(file_exists(AT_SPEECH_TEMPLATE_DIR.$format.'.mp3')){ - - - /* Modified by Eura Ercolani: mimetype support - BEGIN */ - //$outString =' '.$outString.''; - $outString =' '.$outString.''; - /* Modified by Eura Ercolani: mimetype support - END */ - - if(!$embed[$format]){ - /* Modified by Eura Ercolani: mimetype support - BEGIN */ - //$embed[$format] =''."\n"; - $embed[$format] =''."\n"; - /* Modified by Eura Ercolani: mimetype support - END */ - $outString .= $embed[$format]; - } - } - } - - } -?> \ No newline at end of file diff --git a/mods/atalker/text_reader.php b/mods/atalker/text_reader.php deleted file mode 100644 index 9ee6ec837..000000000 --- a/mods/atalker/text_reader.php +++ /dev/null @@ -1,103 +0,0 @@ - 0){ - $file_save = AT_SPEECH_FILES_DIR.$_POST['filename']; - }else{ - $file_save = AT_SPEECH_TEMPLATE_DIR.$_POST['filename']; - } - }else{ - if($_SESSION['course_id'] > 0){ - $file_save = AT_SPEECH_FILES_DIR.$now.'.'.$_POST['file_type']; - }else{ - $file_save = AT_SPEECH_TEMPLATE_DIR.$now.'.'.$_POST['file_type']; - } - - } - - $file_out = AT_SPEECH_DIR.'/'.$now.'.wav'; - $file_out_mp3 = AT_SPEECH_DIR.$now.'.mp3'; - $file_out_ogg = AT_SPEECH_DIR.$now.'.ogg'; - $file_in = AT_SPEECH_DIR.$now.'.txt'; - $file_recieve = AT_SPEECH_URL.$now.'.'.$_POST['file_type']; - $scheme_out = AT_SPEECH_DIR.$now.'.scm'; - - - // Build the Scheme file. Lots more can be done here to customize voices - $scheme_in .= "("; - $scheme_in .= $_POST['voice']; - $scheme_in .= ")\n"; - $scheme_in .= "("; - $scheme_in .= "Parameter.set 'Duration_Stretch ".$_POST['duration']; - $scheme_in .= ")"; - - // create a scheme file with the voice properties - $fp = fopen($scheme_out,'w'); - if (!$fp) { - echo AT_ERROR_TTS_NOT_CREATE_SCHEME; - exit; - } - fputs($fp, $scheme_in); - fclose($fp); - - //$file_props = "-mode --tts -eval ".AT_SPEECH_DIR.$now.".scm"; - - if(!$_POST['create'] && !$_POST['remove']){ - - //create a text file from the inputted text - $fp = fopen($file_in,'w'); - if (!$fp) { - echo AT_ERROR_TTS_NOT_CREATE_TEXT; - exit; - } - fputs($fp, $_POST['textin']); - fclose($fp); - - if($_POST['file_type'] == "mp3"){ - $command = "text2wave $file_props $file_in -o $file_out -F 48000 -scale ".$_POST['volumn'].""; - if(shell_exec('lame --longhelp')){ - $command2 = 'lame --quiet '.$file_out.' '. $file_out_mp3; - }else if (shell_exec('bladeenc -h')) { - $command2 = 'bladeenc -quiet '.$file_out.' '. $file_out_mp3; - } - - escapeshellcmd($command); - escapeshellcmd($command2); - passthru($command); - passthru($command2); - gen_tts(); - - }else if($_POST['file_type'] == "ogg"){ - $command = "text2wave $file_props $file_in -o $file_out -F 48000 -scale ".$_POST['volumn'].""; - $command2 = 'oggenc -quiet '.$file_out.' '. $file_out_ogg; - escapeshellcmd($command); - escapeshellcmd($command2); - passthru($command); - passthru($command2); - gen_tts(); - - }else{ - $command = "text2wave $file_props $file_in -o $file_out -F 48000 -scale ".$_POST['volumn'].""; - escapeshellcmd($command); - passthru($command); - gen_tts(); - - - } - } -?> \ No newline at end of file diff --git a/mods/atsocial_iphone_app/.gitignore b/mods/atsocial_iphone_app/.gitignore deleted file mode 100644 index 4dbdcc030..000000000 --- a/mods/atsocial_iphone_app/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -# xcode noise -build/* -*.pbxuser -*.perspective -*.perspectivev3 -*.mode1v3 -*.mode2v3 - -# old skool -.svn - -# osx noise -.DS_Store diff --git a/mods/atsocial_iphone_app/.gitmodules b/mods/atsocial_iphone_app/.gitmodules deleted file mode 100644 index 4db2498b8..000000000 --- a/mods/atsocial_iphone_app/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "three20"] - path = three20 - url = http://github.com/facebook/three20.git diff --git a/mods/atsocial_iphone_app/ATutor-Info.plist b/mods/atsocial_iphone_app/ATutor-Info.plist deleted file mode 100644 index 7e3aac9d9..000000000 --- a/mods/atsocial_iphone_app/ATutor-Info.plist +++ /dev/null @@ -1,39 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - com.quanganhdo.${PRODUCT_NAME:rfc1034identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - CFBundleURLTypes - - - CFBundleURLSchemes - - atutor - - CFBundleURLName - com.quanganhdo.atutor - - - - diff --git a/mods/atsocial_iphone_app/ATutor.xcodeproj/project.pbxproj b/mods/atsocial_iphone_app/ATutor.xcodeproj/project.pbxproj deleted file mode 100755 index c8382ecb0..000000000 --- a/mods/atsocial_iphone_app/ATutor.xcodeproj/project.pbxproj +++ /dev/null @@ -1,1215 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 45; - objects = { - -/* Begin PBXBuildFile section */ - 1D3623260D0F684500981E51 /* ATutorAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* ATutorAppDelegate.m */; }; - 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; - CD26D9E511E8D30700003274 /* ContactsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = CD26D9E411E8D30700003274 /* ContactsDataSource.m */; }; - CD26DA9C11E8E66800003274 /* ContactItemCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CD26DA9B11E8E66800003274 /* ContactItemCell.m */; }; - CD720BF8120B75FC006EC605 /* IASKAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BDB120B75FB006EC605 /* IASKAppSettingsViewController.m */; }; - CD720BF9120B75FC006EC605 /* IASKSpecifierValuesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BDD120B75FB006EC605 /* IASKSpecifierValuesViewController.m */; }; - CD720BFA120B75FC006EC605 /* IASKSettingsReader.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BE0120B75FB006EC605 /* IASKSettingsReader.m */; }; - CD720BFB120B75FC006EC605 /* IASKSpecifier.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BE2120B75FB006EC605 /* IASKSpecifier.m */; }; - CD720BFC120B75FC006EC605 /* IASKPSSliderSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BE5120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.m */; }; - CD720BFD120B75FC006EC605 /* IASKPSTextFieldSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BE7120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.m */; }; - CD720BFE120B75FC006EC605 /* IASKPSTitleValueSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BE9120B75FB006EC605 /* IASKPSTitleValueSpecifierViewCell.m */; }; - CD720BFF120B75FC006EC605 /* IASKPSToggleSwitchSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BEB120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.m */; }; - CD720C00120B75FC006EC605 /* IASKSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BED120B75FB006EC605 /* IASKSlider.m */; }; - CD720C01120B75FC006EC605 /* IASKSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BEF120B75FB006EC605 /* IASKSwitch.m */; }; - CD720C02120B75FC006EC605 /* IASKTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BF1120B75FB006EC605 /* IASKTextField.m */; }; - CD720C03120B75FC006EC605 /* IASKAppSettingsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD720BF3120B75FB006EC605 /* IASKAppSettingsView.xib */; }; - CD720C04120B75FC006EC605 /* IASKPSSliderSpecifierViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD720BF4120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.xib */; }; - CD720C05120B75FC006EC605 /* IASKPSTextFieldSpecifierViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD720BF5120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.xib */; }; - CD720C06120B75FC006EC605 /* IASKPSToggleSwitchSpecifierViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD720BF6120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.xib */; }; - CD720C07120B75FC006EC605 /* IASKSpecifierValuesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD720BF7120B75FC006EC605 /* IASKSpecifierValuesView.xib */; }; - CD7A89F31204B60F00140865 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = CD7A89F21204B60F00140865 /* Settings.bundle */; }; - CD8235CB11E3D66A00819570 /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD8235CA11E3D66A00819570 /* AddressBook.framework */; }; - CD8235CD11E3D66A00819570 /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD8235CC11E3D66A00819570 /* AddressBookUI.framework */; }; - CD8235E011E3DD7500819570 /* ContactViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD8235DF11E3DD7500819570 /* ContactViewController.m */; }; - CD8F0EF211B2CFCF00D38970 /* QAWebController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD8F0EF111B2CFCF00D38970 /* QAWebController.m */; }; - CD8F0F7211B2D79A00D38970 /* CommonFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = CD8F0F7111B2D79A00D38970 /* CommonFunctions.m */; }; - CD8F0F7E11B2D7A600D38970 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD8F0F7D11B2D7A600D38970 /* SystemConfiguration.framework */; }; - CD90256E11B0C0B500519439 /* SFHFKeychainUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90253411B0C0B500519439 /* SFHFKeychainUtils.m */; }; - CD90256F11B0C0B500519439 /* Base64Transcoder.c in Sources */ = {isa = PBXBuildFile; fileRef = CD90253711B0C0B500519439 /* Base64Transcoder.c */; }; - CD90257011B0C0B500519439 /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = CD90253911B0C0B500519439 /* hmac.c */; }; - CD90257111B0C0B500519439 /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = CD90253B11B0C0B500519439 /* sha1.c */; }; - CD90257211B0C0B500519439 /* NSString+URLEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90253F11B0C0B500519439 /* NSString+URLEncoding.m */; }; - CD90257311B0C0B500519439 /* OAAsynchronousDataFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254111B0C0B500519439 /* OAAsynchronousDataFetcher.m */; }; - CD90257411B0C0B500519439 /* OAConsumer.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254311B0C0B500519439 /* OAConsumer.m */; }; - CD90257511B0C0B500519439 /* OADataFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254511B0C0B500519439 /* OADataFetcher.m */; }; - CD90257611B0C0B500519439 /* OAMutableURLRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254711B0C0B500519439 /* OAMutableURLRequest.m */; }; - CD90257711B0C0B500519439 /* OARequestParameter.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254911B0C0B500519439 /* OARequestParameter.m */; }; - CD90257811B0C0B500519439 /* OAServiceTicket.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254B11B0C0B500519439 /* OAServiceTicket.m */; }; - CD90257911B0C0B500519439 /* OAToken.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254D11B0C0B500519439 /* OAToken.m */; }; - CD90257A11B0C0B500519439 /* OAToken_KeychainExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254F11B0C0B500519439 /* OAToken_KeychainExtensions.m */; }; - CD90257B11B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90255211B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.m */; }; - CD90257C11B0C0B500519439 /* OAPlaintextSignatureProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90255411B0C0B500519439 /* OAPlaintextSignatureProvider.m */; }; - CD90258011B0C0B500519439 /* CDataScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90255F11B0C0B500519439 /* CDataScanner.m */; }; - CD90258111B0C0B500519439 /* CDataScanner_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90256211B0C0B500519439 /* CDataScanner_Extensions.m */; }; - CD90258211B0C0B500519439 /* NSCharacterSet_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90256411B0C0B500519439 /* NSCharacterSet_Extensions.m */; }; - CD90258311B0C0B500519439 /* NSDictionary_JSONExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90256611B0C0B500519439 /* NSDictionary_JSONExtensions.m */; }; - CD90258411B0C0B500519439 /* CJSONDeserializer.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90256911B0C0B500519439 /* CJSONDeserializer.m */; }; - CD90258511B0C0B500519439 /* CJSONScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90256B11B0C0B500519439 /* CJSONScanner.m */; }; - CD90258611B0C0B500519439 /* CJSONSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90256D11B0C0B500519439 /* CJSONSerializer.m */; }; - CD9025D911B1438600519439 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD9025D811B1438600519439 /* Security.framework */; }; - CD90260B11B14D2400519439 /* OSProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90260A11B14D2400519439 /* OSProvider.m */; }; - CD90260F11B14DD300519439 /* OSConsumer.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90260E11B14DD300519439 /* OSConsumer.m */; }; - CDA8E3C011BD323500B53FCF /* ActivitiesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA8E3BF11BD323500B53FCF /* ActivitiesViewController.m */; }; - CDA8E3CE11BD32F500B53FCF /* ATutorHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA8E3CD11BD32F500B53FCF /* ATutorHelper.m */; }; - CDDEEEB4120F2C240016E33F /* GroupsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDDEEEB3120F2C240016E33F /* GroupsViewController.m */; }; - CDE2828711ABAB8B00A7F0EE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDE2828611ABAB8B00A7F0EE /* QuartzCore.framework */; }; - CDE2832011ABAF5100A7F0EE /* LauncherViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDE2831F11ABAF5100A7F0EE /* LauncherViewController.m */; }; - CDE2834811ABB0A500A7F0EE /* StyleSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = CDE2834711ABB0A500A7F0EE /* StyleSheet.m */; }; - CDE2836111ABB71F00A7F0EE /* Activities.png in Resources */ = {isa = PBXBuildFile; fileRef = CDE2835D11ABB71F00A7F0EE /* Activities.png */; }; - CDE2836211ABB71F00A7F0EE /* Contacts.png in Resources */ = {isa = PBXBuildFile; fileRef = CDE2835E11ABB71F00A7F0EE /* Contacts.png */; }; - CDE2836311ABB71F00A7F0EE /* Gadgets.png in Resources */ = {isa = PBXBuildFile; fileRef = CDE2835F11ABB71F00A7F0EE /* Gadgets.png */; }; - CDE2836411ABB71F00A7F0EE /* Groups.png in Resources */ = {isa = PBXBuildFile; fileRef = CDE2836011ABB71F00A7F0EE /* Groups.png */; }; - CDF0DEE611DF6F9000B2500F /* Contact.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF0DEE511DF6F9000B2500F /* Contact.m */; }; - CDF0DF0111DF72A100B2500F /* ContactsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF0DF0011DF72A100B2500F /* ContactsViewController.m */; }; - CDF0E03511DF7E5300B2500F /* libThree20.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0DFDF11DF7E1900B2500F /* libThree20.a */; }; - CDF0E03611DF7E5400B2500F /* libThree20Core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0E00A11DF7E4100B2500F /* libThree20Core.a */; }; - CDF0E03711DF7E5400B2500F /* libThree20Network.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0E01211DF7E4100B2500F /* libThree20Network.a */; }; - CDF0E03811DF7E5500B2500F /* libThree20Style.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0E01A11DF7E4100B2500F /* libThree20Style.a */; }; - CDF0E03911DF7E5500B2500F /* libThree20UI.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0E03211DF7E4100B2500F /* libThree20UI.a */; }; - CDF0E03A11DF7E5900B2500F /* libThree20UICommon.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0E02211DF7E4100B2500F /* libThree20UICommon.a */; }; - CDF0E03B11DF7E5900B2500F /* libThree20UINavigator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0E02A11DF7E4100B2500F /* libThree20UINavigator.a */; }; - CDF0E05111DF7EAC00B2500F /* Three20.bundle in Resources */ = {isa = PBXBuildFile; fileRef = CDF0E05011DF7EAC00B2500F /* Three20.bundle */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - CDF0DFDE11DF7E1900B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFB111DF7E1900B2500F /* Three20.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2; - remoteInfo = Three20; - }; - CDF0DFE011DF7E1900B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFB111DF7E1900B2500F /* Three20.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EB9E6C6210B6A8F800DE563C; - remoteInfo = UnitTests; - }; - CDF0E00911DF7E4100B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFF311DF7E4100B2500F /* Three20Core.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2; - remoteInfo = Three20Core; - }; - CDF0E00B11DF7E4100B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFF311DF7E4100B2500F /* Three20Core.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EB9E6C6210B6A8F800DE563C; - remoteInfo = UnitTests; - }; - CDF0E01111DF7E4100B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFF611DF7E4100B2500F /* Three20Network.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2; - remoteInfo = Three20Network; - }; - CDF0E01311DF7E4100B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFF611DF7E4100B2500F /* Three20Network.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EB9E6C6210B6A8F800DE563C; - remoteInfo = UnitTests; - }; - CDF0E01911DF7E4100B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFF911DF7E4100B2500F /* Three20Style.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2; - remoteInfo = Three20Style; - }; - CDF0E01B11DF7E4100B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFF911DF7E4100B2500F /* Three20Style.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EB9E6C6210B6A8F800DE563C; - remoteInfo = UnitTests; - }; - CDF0E02111DF7E4100B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFFC11DF7E4100B2500F /* Three20UICommon.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2; - remoteInfo = Three20UICommon; - }; - CDF0E02311DF7E4100B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFFC11DF7E4100B2500F /* Three20UICommon.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EB9E6C6210B6A8F800DE563C; - remoteInfo = UnitTests; - }; - CDF0E02911DF7E4100B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFFF11DF7E4100B2500F /* Three20UINavigator.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2; - remoteInfo = Three20UINavigator; - }; - CDF0E02B11DF7E4100B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFFF11DF7E4100B2500F /* Three20UINavigator.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EB9E6C6210B6A8F800DE563C; - remoteInfo = UnitTests; - }; - CDF0E03111DF7E4100B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0E00211DF7E4100B2500F /* Three20UI.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2; - remoteInfo = Three20UI; - }; - CDF0E03311DF7E4100B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0E00211DF7E4100B2500F /* Three20UI.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EB9E6C6210B6A8F800DE563C; - remoteInfo = UnitTests; - }; - CDF0E04211DF7E8D00B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFF311DF7E4100B2500F /* Three20Core.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = BEF31F390F352DF5000DE5D2; - remoteInfo = Three20Core; - }; - CDF0E04411DF7E8D00B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0E00211DF7E4100B2500F /* Three20UI.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = BEF31F390F352DF5000DE5D2; - remoteInfo = Three20UI; - }; - CDF0E04611DF7E8D00B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFF911DF7E4100B2500F /* Three20Style.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = BEF31F390F352DF5000DE5D2; - remoteInfo = Three20Style; - }; - CDF0E04811DF7E8D00B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFF611DF7E4100B2500F /* Three20Network.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = BEF31F390F352DF5000DE5D2; - remoteInfo = Three20Network; - }; - CDF0E04A11DF7E8D00B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFFF11DF7E4100B2500F /* Three20UINavigator.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = BEF31F390F352DF5000DE5D2; - remoteInfo = Three20UINavigator; - }; - CDF0E04C11DF7E8D00B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFFC11DF7E4100B2500F /* Three20UICommon.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = BEF31F390F352DF5000DE5D2; - remoteInfo = Three20UICommon; - }; - CDF0E04E11DF7E8D00B2500F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CDF0DFB111DF7E1900B2500F /* Three20.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = BEF31F390F352DF5000DE5D2; - remoteInfo = Three20; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1D3623240D0F684500981E51 /* ATutorAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATutorAppDelegate.h; sourceTree = ""; }; - 1D3623250D0F684500981E51 /* ATutorAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ATutorAppDelegate.m; sourceTree = ""; }; - 1D6058910D05DD3D006BFB54 /* ATutor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ATutor.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 32CA4F630368D1EE00C91783 /* ATutor_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATutor_Prefix.pch; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* ATutor-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ATutor-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; - CD26D9E311E8D30700003274 /* ContactsDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsDataSource.h; sourceTree = ""; }; - CD26D9E411E8D30700003274 /* ContactsDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactsDataSource.m; sourceTree = ""; }; - CD26DA9A11E8E66800003274 /* ContactItemCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactItemCell.h; sourceTree = ""; }; - CD26DA9B11E8E66800003274 /* ContactItemCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactItemCell.m; sourceTree = ""; }; - CD720BDA120B75FB006EC605 /* IASKAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsViewController.h; sourceTree = ""; }; - CD720BDB120B75FB006EC605 /* IASKAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKAppSettingsViewController.m; sourceTree = ""; }; - CD720BDC120B75FB006EC605 /* IASKSpecifierValuesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifierValuesViewController.h; sourceTree = ""; }; - CD720BDD120B75FB006EC605 /* IASKSpecifierValuesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifierValuesViewController.m; sourceTree = ""; }; - CD720BDF120B75FB006EC605 /* IASKSettingsReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsReader.h; sourceTree = ""; }; - CD720BE0120B75FB006EC605 /* IASKSettingsReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsReader.m; sourceTree = ""; }; - CD720BE1120B75FB006EC605 /* IASKSpecifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifier.h; sourceTree = ""; }; - CD720BE2120B75FB006EC605 /* IASKSpecifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifier.m; sourceTree = ""; }; - CD720BE4120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSSliderSpecifierViewCell.h; sourceTree = ""; }; - CD720BE5120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSSliderSpecifierViewCell.m; sourceTree = ""; }; - CD720BE6120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSTextFieldSpecifierViewCell.h; sourceTree = ""; }; - CD720BE7120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSTextFieldSpecifierViewCell.m; sourceTree = ""; }; - CD720BE8120B75FB006EC605 /* IASKPSTitleValueSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSTitleValueSpecifierViewCell.h; sourceTree = ""; }; - CD720BE9120B75FB006EC605 /* IASKPSTitleValueSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSTitleValueSpecifierViewCell.m; sourceTree = ""; }; - CD720BEA120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSToggleSwitchSpecifierViewCell.h; sourceTree = ""; }; - CD720BEB120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSToggleSwitchSpecifierViewCell.m; sourceTree = ""; }; - CD720BEC120B75FB006EC605 /* IASKSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSlider.h; sourceTree = ""; }; - CD720BED120B75FB006EC605 /* IASKSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSlider.m; sourceTree = ""; }; - CD720BEE120B75FB006EC605 /* IASKSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSwitch.h; sourceTree = ""; }; - CD720BEF120B75FB006EC605 /* IASKSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSwitch.m; sourceTree = ""; }; - CD720BF0120B75FB006EC605 /* IASKTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKTextField.h; sourceTree = ""; }; - CD720BF1120B75FB006EC605 /* IASKTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKTextField.m; sourceTree = ""; }; - CD720BF3120B75FB006EC605 /* IASKAppSettingsView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IASKAppSettingsView.xib; sourceTree = ""; }; - CD720BF4120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IASKPSSliderSpecifierViewCell.xib; sourceTree = ""; }; - CD720BF5120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IASKPSTextFieldSpecifierViewCell.xib; sourceTree = ""; }; - CD720BF6120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IASKPSToggleSwitchSpecifierViewCell.xib; sourceTree = ""; }; - CD720BF7120B75FC006EC605 /* IASKSpecifierValuesView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IASKSpecifierValuesView.xib; sourceTree = ""; }; - CD7A89F21204B60F00140865 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; - CD8235CA11E3D66A00819570 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = iphoneos3.1.3/System/Library/Frameworks/AddressBook.framework; sourceTree = ""; }; - CD8235CC11E3D66A00819570 /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = iphoneos3.1.3/System/Library/Frameworks/AddressBookUI.framework; sourceTree = ""; }; - CD8235DE11E3DD7500819570 /* ContactViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactViewController.h; sourceTree = ""; }; - CD8235DF11E3DD7500819570 /* ContactViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactViewController.m; sourceTree = ""; }; - CD8F0EF011B2CFCF00D38970 /* QAWebController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QAWebController.h; sourceTree = ""; }; - CD8F0EF111B2CFCF00D38970 /* QAWebController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QAWebController.m; sourceTree = ""; }; - CD8F0F7011B2D79A00D38970 /* CommonFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonFunctions.h; sourceTree = ""; }; - CD8F0F7111B2D79A00D38970 /* CommonFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CommonFunctions.m; sourceTree = ""; }; - CD8F0F7D11B2D7A600D38970 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; - CD90253311B0C0B500519439 /* SFHFKeychainUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SFHFKeychainUtils.h; sourceTree = ""; }; - CD90253411B0C0B500519439 /* SFHFKeychainUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SFHFKeychainUtils.m; sourceTree = ""; }; - CD90253711B0C0B500519439 /* Base64Transcoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Base64Transcoder.c; sourceTree = ""; }; - CD90253811B0C0B500519439 /* Base64Transcoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Base64Transcoder.h; sourceTree = ""; }; - CD90253911B0C0B500519439 /* hmac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hmac.c; sourceTree = ""; }; - CD90253A11B0C0B500519439 /* hmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hmac.h; sourceTree = ""; }; - CD90253B11B0C0B500519439 /* sha1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sha1.c; sourceTree = ""; }; - CD90253C11B0C0B500519439 /* sha1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha1.h; sourceTree = ""; }; - CD90253E11B0C0B500519439 /* NSString+URLEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+URLEncoding.h"; sourceTree = ""; }; - CD90253F11B0C0B500519439 /* NSString+URLEncoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+URLEncoding.m"; sourceTree = ""; }; - CD90254011B0C0B500519439 /* OAAsynchronousDataFetcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAAsynchronousDataFetcher.h; sourceTree = ""; }; - CD90254111B0C0B500519439 /* OAAsynchronousDataFetcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAAsynchronousDataFetcher.m; sourceTree = ""; }; - CD90254211B0C0B500519439 /* OAConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAConsumer.h; sourceTree = ""; }; - CD90254311B0C0B500519439 /* OAConsumer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAConsumer.m; sourceTree = ""; }; - CD90254411B0C0B500519439 /* OADataFetcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OADataFetcher.h; sourceTree = ""; }; - CD90254511B0C0B500519439 /* OADataFetcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OADataFetcher.m; sourceTree = ""; }; - CD90254611B0C0B500519439 /* OAMutableURLRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAMutableURLRequest.h; sourceTree = ""; }; - CD90254711B0C0B500519439 /* OAMutableURLRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAMutableURLRequest.m; sourceTree = ""; }; - CD90254811B0C0B500519439 /* OARequestParameter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OARequestParameter.h; sourceTree = ""; }; - CD90254911B0C0B500519439 /* OARequestParameter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OARequestParameter.m; sourceTree = ""; }; - CD90254A11B0C0B500519439 /* OAServiceTicket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAServiceTicket.h; sourceTree = ""; }; - CD90254B11B0C0B500519439 /* OAServiceTicket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAServiceTicket.m; sourceTree = ""; }; - CD90254C11B0C0B500519439 /* OAToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAToken.h; sourceTree = ""; }; - CD90254D11B0C0B500519439 /* OAToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAToken.m; sourceTree = ""; }; - CD90254E11B0C0B500519439 /* OAToken_KeychainExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAToken_KeychainExtensions.h; sourceTree = ""; }; - CD90254F11B0C0B500519439 /* OAToken_KeychainExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAToken_KeychainExtensions.m; sourceTree = ""; }; - CD90255111B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAHMAC_SHA1SignatureProvider.h; sourceTree = ""; }; - CD90255211B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAHMAC_SHA1SignatureProvider.m; sourceTree = ""; }; - CD90255311B0C0B500519439 /* OAPlaintextSignatureProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAPlaintextSignatureProvider.h; sourceTree = ""; }; - CD90255411B0C0B500519439 /* OAPlaintextSignatureProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAPlaintextSignatureProvider.m; sourceTree = ""; }; - CD90255511B0C0B500519439 /* OASignatureProviding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OASignatureProviding.h; sourceTree = ""; }; - CD90255E11B0C0B500519439 /* CDataScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDataScanner.h; sourceTree = ""; }; - CD90255F11B0C0B500519439 /* CDataScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDataScanner.m; sourceTree = ""; }; - CD90256111B0C0B500519439 /* CDataScanner_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDataScanner_Extensions.h; sourceTree = ""; }; - CD90256211B0C0B500519439 /* CDataScanner_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDataScanner_Extensions.m; sourceTree = ""; }; - CD90256311B0C0B500519439 /* NSCharacterSet_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSCharacterSet_Extensions.h; sourceTree = ""; }; - CD90256411B0C0B500519439 /* NSCharacterSet_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSCharacterSet_Extensions.m; sourceTree = ""; }; - CD90256511B0C0B500519439 /* NSDictionary_JSONExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSDictionary_JSONExtensions.h; sourceTree = ""; }; - CD90256611B0C0B500519439 /* NSDictionary_JSONExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSDictionary_JSONExtensions.m; sourceTree = ""; }; - CD90256811B0C0B500519439 /* CJSONDeserializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONDeserializer.h; sourceTree = ""; }; - CD90256911B0C0B500519439 /* CJSONDeserializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONDeserializer.m; sourceTree = ""; }; - CD90256A11B0C0B500519439 /* CJSONScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONScanner.h; sourceTree = ""; }; - CD90256B11B0C0B500519439 /* CJSONScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONScanner.m; sourceTree = ""; }; - CD90256C11B0C0B500519439 /* CJSONSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONSerializer.h; sourceTree = ""; }; - CD90256D11B0C0B500519439 /* CJSONSerializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONSerializer.m; sourceTree = ""; }; - CD9025D811B1438600519439 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; - CD90260911B14D2400519439 /* OSProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSProvider.h; sourceTree = ""; }; - CD90260A11B14D2400519439 /* OSProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OSProvider.m; sourceTree = ""; }; - CD90260D11B14DD300519439 /* OSConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSConsumer.h; sourceTree = ""; }; - CD90260E11B14DD300519439 /* OSConsumer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OSConsumer.m; sourceTree = ""; }; - CDA8E3BE11BD323500B53FCF /* ActivitiesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActivitiesViewController.h; sourceTree = ""; }; - CDA8E3BF11BD323500B53FCF /* ActivitiesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActivitiesViewController.m; sourceTree = ""; }; - CDA8E3CC11BD32F500B53FCF /* ATutorHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATutorHelper.h; sourceTree = ""; }; - CDA8E3CD11BD32F500B53FCF /* ATutorHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ATutorHelper.m; sourceTree = ""; }; - CDDEEEB2120F2C240016E33F /* GroupsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupsViewController.h; sourceTree = ""; }; - CDDEEEB3120F2C240016E33F /* GroupsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupsViewController.m; sourceTree = ""; }; - CDE2828611ABAB8B00A7F0EE /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - CDE2831E11ABAF5100A7F0EE /* LauncherViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LauncherViewController.h; sourceTree = ""; }; - CDE2831F11ABAF5100A7F0EE /* LauncherViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LauncherViewController.m; sourceTree = ""; }; - CDE2834611ABB0A500A7F0EE /* StyleSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleSheet.h; sourceTree = ""; }; - CDE2834711ABB0A500A7F0EE /* StyleSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StyleSheet.m; sourceTree = ""; }; - CDE2835D11ABB71F00A7F0EE /* Activities.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Activities.png; sourceTree = ""; }; - CDE2835E11ABB71F00A7F0EE /* Contacts.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Contacts.png; sourceTree = ""; }; - CDE2835F11ABB71F00A7F0EE /* Gadgets.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Gadgets.png; sourceTree = ""; }; - CDE2836011ABB71F00A7F0EE /* Groups.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Groups.png; sourceTree = ""; }; - CDF0DEE411DF6F9000B2500F /* Contact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Contact.h; sourceTree = ""; }; - CDF0DEE511DF6F9000B2500F /* Contact.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Contact.m; sourceTree = ""; }; - CDF0DEFF11DF72A100B2500F /* ContactsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsViewController.h; sourceTree = ""; }; - CDF0DF0011DF72A100B2500F /* ContactsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactsViewController.m; sourceTree = ""; }; - CDF0DFB111DF7E1900B2500F /* Three20.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20.xcodeproj; path = three20/src/Three20/Three20.xcodeproj; sourceTree = SOURCE_ROOT; }; - CDF0DFF311DF7E4100B2500F /* Three20Core.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20Core.xcodeproj; path = three20/src/Three20Core/Three20Core.xcodeproj; sourceTree = SOURCE_ROOT; }; - CDF0DFF611DF7E4100B2500F /* Three20Network.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20Network.xcodeproj; path = three20/src/Three20Network/Three20Network.xcodeproj; sourceTree = SOURCE_ROOT; }; - CDF0DFF911DF7E4100B2500F /* Three20Style.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20Style.xcodeproj; path = three20/src/Three20Style/Three20Style.xcodeproj; sourceTree = SOURCE_ROOT; }; - CDF0DFFC11DF7E4100B2500F /* Three20UICommon.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20UICommon.xcodeproj; path = three20/src/Three20UICommon/Three20UICommon.xcodeproj; sourceTree = SOURCE_ROOT; }; - CDF0DFFF11DF7E4100B2500F /* Three20UINavigator.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20UINavigator.xcodeproj; path = three20/src/Three20UINavigator/Three20UINavigator.xcodeproj; sourceTree = SOURCE_ROOT; }; - CDF0E00211DF7E4100B2500F /* Three20UI.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20UI.xcodeproj; path = three20/src/Three20UI/Three20UI.xcodeproj; sourceTree = SOURCE_ROOT; }; - CDF0E05011DF7EAC00B2500F /* Three20.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Three20.bundle; path = three20/src/Three20.bundle; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, - 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */, - CDE2828711ABAB8B00A7F0EE /* QuartzCore.framework in Frameworks */, - CD9025D911B1438600519439 /* Security.framework in Frameworks */, - CD8F0F7E11B2D7A600D38970 /* SystemConfiguration.framework in Frameworks */, - CDF0E03511DF7E5300B2500F /* libThree20.a in Frameworks */, - CDF0E03611DF7E5400B2500F /* libThree20Core.a in Frameworks */, - CDF0E03711DF7E5400B2500F /* libThree20Network.a in Frameworks */, - CDF0E03811DF7E5500B2500F /* libThree20Style.a in Frameworks */, - CDF0E03911DF7E5500B2500F /* libThree20UI.a in Frameworks */, - CDF0E03A11DF7E5900B2500F /* libThree20UICommon.a in Frameworks */, - CDF0E03B11DF7E5900B2500F /* libThree20UINavigator.a in Frameworks */, - CD8235CB11E3D66A00819570 /* AddressBook.framework in Frameworks */, - CD8235CD11E3D66A00819570 /* AddressBookUI.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Classes */ = { - isa = PBXGroup; - children = ( - 1D3623240D0F684500981E51 /* ATutorAppDelegate.h */, - 1D3623250D0F684500981E51 /* ATutorAppDelegate.m */, - CDE2831D11ABAF3B00A7F0EE /* View Controllers & Stuff */, - CD90260C11B14D2C00519439 /* Models */, - CDA8E3CB11BD32E700B53FCF /* Helpers */, - CDE2834511ABB09400A7F0EE /* Miscellaneous */, - ); - path = Classes; - sourceTree = ""; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 1D6058910D05DD3D006BFB54 /* ATutor.app */, - ); - name = Products; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { - isa = PBXGroup; - children = ( - 080E96DDFE201D6D7F000001 /* Classes */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = CustomTemplate; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - CD720BD8120B75FB006EC605 /* InAppSettingsKit */, - CD90253211B0C0B500519439 /* KeychainUtils */, - CD90253511B0C0B500519439 /* OAuth */, - CD90255D11B0C0B500519439 /* TouchJSON */, - CDE2822A11ABAB4D00A7F0EE /* three20 */, - 32CA4F630368D1EE00C91783 /* ATutor_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - CD7A89F21204B60F00140865 /* Settings.bundle */, - CDE2835B11ABB70100A7F0EE /* Graphics */, - 8D1107310486CEB800E47090 /* ATutor-Info.plist */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - CD8235CA11E3D66A00819570 /* AddressBook.framework */, - CD8235CC11E3D66A00819570 /* AddressBookUI.framework */, - CD8F0F7D11B2D7A600D38970 /* SystemConfiguration.framework */, - CD9025D811B1438600519439 /* Security.framework */, - CDE2828611ABAB8B00A7F0EE /* QuartzCore.framework */, - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, - 1D30AB110D05D00D00671497 /* Foundation.framework */, - 288765FC0DF74451002DB57D /* CoreGraphics.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - CD26D9DF11E8D2C900003274 /* Contacts */ = { - isa = PBXGroup; - children = ( - CDF0DEFF11DF72A100B2500F /* ContactsViewController.h */, - CDF0DF0011DF72A100B2500F /* ContactsViewController.m */, - CD8235DE11E3DD7500819570 /* ContactViewController.h */, - CD8235DF11E3DD7500819570 /* ContactViewController.m */, - CD26D9E311E8D30700003274 /* ContactsDataSource.h */, - CD26D9E411E8D30700003274 /* ContactsDataSource.m */, - CD26DA9A11E8E66800003274 /* ContactItemCell.h */, - CD26DA9B11E8E66800003274 /* ContactItemCell.m */, - ); - name = Contacts; - sourceTree = ""; - }; - CD26D9E011E8D2CE00003274 /* Activities */ = { - isa = PBXGroup; - children = ( - CDA8E3BE11BD323500B53FCF /* ActivitiesViewController.h */, - CDA8E3BF11BD323500B53FCF /* ActivitiesViewController.m */, - ); - name = Activities; - sourceTree = ""; - }; - CD26D9E111E8D2DB00003274 /* Generic */ = { - isa = PBXGroup; - children = ( - CD8F0EF011B2CFCF00D38970 /* QAWebController.h */, - CD8F0EF111B2CFCF00D38970 /* QAWebController.m */, - CDE2831E11ABAF5100A7F0EE /* LauncherViewController.h */, - CDE2831F11ABAF5100A7F0EE /* LauncherViewController.m */, - ); - name = Generic; - sourceTree = ""; - }; - CD720BD8120B75FB006EC605 /* InAppSettingsKit */ = { - isa = PBXGroup; - children = ( - CD720BD9120B75FB006EC605 /* Controllers */, - CD720BDE120B75FB006EC605 /* Models */, - CD720BE3120B75FB006EC605 /* Views */, - CD720BF2120B75FB006EC605 /* Xibs */, - ); - path = InAppSettingsKit; - sourceTree = ""; - }; - CD720BD9120B75FB006EC605 /* Controllers */ = { - isa = PBXGroup; - children = ( - CD720BDA120B75FB006EC605 /* IASKAppSettingsViewController.h */, - CD720BDB120B75FB006EC605 /* IASKAppSettingsViewController.m */, - CD720BDC120B75FB006EC605 /* IASKSpecifierValuesViewController.h */, - CD720BDD120B75FB006EC605 /* IASKSpecifierValuesViewController.m */, - ); - path = Controllers; - sourceTree = ""; - }; - CD720BDE120B75FB006EC605 /* Models */ = { - isa = PBXGroup; - children = ( - CD720BDF120B75FB006EC605 /* IASKSettingsReader.h */, - CD720BE0120B75FB006EC605 /* IASKSettingsReader.m */, - CD720BE1120B75FB006EC605 /* IASKSpecifier.h */, - CD720BE2120B75FB006EC605 /* IASKSpecifier.m */, - ); - path = Models; - sourceTree = ""; - }; - CD720BE3120B75FB006EC605 /* Views */ = { - isa = PBXGroup; - children = ( - CD720BE4120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.h */, - CD720BE5120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.m */, - CD720BE6120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.h */, - CD720BE7120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.m */, - CD720BE8120B75FB006EC605 /* IASKPSTitleValueSpecifierViewCell.h */, - CD720BE9120B75FB006EC605 /* IASKPSTitleValueSpecifierViewCell.m */, - CD720BEA120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.h */, - CD720BEB120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.m */, - CD720BEC120B75FB006EC605 /* IASKSlider.h */, - CD720BED120B75FB006EC605 /* IASKSlider.m */, - CD720BEE120B75FB006EC605 /* IASKSwitch.h */, - CD720BEF120B75FB006EC605 /* IASKSwitch.m */, - CD720BF0120B75FB006EC605 /* IASKTextField.h */, - CD720BF1120B75FB006EC605 /* IASKTextField.m */, - ); - path = Views; - sourceTree = ""; - }; - CD720BF2120B75FB006EC605 /* Xibs */ = { - isa = PBXGroup; - children = ( - CD720BF3120B75FB006EC605 /* IASKAppSettingsView.xib */, - CD720BF4120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.xib */, - CD720BF5120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.xib */, - CD720BF6120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.xib */, - CD720BF7120B75FC006EC605 /* IASKSpecifierValuesView.xib */, - ); - path = Xibs; - sourceTree = ""; - }; - CD90253211B0C0B500519439 /* KeychainUtils */ = { - isa = PBXGroup; - children = ( - CD90253311B0C0B500519439 /* SFHFKeychainUtils.h */, - CD90253411B0C0B500519439 /* SFHFKeychainUtils.m */, - ); - path = KeychainUtils; - sourceTree = ""; - }; - CD90253511B0C0B500519439 /* OAuth */ = { - isa = PBXGroup; - children = ( - CD90253611B0C0B500519439 /* Crypto */, - CD90253D11B0C0B500519439 /* Extensions */, - CD90254011B0C0B500519439 /* OAAsynchronousDataFetcher.h */, - CD90254111B0C0B500519439 /* OAAsynchronousDataFetcher.m */, - CD90254211B0C0B500519439 /* OAConsumer.h */, - CD90254311B0C0B500519439 /* OAConsumer.m */, - CD90254411B0C0B500519439 /* OADataFetcher.h */, - CD90254511B0C0B500519439 /* OADataFetcher.m */, - CD90254611B0C0B500519439 /* OAMutableURLRequest.h */, - CD90254711B0C0B500519439 /* OAMutableURLRequest.m */, - CD90254811B0C0B500519439 /* OARequestParameter.h */, - CD90254911B0C0B500519439 /* OARequestParameter.m */, - CD90254A11B0C0B500519439 /* OAServiceTicket.h */, - CD90254B11B0C0B500519439 /* OAServiceTicket.m */, - CD90254C11B0C0B500519439 /* OAToken.h */, - CD90254D11B0C0B500519439 /* OAToken.m */, - CD90254E11B0C0B500519439 /* OAToken_KeychainExtensions.h */, - CD90254F11B0C0B500519439 /* OAToken_KeychainExtensions.m */, - CD90255011B0C0B500519439 /* Signature Providers */, - ); - path = OAuth; - sourceTree = ""; - }; - CD90253611B0C0B500519439 /* Crypto */ = { - isa = PBXGroup; - children = ( - CD90253711B0C0B500519439 /* Base64Transcoder.c */, - CD90253811B0C0B500519439 /* Base64Transcoder.h */, - CD90253911B0C0B500519439 /* hmac.c */, - CD90253A11B0C0B500519439 /* hmac.h */, - CD90253B11B0C0B500519439 /* sha1.c */, - CD90253C11B0C0B500519439 /* sha1.h */, - ); - path = Crypto; - sourceTree = ""; - }; - CD90253D11B0C0B500519439 /* Extensions */ = { - isa = PBXGroup; - children = ( - CD90253E11B0C0B500519439 /* NSString+URLEncoding.h */, - CD90253F11B0C0B500519439 /* NSString+URLEncoding.m */, - ); - path = Extensions; - sourceTree = ""; - }; - CD90255011B0C0B500519439 /* Signature Providers */ = { - isa = PBXGroup; - children = ( - CD90255111B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.h */, - CD90255211B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.m */, - CD90255311B0C0B500519439 /* OAPlaintextSignatureProvider.h */, - CD90255411B0C0B500519439 /* OAPlaintextSignatureProvider.m */, - CD90255511B0C0B500519439 /* OASignatureProviding.h */, - ); - path = "Signature Providers"; - sourceTree = ""; - }; - CD90255D11B0C0B500519439 /* TouchJSON */ = { - isa = PBXGroup; - children = ( - CD90255E11B0C0B500519439 /* CDataScanner.h */, - CD90255F11B0C0B500519439 /* CDataScanner.m */, - CD90256011B0C0B500519439 /* Extensions */, - CD90256711B0C0B500519439 /* JSON */, - ); - path = TouchJSON; - sourceTree = ""; - }; - CD90256011B0C0B500519439 /* Extensions */ = { - isa = PBXGroup; - children = ( - CD90256111B0C0B500519439 /* CDataScanner_Extensions.h */, - CD90256211B0C0B500519439 /* CDataScanner_Extensions.m */, - CD90256311B0C0B500519439 /* NSCharacterSet_Extensions.h */, - CD90256411B0C0B500519439 /* NSCharacterSet_Extensions.m */, - CD90256511B0C0B500519439 /* NSDictionary_JSONExtensions.h */, - CD90256611B0C0B500519439 /* NSDictionary_JSONExtensions.m */, - ); - path = Extensions; - sourceTree = ""; - }; - CD90256711B0C0B500519439 /* JSON */ = { - isa = PBXGroup; - children = ( - CD90256811B0C0B500519439 /* CJSONDeserializer.h */, - CD90256911B0C0B500519439 /* CJSONDeserializer.m */, - CD90256A11B0C0B500519439 /* CJSONScanner.h */, - CD90256B11B0C0B500519439 /* CJSONScanner.m */, - CD90256C11B0C0B500519439 /* CJSONSerializer.h */, - CD90256D11B0C0B500519439 /* CJSONSerializer.m */, - ); - path = JSON; - sourceTree = ""; - }; - CD90260C11B14D2C00519439 /* Models */ = { - isa = PBXGroup; - children = ( - CD90260911B14D2400519439 /* OSProvider.h */, - CD90260A11B14D2400519439 /* OSProvider.m */, - CD90260D11B14DD300519439 /* OSConsumer.h */, - CD90260E11B14DD300519439 /* OSConsumer.m */, - CDF0DEE411DF6F9000B2500F /* Contact.h */, - CDF0DEE511DF6F9000B2500F /* Contact.m */, - ); - name = Models; - sourceTree = ""; - }; - CDA8E3CB11BD32E700B53FCF /* Helpers */ = { - isa = PBXGroup; - children = ( - CDA8E3CC11BD32F500B53FCF /* ATutorHelper.h */, - CDA8E3CD11BD32F500B53FCF /* ATutorHelper.m */, - ); - name = Helpers; - sourceTree = ""; - }; - CDDEEEB1120F2C110016E33F /* Groups */ = { - isa = PBXGroup; - children = ( - CDDEEEB2120F2C240016E33F /* GroupsViewController.h */, - CDDEEEB3120F2C240016E33F /* GroupsViewController.m */, - ); - name = Groups; - sourceTree = ""; - }; - CDE2822A11ABAB4D00A7F0EE /* three20 */ = { - isa = PBXGroup; - children = ( - CDF0E05011DF7EAC00B2500F /* Three20.bundle */, - CDF0DFF311DF7E4100B2500F /* Three20Core.xcodeproj */, - CDF0DFF611DF7E4100B2500F /* Three20Network.xcodeproj */, - CDF0DFF911DF7E4100B2500F /* Three20Style.xcodeproj */, - CDF0DFFC11DF7E4100B2500F /* Three20UICommon.xcodeproj */, - CDF0DFFF11DF7E4100B2500F /* Three20UINavigator.xcodeproj */, - CDF0E00211DF7E4100B2500F /* Three20UI.xcodeproj */, - CDF0DFB111DF7E1900B2500F /* Three20.xcodeproj */, - ); - name = three20; - sourceTree = ""; - }; - CDE2831D11ABAF3B00A7F0EE /* View Controllers & Stuff */ = { - isa = PBXGroup; - children = ( - CD26D9E111E8D2DB00003274 /* Generic */, - CD26D9E011E8D2CE00003274 /* Activities */, - CD26D9DF11E8D2C900003274 /* Contacts */, - CDDEEEB1120F2C110016E33F /* Groups */, - ); - name = "View Controllers & Stuff"; - sourceTree = ""; - }; - CDE2834511ABB09400A7F0EE /* Miscellaneous */ = { - isa = PBXGroup; - children = ( - CDE2834611ABB0A500A7F0EE /* StyleSheet.h */, - CDE2834711ABB0A500A7F0EE /* StyleSheet.m */, - CD8F0F7011B2D79A00D38970 /* CommonFunctions.h */, - CD8F0F7111B2D79A00D38970 /* CommonFunctions.m */, - ); - name = Miscellaneous; - sourceTree = ""; - }; - CDE2835B11ABB70100A7F0EE /* Graphics */ = { - isa = PBXGroup; - children = ( - CDE2835C11ABB70500A7F0EE /* Launcher Icons */, - ); - name = Graphics; - sourceTree = ""; - }; - CDE2835C11ABB70500A7F0EE /* Launcher Icons */ = { - isa = PBXGroup; - children = ( - CDE2835D11ABB71F00A7F0EE /* Activities.png */, - CDE2835E11ABB71F00A7F0EE /* Contacts.png */, - CDE2835F11ABB71F00A7F0EE /* Gadgets.png */, - CDE2836011ABB71F00A7F0EE /* Groups.png */, - ); - name = "Launcher Icons"; - sourceTree = ""; - }; - CDF0DFDA11DF7E1900B2500F /* Products */ = { - isa = PBXGroup; - children = ( - CDF0DFDF11DF7E1900B2500F /* libThree20.a */, - CDF0DFE111DF7E1900B2500F /* UnitTests.octest */, - ); - name = Products; - sourceTree = ""; - }; - CDF0E00511DF7E4100B2500F /* Products */ = { - isa = PBXGroup; - children = ( - CDF0E00A11DF7E4100B2500F /* libThree20Core.a */, - CDF0E00C11DF7E4100B2500F /* CoreUnitTests.octest */, - ); - name = Products; - sourceTree = ""; - }; - CDF0E00D11DF7E4100B2500F /* Products */ = { - isa = PBXGroup; - children = ( - CDF0E01211DF7E4100B2500F /* libThree20Network.a */, - CDF0E01411DF7E4100B2500F /* UnitTests.octest */, - ); - name = Products; - sourceTree = ""; - }; - CDF0E01511DF7E4100B2500F /* Products */ = { - isa = PBXGroup; - children = ( - CDF0E01A11DF7E4100B2500F /* libThree20Style.a */, - CDF0E01C11DF7E4100B2500F /* UnitTests.octest */, - ); - name = Products; - sourceTree = ""; - }; - CDF0E01D11DF7E4100B2500F /* Products */ = { - isa = PBXGroup; - children = ( - CDF0E02211DF7E4100B2500F /* libThree20UICommon.a */, - CDF0E02411DF7E4100B2500F /* UnitTests.octest */, - ); - name = Products; - sourceTree = ""; - }; - CDF0E02511DF7E4100B2500F /* Products */ = { - isa = PBXGroup; - children = ( - CDF0E02A11DF7E4100B2500F /* libThree20UINavigator.a */, - CDF0E02C11DF7E4100B2500F /* UnitTests.octest */, - ); - name = Products; - sourceTree = ""; - }; - CDF0E02D11DF7E4100B2500F /* Products */ = { - isa = PBXGroup; - children = ( - CDF0E03211DF7E4100B2500F /* libThree20UI.a */, - CDF0E03411DF7E4100B2500F /* UnitTests.octest */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* ATutor */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ATutor" */; - buildPhases = ( - 1D60588D0D05DD3D006BFB54 /* Resources */, - 1D60588E0D05DD3D006BFB54 /* Sources */, - 1D60588F0D05DD3D006BFB54 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - CDF0E04311DF7E8D00B2500F /* PBXTargetDependency */, - CDF0E04511DF7E8D00B2500F /* PBXTargetDependency */, - CDF0E04711DF7E8D00B2500F /* PBXTargetDependency */, - CDF0E04911DF7E8D00B2500F /* PBXTargetDependency */, - CDF0E04B11DF7E8D00B2500F /* PBXTargetDependency */, - CDF0E04D11DF7E8D00B2500F /* PBXTargetDependency */, - CDF0E04F11DF7E8D00B2500F /* PBXTargetDependency */, - ); - name = ATutor; - productName = ATutor; - productReference = 1D6058910D05DD3D006BFB54 /* ATutor.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ATutor" */; - compatibilityVersion = "Xcode 3.1"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = CDF0DFDA11DF7E1900B2500F /* Products */; - ProjectRef = CDF0DFB111DF7E1900B2500F /* Three20.xcodeproj */; - }, - { - ProductGroup = CDF0E00511DF7E4100B2500F /* Products */; - ProjectRef = CDF0DFF311DF7E4100B2500F /* Three20Core.xcodeproj */; - }, - { - ProductGroup = CDF0E00D11DF7E4100B2500F /* Products */; - ProjectRef = CDF0DFF611DF7E4100B2500F /* Three20Network.xcodeproj */; - }, - { - ProductGroup = CDF0E01511DF7E4100B2500F /* Products */; - ProjectRef = CDF0DFF911DF7E4100B2500F /* Three20Style.xcodeproj */; - }, - { - ProductGroup = CDF0E02D11DF7E4100B2500F /* Products */; - ProjectRef = CDF0E00211DF7E4100B2500F /* Three20UI.xcodeproj */; - }, - { - ProductGroup = CDF0E01D11DF7E4100B2500F /* Products */; - ProjectRef = CDF0DFFC11DF7E4100B2500F /* Three20UICommon.xcodeproj */; - }, - { - ProductGroup = CDF0E02511DF7E4100B2500F /* Products */; - ProjectRef = CDF0DFFF11DF7E4100B2500F /* Three20UINavigator.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 1D6058900D05DD3D006BFB54 /* ATutor */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - CDF0DFDF11DF7E1900B2500F /* libThree20.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libThree20.a; - remoteRef = CDF0DFDE11DF7E1900B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0DFE111DF7E1900B2500F /* UnitTests.octest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = UnitTests.octest; - remoteRef = CDF0DFE011DF7E1900B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0E00A11DF7E4100B2500F /* libThree20Core.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libThree20Core.a; - remoteRef = CDF0E00911DF7E4100B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0E00C11DF7E4100B2500F /* CoreUnitTests.octest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = CoreUnitTests.octest; - remoteRef = CDF0E00B11DF7E4100B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0E01211DF7E4100B2500F /* libThree20Network.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libThree20Network.a; - remoteRef = CDF0E01111DF7E4100B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0E01411DF7E4100B2500F /* UnitTests.octest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = UnitTests.octest; - remoteRef = CDF0E01311DF7E4100B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0E01A11DF7E4100B2500F /* libThree20Style.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libThree20Style.a; - remoteRef = CDF0E01911DF7E4100B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0E01C11DF7E4100B2500F /* UnitTests.octest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = UnitTests.octest; - remoteRef = CDF0E01B11DF7E4100B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0E02211DF7E4100B2500F /* libThree20UICommon.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libThree20UICommon.a; - remoteRef = CDF0E02111DF7E4100B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0E02411DF7E4100B2500F /* UnitTests.octest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = UnitTests.octest; - remoteRef = CDF0E02311DF7E4100B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0E02A11DF7E4100B2500F /* libThree20UINavigator.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libThree20UINavigator.a; - remoteRef = CDF0E02911DF7E4100B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0E02C11DF7E4100B2500F /* UnitTests.octest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = UnitTests.octest; - remoteRef = CDF0E02B11DF7E4100B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0E03211DF7E4100B2500F /* libThree20UI.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libThree20UI.a; - remoteRef = CDF0E03111DF7E4100B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - CDF0E03411DF7E4100B2500F /* UnitTests.octest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = UnitTests.octest; - remoteRef = CDF0E03311DF7E4100B2500F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 1D60588D0D05DD3D006BFB54 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CDE2836111ABB71F00A7F0EE /* Activities.png in Resources */, - CDE2836211ABB71F00A7F0EE /* Contacts.png in Resources */, - CDE2836311ABB71F00A7F0EE /* Gadgets.png in Resources */, - CDE2836411ABB71F00A7F0EE /* Groups.png in Resources */, - CDF0E05111DF7EAC00B2500F /* Three20.bundle in Resources */, - CD7A89F31204B60F00140865 /* Settings.bundle in Resources */, - CD720C03120B75FC006EC605 /* IASKAppSettingsView.xib in Resources */, - CD720C04120B75FC006EC605 /* IASKPSSliderSpecifierViewCell.xib in Resources */, - CD720C05120B75FC006EC605 /* IASKPSTextFieldSpecifierViewCell.xib in Resources */, - CD720C06120B75FC006EC605 /* IASKPSToggleSwitchSpecifierViewCell.xib in Resources */, - CD720C07120B75FC006EC605 /* IASKSpecifierValuesView.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1D60588E0D05DD3D006BFB54 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589B0D05DD56006BFB54 /* main.m in Sources */, - 1D3623260D0F684500981E51 /* ATutorAppDelegate.m in Sources */, - CDE2832011ABAF5100A7F0EE /* LauncherViewController.m in Sources */, - CDE2834811ABB0A500A7F0EE /* StyleSheet.m in Sources */, - CD90256E11B0C0B500519439 /* SFHFKeychainUtils.m in Sources */, - CD90256F11B0C0B500519439 /* Base64Transcoder.c in Sources */, - CD90257011B0C0B500519439 /* hmac.c in Sources */, - CD90257111B0C0B500519439 /* sha1.c in Sources */, - CD90257211B0C0B500519439 /* NSString+URLEncoding.m in Sources */, - CD90257311B0C0B500519439 /* OAAsynchronousDataFetcher.m in Sources */, - CD90257411B0C0B500519439 /* OAConsumer.m in Sources */, - CD90257511B0C0B500519439 /* OADataFetcher.m in Sources */, - CD90257611B0C0B500519439 /* OAMutableURLRequest.m in Sources */, - CD90257711B0C0B500519439 /* OARequestParameter.m in Sources */, - CD90257811B0C0B500519439 /* OAServiceTicket.m in Sources */, - CD90257911B0C0B500519439 /* OAToken.m in Sources */, - CD90257A11B0C0B500519439 /* OAToken_KeychainExtensions.m in Sources */, - CD90257B11B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.m in Sources */, - CD90257C11B0C0B500519439 /* OAPlaintextSignatureProvider.m in Sources */, - CD90258011B0C0B500519439 /* CDataScanner.m in Sources */, - CD90258111B0C0B500519439 /* CDataScanner_Extensions.m in Sources */, - CD90258211B0C0B500519439 /* NSCharacterSet_Extensions.m in Sources */, - CD90258311B0C0B500519439 /* NSDictionary_JSONExtensions.m in Sources */, - CD90258411B0C0B500519439 /* CJSONDeserializer.m in Sources */, - CD90258511B0C0B500519439 /* CJSONScanner.m in Sources */, - CD90258611B0C0B500519439 /* CJSONSerializer.m in Sources */, - CD90260B11B14D2400519439 /* OSProvider.m in Sources */, - CD90260F11B14DD300519439 /* OSConsumer.m in Sources */, - CD8F0EF211B2CFCF00D38970 /* QAWebController.m in Sources */, - CD8F0F7211B2D79A00D38970 /* CommonFunctions.m in Sources */, - CDA8E3C011BD323500B53FCF /* ActivitiesViewController.m in Sources */, - CDA8E3CE11BD32F500B53FCF /* ATutorHelper.m in Sources */, - CDF0DEE611DF6F9000B2500F /* Contact.m in Sources */, - CDF0DF0111DF72A100B2500F /* ContactsViewController.m in Sources */, - CD8235E011E3DD7500819570 /* ContactViewController.m in Sources */, - CD26D9E511E8D30700003274 /* ContactsDataSource.m in Sources */, - CD26DA9C11E8E66800003274 /* ContactItemCell.m in Sources */, - CD720BF8120B75FC006EC605 /* IASKAppSettingsViewController.m in Sources */, - CD720BF9120B75FC006EC605 /* IASKSpecifierValuesViewController.m in Sources */, - CD720BFA120B75FC006EC605 /* IASKSettingsReader.m in Sources */, - CD720BFB120B75FC006EC605 /* IASKSpecifier.m in Sources */, - CD720BFC120B75FC006EC605 /* IASKPSSliderSpecifierViewCell.m in Sources */, - CD720BFD120B75FC006EC605 /* IASKPSTextFieldSpecifierViewCell.m in Sources */, - CD720BFE120B75FC006EC605 /* IASKPSTitleValueSpecifierViewCell.m in Sources */, - CD720BFF120B75FC006EC605 /* IASKPSToggleSwitchSpecifierViewCell.m in Sources */, - CD720C00120B75FC006EC605 /* IASKSlider.m in Sources */, - CD720C01120B75FC006EC605 /* IASKSwitch.m in Sources */, - CD720C02120B75FC006EC605 /* IASKTextField.m in Sources */, - CDDEEEB4120F2C240016E33F /* GroupsViewController.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - CDF0E04311DF7E8D00B2500F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Three20Core; - targetProxy = CDF0E04211DF7E8D00B2500F /* PBXContainerItemProxy */; - }; - CDF0E04511DF7E8D00B2500F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Three20UI; - targetProxy = CDF0E04411DF7E8D00B2500F /* PBXContainerItemProxy */; - }; - CDF0E04711DF7E8D00B2500F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Three20Style; - targetProxy = CDF0E04611DF7E8D00B2500F /* PBXContainerItemProxy */; - }; - CDF0E04911DF7E8D00B2500F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Three20Network; - targetProxy = CDF0E04811DF7E8D00B2500F /* PBXContainerItemProxy */; - }; - CDF0E04B11DF7E8D00B2500F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Three20UINavigator; - targetProxy = CDF0E04A11DF7E8D00B2500F /* PBXContainerItemProxy */; - }; - CDF0E04D11DF7E8D00B2500F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Three20UICommon; - targetProxy = CDF0E04C11DF7E8D00B2500F /* PBXContainerItemProxy */; - }; - CDF0E04F11DF7E8D00B2500F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Three20; - targetProxy = CDF0E04E11DF7E8D00B2500F /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 1D6058940D05DD3E006BFB54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ATutor_Prefix.pch; - HEADER_SEARCH_PATHS = three20/Build/Products/three20; - INFOPLIST_FILE = "ATutor-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - OTHER_LDFLAGS = ( - "-ObjC", - "-all_load", - ); - PRODUCT_NAME = ATutor; - SDKROOT = iphoneos4.1; - }; - name = Debug; - }; - 1D6058950D05DD3E006BFB54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ATutor_Prefix.pch; - HEADER_SEARCH_PATHS = three20/Build/Products/three20; - INFOPLIST_FILE = "ATutor-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - OTHER_LDFLAGS = ( - "-ObjC", - "-all_load", - ); - PRODUCT_NAME = ATutor; - SDKROOT = iphoneos4.1; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; - SDKROOT = iphoneos3.1.3; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; - PREBINDING = NO; - SDKROOT = iphoneos3.1.3; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ATutor" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1D6058940D05DD3E006BFB54 /* Debug */, - 1D6058950D05DD3E006BFB54 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ATutor" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/mods/atsocial_iphone_app/ATutor_Prefix.pch b/mods/atsocial_iphone_app/ATutor_Prefix.pch deleted file mode 100644 index dd43edb73..000000000 --- a/mods/atsocial_iphone_app/ATutor_Prefix.pch +++ /dev/null @@ -1,18 +0,0 @@ -// -// Prefix header for all source files of the 'ATutor' target in the 'ATutor' project -// - -#ifdef __OBJC__ - #import - #import -#endif - -// Service name -#define kATutor @"atutor" - -#define kConsumerKey @"key" -#define kConsumerSecret @"secret" - -// E.g. @"http://localhost:8888/atutor/docs" & @"http://localhost:8888/shindig/php" -#define kATutorURL [[NSUserDefaults standardUserDefaults] stringForKey:@"atutorURL"] -#define kShindigURL [[NSUserDefaults standardUserDefaults] stringForKey:@"shindigURL"] \ No newline at end of file diff --git a/mods/atsocial_iphone_app/Activities.png b/mods/atsocial_iphone_app/Activities.png deleted file mode 100644 index 059715d70e0660b6334ce73202ef6560361f7b54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4627 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 JPDHLkV1nsAujl{( diff --git a/mods/atsocial_iphone_app/Classes/ATutorAppDelegate.h b/mods/atsocial_iphone_app/Classes/ATutorAppDelegate.h deleted file mode 100644 index 534e07873..000000000 --- a/mods/atsocial_iphone_app/Classes/ATutorAppDelegate.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// ATutorAppDelegate.h -// ATutor -// -// Created by Quang Anh Do on 25/05/2010. -// Copyright Quang Anh Do 2010. All rights reserved. -// - -#import -#import "LauncherViewController.h" -#import "QAWebController.h" -#import "ATutorHelper.h" -#import "IASKAppSettingsViewController.h" - -@class OSConsumer; - -@interface ATutorAppDelegate : NSObject { - UIWindow *window; - OSConsumer *consumer; - LauncherViewController *launcher; - QAWebController *webController; - ATutorHelper *helper; - IASKAppSettingsViewController *settingsViewController; -} - -@property (nonatomic, retain) IBOutlet UIWindow *window; -@property (nonatomic, retain) OSConsumer *consumer; -@property (nonatomic, retain) LauncherViewController *launcher; -@property (nonatomic, retain) TTWebController *webController; -@property (nonatomic, retain) ATutorHelper *helper; -@property (nonatomic, retain) IASKAppSettingsViewController *settingsViewController; - -@end - diff --git a/mods/atsocial_iphone_app/Classes/ATutorAppDelegate.m b/mods/atsocial_iphone_app/Classes/ATutorAppDelegate.m deleted file mode 100644 index 9a0d180ab..000000000 --- a/mods/atsocial_iphone_app/Classes/ATutorAppDelegate.m +++ /dev/null @@ -1,119 +0,0 @@ -// -// ATutorAppDelegate.m -// ATutor -// -// Created by Quang Anh Do on 25/05/2010. -// Copyright Quang Anh Do 2010. All rights reserved. -// - -#import "ATutorAppDelegate.h" -#import "StyleSheet.h" -#import "OSConsumer.h" -#import "OSProvider.h" - -#import "ActivitiesViewController.h" -#import "ContactsViewController.h" -#import "ContactViewController.h" -#import "GroupsViewController.h" -#import "CommonFunctions.h" - -@interface ATutorAppDelegate (Private) - -- (void)wireUpNavigator; - -@end - - -@implementation ATutorAppDelegate - -@synthesize window; -@synthesize consumer; -@synthesize launcher; -@synthesize webController; -@synthesize helper; -@synthesize settingsViewController; - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Set service consumer - consumer = [[OSConsumer alloc] init]; - - // Set global stylesheet - [TTDefaultStyleSheet setGlobalStyleSheet:[[[StyleSheet alloc] init] autorelease]]; - - // Set web controller handler - launcher = [[LauncherViewController alloc] init]; - - webController = [[QAWebController alloc] init]; - webController.oAuthDelegate = launcher; - - // Set up settings VC - settingsViewController = [[IASKAppSettingsViewController alloc] initWithNibName:@"IASKAppSettingsView" - bundle:nil]; - [settingsViewController setDelegate:self]; - - // Wire things up - [self wireUpNavigator]; - - // Home screen - [[TTNavigator navigator] openURLAction:[TTURLAction actionWithURLPath:@"atutor://launcher"]]; - - // Prepare helper - helper = [[ATutorHelper alloc] init]; - [helper setDelegate:self]; - - if (!kATutorURL || !kShindigURL) { - NSLog(@"Settings required"); - [[TTNavigator navigator] openURLAction:[[TTURLAction actionWithURLPath:@"atutor://settings"] applyAnimated:YES]]; - } else { - [helper fetchContactList]; - } - - return YES; -} - -- (void)dealloc { - [window release]; - [consumer release]; - [launcher release]; - [webController release]; - [helper release]; - [settingsViewController release]; - - [super dealloc]; -} - -#pragma mark - -#pragma mark Misc - -- (void)wireUpNavigator { - TTNavigator *navigator = [TTNavigator navigator]; - navigator.window = window; - navigator.persistenceMode = TTNavigatorPersistenceModeNone; - - TTURLMap *map = navigator.URLMap; - [map from:@"*" toViewController:webController]; - [map from:@"atutor://launcher" toViewController:launcher]; - [map from:@"atutor://activities" toViewController:[ActivitiesViewController class]]; - [map from:@"atutor://contacts" toViewController:[ContactsViewController class]]; - [map from:@"atutor://contact/(initWithId:)" toViewController:[ContactViewController class]]; - [map from:@"atutor://contact/(initWithId:)/(name:)" toViewController:[ContactViewController class]]; - [map from:@"atutor://groups" toViewController:[GroupsViewController class]]; - [map from:@"atutor://settings" toViewController:settingsViewController]; -} - -#pragma mark - -#pragma mark Helper delegate - -- (void)doneFetchingContactList { - [[TTNavigator navigator] openURLAction:[TTURLAction actionWithURLPath:@"atutor://launcher"]]; -} - -#pragma mark - -#pragma mark IASK delegate - -- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController *)sender { - NSLog(@"Settings updated, refresh consumer"); - consumer.currentProvider = [OSProvider getATutorProviderWithKey:kConsumerKey withSecret:kConsumerSecret]; -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/ATutorHelper.h b/mods/atsocial_iphone_app/Classes/ATutorHelper.h deleted file mode 100644 index ae162a55d..000000000 --- a/mods/atsocial_iphone_app/Classes/ATutorHelper.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// ATutorHelper.h -// ATutor -// -// Created by Quang Anh Do on 07/06/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import -#import "OSConsumer.h" - -@protocol ATutorHelperDelegate; - -@interface ATutorHelper : NSObject { - OSConsumer *consumer; - - int numberOfContacts; - NSMutableArray *contacts; - NSMutableArray *contactMapping; - - id delegate; -} - -@property (nonatomic, retain) OSConsumer *consumer; -@property int numberOfContacts; -@property (nonatomic, retain) NSMutableArray *contacts; -@property (nonatomic, retain) NSMutableArray *contactMapping; -@property (nonatomic, assign) id delegate; - -- (void)fetchContactList; -- (void)fetchOwnProfile; - -@end - -@protocol ATutorHelperDelegate - -- (void)doneFetchingContactList; - -@end \ No newline at end of file diff --git a/mods/atsocial_iphone_app/Classes/ATutorHelper.m b/mods/atsocial_iphone_app/Classes/ATutorHelper.m deleted file mode 100644 index e1ced1853..000000000 --- a/mods/atsocial_iphone_app/Classes/ATutorHelper.m +++ /dev/null @@ -1,141 +0,0 @@ -// -// ATutorHelper.m -// ATutor -// -// Created by Quang Anh Do on 07/06/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "ATutorHelper.h" -#import "ATutorAppDelegate.h" -#import "OARequestParameter.h" -#import "CommonFunctions.h" -#import "OAServiceTicket.h" -#import "NSDictionary_JSONExtensions.h" -#import "Contact.h" - -@interface ATutorHelper (Private) - -- (void)peopleCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response; -- (void)personCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response; -- (NSDictionary *)matchDisplayNameWithId:(NSArray *)data; - -@end - - -@implementation ATutorHelper - -@synthesize consumer; -@synthesize numberOfContacts; -@synthesize contacts; -@synthesize contactMapping; -@synthesize delegate; - -- (void)dealloc { - [consumer dealloc]; - [contacts dealloc]; - [contactMapping dealloc]; - [delegate release]; - - [super dealloc]; -} - -- (id)init { - if (self = [super init]) { - self.consumer = [(ATutorAppDelegate *)[[UIApplication sharedApplication] delegate] consumer]; - self.numberOfContacts = 0; - self.contacts = [[NSMutableArray alloc] init]; - self.contactMapping = [[NSMutableArray alloc] init]; - } - - return self; -} - -- (void)fetchContactList { - NSLog(@"=-=-=-=-=-=-=-=-Fetching contact list-=-=-=-=-=-=-=-="); - - [consumer getDataForUrl:@"/people/@me/@contacts" - andParameters:[NSArray arrayWithObjects:[OARequestParameter requestParameterWithName:@"count" value:@"100"], - [OARequestParameter requestParameterWithName:@"startIndex" value:[NSString stringWithFormat:@"%d", numberOfContacts]], - [OARequestParameter requestParameterWithName:@"sortBy" value:@"displayName"], - nil] - delegate:self - didFinishSelector:@selector(peopleCallback:didFinishWithResponse:)]; -} - -- (void)fetchOwnProfile { - NSLog(@"=-=-=-=-=-=-=-=-Fetching own profile-=-=-=-=-=-=-=-="); - - [consumer getDataForUrl:@"/people/@me/@self" - andParameters:nil - delegate:self - didFinishSelector:@selector(personCallback:didFinishWithResponse:)]; -} - -- (void)peopleCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response { - if (ticket.didSucceed) { - NSError *error = nil; - NSDictionary *data = [NSDictionary dictionaryWithJSONData:[response dataUsingEncoding:NSUTF8StringEncoding] error:&error]; - NSArray *entries = [data objectForKey:@"entry"]; - - // Mapping - [contactMapping addObjectsFromArray:entries]; - numberOfContacts += [entries count]; - - for (NSDictionary *entry in entries) { - [contacts addObject:[Contact contactWithDictionary:entry]]; - } - - // Continue fetching or not? - if (numberOfContacts < [[data objectForKey:@"totalResults"] intValue]) { // Fetch friend - [self fetchContactList]; - } else { // Fetch own profile - [self fetchOwnProfile]; - } - } else { - alertMessage(@"Error", @"Unable to fetch your contact list"); - } -} - -- (void)personCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response { - if (ticket.didSucceed) { - NSError *error = nil; - NSDictionary *data = [NSDictionary dictionaryWithJSONData:[response dataUsingEncoding:NSUTF8StringEncoding] error:&error]; - NSDictionary *entry = [data objectForKey:@"entry"]; - - // Mapping - [contactMapping addObject:entry]; - numberOfContacts++; - - [contacts addObject:[Contact contactWithDictionary:entry]]; - - // Wrap things up - NSLog(@"Archiving contact list"); - - [NSKeyedArchiver archiveRootObject:[self matchDisplayNameWithId:contactMapping] - toFile:[applicationDocumentsDirectory() stringByAppendingPathComponent:@"contact_mapping.plist"]]; - - [NSKeyedArchiver archiveRootObject:contacts - toFile:[applicationDocumentsDirectory() stringByAppendingPathComponent:@"contacts.plist"]]; - - // Good to go - if (delegate && [delegate respondsToSelector:@selector(doneFetchingContactList)]) { - [delegate performSelector:@selector(doneFetchingContactList)]; - } - } else { - alertMessage(@"Error", @"Unable to fetch your profile"); - } -} - -- (NSDictionary *)matchDisplayNameWithId:(NSArray *)data { - NSMutableDictionary *retVal = [[NSMutableDictionary alloc] init]; - - for (NSDictionary *contact in data) { - [retVal setObject:[contact objectForKey:@"displayName"] - forKey:[contact objectForKey:@"id"]]; - } - - return [retVal autorelease]; -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/ActivitiesViewController.h b/mods/atsocial_iphone_app/Classes/ActivitiesViewController.h deleted file mode 100644 index 0ac6a4628..000000000 --- a/mods/atsocial_iphone_app/Classes/ActivitiesViewController.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// ActivitiesViewController.h -// ATutor -// -// Created by Quang Anh Do on 07/06/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import -#import - - -@interface ActivitiesViewController : TTTableViewController { - -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/ActivitiesViewController.m b/mods/atsocial_iphone_app/Classes/ActivitiesViewController.m deleted file mode 100644 index 1ac0a0b22..000000000 --- a/mods/atsocial_iphone_app/Classes/ActivitiesViewController.m +++ /dev/null @@ -1,82 +0,0 @@ -// -// ActivitiesViewController.m -// ATutor -// -// Created by Quang Anh Do on 07/06/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "ActivitiesViewController.h" -#import "CommonFunctions.h" -#import "OSConsumer.h" -#import "OAServiceTicket.h" -#import "NSDictionary_JSONExtensions.h" -#import "ATutorAppDelegate.h" - -@interface LauncherViewController (Private) - -- (void)activitiesCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response; - -@end - -@implementation ActivitiesViewController - -- (id)init { - if (self = [super init]) { - self.title = TTLocalizedString(@"Activities", @""); - self.autoresizesForKeyboard = YES; - self.variableHeightRows = YES; - - OSConsumer *consumer = [(ATutorAppDelegate *)[[UIApplication sharedApplication] delegate] consumer]; - [consumer getDataForUrl:@"/activities/@me/@contacts" - andParameters:nil - delegate:self - didFinishSelector:@selector(activitiesCallback:didFinishWithResponse:)]; - } - - return self; -} - -- (void)loadView { - [super loadView]; - - self.tableView.allowsSelection = NO; -} - -- (void)activitiesCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response { - if (ticket.didSucceed) { - // Load contact list - NSDictionary *contactList = [NSKeyedUnarchiver unarchiveObjectWithFile:[applicationDocumentsDirectory() stringByAppendingPathComponent:@"contact_mapping.plist"]]; - NSLog(@"Contact list: %@", contactList); - - // Build data source - NSError *error = nil; - NSDictionary *data = [NSDictionary dictionaryWithJSONData:[response dataUsingEncoding:NSUTF8StringEncoding] error:&error]; - - int numberOfItems = [[data objectForKey:@"totalResults"] intValue] % [[data objectForKey:@"itemsPerPage"] intValue]; - - TTListDataSource *dataSource = [[[TTListDataSource alloc] init] autorelease]; - for (int i = 0; i < numberOfItems; i++) { - NSDictionary *entry = [[data objectForKey:@"entry"] objectAtIndex:i]; - - NSString *contact = [NSString stringWithFormat:@"%@", - linkToContact([[entry objectForKey:@"userId"] integerValue], [contactList objectForKey:[entry objectForKey:@"userId"]]), // link - [contactList objectForKey:[entry objectForKey:@"userId"]]]; // name - NSString *xhtml = [NSString stringWithFormat:@"%@ - %@ %@", - niceTimeString([entry objectForKey:@"postedTime"]), // time - contact, // contact - rewriteURLStrings([entry objectForKey:@"title"]) // title - ]; - - TTStyledText *text = [TTStyledText textFromXHTML:xhtml]; - - [dataSource.items addObject:[TTTableStyledTextItem itemWithText:text URL:nil]]; - } - - self.dataSource = dataSource; - } else { - alertMessage(@"Error", @"Unable to process your request"); - } -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/CommonFunctions.h b/mods/atsocial_iphone_app/Classes/CommonFunctions.h deleted file mode 100644 index 1398f0c6e..000000000 --- a/mods/atsocial_iphone_app/Classes/CommonFunctions.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// CommonFunctions.h -// ATutor -// -// Created by Quang Anh Do on 30/05/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import -#import - - -@interface CommonFunctions : NSObject { - -} - -void alertMessage(NSString *title, NSString *message); -BOOL dataSourceAvailable(); -NSString *applicationDocumentsDirectory(); - -BOOL isLoggedIn(); - -NSString *shortLinkToContact(int id); -NSString *linkToContact(int id, NSString *name); -NSString *rewriteURLStrings(NSString *content); -NSString *niceTimeString(NSString *timeString); - -@end diff --git a/mods/atsocial_iphone_app/Classes/CommonFunctions.m b/mods/atsocial_iphone_app/Classes/CommonFunctions.m deleted file mode 100644 index 2ab761bdb..000000000 --- a/mods/atsocial_iphone_app/Classes/CommonFunctions.m +++ /dev/null @@ -1,76 +0,0 @@ -// -// CommonFunctions.m -// ATutor -// -// Created by Quang Anh Do on 30/05/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "CommonFunctions.h" - -#import -#import "SFHFKeychainUtils.h" - -@implementation CommonFunctions - -void alertMessage(NSString *title, NSString *message) { - UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:TTLocalizedString(title, @"") - message:TTLocalizedString(message, @"") - delegate:nil cancelButtonTitle:TTLocalizedString(@"OK", @"") otherButtonTitles:nil]; - [alertView show]; - [alertView release]; -} - -BOOL dataSourceAvailable() { - Boolean success; - const char *host_name = "www.google.com"; - - SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, host_name); - SCNetworkReachabilityFlags flags; - success = SCNetworkReachabilityGetFlags(reachability, &flags); - BOOL _isDataSourceAvailable = success && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired); - CFRelease(reachability); - - return _isDataSourceAvailable; -} - -NSString *applicationDocumentsDirectory() { - return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; -} - -BOOL isLoggedIn() { - return ![[SFHFKeychainUtils getPasswordForUsername:@"accessToken" andServiceName:kATutor error:nil] isEqualToString:@""] - && ![[SFHFKeychainUtils getPasswordForUsername:@"requestToken" andServiceName:kATutor error:nil] isEqualToString:@""]; -} - -NSString *shortLinkToContact(int id) { - return [NSString stringWithFormat:@"atutor://contact/%d", id]; -} - -NSString *linkToContact(int id, NSString *name) { - return [NSString stringWithFormat:@"atutor://contact/%d/%@", id, [name stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; -} - -NSString *rewriteURLStrings(NSString *content) { - NSMutableString *retVal = [NSMutableString stringWithString:content]; - - // Links to contacts - [retVal replaceOccurrencesOfString:[NSString stringWithFormat:@"%@/mods/_standard/social/sprofile.php?id=", kATutorURL] - withString:@"atutor://contact/" - options:NSCaseInsensitiveSearch - range:NSMakeRange(0, [retVal length])]; - - return retVal; -} - -NSString *niceTimeString(NSString *timeString) { - NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease]; - [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; - - NSDate *date = [dateFormatter dateFromString:timeString]; - [dateFormatter setDateStyle:NSDateFormatterShortStyle]; - - return [dateFormatter stringFromDate:date]; -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/Contact.h b/mods/atsocial_iphone_app/Classes/Contact.h deleted file mode 100644 index 5a6557644..000000000 --- a/mods/atsocial_iphone_app/Classes/Contact.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Contact.h -// ATutor -// -// Created by Quang Anh Do on 03/07/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import - - -@interface Contact : NSObject { - int identifier; - NSString *displayName; -} - -@property int identifier; -@property (nonatomic, retain) NSString *displayName; - -+ (Contact *)contactWithDictionary:(NSDictionary *)dictionary; - -@end diff --git a/mods/atsocial_iphone_app/Classes/Contact.m b/mods/atsocial_iphone_app/Classes/Contact.m deleted file mode 100644 index 741ad1a77..000000000 --- a/mods/atsocial_iphone_app/Classes/Contact.m +++ /dev/null @@ -1,52 +0,0 @@ -// -// Contact.m -// ATutor -// -// Created by Quang Anh Do on 03/07/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "Contact.h" - - -@implementation Contact - -@synthesize identifier; -@synthesize displayName; - - -/* dealloc */ -- (void) dealloc { - [displayName release]; - - [super dealloc]; -} - -+ (Contact *)contactWithDictionary:(NSDictionary *)dictionary { - Contact *contact = [[self alloc] init]; - contact.identifier = [[dictionary objectForKey:@"id"] intValue]; - contact.displayName = [dictionary objectForKey:@"displayName"]; - - return [contact autorelease]; -} - -#pragma mark - -#pragma mark Keyed Archiving - -/* Keyed Archiving */ -// -- (void) encodeWithCoder: (NSCoder *)encoder { - [encoder encodeInt: [self identifier] forKey: @"identifier"]; - [encoder encodeObject: [self displayName] forKey: @"displayName"]; -} - -- (id) initWithCoder: (NSCoder *)decoder { - self = [super init]; - if (self) { - [self setIdentifier: [decoder decodeIntForKey: @"identifier"]]; - [self setDisplayName: [decoder decodeObjectForKey: @"displayName"]]; - } - return self; -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/ContactItemCell.h b/mods/atsocial_iphone_app/Classes/ContactItemCell.h deleted file mode 100644 index 257ecfedf..000000000 --- a/mods/atsocial_iphone_app/Classes/ContactItemCell.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// ContactItemCell.h -// ATutor -// -// Created by Quang Anh Do on 10/07/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import -#import - - -@interface ContactItemCell : TTTableTextItemCell { - -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/ContactItemCell.m b/mods/atsocial_iphone_app/Classes/ContactItemCell.m deleted file mode 100644 index a6f634832..000000000 --- a/mods/atsocial_iphone_app/Classes/ContactItemCell.m +++ /dev/null @@ -1,20 +0,0 @@ -// -// ContactItemCell.m -// ATutor -// -// Created by Quang Anh Do on 10/07/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "ContactItemCell.h" - - -@implementation ContactItemCell - -- (void)setObject:(id)object { - [super setObject:object]; - - self.accessoryType = UITableViewCellAccessoryNone; -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/ContactViewController.h b/mods/atsocial_iphone_app/Classes/ContactViewController.h deleted file mode 100644 index c856df391..000000000 --- a/mods/atsocial_iphone_app/Classes/ContactViewController.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// ContactViewController.h -// ATutor -// -// Created by Quang Anh Do on 06/07/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import -#import -#import - - -@interface ContactViewController : UIViewController { - ABAddressBookRef addressBook; -} - -- (id)initWithId:(int)identifier; -- (id)initWithId:(int)identifier name:(NSString *)name; - -@end diff --git a/mods/atsocial_iphone_app/Classes/ContactViewController.m b/mods/atsocial_iphone_app/Classes/ContactViewController.m deleted file mode 100644 index 6d65fc0b2..000000000 --- a/mods/atsocial_iphone_app/Classes/ContactViewController.m +++ /dev/null @@ -1,73 +0,0 @@ -// -// ContactViewController.m -// ATutor -// -// Created by Quang Anh Do on 06/07/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "ContactViewController.h" -#import "CommonFunctions.h" - -@implementation ContactViewController - -- (void)dealloc { - CFRelease(addressBook); - - [super dealloc]; -} - -- (id)initWithId:(int)identifier { - NSDictionary *contactList = [NSKeyedUnarchiver unarchiveObjectWithFile:[applicationDocumentsDirectory() stringByAppendingPathComponent:@"contact_mapping.plist"]]; - - return [self initWithId:identifier - name:[contactList objectForKey:[NSString stringWithFormat:@"%d", identifier]]]; -} - -- (id)initWithId:(int)identifier name:(NSString *)name { - addressBook = ABAddressBookCreate(); - - ABRecordRef person = NULL; - CFArrayRef matches = ABAddressBookCopyPeopleWithName(addressBook, (CFStringRef)name); - - if (matches && CFArrayGetCount(matches)) { - person = (id)CFArrayGetValueAtIndex(matches, 0); - - ABMultiValueRef urls = ABRecordCopyValue(person, kABPersonURLProperty); - ABMutableMultiValueRef mutableURLs = NULL; - if (urls) { - mutableURLs = ABMultiValueCreateMutableCopy(urls); - CFRelease(urls); - } else { - mutableURLs = ABMultiValueCreateMutable(kABStringPropertyType); - } - ABMultiValueAddValueAndLabel(mutableURLs, shortLinkToContact(identifier), CFSTR("ATutor"), NULL); - CFRelease(mutableURLs); - } else { - person = ABPersonCreate(); - ABRecordSetValue(person, kABPersonFirstNameProperty, name, NULL); - - ABMutableMultiValueRef urls = ABMultiValueCreateMutable(kABMultiStringPropertyType); - ABMultiValueAddValueAndLabel(urls, shortLinkToContact(identifier), CFSTR("ATutor"), NULL); - ABRecordSetValue(person, kABPersonURLProperty, urls, NULL); - CFRelease(urls); - [(id)person autorelease]; - } - - if (ABRecordGetRecordID(person) != kABRecordInvalidID) { - self = [[ABPersonViewController alloc] init]; - [(ABPersonViewController *)self setAllowsEditing:YES]; - [(ABPersonViewController *)self setDisplayedPerson:person]; - } else { - self = [[ABUnknownPersonViewController alloc] init]; - [(ABUnknownPersonViewController *)self setAllowsActions:YES]; - [(ABUnknownPersonViewController *)self setAllowsAddingToAddressBook:YES]; - [(ABUnknownPersonViewController *)self setDisplayedPerson:person]; - } - - if (matches) CFRelease(matches); - - return self; -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/ContactsDataSource.h b/mods/atsocial_iphone_app/Classes/ContactsDataSource.h deleted file mode 100644 index 7c3989f56..000000000 --- a/mods/atsocial_iphone_app/Classes/ContactsDataSource.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// ContactsDataSource.h -// ATutor -// -// Created by Quang Anh Do on 10/07/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import -#import - - -@interface ContactsDataSource : TTSectionedDataSource { - -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/ContactsDataSource.m b/mods/atsocial_iphone_app/Classes/ContactsDataSource.m deleted file mode 100644 index ad7f5664f..000000000 --- a/mods/atsocial_iphone_app/Classes/ContactsDataSource.m +++ /dev/null @@ -1,65 +0,0 @@ -// -// ContactsDataSource.m -// ATutor -// -// Created by Quang Anh Do on 10/07/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "ContactsDataSource.h" -#import "CommonFunctions.h" -#import "Contact.h" -#import "ContactItemCell.h" - - -@implementation ContactsDataSource - -- (id)init { - if (self = [super init]) { - NSDictionary *contactList = [NSKeyedUnarchiver unarchiveObjectWithFile:[applicationDocumentsDirectory() stringByAppendingPathComponent:@"contacts.plist"]]; - - NSMutableDictionary *nameIndexes = [NSMutableDictionary dictionary]; - - for (Contact *contact in contactList) { - // Setup contact item - NSString *urlString = linkToContact(contact.identifier, contact.displayName); - TTTableTextItem *contactItem = [TTTableTextItem itemWithText:contact.displayName URL:urlString]; - - // Setup name indexes for section headers - NSString *firstLetter = [contact.displayName substringToIndex:1]; - NSMutableArray *existingArray; - if (existingArray = [nameIndexes valueForKey:firstLetter]) { - [existingArray addObject:contactItem]; - } else { - NSMutableArray *tempArray = [NSMutableArray array]; - [nameIndexes setObject:tempArray forKey:firstLetter]; - [tempArray addObject:contactItem]; - } - - [self.items addObject:contactItem]; - } - - // Final touches - self.sections = [[[nameIndexes allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] mutableCopy]; - self.items = [NSMutableArray array]; - - for (NSString *index in self.sections) { - [self.items addObject:[nameIndexes objectForKey:index]]; - } - - TTTableSummaryItem *countItem = [TTTableSummaryItem itemWithText:[NSString stringWithFormat:@"%d Contacts", [contactList count]] URL:NULL]; - [[self.items lastObject] addObject:countItem]; - } - - return self; -} - -- (NSArray*)sectionIndexTitlesForTableView:(UITableView*)tableView { - return [TTSectionedDataSource lettersForSectionsWithSearch:NO summary:YES]; -} - -- (Class)tableView:(UITableView*)tableView cellClassForObject:(id)object { - return [ContactItemCell class]; -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/ContactsViewController.h b/mods/atsocial_iphone_app/Classes/ContactsViewController.h deleted file mode 100644 index f17f1bd8c..000000000 --- a/mods/atsocial_iphone_app/Classes/ContactsViewController.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// ContactsViewController.h -// ATutor -// -// Created by Quang Anh Do on 03/07/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import -#import - -@interface ContactsViewController : TTTableViewController { - -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/ContactsViewController.m b/mods/atsocial_iphone_app/Classes/ContactsViewController.m deleted file mode 100644 index b2ad54695..000000000 --- a/mods/atsocial_iphone_app/Classes/ContactsViewController.m +++ /dev/null @@ -1,35 +0,0 @@ -// -// ContactsViewController.m -// ATutor -// -// Created by Quang Anh Do on 03/07/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "ContactsViewController.h" -#import "Contact.h" -#import "CommonFunctions.h" -#import "ContactsDataSource.h" - -@implementation ContactsViewController - -- (void)dealloc { - [super dealloc]; -} - -- (id)init { - if (self = [super init]) { - self.title = TTLocalizedString(@"Contacts", @""); - self.autoresizesForKeyboard = YES; - } - - return self; -} - -- (void)loadView { - [super loadView]; - - self.dataSource = [[ContactsDataSource alloc] init]; -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/GroupsViewController.h b/mods/atsocial_iphone_app/Classes/GroupsViewController.h deleted file mode 100644 index e047ea4ce..000000000 --- a/mods/atsocial_iphone_app/Classes/GroupsViewController.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// GroupsViewController.h -// ATutor -// -// Created by Quang Anh Do on 08/08/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import -#import - - -@interface GroupsViewController : TTTableViewController { - -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/GroupsViewController.m b/mods/atsocial_iphone_app/Classes/GroupsViewController.m deleted file mode 100644 index acfcbd32a..000000000 --- a/mods/atsocial_iphone_app/Classes/GroupsViewController.m +++ /dev/null @@ -1,54 +0,0 @@ -// -// GroupsViewController.m -// ATutor -// -// Created by Quang Anh Do on 08/08/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "GroupsViewController.h" -#import "CommonFunctions.h" -#import "OSConsumer.h" -#import "OAServiceTicket.h" -#import "NSDictionary_JSONExtensions.h" -#import "ATutorAppDelegate.h" - -@interface GroupsViewController (Private) - -- (void)groupsCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response; - -@end - -@implementation GroupsViewController - -- (id)init { - if (self = [super init]) { - self.title = TTLocalizedString(@"Groups", @""); - self.autoresizesForKeyboard = YES; - self.variableHeightRows = YES; - - OSConsumer *consumer = [(ATutorAppDelegate *)[[UIApplication sharedApplication] delegate] consumer]; - [consumer getDataForUrl:@"/groups/@me" - andParameters:nil - delegate:self - didFinishSelector:@selector(groupsCallback:didFinishWithResponse:)]; - } - - return self; -} - -- (void)loadView { - [super loadView]; - - self.tableView.allowsSelection = NO; -} - -- (void)groupsCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response { - if (ticket.didSucceed) { - - } else { - alertMessage(@"Error", @"The service groups is not implemented"); - } -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/LauncherViewController.h b/mods/atsocial_iphone_app/Classes/LauncherViewController.h deleted file mode 100644 index 9fcebb013..000000000 --- a/mods/atsocial_iphone_app/Classes/LauncherViewController.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// LauncherViewController.h -// ATutor -// -// Created by Quang Anh Do on 25/05/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import -#import -#import "QAWebController.h" -#import "OSConsumer.h" - -@interface LauncherViewController : TTViewController { - TTLauncherView *launcherView; - UIBarButtonItem *logoutButton; - OSConsumer *consumer; -} - -@property (nonatomic, retain) TTLauncherView *launcherView; -@property (nonatomic, retain) UIBarButtonItem *logoutButton; -@property (nonatomic, retain) OSConsumer *consumer; - -- (void)restorePages; - -@end diff --git a/mods/atsocial_iphone_app/Classes/LauncherViewController.m b/mods/atsocial_iphone_app/Classes/LauncherViewController.m deleted file mode 100644 index 46ea61d2e..000000000 --- a/mods/atsocial_iphone_app/Classes/LauncherViewController.m +++ /dev/null @@ -1,155 +0,0 @@ -// -// LauncherViewController.m -// ATutor -// -// Created by Quang Anh Do on 25/05/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "LauncherViewController.h" -#import "ATutorAppDelegate.h" -#import "CommonFunctions.h" - -@interface LauncherViewController (Private) - -- (BOOL)isLoggedIn; -- (void)logout; - -@end - -@implementation LauncherViewController - -@synthesize launcherView; -@synthesize logoutButton; -@synthesize consumer; - -- (id)init { - if (self = [super init]) { - self.consumer = [(ATutorAppDelegate *)[[UIApplication sharedApplication] delegate] consumer]; - } - - return self; -} - -- (void)dealloc { - [launcherView release]; - [logoutButton release]; - [consumer release]; - - [super dealloc]; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - logoutButton = [[UIBarButtonItem alloc] initWithTitle:TTLocalizedString(@"Logout", @"") - style:UIBarButtonItemStyleBordered - target:self action:@selector(logout)]; - - self.title = TTLocalizedString(@"ATutor Social", @""); -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - self.navigationItem.rightBarButtonItem = [self isLoggedIn] ? logoutButton : nil; -} - -- (void)didReceiveMemoryWarning { - // Releases the view if it doesn't have a superview. - [super didReceiveMemoryWarning]; - - // Release any cached data, images, etc that aren't in use. -} - -- (void)viewDidUnload { - [super viewDidUnload]; - // Release any retained subviews of the main view. - // e.g. self.myOutlet = nil; -} - -- (void)loadView { - [super loadView]; - - launcherView = [[TTLauncherView alloc] initWithFrame:self.view.bounds]; - - launcherView.delegate = self; - launcherView.backgroundColor = [UIColor colorWithRed:0.875 green:0.871 blue:0.925 alpha:1.000]; - launcherView.columnCount = 2; - - // Attempt to restore data if exists - [self restorePages]; - - [self.view addSubview:launcherView]; -} - -#pragma mark - -#pragma mark TTLauncherViewDelegate - -- (void)launcherViewDidBeginEditing:(TTLauncherView*)launcher { - [self.navigationItem setRightBarButtonItem:[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone - target:launcherView - action:@selector(endEditing)] autorelease] - animated:YES]; -} - -- (void)launcherViewDidEndEditing:(TTLauncherView*)launcher { - [self.navigationItem setRightBarButtonItem:logoutButton animated:YES]; - - // Persist data the ugly way - NSData *pages = [NSKeyedArchiver archivedDataWithRootObject:launcherView.pages]; - [[NSUserDefaults standardUserDefaults] setObject:pages forKey:@"launcher.pages"]; -} - -- (void)launcherView:(TTLauncherView*)launcher didSelectItem:(TTLauncherItem*)item { - if ([item.title isEqualToString:TTLocalizedString(@"Activities", @"")]) { - [[TTNavigator navigator] openURLAction:[[TTURLAction actionWithURLPath:@"atutor://activities"] applyAnimated:YES]]; - } else if ([item.title isEqualToString:TTLocalizedString(@"Contacts", @"")]) { - [[TTNavigator navigator] openURLAction:[[TTURLAction actionWithURLPath:@"atutor://contacts"] applyAnimated:YES]]; - } else if ([item.title isEqualToString:TTLocalizedString(@"Gadgets", @"")]) { - [[TTNavigator navigator] openURLs: - [NSString stringWithFormat:@"%@/mods/_standard/social/applications.php", kATutorURL], nil]; - } else if ([item.title isEqualToString:TTLocalizedString(@"Groups", @"")]) { - [[TTNavigator navigator] openURLAction:[[TTURLAction actionWithURLPath:@"atutor://groups"] applyAnimated:YES]]; - } -} - -#pragma mark - -#pragma mark QAWebControllerDelegate - -- (void)didFinishAuthorizationInWebViewController:(QAWebController *)webViewController { - [consumer finishAuthProcess]; - - [[(ATutorAppDelegate *)[[UIApplication sharedApplication] delegate] helper] fetchContactList]; -} - -#pragma mark - -#pragma mark Misc - -- (void)restorePages { - NSData *pages = [[NSUserDefaults standardUserDefaults] objectForKey:@"launcher.pages"]; - if (pages != nil) { - launcherView.pages = [NSKeyedUnarchiver unarchiveObjectWithData:pages]; - } else { - for (NSString *module in [NSArray arrayWithObjects:@"Activities", @"Contacts", @"Gadgets", @"Groups", nil]) { - [launcherView addItem:[[[TTLauncherItem alloc] initWithTitle:TTLocalizedString(module, @"") - image:[NSString stringWithFormat:@"bundle://%@.png", module] - URL:[NSString stringWithFormat:@"atutor://modules/%@", module] - canDelete:NO] autorelease] - animated:NO]; - } - } -} - -- (BOOL)isLoggedIn { - return consumer.accessToken != nil; -} - -- (void)logout { - [consumer clearAuthentication]; - - [self.navigationItem setRightBarButtonItem:nil animated:YES]; - - alertMessage(@"", @"You have been logged out"); -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/OSConsumer.h b/mods/atsocial_iphone_app/Classes/OSConsumer.h deleted file mode 100644 index 4515138f4..000000000 --- a/mods/atsocial_iphone_app/Classes/OSConsumer.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// OSConsumer.h -// ATutor -// -// Created by Quang Anh Do on 29/05/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import - -@class OSProvider; -@class OAConsumer; -@class OAToken; - -@interface OSConsumer : NSObject { - OAConsumer *consumer; - OAToken *accessToken; - OSProvider *currentProvider; -} - -@property (nonatomic, retain) OAToken *accessToken; -@property (nonatomic, retain) OAConsumer *consumer; -@property (nonatomic, retain) OSProvider *currentProvider; - -- (id)initWithProvider:(OSProvider *)provider; -- (void)getDataForUrl:(NSString *)relativeUrl - andParameters:(NSArray*)params - delegate:(id)delegate - didFinishSelector:(SEL)didFinishSelector; -- (void)startAuthProcess; -- (void)finishAuthProcess; -- (void)clearAuthentication; - -@end diff --git a/mods/atsocial_iphone_app/Classes/OSConsumer.m b/mods/atsocial_iphone_app/Classes/OSConsumer.m deleted file mode 100644 index e3cd4db16..000000000 --- a/mods/atsocial_iphone_app/Classes/OSConsumer.m +++ /dev/null @@ -1,163 +0,0 @@ -// -// OSConsumer.m -// ATutor -// -// Created by Quang Anh Do on 29/05/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "OSConsumer.h" -#import "OSProvider.h" -#import "SFHFKeychainUtils.h" -#import "OAMutableURLRequest.h" -#import "OAServiceTicket.h" -#import "OAConsumer.h" -#import "OADataFetcher.h" -#import "OAToken.h" -#import "OAToken_KeychainExtensions.h" -#import - -@interface OSConsumer (Private) -- (void)setupConsumer; -- (void)getRequestToken; -- (void)requestTokenCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response; -- (void)getAccessToken; -- (void)accessTokenCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response; -@end - -@implementation OSConsumer - -@synthesize consumer, accessToken, currentProvider; - -- (void)dealloc { - [consumer release]; - [accessToken release]; - [currentProvider release]; - - [super dealloc]; -} - -- (id)init { - return [self initWithProvider:[OSProvider getATutorProviderWithKey:kConsumerKey withSecret:kConsumerSecret]]; -} - -- (id)initWithProvider:(OSProvider *)provider { - if (self = [super init]) { - self.accessToken = [[[OAToken alloc] initWithKeychainUsingAppName:kATutor tokenType:@"accessToken"] autorelease]; - self.currentProvider = provider; - - [self setupConsumer]; - } - - return self; -} - -- (void)startAuthProcess { - [self getRequestToken]; -} - -- (void)finishAuthProcess { - [self getAccessToken]; -} - -// Should be called within a handleOpenUrl method. -// This method assumes the request token was authorized and will retrieve the access token -- (void)clearAuthentication { - [SFHFKeychainUtils storeUsername:@"accessToken" andPassword:@"" forServiceName:kATutor updateExisting:TRUE error:nil]; - [SFHFKeychainUtils storeUsername:@"requestToken" andPassword:@"" forServiceName:kATutor updateExisting:TRUE error:nil]; - - self.accessToken = nil; -} - -- (void)getDataForUrl:(NSString *)relativeUrl andParameters:(NSArray*)params - delegate:(id)delegate didFinishSelector:(SEL)didFinishSelector { - if (!accessToken) { - [self startAuthProcess]; - return; - } - - NSLog(@"Getting data with access token: %@ : %@", [accessToken key], [accessToken secret]); - - NSString *url = [[currentProvider endpointUrl] stringByAppendingString:relativeUrl]; - OAMutableURLRequest *request = [[[OAMutableURLRequest alloc] - initWithURL:[NSURL URLWithString:url] - parameters:params - consumer:consumer token:accessToken] autorelease]; - [request setHTTPMethod:@"GET"]; - - [OADataFetcher fetchDataWithRequest:request delegate:delegate - didFinishSelector:didFinishSelector]; -} - -#pragma mark - -#pragma mark Private - -- (void)setupConsumer { - self.consumer = [[[OAConsumer alloc] initWithKey:[currentProvider consumerKey] - secret:[currentProvider consumerSecret]] autorelease]; -} - -- (void)getRequestToken { - OAMutableURLRequest *request = [[[OAMutableURLRequest alloc] - initWithURL:[NSURL URLWithString:[currentProvider requestUrl]] - parameters:[currentProvider extraRequestUrlParams] - consumer:consumer - token:nil] autorelease]; - [request setHTTPMethod:@"GET"]; - - [OADataFetcher fetchDataWithRequest:request - delegate:self - didFinishSelector:@selector(requestTokenCallback:didFinishWithResponse:)]; -} - -- (void)requestTokenCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response { - if (ticket.didSucceed) { - NSLog(@"%@", response); - OAToken *requestToken = [[OAToken alloc] initWithHTTPResponseBody:response]; - [requestToken storeInDefaultKeychainWithAppName:kATutor tokenType:@"requestToken"]; - NSLog(@"Stored this secret and key: %@ : %@", [requestToken key], [requestToken secret]); - - NSString *urlString = [NSString stringWithFormat:@"%@?oauth_callback=internal://finish-auth&oauth_token=%@", - [currentProvider authorizeUrl], [requestToken key]]; - - NSLog(@"Request string: %@", urlString); - - [[TTNavigator navigator] openURLAction:[[TTURLAction actionWithURLPath:urlString] applyAnimated:YES]]; - } else { - NSString *error = [NSString stringWithFormat:@"Got error while requesting request token. %@", response]; - NSLog(@"Error retriving request token: %@", error); - - @throw [NSException exceptionWithName:@"RequestTokenException" reason:error userInfo:nil]; - } -} - -- (void)getAccessToken { - OAToken *requestToken = [[OAToken alloc] initWithKeychainUsingAppName:kATutor - tokenType:@"requestToken"]; - NSLog(@"Getting access token for request token: %@ : %@", [requestToken key], [requestToken secret]); - - OAMutableURLRequest *request = [[[OAMutableURLRequest alloc] - initWithURL:[NSURL URLWithString:[currentProvider accessUrl]] - consumer:consumer token:requestToken] autorelease]; - [request setHTTPMethod:@"GET"]; - - [OADataFetcher fetchDataWithRequest:request delegate:self - didFinishSelector:@selector(accessTokenCallback:didFinishWithResponse:)]; -} - -- (void)accessTokenCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response { - if (ticket.didSucceed) { - self.accessToken = [[[OAToken alloc] initWithHTTPResponseBody:response] autorelease]; - [accessToken storeInDefaultKeychainWithAppName:kATutor tokenType:@"accessToken"]; - - NSLog(@"Got an access token: %@ : %@", [accessToken key], [accessToken secret]); - - } else { - NSString *error = [NSString stringWithFormat:@"Got error while requesting access token. %@", response]; - NSLog(@"Error retriving access token: %@", error); - - @throw [NSException exceptionWithName:@"AccessTokenException" reason:error userInfo:nil]; - } -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/OSProvider.h b/mods/atsocial_iphone_app/Classes/OSProvider.h deleted file mode 100644 index dfcfb8e33..000000000 --- a/mods/atsocial_iphone_app/Classes/OSProvider.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// OSProvider.h -// ATutor -// -// Created by Quang Anh Do on 29/05/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import - - -@interface OSProvider : NSObject { - NSString *requestUrl; - NSString *authorizeUrl; - NSString *accessUrl; - NSString *endpointUrl; - - NSArray *extraRequestUrlParams; - BOOL isOpenSocial; - - NSString *consumerKey; - NSString *consumerSecret; - - NSString *name; -} - -@property(retain) NSString *requestUrl; -@property(retain) NSString *authorizeUrl; -@property(retain) NSString *accessUrl; -@property(retain) NSString *endpointUrl; - -@property(retain) NSArray *extraRequestUrlParams; -@property BOOL isOpenSocial; - -@property(retain) NSString *consumerKey; -@property(retain) NSString *consumerSecret; - -@property(retain) NSString *name; - -+ (OSProvider *)getATutorProviderWithKey:(NSString *)key withSecret:(NSString *)secret; - -@end diff --git a/mods/atsocial_iphone_app/Classes/OSProvider.m b/mods/atsocial_iphone_app/Classes/OSProvider.m deleted file mode 100644 index 1b9509693..000000000 --- a/mods/atsocial_iphone_app/Classes/OSProvider.m +++ /dev/null @@ -1,46 +0,0 @@ -// -// OSProvider.m -// ATutor -// -// Created by Quang Anh Do on 29/05/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "OSProvider.h" -#import "OARequestParameter.h" - - -@implementation OSProvider - -@synthesize requestUrl, authorizeUrl, accessUrl, endpointUrl, extraRequestUrlParams, isOpenSocial, consumerKey, consumerSecret, name; - -- (void)dealloc { - [requestUrl release]; - [authorizeUrl release]; - [accessUrl release]; - [endpointUrl release]; - [consumerKey release]; - [consumerSecret release]; - [name release]; - - [super dealloc]; -} - -+ (OSProvider *)getATutorProviderWithKey:(NSString *)key withSecret:(NSString *)secret { - OSProvider *atutor = [[[OSProvider alloc] init] autorelease]; - atutor.requestUrl = [NSString stringWithFormat:@"%@/mods/_standard/social/lib/oauth/request_token.php", kATutorURL]; - atutor.authorizeUrl = [NSString stringWithFormat:@"%@/mods/_standard/social/lib/oauth/authorize.php", kATutorURL]; - atutor.accessUrl = [NSString stringWithFormat:@"%@/mods/_standard/social/lib/oauth/access_token.php", kATutorURL]; - atutor.endpointUrl = [NSString stringWithFormat:@"%@/social/rest", kShindigURL]; - - atutor.isOpenSocial = YES; - - atutor.consumerKey = key; - atutor.consumerSecret = secret; - - atutor.name = @"ATutor"; - - return atutor; -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/QAWebController.h b/mods/atsocial_iphone_app/Classes/QAWebController.h deleted file mode 100644 index 9edadb301..000000000 --- a/mods/atsocial_iphone_app/Classes/QAWebController.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// QAWebController.h -// ATutor -// -// Created by Quang Anh Do on 30/05/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import -#import - -@protocol QAWebControllerDelegate; - -@interface QAWebController : TTWebController { - id oAuthDelegate; -} - -@property (nonatomic, assign) id oAuthDelegate; - -@end - -@protocol QAWebControllerDelegate - -- (void)didFinishAuthorizationInWebViewController:(QAWebController *)webViewController; - -@end - diff --git a/mods/atsocial_iphone_app/Classes/QAWebController.m b/mods/atsocial_iphone_app/Classes/QAWebController.m deleted file mode 100644 index 75db3beae..000000000 --- a/mods/atsocial_iphone_app/Classes/QAWebController.m +++ /dev/null @@ -1,38 +0,0 @@ - // -// QAWebController.m -// ATutor -// -// Created by Quang Anh Do on 30/05/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "QAWebController.h" - - -@implementation QAWebController - -@synthesize oAuthDelegate; - -- (void)dealloc { - [oAuthDelegate release]; - - [super dealloc]; -} - -- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { - // Ignore normal URLs - if (![[[request URL] scheme] isEqualToString:@"internal"]) { - return [super webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; - } - - // OAuth - if ([[[request URL] host] isEqualToString:@"finish-auth"]) { - if (oAuthDelegate && [oAuthDelegate respondsToSelector:@selector(didFinishAuthorizationInWebViewController:)]) { - [oAuthDelegate performSelector:@selector(didFinishAuthorizationInWebViewController:) withObject:self]; - } - } - - return YES; -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/StyleSheet.h b/mods/atsocial_iphone_app/Classes/StyleSheet.h deleted file mode 100644 index 83a4bb9c3..000000000 --- a/mods/atsocial_iphone_app/Classes/StyleSheet.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// StyleSheet.h -// ATutor -// -// Created by Quang Anh Do on 25/05/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import -#import - -@interface StyleSheet : TTDefaultStyleSheet { - -} - -@end diff --git a/mods/atsocial_iphone_app/Classes/StyleSheet.m b/mods/atsocial_iphone_app/Classes/StyleSheet.m deleted file mode 100644 index 0213c5f77..000000000 --- a/mods/atsocial_iphone_app/Classes/StyleSheet.m +++ /dev/null @@ -1,30 +0,0 @@ -// -// StyleSheet.m -// ATutor -// -// Created by Quang Anh Do on 25/05/2010. -// Copyright 2010 Quang Anh Do. All rights reserved. -// - -#import "StyleSheet.h" - - -@implementation StyleSheet - -- (TTStyle*)launcherButton:(UIControlState)state { - return - [TTPartStyle styleWithName:@"image" style:TTSTYLESTATE(launcherButtonImage:, state) next: - [TTTextStyle styleWithFont:[UIFont boldSystemFontOfSize:11] color:[UIColor blackColor] - minimumFontSize:11 shadowColor:nil - shadowOffset:CGSizeZero next:nil]]; -} - -- (TTStyle*)launcherPageDot:(UIControlState)state { - if (state != UIControlStateSelected) { - return [self pageDotWithColor:[UIColor whiteColor]]; - } else { - return [self pageDotWithColor:[UIColor colorWithRed:0.227 green:0.455 blue:0.647 alpha:1.000]]; - } -} - -@end diff --git a/mods/atsocial_iphone_app/Contacts.png b/mods/atsocial_iphone_app/Contacts.png deleted file mode 100644 index 537099758107aa8ada1524821dadf39b8e167cea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3560 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 diff --git a/mods/atsocial_iphone_app/Groups.png b/mods/atsocial_iphone_app/Groups.png deleted file mode 100644 index d3cc4804a608fc67b2bbc6a91e1a0ad55d1d609a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5209 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 T%U2N+00000NkvXXu0mjf)X(rX diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKAppSettingsViewController.h b/mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKAppSettingsViewController.h deleted file mode 100644 index da7f99309..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKAppSettingsViewController.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// IASKAppSettingsViewController.h -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import - -@class IASKSettingsReader; -@class IASKAppSettingsViewController; - -@protocol IASKSettingsDelegate -- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender; -@end - - -@interface IASKAppSettingsViewController : UIViewController { - id _delegate; - IBOutlet UITableView *_tableView; - - NSMutableArray *_viewList; - NSIndexPath *_currentIndexPath; - NSIndexPath *_topmostRowBeforeKeyboardWasShown; - - IASKSettingsReader *_settingsReader; - NSString *_file; - - id _currentFirstResponder; - - BOOL _showCreditsFooter; - BOOL _showDoneButton; -} - -@property (nonatomic, assign) id delegate; -@property (nonatomic, retain) NSIndexPath *currentIndexPath; -@property (nonatomic, retain) IASKSettingsReader *settingsReader; -@property (nonatomic, copy) NSString *file; -@property (nonatomic, retain) id currentFirstResponder; -@property (nonatomic, assign) BOOL showCreditsFooter; -@property (nonatomic, assign) BOOL showDoneButton; - -- (IBAction)dismiss:(id)sender; - -// subclassing: optionally override these methods to customize appearance and functionality -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; -- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath; -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m b/mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m deleted file mode 100644 index e1968ac36..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m +++ /dev/null @@ -1,620 +0,0 @@ -// -// IASKAppSettingsViewController.m -// http://www.inappsettingskit.com -// -// Copyright (c) 2009-2010: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - - -#import "IASKAppSettingsViewController.h" -#import "IASKSettingsReader.h" -#import "IASKPSToggleSwitchSpecifierViewCell.h" -#import "IASKPSSliderSpecifierViewCell.h" -#import "IASKPSTextFieldSpecifierViewCell.h" -#import "IASKPSTitleValueSpecifierViewCell.h" -#import "IASKSwitch.h" -#import "IASKSlider.h" -#import "IASKSpecifier.h" -#import "IASKSpecifierValuesViewController.h" -#import "IASKTextField.h" - -static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3; -static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2; -static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8; - -static NSString *kIASKCredits = @"Powered by InAppSettingsKit"; // Leave this as-is!!! - -#define kIASKSpecifierValuesViewControllerIndex 0 -#define kIASKSpecifierChildViewControllerIndex 1 - -#define kIASKCreditsViewWidth 285 - -@interface IASKAppSettingsViewController () -- (void)_textChanged:(id)sender; -- (void)_keyboardWillShow:(NSNotification*)notification; -- (void)_keyboardWillHide:(NSNotification*)notification; -@end - -@implementation IASKAppSettingsViewController - -@synthesize delegate = _delegate; -@synthesize currentIndexPath=_currentIndexPath; -@synthesize settingsReader = _settingsReader; -@synthesize file = _file; -@synthesize currentFirstResponder = _currentFirstResponder; -@synthesize showCreditsFooter = _showCreditsFooter; -@synthesize showDoneButton = _showDoneButton; - -#pragma mark accessors -- (IASKSettingsReader*)settingsReader { - if (!_settingsReader) { - _settingsReader = [[IASKSettingsReader alloc] initWithFile:self.file]; - } - return _settingsReader; -} - -- (NSString*)file { - if (!_file) { - return @"Root"; - } - return [[_file retain] autorelease]; -} - -- (void)setFile:(NSString *)file { - if (file != _file) { - [_file release]; - _file = [file copy]; - } - - self.settingsReader = nil; // automatically initializes itself -} - -#pragma mark standard view controller methods -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - if ([super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { - // If set to YES, will display credits for InAppSettingsKit creators - _showCreditsFooter = YES; - - // If set to YES, will add a DONE button at the right of the navigation bar - _showDoneButton = NO; - } - return self; -} - -- (void)awakeFromNib { - // If set to YES, will display credits for InAppSettingsKit creators - _showCreditsFooter = YES; - - // If set to YES, will add a DONE button at the right of the navigation bar - // if loaded via NIB, it's likely we sit in a TabBar- or NavigationController - // and thus don't need the Done button - _showDoneButton = NO; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // Add views - _viewList = [[NSMutableArray alloc] init]; - [_viewList addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"IASKSpecifierValuesView", @"ViewName",nil]]; - [_viewList addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"IASKAppSettingsView", @"ViewName",nil]]; - -} - -- (void)viewDidUnload { - // Release any retained subviews of the main view. - // e.g. self.myOutlet = nil; -} - -- (void)viewWillAppear:(BOOL)animated { - if (_tableView) { - [_tableView reloadData]; - _tableView.frame = self.view.bounds; - } - - self.navigationItem.rightBarButtonItem = nil; - self.navigationController.delegate = nil; - if ([self.file isEqualToString:@"Root"]) { - self.navigationController.delegate = self; - if (_showDoneButton) { - UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone - target:self - action:@selector(dismiss:)]; - self.navigationItem.rightBarButtonItem = buttonItem; - [buttonItem release]; - } - if (!self.title) { - self.title = NSLocalizedString(@"Settings", @""); - } - } - [super viewWillAppear:animated]; -} - -- (void)viewDidAppear:(BOOL)animated { - [_tableView flashScrollIndicators]; -// _tableView.frame = self.view.bounds; - [super viewDidAppear:animated]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(_keyboardWillShow:) - name:UIKeyboardWillShowNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(_keyboardWillHide:) - name:UIKeyboardWillHideNotification - object:nil]; -} - -- (void)viewWillDisappear:(BOOL)animated { - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; - if ([self.currentFirstResponder canResignFirstResponder]) { - [self.currentFirstResponder resignFirstResponder]; - } - [super viewWillDisappear:animated]; -} - -- (void)viewDidDisappear:(BOOL)animated { - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; - [super viewDidDisappear:animated]; -} - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { - return (interfaceOrientation == UIInterfaceOrientationPortrait) || (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown); -} - -- (void)didReceiveMemoryWarning { - // Releases the view if it doesn't have a superview. - [super didReceiveMemoryWarning]; - - // Release any cached data, images, etc that aren't in use. -} - -- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { - if (![viewController isKindOfClass:[IASKAppSettingsViewController class]] && ![viewController isKindOfClass:[IASKSpecifierValuesViewController class]]) { - [self dismiss:nil]; - } -} - -- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [_viewList release]; - [_currentIndexPath release]; - [_file release]; - _file = nil; - - [_currentFirstResponder release]; - _currentFirstResponder = nil; - - self.settingsReader = nil; - _delegate = nil; - - [super dealloc]; -} - - -#pragma mark - -#pragma mark Actions - -- (IBAction)dismiss:(id)sender { - if ([self.currentFirstResponder canResignFirstResponder]) { - [self.currentFirstResponder resignFirstResponder]; - } - - self.navigationController.delegate = nil; - - if (self.delegate && [self.delegate conformsToProtocol:@protocol(IASKSettingsDelegate)]) { - [self.delegate settingsViewControllerDidEnd:self]; - } -} - -- (void)toggledValue:(id)sender { - IASKSwitch *toggle = (IASKSwitch*)sender; - IASKSpecifier *spec = [_settingsReader specifierForKey:[toggle key]]; - - if ([toggle isOn]) { - if ([spec trueValue] != nil) { - [[NSUserDefaults standardUserDefaults] setObject:[spec trueValue] forKey:[toggle key]]; - } - else { - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:[toggle key]]; - } - } - else { - if ([spec falseValue] != nil) { - [[NSUserDefaults standardUserDefaults] setObject:[spec falseValue] forKey:[toggle key]]; - } - else { - [[NSUserDefaults standardUserDefaults] setBool:NO forKey:[toggle key]]; - } - } - [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged object:[toggle key]]; -} - -- (void)sliderChangedValue:(id)sender { - IASKSlider *slider = (IASKSlider*)sender; - [[NSUserDefaults standardUserDefaults] setFloat:[slider value] forKey:[slider key]]; - [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged object:[slider key]]; -} - - -#pragma mark - -#pragma mark UITableView Functions - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return [self.settingsReader numberOfSections]; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [self.settingsReader numberOfRowsForSection:section]; -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - return [self.settingsReader titleForSection:section]; -} - -- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { - if (!_showCreditsFooter || section != [self.settingsReader numberOfSections]-1) return nil; - - // Show the credits only in the last section's footer - UILabel *credits = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, kIASKCreditsViewWidth, 0)] autorelease]; - [credits setOpaque:NO]; - [credits setNumberOfLines:0]; - [credits setFont:[UIFont systemFontOfSize:14.0f]]; - [credits setTextAlignment:UITextAlignmentRight]; - [credits setTextColor:[UIColor colorWithRed:77.0f/255.0f green:87.0f/255.0f blue:107.0f/255.0f alpha:1.0f]]; - [credits setShadowColor:[UIColor whiteColor]]; - [credits setShadowOffset:CGSizeMake(0, 1)]; - [credits setBackgroundColor:[UIColor clearColor]]; - [credits setText:kIASKCredits]; - [credits sizeToFit]; - - UIView* view = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, kIASKCreditsViewWidth, credits.frame.size.height + 6 + 11)] autorelease]; - [view setBackgroundColor:[UIColor clearColor]]; - - CGRect frame = credits.frame; - frame.origin.y = 8; - frame.origin.x = 16; - frame.size.width = kIASKCreditsViewWidth; - credits.frame = frame; - - [view addSubview:credits]; - [view sizeToFit]; - - return view; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { - if (!_showCreditsFooter || section != [self.settingsReader numberOfSections]-1) return 0.0f; - - UIView* view = [self tableView:tableView viewForFooterInSection:section]; - if (view != nil) { - return view.frame.size.height; - } - return -1; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath]; - NSString *key = [specifier key]; - - if ([[specifier type] isEqualToString:kIASKPSToggleSwitchSpecifier]) { - IASKPSToggleSwitchSpecifierViewCell *cell = (IASKPSToggleSwitchSpecifierViewCell*)[tableView dequeueReusableCellWithIdentifier:[specifier type]]; - - if (!cell) { - cell = (IASKPSToggleSwitchSpecifierViewCell*) [[[NSBundle mainBundle] loadNibNamed:@"IASKPSToggleSwitchSpecifierViewCell" - owner:self - options:nil] objectAtIndex:0]; - } - [[cell label] setText:[specifier title]]; - - id currentValue = [[NSUserDefaults standardUserDefaults] objectForKey:key]; - BOOL toggleState; - if (currentValue) { - if ([currentValue isEqual:[specifier trueValue]]) { - toggleState = YES; - } else if ([currentValue isEqual:[specifier falseValue]]) { - toggleState = NO; - } else { - toggleState = [currentValue boolValue]; - } - } else { - toggleState = [specifier defaultBoolValue]; - } - [[cell toggle] setOn:toggleState]; - - [[cell toggle] addTarget:self action:@selector(toggledValue:) forControlEvents:UIControlEventValueChanged]; - [[cell toggle] setKey:key]; - return cell; - } - else if ([[specifier type] isEqualToString:kIASKPSMultiValueSpecifier]) { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[specifier type]]; - - if (!cell) { - cell = [[[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:[specifier type]] autorelease]; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - } - [[cell textLabel] setText:[specifier title]]; - [[cell detailTextLabel] setText:[[specifier titleForCurrentValue:[[NSUserDefaults standardUserDefaults] objectForKey:key] != nil ? - [[NSUserDefaults standardUserDefaults] objectForKey:key] : [specifier defaultValue]] description]]; - return cell; - } - else if ([[specifier type] isEqualToString:kIASKPSTitleValueSpecifier]) { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[specifier type]]; - - if (!cell) { - cell = [[[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:[specifier type]] autorelease]; - cell.accessoryType = UITableViewCellAccessoryNone; - } - - cell.textLabel.text = [specifier title]; - id value = [[NSUserDefaults standardUserDefaults] objectForKey:key] ? : [specifier defaultValue]; - - NSString *stringValue; - if ([specifier multipleValues] || [specifier multipleTitles]) { - stringValue = [specifier titleForCurrentValue:value]; - } else { - stringValue = [value description]; - } - - cell.detailTextLabel.text = stringValue; - [cell setUserInteractionEnabled:NO]; - - return cell; - } - else if ([[specifier type] isEqualToString:kIASKPSTextFieldSpecifier]) { - IASKPSTextFieldSpecifierViewCell *cell = (IASKPSTextFieldSpecifierViewCell*)[tableView dequeueReusableCellWithIdentifier:[specifier type]]; - - if (!cell) { - cell = (IASKPSTextFieldSpecifierViewCell*) [[[NSBundle mainBundle] loadNibNamed:@"IASKPSTextFieldSpecifierViewCell" - owner:self - options:nil] objectAtIndex:0]; - cell.textField.textAlignment = UITextAlignmentLeft; - cell.textField.returnKeyType = UIReturnKeyDone; - cell.accessoryType = UITableViewCellAccessoryNone; - } - [[cell label] setText:[specifier title]]; - [[cell textField] setText:[[NSUserDefaults standardUserDefaults] objectForKey:key] != nil ? - [[NSUserDefaults standardUserDefaults] objectForKey:key] : [specifier defaultStringValue]]; - [[cell textField] setKey:key]; - [[cell textField] setDelegate:self]; - [[cell textField] addTarget:self action:@selector(_textChanged:) forControlEvents:UIControlEventEditingChanged]; - [[cell textField] setSecureTextEntry:[specifier isSecure]]; - [[cell textField] setKeyboardType:[specifier keyboardType]]; - [[cell textField] setAutocapitalizationType:[specifier autocapitalizationType]]; - [[cell textField] setAutocorrectionType:[specifier autoCorrectionType]]; - [cell setNeedsLayout]; - return cell; - } - else if ([[specifier type] isEqualToString:kIASKPSSliderSpecifier]) { - IASKPSSliderSpecifierViewCell *cell = (IASKPSSliderSpecifierViewCell*)[tableView dequeueReusableCellWithIdentifier:[specifier type]]; - - if (!cell) { - cell = (IASKPSSliderSpecifierViewCell*) [[[NSBundle mainBundle] loadNibNamed:@"IASKPSSliderSpecifierViewCell" - owner:self - options:nil] objectAtIndex:0]; - } - - if ([[specifier minimumValueImage] length] > 0) { - [[cell minImage] setImage:[UIImage imageWithContentsOfFile:[_settingsReader pathForImageNamed:[specifier minimumValueImage]]]]; - } - - if ([[specifier maximumValueImage] length] > 0) { - [[cell maxImage] setImage:[UIImage imageWithContentsOfFile:[_settingsReader pathForImageNamed:[specifier maximumValueImage]]]]; - } - - [[cell slider] setMinimumValue:[specifier minimumValue]]; - [[cell slider] setMaximumValue:[specifier maximumValue]]; - [[cell slider] setValue:[[NSUserDefaults standardUserDefaults] objectForKey:key] != nil ? - [[[NSUserDefaults standardUserDefaults] objectForKey:key] floatValue] : [[specifier defaultValue] floatValue]]; - [[cell slider] addTarget:self action:@selector(sliderChangedValue:) forControlEvents:UIControlEventValueChanged]; - [[cell slider] setKey:key]; - [cell setNeedsLayout]; - return cell; - } - else if ([[specifier type] isEqualToString:kIASKPSChildPaneSpecifier]) { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[specifier type]]; - - if (!cell) { - cell = [[[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:[specifier type]] autorelease]; - [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; - } - - [[cell textLabel] setText:[specifier title]]; - return cell; - } else if ([[specifier type] isEqualToString:kIASKOpenURLSpecifier]) { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[specifier type]]; - - if (!cell) { - cell = [[[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:[specifier type]] autorelease]; - [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; - } - - cell.textLabel.text = [specifier title]; - cell.detailTextLabel.text = [[specifier defaultValue] description]; - return cell; - } else { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[specifier type]]; - - if (!cell) { - cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[specifier type]] autorelease]; - } - [[cell textLabel] setText:[specifier title]]; - return cell; - } -} - -- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { - IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath]; - - if ([[specifier type] isEqualToString:kIASKPSToggleSwitchSpecifier]) { - return nil; - } else { - return indexPath; - } -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath]; - - if ([[specifier type] isEqualToString:kIASKPSToggleSwitchSpecifier]) { - [tableView deselectRowAtIndexPath:indexPath animated:NO]; - } - else if ([[specifier type] isEqualToString:kIASKPSMultiValueSpecifier]) { - IASKSpecifierValuesViewController *targetViewController = [[_viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex] objectForKey:@"viewController"]; - - if (targetViewController == nil) { - // the view controller has not been created yet, create it and set it to our viewList array - // create a new dictionary with the new view controller - NSMutableDictionary *newItemDict = [NSMutableDictionary dictionaryWithCapacity:3]; - [newItemDict addEntriesFromDictionary: [_viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex]]; // copy the title and explain strings - - targetViewController = [[IASKSpecifierValuesViewController alloc] initWithNibName:@"IASKSpecifierValuesView" bundle:nil]; - - // add the new view controller to the dictionary and then to the 'viewList' array - [newItemDict setObject:targetViewController forKey:@"viewController"]; - [_viewList replaceObjectAtIndex:kIASKSpecifierValuesViewControllerIndex withObject:newItemDict]; - [targetViewController release]; - - // load the view controll back in to push it - targetViewController = [[_viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex] objectForKey:@"viewController"]; - } - _currentIndexPath = indexPath; - [targetViewController setCurrentSpecifier:specifier]; - targetViewController.settingsReader = self.settingsReader; - [[self navigationController] pushViewController:targetViewController animated:YES]; - } - else if ([[specifier type] isEqualToString:kIASKPSSliderSpecifier]) { - [tableView deselectRowAtIndexPath:indexPath animated:NO]; - } - else if ([[specifier type] isEqualToString:kIASKPSTextFieldSpecifier]) { - IASKPSTextFieldSpecifierViewCell *textFieldCell = (id)[tableView cellForRowAtIndexPath:indexPath]; - [textFieldCell.textField becomeFirstResponder]; - } - else if ([[specifier type] isEqualToString:kIASKPSChildPaneSpecifier]) { - IASKAppSettingsViewController *targetViewController = [[_viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex] objectForKey:@"viewController"]; - - if (targetViewController == nil) { - // the view controller has not been created yet, create it and set it to our viewList array - // create a new dictionary with the new view controller - NSMutableDictionary *newItemDict = [NSMutableDictionary dictionaryWithCapacity:3]; - [newItemDict addEntriesFromDictionary: [_viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex]]; // copy the title and explain strings - - targetViewController = [[[self class] alloc] initWithNibName:@"IASKAppSettingsView" bundle:nil]; - - // add the new view controller to the dictionary and then to the 'viewList' array - [newItemDict setObject:targetViewController forKey:@"viewController"]; - [_viewList replaceObjectAtIndex:kIASKSpecifierChildViewControllerIndex withObject:newItemDict]; - [targetViewController release]; - - // load the view controll back in to push it - targetViewController = [[_viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex] objectForKey:@"viewController"]; - } - _currentIndexPath = indexPath; - targetViewController.file = specifier.file; - targetViewController.title = specifier.title; - targetViewController.showCreditsFooter = NO; - [[self navigationController] pushViewController:targetViewController animated:YES]; - } else if ([[specifier type] isEqualToString:kIASKOpenURLSpecifier]) { - [tableView deselectRowAtIndexPath:indexPath animated:YES]; - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:specifier.file]]; - } else { - [tableView deselectRowAtIndexPath:indexPath animated:NO]; - } -} - - -#pragma mark - -#pragma mark UITextFieldDelegate Functions - -- (void)_textChanged:(id)sender { - IASKTextField *text = (IASKTextField*)sender; - [[NSUserDefaults standardUserDefaults] setObject:[text text] forKey:[text key]]; - [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged object:[text key]]; -} - -- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { - [textField setTextAlignment:UITextAlignmentLeft]; - self.currentFirstResponder = textField; - return YES; -} - -- (void)textFieldDidBeginEditing:(UITextField *)textField { - if ([_tableView indexPathsForVisibleRows].count) { - _topmostRowBeforeKeyboardWasShown = (NSIndexPath*)[[_tableView indexPathsForVisibleRows] objectAtIndex:0]; - } else { - // this should never happen - _topmostRowBeforeKeyboardWasShown = [NSIndexPath indexPathForRow:0 inSection:0]; - [textField resignFirstResponder]; - } -} - -- (void)textFieldDidEndEditing:(UITextField *)textField { - self.currentFirstResponder = nil; -} - -- (BOOL)textFieldShouldReturn:(UITextField *)textField{ - [textField resignFirstResponder]; - return YES; -} - -#pragma mark Keyboard Management -- (void)_keyboardWillShow:(NSNotification*)notification { - if (self.navigationController.topViewController == self) { - NSDictionary* userInfo = [notification userInfo]; - - // we don't use SDK constants here to be universally compatible with all SDKs ≥ 3.0 - NSValue* keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardBoundsUserInfoKey"]; - if (!keyboardFrameValue) { - keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardFrameEndUserInfoKey"]; - } - - // Reduce the tableView height by the part of the keyboard that actually covers the tableView - CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds; - CGRect viewRectAbsolute = [_tableView convertRect:_tableView.bounds toView:[[UIApplication sharedApplication] keyWindow]]; - CGRect frame = _tableView.frame; - frame.size.height -= [keyboardFrameValue CGRectValue].size.height - CGRectGetMaxY(windowRect) + CGRectGetMaxY(viewRectAbsolute); - - [UIView beginAnimations:nil context:NULL]; - [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]]; - [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]]; - _tableView.frame = frame; - [UIView commitAnimations]; - - UITableViewCell *textFieldCell = (id)((UITextField *)self.currentFirstResponder).superview.superview; - NSIndexPath *textFieldIndexPath = [_tableView indexPathForCell:textFieldCell]; - - // iOS 3 sends hide and show notifications right after each other - // when switching between textFields, so cancel -scrollToOldPosition requests - [NSObject cancelPreviousPerformRequestsWithTarget:self]; - - [_tableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; - } -} - -- (void) scrollToOldPosition { - [_tableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES]; -} - -- (void)_keyboardWillHide:(NSNotification*)notification { - if (self.navigationController.topViewController == self) { - NSDictionary* userInfo = [notification userInfo]; - - [UIView beginAnimations:nil context:NULL]; - [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]]; - [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]]; - _tableView.frame = self.view.bounds; - [UIView commitAnimations]; - - [self performSelector:@selector(scrollToOldPosition) withObject:nil afterDelay:0.1]; - } -} -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.h b/mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.h deleted file mode 100644 index b3276d2ff..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// IASKSpecifierValuesViewController.h -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import - -@class IASKSpecifier; -@class IASKSettingsReader; - -@interface IASKSpecifierValuesViewController : UIViewController { - IBOutlet UITableView *_tableView; - - IASKSpecifier *_currentSpecifier; - NSIndexPath *_checkedItem; - IASKSettingsReader *_settingsReader; -} - -@property (nonatomic, retain) NSIndexPath *checkedItem; -@property (nonatomic, retain) IASKSpecifier *currentSpecifier; -@property (nonatomic, retain) IASKSettingsReader *settingsReader; - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m b/mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m deleted file mode 100644 index 02063186d..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m +++ /dev/null @@ -1,142 +0,0 @@ -// -// IASKSpecifierValuesViewController.m -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import "IASKSpecifierValuesViewController.h" -#import "IASKSpecifier.h" -#import "IASKSettingsReader.h" - -#define kCellValue @"kCellValue" - -@implementation IASKSpecifierValuesViewController - -@synthesize currentSpecifier=_currentSpecifier; -@synthesize checkedItem=_checkedItem; -@synthesize settingsReader = _settingsReader; - -/* - // The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad. -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { - // Custom initialization - } - return self; -} -*/ - - -/*- (void)viewDidLoad { - [super viewDidLoad]; -}*/ - -- (void)viewWillAppear:(BOOL)animated { - if (_currentSpecifier) { - [self setTitle:[_currentSpecifier title]]; - } - - if (_tableView) { - [_tableView reloadData]; - } - [super viewWillAppear:animated]; -} - -- (void)viewDidAppear:(BOOL)animated { - [_tableView flashScrollIndicators]; - [super viewDidAppear:animated]; -} - - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { - return (interfaceOrientation == UIInterfaceOrientationPortrait) || (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown); -} - -- (void)didReceiveMemoryWarning { - // Releases the view if it doesn't have a superview. - [super didReceiveMemoryWarning]; - - // Release any cached data, images, etc that aren't in use. -} - -- (void)viewDidUnload { - // Release any retained subviews of the main view. - // e.g. self.myOutlet = nil; -} - - -- (void)dealloc { - [_currentSpecifier release]; - [_settingsReader release]; - _settingsReader = nil; - - [super dealloc]; -} - - -#pragma mark - -#pragma mark UITableView delegates - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [_currentSpecifier multipleValuesCount]; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellValue]; - NSArray *values = [_currentSpecifier multipleValues]; - NSArray *titles = [_currentSpecifier multipleTitles]; - - if (!cell) { - cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellValue] autorelease]; - } - - if ([[NSUserDefaults standardUserDefaults] objectForKey:[_currentSpecifier key]] ? - [[[NSUserDefaults standardUserDefaults] objectForKey:[_currentSpecifier key]] isEqual:[values objectAtIndex:indexPath.row]] : - [[_currentSpecifier defaultValue] isEqual:[values objectAtIndex:indexPath.row]]) { - [self setCheckedItem:indexPath]; - [cell setAccessoryType:UITableViewCellAccessoryCheckmark]; - } - else { - [cell setAccessoryType:UITableViewCellAccessoryNone]; - } - - @try { - [[cell textLabel] setText:[self.settingsReader titleForStringId:[titles objectAtIndex:indexPath.row]]]; - } - @catch (NSException * e) {} - return cell; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (indexPath == [self checkedItem]) { - [tableView deselectRowAtIndexPath:indexPath animated:YES]; - return; - } - - NSArray *values = [_currentSpecifier multipleValues]; - - [tableView deselectRowAtIndexPath:indexPath animated:YES]; - [[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark]; - [[tableView cellForRowAtIndexPath:[self checkedItem]] setAccessoryType:UITableViewCellAccessoryNone]; - [self setCheckedItem:indexPath]; - - [[NSUserDefaults standardUserDefaults] setObject:[values objectAtIndex:indexPath.row] forKey:[_currentSpecifier key]]; - [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged object:[_currentSpecifier key]]; -} - - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSettingsReader.h b/mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSettingsReader.h deleted file mode 100644 index e9d295819..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSettingsReader.h +++ /dev/null @@ -1,107 +0,0 @@ -// -// IASKSettingsReader.h -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import - -#define kIASKPreferenceSpecifiers @"PreferenceSpecifiers" -#define kIASKType @"Type" -#define kIASKTitle @"Title" -#define kIASKKey @"Key" -#define kIASKFile @"File" -#define kIASKDefaultValue @"DefaultValue" -#define kIASKMinimumValue @"MinimumValue" -#define kIASKMaximumValue @"MaximumValue" -#define kIASKTrueValue @"TrueValue" -#define kIASKFalseValue @"FalseValue" -#define kIASKIsSecure @"IsSecure" -#define KIASKKeyboardType @"KeyboardType" -#define kIASKAutocapitalizationType @"AutocapitalizationType" -#define kIASKAutoCorrectionType @"AutocorrectionType" -#define kIASKValues @"Values" -#define kIASKTitles @"Titles" -#define kIASKKeyboardAlphabet @"Alphabet" -#define kIASKKeyboardNumbersAndPunctuation @"NumbersAndPunctuation" -#define kIASKKeyboardNumberPad @"NumberPad" -#define KIASKKeyboardURL @"URL" -#define kIASKKeyboardEmailAddress @"EmailAddress" -#define kIASKAutoCapNone @"None" -#define kIASKAutoCapSentences @"Sentences" -#define kIASKAutoCapWords @"Words" -#define kIASKAutoCapAllCharacters @"AllCharacters" -#define kIASKAutoCorrDefault @"Default" -#define kIASKAutoCorrNo @"No" -#define kIASKAutoCorrYes @"Yes" -#define kIASKMinimumValueImage @"MinimumValueImage" -#define kIASKMaximumValueImage @"MaximumValueImage" - -#define kIASKPSGroupSpecifier @"PSGroupSpecifier" -#define kIASKPSToggleSwitchSpecifier @"PSToggleSwitchSpecifier" -#define kIASKPSMultiValueSpecifier @"PSMultiValueSpecifier" -#define kIASKPSSliderSpecifier @"PSSliderSpecifier" -#define kIASKPSTitleValueSpecifier @"PSTitleValueSpecifier" -#define kIASKPSTextFieldSpecifier @"PSTextFieldSpecifier" -#define kIASKPSChildPaneSpecifier @"PSChildPaneSpecifier" -#define kIASKOpenURLSpecifier @"IASKOpenURLSpecifier" - -#define kIASKBundleFolder @"Settings.bundle" -#define kIASKBundleFolderAlt @"InAppSettings.bundle" -#define kIASKBundleFilename @"Root.plist" - -#define kIASKAppSettingChanged @"kAppSettingChanged" - -#define kIASKSectionHeaderIndex 0 - -#define kIASKSliderNoImagesX 21 -#define kIASKSliderNoImagesWidth 278 -#define kIASKSliderBothImagesX 53 -#define kIASKSliderBothImagesWidth 214 -#define kIASKSliderOneImageWidth 246 - -#define kIASKTableWidth 320 -#define kIASKSpacing 5 -#define kIASKMinLabelWidth 97 -#define kIASKMinValueWidth 35 -#define kIASKPaddingLeft 9 -#define kIASKPaddingRight 10 - -#define kIASKLabelFontSize 17 - -@class IASKSpecifier; - -@interface IASKSettingsReader : NSObject { - NSString *_path; - NSString *_bundleFolder; - NSDictionary *_settingsBundle; - NSArray *_dataSource; - NSBundle *_bundle; -} - -- (id)initWithFile:(NSString*)file; -- (NSInteger)numberOfSections; -- (NSInteger)numberOfRowsForSection:(NSInteger)section; -- (IASKSpecifier*)specifierForIndexPath:(NSIndexPath*)indexPath; -- (IASKSpecifier*)specifierForKey:(NSString*)key; -- (NSString*)titleForSection:(NSInteger)section; -- (NSString*)titleForStringId:(NSString*)stringId; -- (NSString*)bundlePath; -- (NSString*)pathForImageNamed:(NSString*)image; - -@property (nonatomic, retain) NSString *path; -@property (nonatomic, retain) NSString *bundleFolder; -@property (nonatomic, retain) NSDictionary *settingsBundle; -@property (nonatomic, retain) NSArray *dataSource; - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSettingsReader.m b/mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSettingsReader.m deleted file mode 100644 index 1b694b2c1..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSettingsReader.m +++ /dev/null @@ -1,157 +0,0 @@ -// -// IASKSettingsReader.m -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import "IASKSettingsReader.h" -#import "IASKSpecifier.h" - -@interface IASKSettingsReader (private) -- (void)_reinterpretBundle:(NSDictionary*)settingsBundle; -- (BOOL)_sectionHasHeading:(NSInteger)section; -@end - -@implementation IASKSettingsReader - -@synthesize path=_path, -bundleFolder=_bundleFolder, -settingsBundle=_settingsBundle, -dataSource=_dataSource; - -- (id)init { - return [self initWithFile:@"Root"]; -} - -- (id)initWithFile:(NSString*)file { - if ((self=[super init])) { - [self setBundleFolder:kIASKBundleFolderAlt]; - // Generate the settings bundle path - NSString *path = [self bundlePath]; - - // Try both bundle folders - for (int i=0;i<2;i++) { - [self setPath:[path stringByAppendingPathComponent:[file stringByAppendingString:@".inApp.plist"]]]; - [self setSettingsBundle:[NSDictionary dictionaryWithContentsOfFile:[self path]]]; - if (!self.settingsBundle) { - [self setPath:[path stringByAppendingPathComponent:[file stringByAppendingString:@".plist"]]]; - [self setSettingsBundle:[NSDictionary dictionaryWithContentsOfFile:[self path]]]; - } - if (self.settingsBundle) - break; - [self setBundleFolder:kIASKBundleFolder]; - path = [self bundlePath]; - } - _bundle = [[NSBundle bundleWithPath:path] retain]; - - if (_settingsBundle) { - [self _reinterpretBundle:_settingsBundle]; - } - } - return self; -} - -- (void)dealloc { - [_path release]; - [_settingsBundle release]; - [_dataSource release]; - [_bundle release]; - [super dealloc]; -} - -- (void)_reinterpretBundle:(NSDictionary*)settingsBundle { - NSArray *preferenceSpecifiers = [settingsBundle objectForKey:kIASKPreferenceSpecifiers]; - NSInteger sectionCount = -1; - NSMutableArray *dataSource = [[[NSMutableArray alloc] init] autorelease]; - - for (NSDictionary *specifier in preferenceSpecifiers) { - if ([(NSString*)[specifier objectForKey:kIASKType] isEqualToString:kIASKPSGroupSpecifier]) { - NSMutableArray *newArray = [[NSMutableArray alloc] init]; - - [newArray addObject:specifier]; - [dataSource addObject:newArray]; - [newArray release]; - sectionCount++; - } - else { - if (sectionCount == -1) { - NSMutableArray *newArray = [[NSMutableArray alloc] init]; - [dataSource addObject:newArray]; - [newArray release]; - sectionCount++; - } - - IASKSpecifier *newSpecifier = [[IASKSpecifier alloc] initWithSpecifier:specifier]; - [(NSMutableArray*)[dataSource objectAtIndex:sectionCount] addObject:newSpecifier]; - [newSpecifier release]; - } - } - [self setDataSource:dataSource]; -} - -- (BOOL)_sectionHasHeading:(NSInteger)section { - return [[[[self dataSource] objectAtIndex:section] objectAtIndex:0] isKindOfClass:[NSDictionary class]]; -} - -- (NSInteger)numberOfSections { - return [[self dataSource] count]; -} - -- (NSInteger)numberOfRowsForSection:(NSInteger)section { - int headingCorrection = [self _sectionHasHeading:section] ? 1 : 0; - return [(NSArray*)[[self dataSource] objectAtIndex:section] count] - headingCorrection; -} - -- (IASKSpecifier*)specifierForIndexPath:(NSIndexPath*)indexPath { - int headingCorrection = [self _sectionHasHeading:indexPath.section] ? 1 : 0; - - IASKSpecifier *specifier = [[[self dataSource] objectAtIndex:indexPath.section] objectAtIndex:(indexPath.row+headingCorrection)]; - specifier.settingsReader = self; - return specifier; -} - -- (IASKSpecifier*)specifierForKey:(NSString*)key { - for (NSArray *specifiers in _dataSource) { - for (id sp in specifiers) { - if ([sp isKindOfClass:[IASKSpecifier class]]) { - if ([[sp key] isEqualToString:key]) { - return sp; - } - } - } - } - return nil; -} - -- (NSString*)titleForSection:(NSInteger)section { - if ([self _sectionHasHeading:section]) { - NSDictionary *dict = [[[self dataSource] objectAtIndex:section] objectAtIndex:kIASKSectionHeaderIndex]; - return [_bundle localizedStringForKey:[dict objectForKey:kIASKTitle] value:[dict objectForKey:kIASKTitle] table:@"Root"]; - } - return nil; -} - -- (NSString*)titleForStringId:(NSString*)stringId { - return [_bundle localizedStringForKey:stringId value:stringId table:@"Root"]; -} - -- (NSString*)bundlePath { - NSString *libDirectory = [[NSBundle mainBundle] bundlePath]; - return [libDirectory stringByAppendingPathComponent:_bundleFolder]; -} - -- (NSString*)pathForImageNamed:(NSString*)image { - return [[self bundlePath] stringByAppendingPathComponent:image]; -} - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSpecifier.h b/mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSpecifier.h deleted file mode 100644 index 48bd2a971..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSpecifier.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// IASKSpecifier.h -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import - -@class IASKSettingsReader; - -@interface IASKSpecifier : NSObject { - NSDictionary *_specifierDict; - NSDictionary *_multipleValuesDict; - IASKSettingsReader *_settingsReader; -} -@property (nonatomic, retain) NSDictionary *specifierDict; -@property (nonatomic, assign) IASKSettingsReader *settingsReader; - -- (id)initWithSpecifier:(NSDictionary*)specifier; -- (NSString*)title; -- (NSString*)key; -- (NSString*)type; -- (NSString*)titleForCurrentValue:(id)currentValue; -- (NSInteger)multipleValuesCount; -- (NSArray*)multipleValues; -- (NSArray*)multipleTitles; -- (NSString*)file; -- (id)defaultValue; -- (id)defaultStringValue; -- (BOOL)defaultBoolValue; -- (id)trueValue; -- (id)falseValue; -- (float)minimumValue; -- (float)maximumValue; -- (NSString*)minimumValueImage; -- (NSString*)maximumValueImage; -- (BOOL)isSecure; -- (UIKeyboardType)keyboardType; -- (UITextAutocapitalizationType)autocapitalizationType; -- (UITextAutocorrectionType)autoCorrectionType; - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSpecifier.m b/mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSpecifier.m deleted file mode 100644 index c227f3bd9..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Models/IASKSpecifier.m +++ /dev/null @@ -1,208 +0,0 @@ -// -// IASKSpecifier.m -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import "IASKSpecifier.h" -#import "IASKSettingsReader.h" - -@interface IASKSpecifier () -@property (nonatomic, retain) NSDictionary *multipleValuesDict; -- (void)_reinterpretValues:(NSDictionary*)specifierDict; -@end - -@implementation IASKSpecifier - -@synthesize specifierDict=_specifierDict; -@synthesize multipleValuesDict=_multipleValuesDict; -@synthesize settingsReader = _settingsReader; - -- (id)initWithSpecifier:(NSDictionary*)specifier { - if ([super init]) { - [self setSpecifierDict:specifier]; - - if ([[self type] isEqualToString:kIASKPSMultiValueSpecifier] || - [[self type] isEqualToString:kIASKPSTitleValueSpecifier]) { - [self _reinterpretValues:[self specifierDict]]; - } - } - return self; -} - -- (void)dealloc { - [_specifierDict release]; - [_multipleValuesDict release]; - _settingsReader = nil; - - [super dealloc]; -} - -- (void)_reinterpretValues:(NSDictionary*)specifierDict { - NSArray *values = [_specifierDict objectForKey:kIASKValues]; - NSArray *titles = [_specifierDict objectForKey:kIASKTitles]; - - NSMutableDictionary *multipleValuesDict = [[[NSMutableDictionary alloc] init] autorelease]; - - if (values) { - [multipleValuesDict setObject:values forKey:kIASKValues]; - } - - if (titles) { - [multipleValuesDict setObject:titles forKey:kIASKTitles]; - } - - [self setMultipleValuesDict:multipleValuesDict]; -} - -- (NSString*)title { - return [self.settingsReader titleForStringId:[_specifierDict objectForKey:kIASKTitle]]; -} - -- (NSString*)key { - return [_specifierDict objectForKey:kIASKKey]; -} - -- (NSString*)type { - return [_specifierDict objectForKey:kIASKType]; -} - -- (NSString*)titleForCurrentValue:(id)currentValue { - NSArray *values = [self multipleValues]; - NSArray *titles = [self multipleTitles]; - if (values.count != titles.count) { - return nil; - } - NSInteger keyIndex = [values indexOfObject:currentValue]; - if (keyIndex == NSNotFound) { - return nil; - } - @try { - return [self.settingsReader titleForStringId:[titles objectAtIndex:keyIndex]]; - } - @catch (NSException * e) {} - return nil; -} - -- (NSInteger)multipleValuesCount { - return [[_multipleValuesDict objectForKey:kIASKValues] count]; -} - -- (NSArray*)multipleValues { - return [_multipleValuesDict objectForKey:kIASKValues]; -} - -- (NSArray*)multipleTitles { - return [_multipleValuesDict objectForKey:kIASKTitles]; -} - -- (NSString*)file { - return [_specifierDict objectForKey:kIASKFile]; -} - -- (id)defaultValue { - return [_specifierDict objectForKey:kIASKDefaultValue]; -} - -- (id)defaultStringValue { - return [[_specifierDict objectForKey:kIASKDefaultValue] description]; -} - -- (BOOL)defaultBoolValue { - id defaultValue = [self defaultValue]; - if ([defaultValue isEqual:[self trueValue]]) { - return YES; - } - if ([defaultValue isEqual:[self falseValue]]) { - return NO; - } - return [defaultValue boolValue]; -} - -- (id)trueValue { - return [_specifierDict objectForKey:kIASKTrueValue]; -} - -- (id)falseValue { - return [_specifierDict objectForKey:kIASKFalseValue]; -} - -- (float)minimumValue { - return [[_specifierDict objectForKey:kIASKMinimumValue] floatValue]; -} - -- (float)maximumValue { - return [[_specifierDict objectForKey:kIASKMaximumValue] floatValue]; -} - -- (NSString*)minimumValueImage { - return [_specifierDict objectForKey:kIASKMinimumValueImage]; -} - -- (NSString*)maximumValueImage { - return [_specifierDict objectForKey:kIASKMaximumValueImage]; -} - -- (BOOL)isSecure { - return [[_specifierDict objectForKey:kIASKIsSecure] boolValue]; -} - -- (UIKeyboardType)keyboardType { - if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardAlphabet]) { - return UIKeyboardTypeASCIICapable; - } - else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardNumbersAndPunctuation]) { - return UIKeyboardTypeNumbersAndPunctuation; - } - else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardNumberPad]) { - return UIKeyboardTypeNumberPad; - } - else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:KIASKKeyboardURL]) { - return UIKeyboardTypeURL; - } - else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardEmailAddress]) { - return UIKeyboardTypeEmailAddress; - } - return UIKeyboardTypeDefault; -} - -- (UITextAutocapitalizationType)autocapitalizationType { - if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapNone]) { - return UITextAutocapitalizationTypeNone; - } - else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapSentences]) { - return UITextAutocapitalizationTypeSentences; - } - else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapWords]) { - return UITextAutocapitalizationTypeWords; - } - else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapAllCharacters]) { - return UITextAutocapitalizationTypeAllCharacters; - } - return UITextAutocapitalizationTypeNone; -} - -- (UITextAutocorrectionType)autoCorrectionType { - if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrDefault]) { - return UITextAutocorrectionTypeDefault; - } - else if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrNo]) { - return UITextAutocorrectionTypeNo; - } - else if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrYes]) { - return UITextAutocorrectionTypeYes; - } - return UITextAutocorrectionTypeDefault; -} - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.h b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.h deleted file mode 100644 index 77e6a545f..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// IASKPSSliderSpecifierViewCell.h -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import - -@class IASKSlider; - -@interface IASKPSSliderSpecifierViewCell : UITableViewCell { - IBOutlet IASKSlider *_slider; - IBOutlet UIImageView *_minImage; - IBOutlet UIImageView *_maxImage; -} - -@property (nonatomic, readonly) IASKSlider *slider; -@property (nonatomic, readonly) UIImageView *minImage; -@property (nonatomic, readonly) UIImageView *maxImage; - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.m b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.m deleted file mode 100644 index 884ee8f44..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.m +++ /dev/null @@ -1,66 +0,0 @@ -// -// IASKPSSliderSpecifierViewCell.m -// http://www.inappsettingskit.com -// -// Copyright (c) 2009-2010: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import "IASKPSSliderSpecifierViewCell.h" -#import "IASKSlider.h" -#import "IASKSettingsReader.h" - -@implementation IASKPSSliderSpecifierViewCell - -@synthesize slider=_slider, - minImage=_minImage, - maxImage=_maxImage; - -- (void)layoutSubviews { - CGRect sliderFrame = _slider.frame; - sliderFrame.origin.x = kIASKSliderNoImagesX; - sliderFrame.size.width = kIASKSliderNoImagesWidth; - _minImage.hidden = YES; - _maxImage.hidden = YES; - - // Check if there are min and max images. If so, change the layout accordingly. - if (_minImage.image && _maxImage.image) { - // Both images - _minImage.hidden = NO; - _maxImage.hidden = NO; - sliderFrame.origin.x = kIASKSliderBothImagesX; - sliderFrame.size.width = kIASKSliderBothImagesWidth; - } - else if (_minImage.image) { - // Min image - _minImage.hidden = NO; - sliderFrame.origin.x = kIASKSliderBothImagesX; - sliderFrame.size.width = kIASKSliderOneImageWidth; - } - else if (_maxImage.image) { - // Max image - _maxImage.hidden = NO; - sliderFrame.origin.x = kIASKSliderNoImagesX; - sliderFrame.size.width = kIASKSliderOneImageWidth; - } - - _slider.frame = sliderFrame; -} - -- (void)dealloc { - [super dealloc]; -} - -- (void)prepareForReuse { - _minImage.image = nil; - _maxImage.image = nil; -} -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.h b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.h deleted file mode 100644 index b24fe5a34..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// IASKPSTextFieldSpecifierViewCell.h -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import - -@class IASKTextField; - -@interface IASKPSTextFieldSpecifierViewCell : UITableViewCell { - IBOutlet UILabel *_label; - IBOutlet IASKTextField *_textField; -} - -@property (nonatomic, readonly) UILabel *label; -@property (nonatomic, readonly) IASKTextField *textField; - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.m b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.m deleted file mode 100644 index 8a7a6a987..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.m +++ /dev/null @@ -1,51 +0,0 @@ -// -// IASKPSTextFieldSpecifierViewCell.m -// http://www.inappsettingskit.com -// -// Copyright (c) 2009-2010: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import "IASKPSTextFieldSpecifierViewCell.h" -#import "IASKTextField.h" -#import "IASKSettingsReader.h" - -@implementation IASKPSTextFieldSpecifierViewCell - -@synthesize label=_label, - textField=_textField; - -- (void)layoutSubviews { - CGSize labelSize = [_label sizeThatFits:CGSizeZero]; - labelSize.width = MIN(labelSize.width, _label.bounds.size.width); - - CGRect textFieldFrame = _textField.frame; - textFieldFrame.origin.x = _label.frame.origin.x + MAX(kIASKMinLabelWidth, labelSize.width) + kIASKSpacing; - if (!_label.text.length) - textFieldFrame.origin.x = _label.frame.origin.x; - textFieldFrame.size.width = kIASKTableWidth - textFieldFrame.origin.x - _label.frame.origin.x; - _textField.frame = textFieldFrame; -} - -- (void)setSelected:(BOOL)selected animated:(BOOL)animated { - - [super setSelected:selected animated:animated]; - - // Configure the view for the selected state -} - - -- (void)dealloc { - [super dealloc]; -} - - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTitleValueSpecifierViewCell.h b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTitleValueSpecifierViewCell.h deleted file mode 100644 index b3185b410..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTitleValueSpecifierViewCell.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// IASKPSTitleValueSpecifierViewCell.h -// http://www.inappsettingskit.com -// -// Copyright (c) 2010: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import - - -@interface IASKPSTitleValueSpecifierViewCell : UITableViewCell - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTitleValueSpecifierViewCell.m b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTitleValueSpecifierViewCell.m deleted file mode 100644 index cd6ba974a..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSTitleValueSpecifierViewCell.m +++ /dev/null @@ -1,54 +0,0 @@ -// -// IASKPSTitleValueSpecifierViewCell.m -// http://www.inappsettingskit.com -// -// Copyright (c) 2010: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import "IASKPSTitleValueSpecifierViewCell.h" -#import "IASKSettingsReader.h" - - -@implementation IASKPSTitleValueSpecifierViewCell - -- (void)layoutSubviews { - // left align the value if the title is empty - if (!self.textLabel.text.length) { - self.textLabel.text = self.detailTextLabel.text; - self.detailTextLabel.text = nil; - if ([self.reuseIdentifier isEqualToString:kIASKPSMultiValueSpecifier]) { - self.textLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]]; - self.textLabel.textColor = self.detailTextLabel.textColor; - } - } - [super layoutSubviews]; - - CGSize viewSize = [self.textLabel superview].frame.size; - - // set the left title label frame - CGFloat labelWidth = [self.textLabel sizeThatFits:CGSizeZero].width; - CGFloat minValueWidth = (self.detailTextLabel.text.length) ? kIASKMinValueWidth + kIASKSpacing : 0; - labelWidth = MIN(labelWidth, viewSize.width - minValueWidth - kIASKPaddingLeft -kIASKPaddingRight); - CGRect labelFrame = CGRectMake(kIASKPaddingLeft, 0, labelWidth, viewSize.height -2); - self.textLabel.frame = labelFrame; - - // set the right value label frame - if (self.detailTextLabel.text.length) { - CGRect valueFrame = CGRectMake(kIASKPaddingLeft + labelWidth + kIASKSpacing, - 0, - viewSize.width - (kIASKPaddingLeft + labelWidth + kIASKSpacing) - kIASKPaddingRight, - viewSize.height -2); - self.detailTextLabel.frame = valueFrame; - } -} - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSToggleSwitchSpecifierViewCell.h b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSToggleSwitchSpecifierViewCell.h deleted file mode 100644 index 25a83aa13..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSToggleSwitchSpecifierViewCell.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// IASKPSToggleSwitchSpecifierViewCell.h -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import - -@class IASKSwitch; - -@interface IASKPSToggleSwitchSpecifierViewCell : UITableViewCell { - IBOutlet UILabel *_label; - IBOutlet IASKSwitch *_toggle; -} - -@property (nonatomic, readonly) UILabel *label; -@property (nonatomic, readonly) IASKSwitch *toggle; - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSToggleSwitchSpecifierViewCell.m b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSToggleSwitchSpecifierViewCell.m deleted file mode 100644 index a4a5c0d01..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKPSToggleSwitchSpecifierViewCell.m +++ /dev/null @@ -1,46 +0,0 @@ -// -// IASKPSToggleSwitchSpecifierViewCell.m -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import "IASKPSToggleSwitchSpecifierViewCell.h" -#import "IASKSwitch.h" - -@implementation IASKPSToggleSwitchSpecifierViewCell - -@synthesize label=_label, - toggle=_toggle; - -- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { - if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { - // Initialization code - } - return self; -} - - -- (void)setSelected:(BOOL)selected animated:(BOOL)animated { - - [super setSelected:selected animated:animated]; - - // Configure the view for the selected state -} - - -- (void)dealloc { - [super dealloc]; -} - - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSlider.h b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSlider.h deleted file mode 100644 index 34c5ecbbe..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSlider.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// IASKSlider.h -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import - - -@interface IASKSlider : UISlider { - NSString *_key; -} - -@property (nonatomic, retain) NSString *key; - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSlider.m b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSlider.m deleted file mode 100644 index d729b8214..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSlider.m +++ /dev/null @@ -1,29 +0,0 @@ -// -// IASKSlider.m -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import "IASKSlider.h" - - -@implementation IASKSlider - -@synthesize key=_key; - -- (void)dealloc { - [_key release]; - [super dealloc]; -} - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSwitch.h b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSwitch.h deleted file mode 100644 index b1439bd1c..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSwitch.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// IASKSwitch.h -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import - - -@interface IASKSwitch : UISwitch { - NSString *_key; -} - -@property (nonatomic, retain) NSString *key; - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSwitch.m b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSwitch.m deleted file mode 100644 index 79d2d67ca..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKSwitch.m +++ /dev/null @@ -1,30 +0,0 @@ -// -// IASKSwitch.m -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import "IASKSwitch.h" - - -@implementation IASKSwitch - -@synthesize key=_key; - -- (void)dealloc { - [_key release]; - [super dealloc]; -} - - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKTextField.h b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKTextField.h deleted file mode 100644 index 47c9be375..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKTextField.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// IASKTextField.h -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import - - -@interface IASKTextField : UITextField { - NSString *_key; -} - -@property (nonatomic, retain) NSString *key; - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKTextField.m b/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKTextField.m deleted file mode 100644 index 8ee840e8f..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Views/IASKTextField.m +++ /dev/null @@ -1,29 +0,0 @@ -// -// IASKTextField.m -// http://www.inappsettingskit.com -// -// Copyright (c) 2009: -// Luc Vandal, Edovia Inc., http://www.edovia.com -// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com -// All rights reserved. -// -// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz, -// as the original authors of this code. You can give credit in a blog post, a tweet or on -// a info page of your app. Also, the original authors appreciate letting them know if you use this code. -// -// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php -// - -#import "IASKTextField.h" - - -@implementation IASKTextField - -@synthesize key=_key; - -- (void)dealloc { - [_key release]; - [super dealloc]; -} - -@end diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKAppSettingsView.xib b/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKAppSettingsView.xib deleted file mode 100644 index 898546830..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKAppSettingsView.xib +++ /dev/null @@ -1,460 +0,0 @@ - - - - 768 - 10F569 - 788 - 1038.29 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 117 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 276 - - YES - - - 274 - {320, 460} - - - 10 - - 549453824 - {84, 1} - - YES - - YES - - - - TU0AKgAAAVjFzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/ -y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/ -xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/ -xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/ -xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/ -xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P8ADQEAAAMAAAABAFQAAAEB -AAMAAAABAAEAAAECAAMAAAAEAAAB+gEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES -AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABAAEAAAEXAAQAAAABAAABUAEcAAMAAAABAAEAAAFS -AAMAAAABAAEAAAFTAAMAAAAEAAACAgAAAAAACAAIAAgACAABAAEAAQABA - - - - - - 3 - MCAwAA - - - groupTableViewBackgroundColor - - NO - YES - NO - IBCocoaTouchFramework - NO - 1 - 1 - 0 - YES - 44 - 10 - 10 - - - {320, 460} - - - 3 - MQA - - IBCocoaTouchFramework - - - - - YES - - - view - - - - 3 - - - - _tableView - - - - 5 - - - - dataSource - - - - 6 - - - - delegate - - - - 7 - - - - - YES - - 0 - - - - - - 1 - - - YES - - - - - - -1 - - - File's Owner - - - -2 - - - - - 4 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 1.IBEditorWindowLastContentRect - 1.IBPluginDependency - 4.IBPluginDependency - - - YES - IASKAppSettingsViewController - UIResponder - {{549, 492}, {320, 460}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - YES - - - - - YES - - - YES - - - - 7 - - - - YES - - IASKAppSettingsViewController - UIViewController - - dismiss: - id - - - dismiss: - - dismiss: - id - - - - _tableView - UITableView - - - _tableView - - _tableView - UITableView - - - - IBProjectSource - ../InAppSettingsKit/Controllers/IASKAppSettingsViewController.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSNetServices.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPort.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSStream.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSXMLParser.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIResponder - NSObject - - - - UIScrollView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIScrollView.h - - - - UISearchBar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h - - - - UISearchDisplayController - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h - - - - UITableView - UIScrollView - - IBFrameworkSource - UIKit.framework/Headers/UITableView.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIViewController.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - ../InAppSettingsKitSampleApp.xcodeproj - 3 - 117 - - diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKPSSliderSpecifierViewCell.xib b/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKPSSliderSpecifierViewCell.xib deleted file mode 100644 index a221fd24c..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKPSSliderSpecifierViewCell.xib +++ /dev/null @@ -1,449 +0,0 @@ - - - - 768 - 10C540 - 740 - 1038.25 - 458.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 62 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - 290 - - YES - - - 256 - - YES - - - 290 - {{52, 12}, {216, 23}} - - NO - YES - YES - 0 - 0 - 0.5 - - - - 289 - {{278, 13}, {21, 21}} - - NO - NO - 4 - NO - - - - 292 - {{21, 13}, {21, 21}} - - NO - NO - 4 - NO - - - {320, 43} - - - 3 - MCAwAA - - NO - YES - 4 - YES - - - {320, 44} - - - 1 - MSAxIDEAA - - YES - NO - 1 - - PSSliderSpecifier - - - - - YES - - - _slider - - - - 4 - - - - _maxImage - - - - 8 - - - - _minImage - - - - 10 - - - - - YES - - 0 - - - - - - -1 - - - File's Owner - - - -2 - - - - - 2 - - - YES - - - - - - - - 3 - - - - - 6 - - - - - 9 - - - - - - - YES - - YES - -2.CustomClassName - 2.CustomClassName - 2.IBEditorWindowLastContentRect - 2.IBPluginDependency - 3.CustomClassName - 3.IBPluginDependency - 6.IBPluginDependency - 9.IBPluginDependency - - - YES - UIResponder - IASKPSSliderSpecifierViewCell - {{171, 925}, {320, 44}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - IASKSlider - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - YES - - - - - YES - - - YES - - - - 10 - - - - YES - - IASKPSSliderSpecifierViewCell - UITableViewCell - - YES - - YES - _maxImage - _minImage - _slider - - - YES - UIImageView - UIImageView - IASKSlider - - - - IBProjectSource - ../InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.h - - - - IASKSlider - UISlider - - IBProjectSource - ../InAppSettingsKit/Views/IASKSlider.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSNetServices.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPort.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSStream.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSXMLParser.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIControl - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIControl.h - - - - UIImageView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIImageView.h - - - - UIResponder - NSObject - - - - UISlider - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UISlider.h - - - - UITableViewCell - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITableViewCell.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - - 0 - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - ../InAppSettingsKitSampleApp.xcodeproj - 3 - 3.1 - - diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKPSTextFieldSpecifierViewCell.xib b/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKPSTextFieldSpecifierViewCell.xib deleted file mode 100644 index 755dc3762..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKPSTextFieldSpecifierViewCell.xib +++ /dev/null @@ -1,469 +0,0 @@ - - - - 1024 - 10F569 - 788 - 1038.29 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 117 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 290 - - YES - - - 256 - - YES - - - 294 - {{19, 11}, {240, 21}} - - NO - YES - NO - IBCocoaTouchFramework - Label - - Helvetica-Bold - 17 - 16 - - - 1 - MCAwIDAAA - - - 1 - 10 - - - - 291 - {{100, 11}, {201, 21}} - - NO - NO - IBCocoaTouchFramework - hello - - 1 - MC4yNzQ1MDk4MiAwLjM3NjQ3MDYgMC41MjE1Njg2NgA - - - Helvetica - 17 - 16 - - 2 - YES - 10 - - IBCocoaTouchFramework - - - - {320, 44} - - - 3 - MCAwAA - - NO - YES - 4 - YES - IBCocoaTouchFramework - - - {320, 44} - - - 1 - MSAxIDEAA - - YES - NO - IBCocoaTouchFramework - 1 - 0 - - PSTextFieldSpecifier - - - - - YES - - - _label - - - - 5 - - - - _textField - - - - 6 - - - - - YES - - 0 - - - - - - -1 - - - File's Owner - - - -2 - - - - - 2 - - - YES - - - - - - - 3 - - - - - 4 - - - - - - - YES - - YES - -2.CustomClassName - 2.CustomClassName - 2.IBEditorWindowLastContentRect - 2.IBPluginDependency - 3.IBPluginDependency - 4.CustomClassName - 4.IBPluginDependency - - - YES - UIResponder - IASKPSTextFieldSpecifierViewCell - {{105, 513}, {320, 44}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - IASKTextField - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - YES - - - - - YES - - - YES - - - - 7 - - - - YES - - IASKPSTextFieldSpecifierViewCell - UITableViewCell - - YES - - YES - _label - _textField - - - YES - UILabel - IASKTextField - - - - YES - - YES - _label - _textField - - - YES - - _label - UILabel - - - _textField - IASKTextField - - - - - IBProjectSource - ../InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.h - - - - IASKTextField - UITextField - - IBProjectSource - ../InAppSettingsKit/Views/IASKTextField.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSNetServices.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPort.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSStream.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSXMLParser.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIControl - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIControl.h - - - - UILabel - UIView - - IBFrameworkSource - UIKit.framework/Headers/UILabel.h - - - - UIResponder - NSObject - - - - UITableViewCell - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITableViewCell.h - - - - UITextField - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - ../InAppSettingsKitSampleApp.xcodeproj - 3 - 117 - - diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKPSToggleSwitchSpecifierViewCell.xib b/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKPSToggleSwitchSpecifierViewCell.xib deleted file mode 100644 index f59e3ade3..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKPSToggleSwitchSpecifierViewCell.xib +++ /dev/null @@ -1,434 +0,0 @@ - - - - 768 - 10C540 - 740 - 1038.25 - 458.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 62 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - 290 - - YES - - - 256 - - YES - - - 294 - {{9, 10}, {200, 21}} - - NO - YES - NO - Label - - Helvetica-Bold - 17 - 16 - - - 1 - MCAwIDAAA - - - 1 - 10 - - - - 289 - {{218, 8}, {94, 27}} - - NO - YES - YES - 0 - 0 - YES - - - {320, 43} - - - 3 - MCAwAA - - NO - YES - 4 - YES - - - {320, 44} - - - 1 - MSAxIDEAA - - YES - NO - 1 - 0 - - PSToggleSwitchSpecifier - - - - - YES - - - _label - - - - 5 - - - - _toggle - - - - 7 - - - - - YES - - 0 - - - - - - -1 - - - File's Owner - - - -2 - - - - - 2 - - - YES - - - - - - - 3 - - - - - 4 - - - - - - - YES - - YES - -2.CustomClassName - 2.CustomClassName - 2.IBEditorWindowLastContentRect - 2.IBPluginDependency - 3.IBPluginDependency - 4.CustomClassName - 4.IBPluginDependency - - - YES - UIResponder - IASKPSToggleSwitchSpecifierViewCell - {{1676, 1200}, {320, 44}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - IASKSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - YES - - - - - YES - - - YES - - - - 7 - - - - YES - - IASKPSToggleSwitchSpecifierViewCell - UITableViewCell - - YES - - YES - _label - _toggle - - - YES - UILabel - IASKSwitch - - - - IBProjectSource - ../InAppSettingsKit/Views/IASKPSToggleSwitchSpecifierViewCell.h - - - - IASKSwitch - UISwitch - - IBProjectSource - ../InAppSettingsKit/Views/IASKSwitch.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSNetServices.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPort.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSStream.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSXMLParser.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIControl - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIControl.h - - - - UILabel - UIView - - IBFrameworkSource - UIKit.framework/Headers/UILabel.h - - - - UIResponder - NSObject - - - - UISwitch - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UISwitch.h - - - - UITableViewCell - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITableViewCell.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - - 0 - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - ../InAppSettingsKitSampleApp.xcodeproj - 3 - 3.1 - - diff --git a/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKSpecifierValuesView.xib b/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKSpecifierValuesView.xib deleted file mode 100644 index 3046a184c..000000000 --- a/mods/atsocial_iphone_app/InAppSettingsKit/Xibs/IASKSpecifierValuesView.xib +++ /dev/null @@ -1,408 +0,0 @@ - - - - 768 - 10B504 - 732 - 1038.2 - 437.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 62 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - - - IBFirstResponder - - - - 292 - - YES - - - 274 - {320, 460} - - NO - YES - NO - NO - 1 - 1 - 0 - YES - 44 - 10 - 10 - - - {320, 460} - - - 3 - MQA - - 2 - - - - - - - YES - - - view - - - - 3 - - - - dataSource - - - - 5 - - - - delegate - - - - 6 - - - - _tableView - - - - 7 - - - - - YES - - 0 - - - - - - 1 - - - YES - - - - - - -1 - - - File's Owner - - - -2 - - - - - 4 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 1.IBEditorWindowLastContentRect - 1.IBPluginDependency - 4.IBPluginDependency - - - YES - IASKSpecifierValuesViewController - UIResponder - {{556, 432}, {320, 460}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - YES - - - - - YES - - - YES - - - - 7 - - - - YES - - IASKSpecifierValuesViewController - UIViewController - - _tableView - UITableView - - - IBProjectSource - IASKSpecifierValuesViewController.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSNetServices.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPort.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSStream.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSXMLParser.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIResponder - NSObject - - - - UIScrollView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIScrollView.h - - - - UISearchBar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h - - - - UISearchDisplayController - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h - - - - UITableView - UIScrollView - - IBFrameworkSource - UIKit.framework/Headers/UITableView.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIViewController.h - - - - - 0 - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - TouchPad.xcodeproj - 3 - 3.1 - - diff --git a/mods/atsocial_iphone_app/KeychainUtils/SFHFKeychainUtils.h b/mods/atsocial_iphone_app/KeychainUtils/SFHFKeychainUtils.h deleted file mode 100755 index e24d7116f..000000000 --- a/mods/atsocial_iphone_app/KeychainUtils/SFHFKeychainUtils.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// SFHFKeychainUtils.h -// -// Created by Buzz Andersen on 10/20/08. -// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone. -// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved. -// -// 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. -// - -#import - - -@interface SFHFKeychainUtils : NSObject { - -} - -+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error; -+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error; -+ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error; - -@end \ No newline at end of file diff --git a/mods/atsocial_iphone_app/KeychainUtils/SFHFKeychainUtils.m b/mods/atsocial_iphone_app/KeychainUtils/SFHFKeychainUtils.m deleted file mode 100755 index d9d7253ef..000000000 --- a/mods/atsocial_iphone_app/KeychainUtils/SFHFKeychainUtils.m +++ /dev/null @@ -1,390 +0,0 @@ -// -// SFHFKeychainUtils.m -// -// Created by Buzz Andersen on 10/20/08. -// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone. -// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved. -// -// 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. -// - -#import "SFHFKeychainUtils.h" -#import - -static NSString *SFHFKeychainUtilsErrorDomain = @"SFHFKeychainUtilsErrorDomain"; - -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR -@interface SFHFKeychainUtils (PrivateMethods) -+ (SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error; -@end -#endif - -@implementation SFHFKeychainUtils - -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR - -+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { - if (!username || !serviceName) { - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; - return nil; - } - - SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error]; - - if (*error || !item) { - return nil; - } - - // from Advanced Mac OS X Programming, ch. 16 - UInt32 length; - char *password; - SecKeychainAttribute attributes[8]; - SecKeychainAttributeList list; - - attributes[0].tag = kSecAccountItemAttr; - attributes[1].tag = kSecDescriptionItemAttr; - attributes[2].tag = kSecLabelItemAttr; - attributes[3].tag = kSecModDateItemAttr; - - list.count = 4; - list.attr = attributes; - - OSStatus status = SecKeychainItemCopyContent(item, NULL, &list, &length, (void **)&password); - - if (status != noErr) { - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; - return nil; - } - - NSString *passwordString = nil; - - if (password != NULL) { - char passwordBuffer[1024]; - - if (length > 1023) { - length = 1023; - } - strncpy(passwordBuffer, password, length); - - passwordBuffer[length] = '\0'; - passwordString = [NSString stringWithCString:passwordBuffer]; - } - - SecKeychainItemFreeContent(&list, password); - - CFRelease(item); - - return passwordString; -} - -+ (void) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error { - if (!username || !password || !serviceName) { - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; - return; - } - - OSStatus status = noErr; - - SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error]; - - if (*error && [*error code] != noErr) { - return; - } - - *error = nil; - - if (item) { - status = SecKeychainItemModifyAttributesAndData(item, - NULL, - strlen([password UTF8String]), - [password UTF8String]); - - CFRelease(item); - } - else { - status = SecKeychainAddGenericPassword(NULL, - strlen([serviceName UTF8String]), - [serviceName UTF8String], - strlen([username UTF8String]), - [username UTF8String], - strlen([password UTF8String]), - [password UTF8String], - NULL); - } - - if (status != noErr) { - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; - } -} - -+ (void) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { - if (!username || !serviceName) { - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: 2000 userInfo: nil]; - return; - } - - *error = nil; - - SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error]; - - if (*error && [*error code] != noErr) { - return; - } - - OSStatus status; - - if (item) { - status = SecKeychainItemDelete(item); - - CFRelease(item); - } - - if (status != noErr) { - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; - } -} - -+ (SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { - if (!username || !serviceName) { - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; - return nil; - } - - *error = nil; - - SecKeychainItemRef item; - - OSStatus status = SecKeychainFindGenericPassword(NULL, - strlen([serviceName UTF8String]), - [serviceName UTF8String], - strlen([username UTF8String]), - [username UTF8String], - NULL, - NULL, - &item); - - if (status != noErr) { - if (status != errSecItemNotFound) { - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; - } - - return nil; - } - - return item; -} - -#else - -+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { - if (!username || !serviceName) { - if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; - return nil; - } - - if (error) *error = nil; - - // Set up a query dictionary with the base query attributes: item type (generic), username, and service - - NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrService, nil] autorelease]; - NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, username, serviceName, nil] autorelease]; - - NSMutableDictionary *query = [[[NSMutableDictionary alloc] initWithObjects: objects forKeys: keys] autorelease]; - - // First do a query for attributes, in case we already have a Keychain item with no password data set. - // One likely way such an incorrect item could have come about is due to the previous (incorrect) - // version of this code (which set the password as a generic attribute instead of password data). - - NSDictionary *attributeResult = NULL; - NSMutableDictionary *attributeQuery = [query mutableCopy]; - [attributeQuery setObject: (id) kCFBooleanTrue forKey:(id) kSecReturnAttributes]; - OSStatus status = SecItemCopyMatching((CFDictionaryRef) attributeQuery, (CFTypeRef *) &attributeResult); - - [attributeResult release]; - [attributeQuery release]; - - if (status != noErr) { - // No existing item found--simply return nil for the password - if (status != errSecItemNotFound) { - //Only return an error if a real exception happened--not simply for "not found." - if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; - } - - return nil; - } - - // We have an existing item, now query for the password data associated with it. - - NSData *resultData = nil; - NSMutableDictionary *passwordQuery = [query mutableCopy]; - [passwordQuery setObject: (id) kCFBooleanTrue forKey: (id) kSecReturnData]; - - status = SecItemCopyMatching((CFDictionaryRef) passwordQuery, (CFTypeRef *) &resultData); - - [resultData autorelease]; - [passwordQuery release]; - - if (status != noErr) { - if (status == errSecItemNotFound) { - // We found attributes for the item previously, but no password now, so return a special error. - // Users of this API will probably want to detect this error and prompt the user to - // re-enter their credentials. When you attempt to store the re-entered credentials - // using storeUsername:andPassword:forServiceName:updateExisting:error - // the old, incorrect entry will be deleted and a new one with a properly encrypted - // password will be added. - if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil]; - } - else { - // Something else went wrong. Simply return the normal Keychain API error code. - if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; - } - - return nil; - } - - NSString *password = nil; - - if (resultData) { - password = [[NSString alloc] initWithData: resultData encoding: NSUTF8StringEncoding]; - } - else { - // There is an existing item, but we weren't able to get password data for it for some reason, - // Possibly as a result of an item being incorrectly entered by the previous code. - // Set the -1999 error so the code above us can prompt the user again. - if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil]; - } - - return [password autorelease]; -} - -+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error { - if (!username || !password || !serviceName) { - if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; - return NO; - } - - // See if we already have a password entered for these credentials. - NSError *checkPasswordError = nil; - NSString *existingPassword = [SFHFKeychainUtils getPasswordForUsername: username andServiceName: serviceName error: &checkPasswordError]; - - if ([checkPasswordError code] == -1999) { - // There is an existing entry without a password properly stored (possibly as a result of the previous incorrect version of this code. - // Delete the existing item before moving on entering a correct one. - - NSError *deleteError = nil; - - [self deleteItemForUsername: username andServiceName: serviceName error: &deleteError]; - - if ([deleteError code] != noErr) { - if (error) *error = deleteError; - return NO; - } - } - else if ([checkPasswordError code] != noErr) { - if (error) *error = checkPasswordError; - return NO; - } - - if (error) *error = nil; - - OSStatus status = noErr; - - if (existingPassword) { - // We have an existing, properly entered item with a password. - // Update the existing item. - - if (![existingPassword isEqualToString:password] && updateExisting) { - //Only update if we're allowed to update existing. If not, simply do nothing. - - NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, - kSecAttrService, - kSecAttrLabel, - kSecAttrAccount, - nil] autorelease]; - - NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, - serviceName, - serviceName, - username, - nil] autorelease]; - - NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease]; - - status = SecItemUpdate((CFDictionaryRef) query, (CFDictionaryRef) [NSDictionary dictionaryWithObject: [password dataUsingEncoding: NSUTF8StringEncoding] forKey: (NSString *) kSecValueData]); - } - } - else { - // No existing entry (or an existing, improperly entered, and therefore now - // deleted, entry). Create a new entry. - - NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, - kSecAttrService, - kSecAttrLabel, - kSecAttrAccount, - kSecValueData, - nil] autorelease]; - - NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, - serviceName, - serviceName, - username, - [password dataUsingEncoding: NSUTF8StringEncoding], - nil] autorelease]; - - NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease]; - - status = SecItemAdd((CFDictionaryRef) query, NULL); - } - - if (status != noErr) { - // Something went wrong with adding the new item. Return the Keychain error code. - if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; - return NO; - } - return YES; -} - -+ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { - if (!username || !serviceName) { - if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; - return NO; - } - - if (error) *error = nil; - - NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrService, kSecReturnAttributes, nil] autorelease]; - NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, username, serviceName, kCFBooleanTrue, nil] autorelease]; - - NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease]; - - OSStatus status = SecItemDelete((CFDictionaryRef) query); - - if (status != noErr) { - if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; - return NO; - } - return YES; -} - -#endif - -@end \ No newline at end of file diff --git a/mods/atsocial_iphone_app/OAuth/Crypto/Base64Transcoder.c b/mods/atsocial_iphone_app/OAuth/Crypto/Base64Transcoder.c deleted file mode 100644 index a655581e9..000000000 --- a/mods/atsocial_iphone_app/OAuth/Crypto/Base64Transcoder.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Base64Transcoder.c - * Base64Test - * - * Created by Jonathan Wight on Tue Mar 18 2003. - * Copyright (c) 2003 Toxic Software. All rights reserved. - * - * 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. - * - */ - -#include "Base64Transcoder.h" - -#include -#include - -const u_int8_t kBase64EncodeTable[64] = { - /* 0 */ 'A', /* 1 */ 'B', /* 2 */ 'C', /* 3 */ 'D', - /* 4 */ 'E', /* 5 */ 'F', /* 6 */ 'G', /* 7 */ 'H', - /* 8 */ 'I', /* 9 */ 'J', /* 10 */ 'K', /* 11 */ 'L', - /* 12 */ 'M', /* 13 */ 'N', /* 14 */ 'O', /* 15 */ 'P', - /* 16 */ 'Q', /* 17 */ 'R', /* 18 */ 'S', /* 19 */ 'T', - /* 20 */ 'U', /* 21 */ 'V', /* 22 */ 'W', /* 23 */ 'X', - /* 24 */ 'Y', /* 25 */ 'Z', /* 26 */ 'a', /* 27 */ 'b', - /* 28 */ 'c', /* 29 */ 'd', /* 30 */ 'e', /* 31 */ 'f', - /* 32 */ 'g', /* 33 */ 'h', /* 34 */ 'i', /* 35 */ 'j', - /* 36 */ 'k', /* 37 */ 'l', /* 38 */ 'm', /* 39 */ 'n', - /* 40 */ 'o', /* 41 */ 'p', /* 42 */ 'q', /* 43 */ 'r', - /* 44 */ 's', /* 45 */ 't', /* 46 */ 'u', /* 47 */ 'v', - /* 48 */ 'w', /* 49 */ 'x', /* 50 */ 'y', /* 51 */ 'z', - /* 52 */ '0', /* 53 */ '1', /* 54 */ '2', /* 55 */ '3', - /* 56 */ '4', /* 57 */ '5', /* 58 */ '6', /* 59 */ '7', - /* 60 */ '8', /* 61 */ '9', /* 62 */ '+', /* 63 */ '/' -}; - -/* --1 = Base64 end of data marker. --2 = White space (tabs, cr, lf, space) --3 = Noise (all non whitespace, non-base64 characters) --4 = Dangerous noise --5 = Illegal noise (null byte) -*/ - -const int8_t kBase64DecodeTable[128] = { - /* 0x00 */ -5, /* 0x01 */ -3, /* 0x02 */ -3, /* 0x03 */ -3, - /* 0x04 */ -3, /* 0x05 */ -3, /* 0x06 */ -3, /* 0x07 */ -3, - /* 0x08 */ -3, /* 0x09 */ -2, /* 0x0a */ -2, /* 0x0b */ -2, - /* 0x0c */ -2, /* 0x0d */ -2, /* 0x0e */ -3, /* 0x0f */ -3, - /* 0x10 */ -3, /* 0x11 */ -3, /* 0x12 */ -3, /* 0x13 */ -3, - /* 0x14 */ -3, /* 0x15 */ -3, /* 0x16 */ -3, /* 0x17 */ -3, - /* 0x18 */ -3, /* 0x19 */ -3, /* 0x1a */ -3, /* 0x1b */ -3, - /* 0x1c */ -3, /* 0x1d */ -3, /* 0x1e */ -3, /* 0x1f */ -3, - /* ' ' */ -2, /* '!' */ -3, /* '"' */ -3, /* '#' */ -3, - /* '$' */ -3, /* '%' */ -3, /* '&' */ -3, /* ''' */ -3, - /* '(' */ -3, /* ')' */ -3, /* '*' */ -3, /* '+' */ 62, - /* ',' */ -3, /* '-' */ -3, /* '.' */ -3, /* '/' */ 63, - /* '0' */ 52, /* '1' */ 53, /* '2' */ 54, /* '3' */ 55, - /* '4' */ 56, /* '5' */ 57, /* '6' */ 58, /* '7' */ 59, - /* '8' */ 60, /* '9' */ 61, /* ':' */ -3, /* ';' */ -3, - /* '<' */ -3, /* '=' */ -1, /* '>' */ -3, /* '?' */ -3, - /* '@' */ -3, /* 'A' */ 0, /* 'B' */ 1, /* 'C' */ 2, - /* 'D' */ 3, /* 'E' */ 4, /* 'F' */ 5, /* 'G' */ 6, - /* 'H' */ 7, /* 'I' */ 8, /* 'J' */ 9, /* 'K' */ 10, - /* 'L' */ 11, /* 'M' */ 12, /* 'N' */ 13, /* 'O' */ 14, - /* 'P' */ 15, /* 'Q' */ 16, /* 'R' */ 17, /* 'S' */ 18, - /* 'T' */ 19, /* 'U' */ 20, /* 'V' */ 21, /* 'W' */ 22, - /* 'X' */ 23, /* 'Y' */ 24, /* 'Z' */ 25, /* '[' */ -3, - /* '\' */ -3, /* ']' */ -3, /* '^' */ -3, /* '_' */ -3, - /* '`' */ -3, /* 'a' */ 26, /* 'b' */ 27, /* 'c' */ 28, - /* 'd' */ 29, /* 'e' */ 30, /* 'f' */ 31, /* 'g' */ 32, - /* 'h' */ 33, /* 'i' */ 34, /* 'j' */ 35, /* 'k' */ 36, - /* 'l' */ 37, /* 'm' */ 38, /* 'n' */ 39, /* 'o' */ 40, - /* 'p' */ 41, /* 'q' */ 42, /* 'r' */ 43, /* 's' */ 44, - /* 't' */ 45, /* 'u' */ 46, /* 'v' */ 47, /* 'w' */ 48, - /* 'x' */ 49, /* 'y' */ 50, /* 'z' */ 51, /* '{' */ -3, - /* '|' */ -3, /* '}' */ -3, /* '~' */ -3, /* 0x7f */ -3 -}; - -const u_int8_t kBits_00000011 = 0x03; -const u_int8_t kBits_00001111 = 0x0F; -const u_int8_t kBits_00110000 = 0x30; -const u_int8_t kBits_00111100 = 0x3C; -const u_int8_t kBits_00111111 = 0x3F; -const u_int8_t kBits_11000000 = 0xC0; -const u_int8_t kBits_11110000 = 0xF0; -const u_int8_t kBits_11111100 = 0xFC; - -size_t EstimateBas64EncodedDataSize(size_t inDataSize) -{ -size_t theEncodedDataSize = (int)ceil(inDataSize / 3.0) * 4; -theEncodedDataSize = theEncodedDataSize / 72 * 74 + theEncodedDataSize % 72; -return(theEncodedDataSize); -} - -size_t EstimateBas64DecodedDataSize(size_t inDataSize) -{ -size_t theDecodedDataSize = (int)ceil(inDataSize / 4.0) * 3; -//theDecodedDataSize = theDecodedDataSize / 72 * 74 + theDecodedDataSize % 72; -return(theDecodedDataSize); -} - -bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize) -{ -size_t theEncodedDataSize = EstimateBas64EncodedDataSize(inInputDataSize); -if (*ioOutputDataSize < theEncodedDataSize) - return(false); -*ioOutputDataSize = theEncodedDataSize; -const u_int8_t *theInPtr = (const u_int8_t *)inInputData; -u_int32_t theInIndex = 0, theOutIndex = 0; -for (; theInIndex < (inInputDataSize / 3) * 3; theInIndex += 3) - { - outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2]; - outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4]; - outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (theInPtr[theInIndex + 2] & kBits_11000000) >> 6]; - outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 2] & kBits_00111111) >> 0]; - if (theOutIndex % 74 == 72) - { - outOutputData[theOutIndex++] = '\r'; - outOutputData[theOutIndex++] = '\n'; - } - } -const size_t theRemainingBytes = inInputDataSize - theInIndex; -if (theRemainingBytes == 1) - { - outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2]; - outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (0 & kBits_11110000) >> 4]; - outOutputData[theOutIndex++] = '='; - outOutputData[theOutIndex++] = '='; - if (theOutIndex % 74 == 72) - { - outOutputData[theOutIndex++] = '\r'; - outOutputData[theOutIndex++] = '\n'; - } - } -else if (theRemainingBytes == 2) - { - outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2]; - outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4]; - outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (0 & kBits_11000000) >> 6]; - outOutputData[theOutIndex++] = '='; - if (theOutIndex % 74 == 72) - { - outOutputData[theOutIndex++] = '\r'; - outOutputData[theOutIndex++] = '\n'; - } - } -return(true); -} - -bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t *ioOutputDataSize) -{ -memset(ioOutputData, '.', *ioOutputDataSize); - -size_t theDecodedDataSize = EstimateBas64DecodedDataSize(inInputDataSize); -if (*ioOutputDataSize < theDecodedDataSize) - return(false); -*ioOutputDataSize = 0; -const u_int8_t *theInPtr = (const u_int8_t *)inInputData; -u_int8_t *theOutPtr = (u_int8_t *)ioOutputData; -size_t theInIndex = 0, theOutIndex = 0; -u_int8_t theOutputOctet; -size_t theSequence = 0; -for (; theInIndex < inInputDataSize; ) - { - int8_t theSextet = 0; - - int8_t theCurrentInputOctet = theInPtr[theInIndex]; - theSextet = kBase64DecodeTable[theCurrentInputOctet]; - if (theSextet == -1) - break; - while (theSextet == -2) - { - theCurrentInputOctet = theInPtr[++theInIndex]; - theSextet = kBase64DecodeTable[theCurrentInputOctet]; - } - while (theSextet == -3) - { - theCurrentInputOctet = theInPtr[++theInIndex]; - theSextet = kBase64DecodeTable[theCurrentInputOctet]; - } - if (theSequence == 0) - { - theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 2 & kBits_11111100; - } - else if (theSequence == 1) - { - theOutputOctet |= (theSextet >- 0 ? theSextet : 0) >> 4 & kBits_00000011; - theOutPtr[theOutIndex++] = theOutputOctet; - } - else if (theSequence == 2) - { - theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 4 & kBits_11110000; - } - else if (theSequence == 3) - { - theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 2 & kBits_00001111; - theOutPtr[theOutIndex++] = theOutputOctet; - } - else if (theSequence == 4) - { - theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 6 & kBits_11000000; - } - else if (theSequence == 5) - { - theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 0 & kBits_00111111; - theOutPtr[theOutIndex++] = theOutputOctet; - } - theSequence = (theSequence + 1) % 6; - if (theSequence != 2 && theSequence != 4) - theInIndex++; - } -*ioOutputDataSize = theOutIndex; -return(true); -} diff --git a/mods/atsocial_iphone_app/OAuth/Crypto/Base64Transcoder.h b/mods/atsocial_iphone_app/OAuth/Crypto/Base64Transcoder.h deleted file mode 100644 index 875209898..000000000 --- a/mods/atsocial_iphone_app/OAuth/Crypto/Base64Transcoder.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Base64Transcoder.h - * Base64Test - * - * Created by Jonathan Wight on Tue Mar 18 2003. - * Copyright (c) 2003 Toxic Software. All rights reserved. - * - * 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. - * - */ - -#include -#include - -extern size_t EstimateBas64EncodedDataSize(size_t inDataSize); -extern size_t EstimateBas64DecodedDataSize(size_t inDataSize); - -extern bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize); -extern bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t *ioOutputDataSize); - diff --git a/mods/atsocial_iphone_app/OAuth/Crypto/hmac.c b/mods/atsocial_iphone_app/OAuth/Crypto/hmac.c deleted file mode 100644 index eea9a7075..000000000 --- a/mods/atsocial_iphone_app/OAuth/Crypto/hmac.c +++ /dev/null @@ -1,86 +0,0 @@ -// -// hmac.c -// OAuthConsumer -// -// Created by Jonathan Wight on 4/8/8. -// Copyright 2008 Jonathan Wight. All rights reserved. -// -// 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. - -/* - * Implementation of HMAC-SHA1. Adapted from example at http://tools.ietf.org/html/rfc2104 - - */ - -#include "sha1.h" - -#include -#include - -void hmac_sha1(const unsigned char *inText, size_t inTextLength, unsigned char* inKey, size_t inKeyLength, unsigned char *outDigest) -{ -const size_t B = 64; -const size_t L = 20; - -SHA1_CTX theSHA1Context; -unsigned char k_ipad[B + 1]; /* inner padding - key XORd with ipad */ -unsigned char k_opad[B + 1]; /* outer padding - key XORd with opad */ - -/* if key is longer than 64 bytes reset it to key=SHA1 (key) */ -if (inKeyLength > B) - { - SHA1Init(&theSHA1Context); - SHA1Update(&theSHA1Context, inKey, inKeyLength); - SHA1Final(inKey, &theSHA1Context); - inKeyLength = L; - } - -/* start out by storing key in pads */ -memset(k_ipad, 0, sizeof k_ipad); -memset(k_opad, 0, sizeof k_opad); -memcpy(k_ipad, inKey, inKeyLength); -memcpy(k_opad, inKey, inKeyLength); - -/* XOR key with ipad and opad values */ -int i; -for (i = 0; i < B; i++) - { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - -/* -* perform inner SHA1 -*/ -SHA1Init(&theSHA1Context); /* init context for 1st pass */ -SHA1Update(&theSHA1Context, k_ipad, B); /* start with inner pad */ -SHA1Update(&theSHA1Context, (unsigned char *)inText, inTextLength); /* then text of datagram */ -SHA1Final((unsigned char *)outDigest, &theSHA1Context); /* finish up 1st pass */ - -/* -* perform outer SHA1 -*/ -SHA1Init(&theSHA1Context); /* init context for 2nd -* pass */ -SHA1Update(&theSHA1Context, k_opad, B); /* start with outer pad */ -SHA1Update(&theSHA1Context, outDigest, L); /* then results of 1st -* hash */ -SHA1Final(outDigest, &theSHA1Context); /* finish up 2nd pass */ - -} \ No newline at end of file diff --git a/mods/atsocial_iphone_app/OAuth/Crypto/hmac.h b/mods/atsocial_iphone_app/OAuth/Crypto/hmac.h deleted file mode 100644 index 51eca9f61..000000000 --- a/mods/atsocial_iphone_app/OAuth/Crypto/hmac.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// hmac.h -// OAuthConsumer -// -// Created by Jonathan Wight on 4/8/8. -// Copyright 2008 Jonathan Wight. All rights reserved. -// -// 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. - -#ifndef HMAC_H -#define HMAC_H 1 - -extern void hmac_sha1(const unsigned char *inText, int inTextLength, unsigned char* inKey, const unsigned int inKeyLength, unsigned char *outDigest); - -#endif /* HMAC_H */ \ No newline at end of file diff --git a/mods/atsocial_iphone_app/OAuth/Crypto/sha1.c b/mods/atsocial_iphone_app/OAuth/Crypto/sha1.c deleted file mode 100644 index 16f5dbcfa..000000000 --- a/mods/atsocial_iphone_app/OAuth/Crypto/sha1.c +++ /dev/null @@ -1,169 +0,0 @@ -/* -SHA-1 in C -By Steve Reid -100% Public Domain - -Test Vectors (from FIPS PUB 180-1) -"abc" - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D -"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 -A million repetitions of "a" - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F -*/ - -/* #define LITTLE_ENDIAN * This should be #define'd if true. */ -#if __LITTLE_ENDIAN__ -#define LITTLE_ENDIAN -#endif -/* #define SHA1HANDSOFF * Copies data before messing with it. */ - -#include -#include - -#include "sha1.h" - -void SHA1Transform(unsigned long state[5], unsigned char buffer[64]); - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -/* blk0() and blk() perform the initial expand. */ -/* I got the idea of expanding during the round function from SSLeay */ -#ifdef LITTLE_ENDIAN -#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ - |(rol(block->l[i],8)&0x00FF00FF)) -#else -#define blk0(i) block->l[i] -#endif -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ - ^block->l[(i+2)&15]^block->l[i&15],1)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - -/* Hash a single 512-bit block. This is the core of the algorithm. */ - -void SHA1Transform(unsigned long state[5], unsigned char buffer[64]) -{ -unsigned long a, b, c, d, e; -typedef union { - unsigned char c[64]; - unsigned long l[16]; -} CHAR64LONG16; -CHAR64LONG16* block; -#ifdef SHA1HANDSOFF -static unsigned char workspace[64]; - block = (CHAR64LONG16*)workspace; - memcpy(block, buffer, 64); -#else - block = (CHAR64LONG16*)buffer; -#endif - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; -} - - -/* SHA1Init - Initialize new context */ - -void SHA1Init(SHA1_CTX* context) -{ - /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -/* Run your data through this. */ - -void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len) -{ -unsigned int i, j; - - j = (context->count[0] >> 3) & 63; - if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; - context->count[1] += (len >> 29); - if ((j + len) > 63) { - memcpy(&context->buffer[j], data, (i = 64-j)); - SHA1Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) { - SHA1Transform(context->state, &data[i]); - } - j = 0; - } - else i = 0; - memcpy(&context->buffer[j], &data[i], len - i); -} - - -/* Add padding and return the message digest. */ - -void SHA1Final(unsigned char digest[20], SHA1_CTX* context) -{ -unsigned long i, j; -unsigned char finalcount[8]; - - for (i = 0; i < 8; i++) { - finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ - } - SHA1Update(context, (unsigned char *)"\200", 1); - while ((context->count[0] & 504) != 448) { - SHA1Update(context, (unsigned char *)"\0", 1); - } - SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ - for (i = 0; i < 20; i++) { - digest[i] = (unsigned char) - ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); - } - /* Wipe variables */ - i = j = 0; - memset(context->buffer, 0, 64); - memset(context->state, 0, 20); - memset(context->count, 0, 8); - memset(&finalcount, 0, 8); -#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ - SHA1Transform(context->state, context->buffer); -#endif -} diff --git a/mods/atsocial_iphone_app/OAuth/Crypto/sha1.h b/mods/atsocial_iphone_app/OAuth/Crypto/sha1.h deleted file mode 100644 index f3218ee52..000000000 --- a/mods/atsocial_iphone_app/OAuth/Crypto/sha1.h +++ /dev/null @@ -1,12 +0,0 @@ - -// From http://www.mirrors.wiretapped.net/security/cryptography/hashes/sha1/sha1.c - -typedef struct { - unsigned long state[5]; - unsigned long count[2]; - unsigned char buffer[64]; -} SHA1_CTX; - -extern void SHA1Init(SHA1_CTX* context); -extern void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len); -extern void SHA1Final(unsigned char digest[20], SHA1_CTX* context); diff --git a/mods/atsocial_iphone_app/OAuth/Extensions/NSString+URLEncoding.h b/mods/atsocial_iphone_app/OAuth/Extensions/NSString+URLEncoding.h deleted file mode 100644 index d82486885..000000000 --- a/mods/atsocial_iphone_app/OAuth/Extensions/NSString+URLEncoding.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// NSString+URLEncoding.h -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// Modified by Cassie Doll on 02/02/09 -// -// 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. - - -#import - - -@interface NSString (OAURLEncodingAdditions) - -- (NSString *)URLEncodedString; -- (NSString *)MinimalURLEncodedString; -- (NSString *)URLDecodedString; - -@end diff --git a/mods/atsocial_iphone_app/OAuth/Extensions/NSString+URLEncoding.m b/mods/atsocial_iphone_app/OAuth/Extensions/NSString+URLEncoding.m deleted file mode 100644 index 1ecf3f03c..000000000 --- a/mods/atsocial_iphone_app/OAuth/Extensions/NSString+URLEncoding.m +++ /dev/null @@ -1,63 +0,0 @@ -// -// NSString+URLEncoding.m -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// Modified by Cassie Doll on 02/02/09 -// -// 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. - - -#import "NSString+URLEncoding.h" - - -@implementation NSString (OAURLEncodingAdditions) - -- (NSString *)URLEncodedString -{ - NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, - (CFStringRef)self, - NULL, - CFSTR("!*'();:@&=+$,/?#[]"), - kCFStringEncodingUTF8); - [result autorelease]; - return result; -} - -- (NSString *)MinimalURLEncodedString { - NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, - (CFStringRef)self, - CFSTR("%"), // characters to leave unescaped (NULL = all escaped sequences are replaced) - CFSTR("?=&+"), // legal URL characters to be escaped (NULL = all legal characters are replaced) - kCFStringEncodingUTF8); // encoding - [result autorelease]; - return result; -} - -- (NSString*)URLDecodedString -{ - NSString *result = (NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, - (CFStringRef)self, - CFSTR(""), - kCFStringEncodingUTF8); - [result autorelease]; - return result; -} - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OAAsynchronousDataFetcher.h b/mods/atsocial_iphone_app/OAuth/OAAsynchronousDataFetcher.h deleted file mode 100644 index de8d2ee43..000000000 --- a/mods/atsocial_iphone_app/OAuth/OAAsynchronousDataFetcher.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// OAAsynchronousDataFetcher.h -// OAuthConsumer -// -// Created by Zsombor Szabó on 12/3/08. -// -// 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. - -#import - -@class OAMutableURLRequest; - -@interface OAAsynchronousDataFetcher : NSObject { - OAMutableURLRequest *request; - NSURLResponse *response; - NSURLConnection *connection; - NSMutableData *responseData; - id delegate; - SEL didFinishSelector; - SEL didFailSelector; -} - -+ (id)asynchronousFetcherWithRequest:(OAMutableURLRequest *)aRequest delegate:(id)aDelegate didFinishSelector:(SEL)finishSelector didFailSelector:(SEL)failSelector; -- (id)initWithRequest:(OAMutableURLRequest *)aRequest delegate:(id)aDelegate didFinishSelector:(SEL)finishSelector didFailSelector:(SEL)failSelector; - -- (void)start; - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OAAsynchronousDataFetcher.m b/mods/atsocial_iphone_app/OAuth/OAAsynchronousDataFetcher.m deleted file mode 100644 index 147e7421f..000000000 --- a/mods/atsocial_iphone_app/OAuth/OAAsynchronousDataFetcher.m +++ /dev/null @@ -1,131 +0,0 @@ -// -// OAAsynchronousDataFetcher.m -// OAuthConsumer -// -// Created by Zsombor Szabó on 12/3/08. -// -// 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. - -#import "OAAsynchronousDataFetcher.h" - -#import "OAServiceTicket.h" - -@implementation OAAsynchronousDataFetcher - -+ (id)asynchronousFetcherWithRequest:(OAMutableURLRequest *)aRequest delegate:(id)aDelegate didFinishSelector:(SEL)finishSelector didFailSelector:(SEL)failSelector -{ - return [[[OAAsynchronousDataFetcher alloc] initWithRequest:aRequest delegate:aDelegate didFinishSelector:finishSelector didFailSelector:failSelector] autorelease]; -} - -- (id)initWithRequest:(OAMutableURLRequest *)aRequest delegate:(id)aDelegate didFinishSelector:(SEL)finishSelector didFailSelector:(SEL)failSelector -{ - if (self = [super init]) - { - request = [aRequest retain]; - delegate = aDelegate; - didFinishSelector = finishSelector; - didFailSelector = failSelector; - } - return self; -} - -- (void)start -{ - [request prepare]; - - if (connection) - [connection release]; - - connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; - - if (connection) - { - if (responseData) - [responseData release]; - responseData = [[NSMutableData data] retain]; - } - else - { - OAServiceTicket *ticket= [[OAServiceTicket alloc] initWithRequest:request - response:nil - didSucceed:NO]; - [delegate performSelector:didFailSelector - withObject:ticket - withObject:nil]; - [ticket release]; - } -} - -- (void)cancel -{ - if (connection) - [connection cancel]; -} - -- (void)dealloc -{ - if (request) [request release]; - if (connection) [connection release]; - if (response) [response release]; - if (responseData) [responseData release]; - [super dealloc]; -} - -#pragma mark - -#pragma mark NSURLConnection's delegate methods - -- (void)connection:(NSURLConnection *)aConnection didReceiveResponse:(NSURLResponse *)aResponse -{ - if (response) - [response release]; - response = [aResponse retain]; - [responseData setLength:0]; -} - -- (void)connection:(NSURLConnection *)aConnection didReceiveData:(NSData *)data -{ - [responseData appendData:data]; -} - -- (void)connection:(NSURLConnection *)aConnection didFailWithError:(NSError *)error -{ - OAServiceTicket *ticket= [[OAServiceTicket alloc] initWithRequest:request - response:response - didSucceed:NO]; - [delegate performSelector:didFailSelector - withObject:ticket - withObject:error]; - - [ticket release]; -} - -- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection -{ - OAServiceTicket *ticket = [[OAServiceTicket alloc] initWithRequest:request - response:response - didSucceed:[(NSHTTPURLResponse *)response statusCode] < 400]; - [delegate performSelector:didFinishSelector - withObject:ticket - withObject:responseData]; - - [ticket release]; -} - -@end - diff --git a/mods/atsocial_iphone_app/OAuth/OAConsumer.h b/mods/atsocial_iphone_app/OAuth/OAConsumer.h deleted file mode 100644 index 05c568397..000000000 --- a/mods/atsocial_iphone_app/OAuth/OAConsumer.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// OAConsumer.h -// OAuthConsumer -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// Modified by Cassie Doll on 02/02/09 -// -// 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. - - -#import - - -@interface OAConsumer : NSObject { -@protected - NSString *key; - NSString *secret; -} -@property(retain) NSString *key; -@property(retain) NSString *secret; - -- (id)initWithKey:(NSString *)aKey secret:(NSString *)aSecret; - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OAConsumer.m b/mods/atsocial_iphone_app/OAuth/OAConsumer.m deleted file mode 100644 index 53d8dd8e9..000000000 --- a/mods/atsocial_iphone_app/OAuth/OAConsumer.m +++ /dev/null @@ -1,52 +0,0 @@ -// -// OAConsumer.m -// OAuthConsumer -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// Modified by Cassie Doll on 02/02/09 -// -// 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. - -#import "OAConsumer.h" - - -@implementation OAConsumer -@synthesize key, secret; - -#pragma mark init - -- (id)initWithKey:(NSString *)aKey secret:(NSString *)aSecret -{ - if (self = [super init]) - { - self.key = aKey; - self.secret = aSecret; - } - return self; -} - -- (void)dealloc -{ - [key release]; - [secret release]; - [super dealloc]; -} - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OADataFetcher.h b/mods/atsocial_iphone_app/OAuth/OADataFetcher.h deleted file mode 100644 index b2d54eae4..000000000 --- a/mods/atsocial_iphone_app/OAuth/OADataFetcher.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// OADataFetcher.h -// OAuthConsumer -// -// Created by Jon Crosby on 11/5/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// Modified by Cassie Doll on 02/02/09 -// -// 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. - -#import -#import "OAMutableURLRequest.h" -#import "OAServiceTicket.h" - - -@interface OADataFetcher : NSObject - -+ (void)fetchDataWithRequest:(OAMutableURLRequest *)aRequest - delegate:(id)aDelegate - didFinishSelector:(SEL)finishSelector; - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OADataFetcher.m b/mods/atsocial_iphone_app/OAuth/OADataFetcher.m deleted file mode 100644 index 8ae7a40bf..000000000 --- a/mods/atsocial_iphone_app/OAuth/OADataFetcher.m +++ /dev/null @@ -1,64 +0,0 @@ -// -// OADataFetcher.m -// OAuthConsumer -// -// Created by Jon Crosby on 11/5/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// Modified by Cassie Doll on 02/02/09 -// -// 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. - - -#import "OADataFetcher.h" - - -@implementation OADataFetcher - -+ (void)fetchDataWithRequest:(OAMutableURLRequest *)request - delegate:(id)delegate - didFinishSelector:(SEL)didFinishSelector { - NSURLResponse *response; - NSError *error = nil; - - [request prepare]; - // TODO: use the asynch fetcher from Google's open source library. - // Never do sync fetches in a client app on the main thread. - NSData *responseData = [NSURLConnection sendSynchronousRequest:request - returningResponse:&response - error:&error]; - - NSString *responseBody = [[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding] autorelease]; - NSLog(@"Request url: %@", [[request URL] absoluteString]); - NSLog(@"Response Body: %@", responseBody); - - if (response == nil || responseData == nil || error != nil) { - OAServiceTicket *ticket = [[[OAServiceTicket alloc] initWithRequest:request response:response didSucceed:NO] autorelease]; - [delegate performSelector:didFinishSelector withObject:ticket withObject:error]; - - } else { - NSLog(@"response had status code %i", [(NSHTTPURLResponse *)response statusCode]); - OAServiceTicket *ticket = [[[OAServiceTicket alloc] initWithRequest:request - response:response - didSucceed:[(NSHTTPURLResponse *)response statusCode] < 400] autorelease]; - - [delegate performSelector:didFinishSelector withObject:ticket withObject:responseBody]; - } -} - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OAMutableURLRequest.h b/mods/atsocial_iphone_app/OAuth/OAMutableURLRequest.h deleted file mode 100644 index 1afe38e61..000000000 --- a/mods/atsocial_iphone_app/OAuth/OAMutableURLRequest.h +++ /dev/null @@ -1,77 +0,0 @@ -// -// OAMutableURLRequest.h -// OAuthConsumer -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// Modified by Cassie Doll on 02/02/09 -// -// 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. - - -#import -#import "OASignatureProviding.h" -@class OAConsumer; -@class OAToken; -@class OAHMAC_SHA1SignatureProvider; -@class OARequestParameter; - - -@interface OAMutableURLRequest : NSMutableURLRequest { -@protected - OAConsumer *consumer; - OAToken *token; - NSString *realm; - NSString *signature; - id signatureProvider; - NSString *nonce; - NSString *timestamp; - NSMutableArray *parameters; -} -@property(readonly) NSString *signature; -@property(readonly) NSString *nonce; -@property(retain) NSMutableArray *parameters; - -- (id)initWithURL:(NSURL *)aUrl - consumer:(OAConsumer *)aConsumer - token:(OAToken *)aToken; - -- (id)initWithURL:(NSURL *)aUrl - parameters:(NSArray *)extraParameters - consumer:(OAConsumer *)aConsumer - token:(OAToken *)aToken; - -- (id)initWithURL:(NSURL *)aUrl - consumer:(OAConsumer *)aConsumer - token:(OAToken *)aToken - realm:(NSString *)aRealm -signatureProvider:(id)aProvider; - -- (id)initWithURL:(NSURL *)aUrl - parameters:(NSArray *)extraParameters - consumer:(OAConsumer *)aConsumer - token:(OAToken *)aToken - realm:(NSString *)aRealm -signatureProvider:(id)aProvider - nonce:(NSString *)aNonce - timestamp:(NSString *)aTimestamp; - -- (void)prepare; - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OAMutableURLRequest.m b/mods/atsocial_iphone_app/OAuth/OAMutableURLRequest.m deleted file mode 100644 index 6a5dac3f6..000000000 --- a/mods/atsocial_iphone_app/OAuth/OAMutableURLRequest.m +++ /dev/null @@ -1,218 +0,0 @@ -// -// OAMutableURLRequest.m -// OAuthConsumer -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// Modified by Cassie Doll on 02/02/09 -// -// 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. - - -#import "OAMutableURLRequest.h" -#import "OAConsumer.h" -#import "OAToken.h" -#import "OAHMAC_SHA1SignatureProvider.h" -#import "OARequestParameter.h" - -@interface OAMutableURLRequest () -@property (nonatomic, retain) id signatureProvider; -- (NSString *)_generateTimestamp; -- (NSString *)_generateNonce; -- (NSString *)_signatureBaseString; -- (void)_putParametersInRequest; -- (NSString *)_getNormalizedRequestParameters; -@end - -@implementation OAMutableURLRequest -@synthesize signatureProvider; -@synthesize signature, nonce, parameters; - -#pragma mark init - -- (id)initWithURL:(NSURL *)aUrl consumer:(OAConsumer *)aConsumer token:(OAToken *)aToken { - return [self initWithURL:aUrl parameters:nil consumer:aConsumer token:aToken]; -} - -- (id)initWithURL:(NSURL *)aUrl parameters:(NSArray *)extraParameters - consumer:(OAConsumer *)aConsumer token:(OAToken *)aToken { - return [self initWithURL:aUrl parameters:extraParameters consumer:aConsumer token:aToken realm:nil - signatureProvider:nil nonce:[self _generateNonce] timestamp:[self _generateTimestamp]]; -} - -- (id)initWithURL:(NSURL *)aUrl consumer:(OAConsumer *)aConsumer token:(OAToken *)aToken - realm:(NSString *)aRealm signatureProvider:(id)aProvider { - return [self initWithURL:aUrl parameters:nil consumer:aConsumer token:aToken realm:aRealm - signatureProvider:aProvider nonce:[self _generateNonce] timestamp:[self _generateTimestamp]]; -} - -// Setting a timestamp and nonce to known -// values can be helpful for testing -- (id)initWithURL:(NSURL *)aUrl - parameters:(NSArray *)extraParameters - consumer:(OAConsumer *)aConsumer - token:(OAToken *)aToken - realm:(NSString *)aRealm -signatureProvider:(id)aProvider - nonce:(NSString *)aNonce - timestamp:(NSString *)aTimestamp { - if (self = [super initWithURL:aUrl - cachePolicy:NSURLRequestReloadIgnoringCacheData - timeoutInterval:20.0]) { - consumer = [aConsumer retain]; - - // empty token for Unauthorized Request Token transaction - if (aToken == nil) { - token = nil; - } else { - token = [aToken retain]; - } - - if (aRealm == nil) { - realm = @""; - } else { - realm = [aRealm retain]; - } - - // default to HMAC-SHA1 - if (aProvider == nil) { - self.signatureProvider = [[[OAHMAC_SHA1SignatureProvider alloc] init] autorelease]; - } else { - self.signatureProvider = aProvider; - } - - timestamp = [aTimestamp retain]; - nonce = [aNonce retain]; - - if (extraParameters) { - self.parameters = [NSMutableArray arrayWithArray:extraParameters]; - } else { - self.parameters = [NSMutableArray arrayWithCapacity:7]; - } - } - return self; -} - -- (void)dealloc { - [consumer release]; - [token release]; - [realm release]; - [signatureProvider release]; - [timestamp release]; - [nonce release]; - [parameters release]; - [super dealloc]; -} - -#pragma mark - -#pragma mark Public - -- (void)prepare { - // Add in all of the oauth parameters - [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_consumer_key" value:consumer.key]]; - [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_signature_method" value:[signatureProvider name]]]; - [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_timestamp" value:timestamp]]; - [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_nonce" value:nonce]]; - [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_version" value:@"1.0"]]; - - if (token) { - [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_token" value:token.key]]; - } - - // TODO: if later RSA-SHA1 support is added then a little code redesign is needed - NSString *baseString = [self _signatureBaseString]; - NSString *secret = [NSString stringWithFormat:@"%@&%@", - [consumer.secret URLEncodedString], - token ? [token.secret URLEncodedString] : @""]; - - NSLog(@"Base string: %@ and secret: %@", baseString, secret); - signature = [signatureProvider signClearText:baseString - withSecret:secret]; - - [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_signature" value:signature]]; - [self _putParametersInRequest]; -} - -#pragma mark - -#pragma mark Private - -- (NSString *)_generateTimestamp { - return [NSString stringWithFormat:@"%d", time(NULL)]; -} - -- (NSString *)_generateNonce { - CFUUIDRef theUUID = CFUUIDCreate(NULL); - CFStringRef string = CFUUIDCreateString(NULL, theUUID); - NSMakeCollectable(theUUID); - return [(NSString *)string autorelease]; -} - -- (NSString *)_signatureBaseString { - return [NSString stringWithFormat:@"%@&%@&%@", - [self HTTPMethod], - [[[self URL] absoluteString] URLEncodedString], - [[self _getNormalizedRequestParameters] URLEncodedString]]; -} - -- (void)_putParametersInRequest { - NSString *normalizedRequestParameters = [self _getNormalizedRequestParameters]; - - if ([[self HTTPMethod] isEqualToString:@"GET"] || [[self HTTPMethod] isEqualToString:@"DELETE"]) { - [self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@?%@", [[self URL] absoluteString], normalizedRequestParameters]]]; - - } else { - // POST, PUT - NSData *postData = [normalizedRequestParameters dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; - [self setHTTPBody:postData]; - [self setValue:[NSString stringWithFormat:@"%d", [postData length]] forHTTPHeaderField:@"Content-Length"]; - [self setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; - - NSString *oauthToken = @""; - if (token) { - oauthToken = [NSString stringWithFormat:@"oauth_token=\"%@\", ", [token.key URLEncodedString]]; - } - - NSString *oauthHeader = [NSString stringWithFormat:@"OAuth realm=\"%@\" oauth_consumer_key=\"%@\", %@oauth_signature_method=\"%@\", oauth_signature=\"%@\", oauth_timestamp=\"%@\", oauth_nonce=\"%@\", oauth_version=\"1.0\"", - [realm URLEncodedString], - [consumer.key URLEncodedString], - oauthToken, - [[signatureProvider name] URLEncodedString], - [signature URLEncodedString], - timestamp, - nonce]; - - [self setValue:oauthHeader forHTTPHeaderField:@"Authorization"]; - [oauthToken release]; - [oauthHeader release]; - } -} - -- (NSString *)_getNormalizedRequestParameters { - NSMutableArray *parameterPairs = [NSMutableArray arrayWithCapacity:([parameters count])]; - - for (OARequestParameter *param in parameters) { - [parameterPairs addObject:[param URLEncodedNameValuePair]]; - } - - NSArray* sortedPairs = [parameterPairs sortedArrayUsingSelector:@selector(compare:)]; - return [sortedPairs componentsJoinedByString:@"&"]; -} - - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OARequestParameter.h b/mods/atsocial_iphone_app/OAuth/OARequestParameter.h deleted file mode 100644 index 4a9c76415..000000000 --- a/mods/atsocial_iphone_app/OAuth/OARequestParameter.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// OARequestParameter.h -// OAuthConsumer -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// -// 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. - - -#import -#import "NSString+URLEncoding.h" - - -@interface OARequestParameter : NSObject { -@protected - NSString *name; - NSString *value; -} -@property(retain) NSString *name; -@property(retain) NSString *value; - -+ (id)requestParameterWithName:(NSString *)aName value:(NSString *)aValue; -- (id)initWithName:(NSString *)aName value:(NSString *)aValue; -- (NSString *)URLEncodedName; -- (NSString *)URLEncodedValue; -- (NSString *)URLEncodedNameValuePair; - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OARequestParameter.m b/mods/atsocial_iphone_app/OAuth/OARequestParameter.m deleted file mode 100644 index 63b0219fa..000000000 --- a/mods/atsocial_iphone_app/OAuth/OARequestParameter.m +++ /dev/null @@ -1,70 +0,0 @@ -// -// OARequestParameter.m -// OAuthConsumer -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// -// 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. - - -#import "OARequestParameter.h" - - -@implementation OARequestParameter -@synthesize name, value; - -+ (id)requestParameterWithName:(NSString *)aName value:(NSString *)aValue -{ - return [[[OARequestParameter alloc] initWithName:aName value:aValue] autorelease]; -} - -- (id)initWithName:(NSString *)aName value:(NSString *)aValue -{ - if (self = [super init]) - { - self.name = aName; - self.value = aValue; - } - return self; -} - -- (void)dealloc -{ - [name release]; - [value release]; - [super dealloc]; -} - -- (NSString *)URLEncodedName -{ - return [self.name URLEncodedString]; -} - -- (NSString *)URLEncodedValue -{ - return [self.value URLEncodedString]; -} - -- (NSString *)URLEncodedNameValuePair -{ - return [NSString stringWithFormat:@"%@=%@", [self URLEncodedName], [self URLEncodedValue]]; -} - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OAServiceTicket.h b/mods/atsocial_iphone_app/OAuth/OAServiceTicket.h deleted file mode 100644 index 0c4d3f5a7..000000000 --- a/mods/atsocial_iphone_app/OAuth/OAServiceTicket.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// OAServiceTicket.h -// OAuthConsumer -// -// Created by Jon Crosby on 11/5/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// -// 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. - - -#import -#import "OAMutableURLRequest.h" - - -@interface OAServiceTicket : NSObject { -@private - OAMutableURLRequest *request; - NSURLResponse *response; - BOOL didSucceed; -} -@property(retain) OAMutableURLRequest *request; -@property(retain) NSURLResponse *response; -@property(assign) BOOL didSucceed; - -- (id)initWithRequest:(OAMutableURLRequest *)aRequest response:(NSURLResponse *)aResponse didSucceed:(BOOL)success; - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OAServiceTicket.m b/mods/atsocial_iphone_app/OAuth/OAServiceTicket.m deleted file mode 100644 index 9b4942263..000000000 --- a/mods/atsocial_iphone_app/OAuth/OAServiceTicket.m +++ /dev/null @@ -1,51 +0,0 @@ -// -// OAServiceTicket.m -// OAuthConsumer -// -// Created by Jon Crosby on 11/5/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// -// 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. - - -#import "OAServiceTicket.h" - - -@implementation OAServiceTicket -@synthesize request, response, didSucceed; - -- (id)initWithRequest:(OAMutableURLRequest *)aRequest response:(NSURLResponse *)aResponse didSucceed:(BOOL)success -{ - if (self = [super init]) - { - self.request = aRequest; - self.response = aResponse; - self.didSucceed = success; - } - return self; -} - -- (void)dealloc -{ - [request release]; - [response release]; - [super dealloc]; -} - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OAToken.h b/mods/atsocial_iphone_app/OAuth/OAToken.h deleted file mode 100644 index 5b71f0c30..000000000 --- a/mods/atsocial_iphone_app/OAuth/OAToken.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// OAToken.h -// OAuthConsumer -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// Modified by Cassie Doll on 02/02/09 -// -// 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. - -#import - -@interface OAToken : NSObject { -@public - NSString *key; - NSString *secret; -} -@property(copy) NSString *key; -@property(copy) NSString *secret; - -- (id)initWithKey:(NSString *)aKey secret:(NSString *)aSecret; -- (id)initWithHTTPResponseBody:(NSString *)body; -@end diff --git a/mods/atsocial_iphone_app/OAuth/OAToken.m b/mods/atsocial_iphone_app/OAuth/OAToken.m deleted file mode 100644 index 57100925d..000000000 --- a/mods/atsocial_iphone_app/OAuth/OAToken.m +++ /dev/null @@ -1,82 +0,0 @@ -// -// OAToken.m -// OAuthConsumer -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// Modified by Cassie Doll on 02/02/09 -// -// 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. - - -#import "OAToken.h" -#import "NSString+URLEncoding.h" - -@implementation OAToken - -@synthesize key, secret; - -#pragma mark init - -- (id)init -{ - if (self = [super init]) - { - self.key = @""; - self.secret = @""; - } - return self; -} - -- (id)initWithKey:(NSString *)aKey secret:(NSString *)aSecret -{ - if (self = [super init]) - { - self.key = aKey; - self.secret = aSecret; - } - return self; -} - -- (id)initWithHTTPResponseBody:(NSString *)body -{ - if (self = [super init]) - { - NSArray *pairs = [body componentsSeparatedByString:@"&"]; - - for (NSString *pair in pairs) { - NSArray *elements = [pair componentsSeparatedByString:@"="]; - if ([[elements objectAtIndex:0] isEqualToString:@"oauth_token"]) { - self.key = [[elements objectAtIndex:1] URLDecodedString]; - } else if ([[elements objectAtIndex:0] isEqualToString:@"oauth_token_secret"]) { - self.secret = [[elements objectAtIndex:1] URLDecodedString]; - } - } - } - return self; -} - -- (void)dealloc -{ - [key release]; - [secret release]; - [super dealloc]; -} - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OAToken_KeychainExtensions.h b/mods/atsocial_iphone_app/OAuth/OAToken_KeychainExtensions.h deleted file mode 100755 index dea76ca51..000000000 --- a/mods/atsocial_iphone_app/OAuth/OAToken_KeychainExtensions.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// OAToken_KeychainExtensions.h -// TouchTheFireEagle -// -// Created by Jonathan Wight on 04/04/08. -// Modified by Cassie Doll on 02/02/09 -// -// 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. - -#import "OAToken.h" - -#import - -@interface OAToken (OAToken_KeychainExtensions) - -- (NSError *)storeInDefaultKeychainWithAppName:(NSString *)name tokenType:(NSString *)type; -- (id)initWithKeychainUsingAppName:(NSString *)name tokenType:(NSString *)type; - -@end diff --git a/mods/atsocial_iphone_app/OAuth/OAToken_KeychainExtensions.m b/mods/atsocial_iphone_app/OAuth/OAToken_KeychainExtensions.m deleted file mode 100755 index 662480135..000000000 --- a/mods/atsocial_iphone_app/OAuth/OAToken_KeychainExtensions.m +++ /dev/null @@ -1,63 +0,0 @@ -// -// OAToken_KeychainExtensions.m -// TouchTheFireEagle -// -// Created by Jonathan Wight on 04/04/08. -// Modified by Cassie Doll on 02/02/09 -// -// 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. - -#import "OAToken_KeychainExtensions.h" -#import "SFHFKeychainUtils.h" - -@implementation OAToken (OAToken_KeychainExtensions) - - -- (NSError *)storeInDefaultKeychainWithAppName:(NSString *)name tokenType:(NSString *)type { - NSString *password = [NSString stringWithFormat:@"%@:::%@", self.key, self.secret]; - - NSError *error = nil; - [SFHFKeychainUtils storeUsername:type andPassword:password - forServiceName:name updateExisting:TRUE error:&error]; - return error; -} - -- (id)initWithKeychainUsingAppName:(NSString *)name tokenType:(NSString *)type { - self = [super init]; - if (self) { - NSString *password = [SFHFKeychainUtils getPasswordForUsername:type andServiceName:name error:nil]; - - if (!password || [password length] == 0) { - [self release]; - return nil; - } - - NSArray *components =[password componentsSeparatedByString:@":::"]; - if (2 <= [components count]) { - self.key = [components objectAtIndex:0]; - self.secret = [components objectAtIndex:1]; - } - // TODO: this will fail if the key or the secret contain ':::' - } - return self; -} - - - -@end diff --git a/mods/atsocial_iphone_app/OAuth/Signature Providers/OAHMAC_SHA1SignatureProvider.h b/mods/atsocial_iphone_app/OAuth/Signature Providers/OAHMAC_SHA1SignatureProvider.h deleted file mode 100644 index d259c4ea3..000000000 --- a/mods/atsocial_iphone_app/OAuth/Signature Providers/OAHMAC_SHA1SignatureProvider.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// OAHMAC_SHA1SignatureProvider.h -// OAuthConsumer -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// -// 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. - - -#import -#import "OASignatureProviding.h" - - -@interface OAHMAC_SHA1SignatureProvider : NSObject -@end diff --git a/mods/atsocial_iphone_app/OAuth/Signature Providers/OAHMAC_SHA1SignatureProvider.m b/mods/atsocial_iphone_app/OAuth/Signature Providers/OAHMAC_SHA1SignatureProvider.m deleted file mode 100644 index c56a3b218..000000000 --- a/mods/atsocial_iphone_app/OAuth/Signature Providers/OAHMAC_SHA1SignatureProvider.m +++ /dev/null @@ -1,57 +0,0 @@ -// -// OAHMAC_SHA1SignatureProvider.m -// OAuthConsumer -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// -// 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. - - -#import "OAHMAC_SHA1SignatureProvider.h" - -#include "hmac.h" -#include "Base64Transcoder.h" - -@implementation OAHMAC_SHA1SignatureProvider - -- (NSString *)name -{ - return @"HMAC-SHA1"; -} - -- (NSString *)signClearText:(NSString *)text withSecret:(NSString *)secret -{ - NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding]; - NSData *clearTextData = [text dataUsingEncoding:NSUTF8StringEncoding]; - unsigned char result[20]; - hmac_sha1((unsigned char *)[clearTextData bytes], [clearTextData length], (unsigned char *)[secretData bytes], [secretData length], result); - - //Base64 Encoding - - char base64Result[32]; - size_t theResultLength = 32; - Base64EncodeData(result, 20, base64Result, &theResultLength); - NSData *theData = [NSData dataWithBytes:base64Result length:theResultLength]; - - NSString *base64EncodedResult = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding]; - return [base64EncodedResult autorelease]; -} - -@end diff --git a/mods/atsocial_iphone_app/OAuth/Signature Providers/OAPlaintextSignatureProvider.h b/mods/atsocial_iphone_app/OAuth/Signature Providers/OAPlaintextSignatureProvider.h deleted file mode 100644 index 96bb2f288..000000000 --- a/mods/atsocial_iphone_app/OAuth/Signature Providers/OAPlaintextSignatureProvider.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// OAPlaintextSignatureProvider.h -// OAuthConsumer -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// -// 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. - - -#import -#import "OASignatureProviding.h" - -@interface OAPlaintextSignatureProvider : NSObject -@end diff --git a/mods/atsocial_iphone_app/OAuth/Signature Providers/OAPlaintextSignatureProvider.m b/mods/atsocial_iphone_app/OAuth/Signature Providers/OAPlaintextSignatureProvider.m deleted file mode 100644 index 3a95dc220..000000000 --- a/mods/atsocial_iphone_app/OAuth/Signature Providers/OAPlaintextSignatureProvider.m +++ /dev/null @@ -1,43 +0,0 @@ -// -// OAPlaintextSignatureProvider.m -// OAuthConsumer -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// -// 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. - - -#import "OAPlaintextSignatureProvider.h" -#import "NSString+URLEncoding.h" - - -@implementation OAPlaintextSignatureProvider - -- (NSString *)name -{ - return @"PLAINTEXT"; -} - -- (NSString *)signClearText:(NSString *)text withSecret:(NSString *)secret -{ - return secret; -} - -@end diff --git a/mods/atsocial_iphone_app/OAuth/Signature Providers/OASignatureProviding.h b/mods/atsocial_iphone_app/OAuth/Signature Providers/OASignatureProviding.h deleted file mode 100644 index 0c7e4f8cf..000000000 --- a/mods/atsocial_iphone_app/OAuth/Signature Providers/OASignatureProviding.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// OASignatureProviding.h -// -// Created by Jon Crosby on 10/19/07. -// Copyright 2007 Kaboomerang LLC. All rights reserved. -// -// 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. - - -#import - - -@protocol OASignatureProviding - -- (NSString *)name; -- (NSString *)signClearText:(NSString *)text withSecret:(NSString *)secret; - -@end diff --git a/mods/atsocial_iphone_app/README.markdown b/mods/atsocial_iphone_app/README.markdown deleted file mode 100644 index b9784028b..000000000 --- a/mods/atsocial_iphone_app/README.markdown +++ /dev/null @@ -1,7 +0,0 @@ -Getting Started -=============== -1. git clone git://github.com/quanganhdo/atutor-social-iphone.git ATutor -2. cd ATutor -3. git submodule update --init -4. open ATutor.xcodeproj -5. Build and Go! \ No newline at end of file diff --git a/mods/atsocial_iphone_app/Settings.bundle/Root.plist b/mods/atsocial_iphone_app/Settings.bundle/Root.plist deleted file mode 100644 index 6734ab297..000000000 --- a/mods/atsocial_iphone_app/Settings.bundle/Root.plist +++ /dev/null @@ -1,61 +0,0 @@ - - - - - StringsTable - Root - Title - ATutor - PreferenceSpecifiers - - - Type - PSGroupSpecifier - Title - ATutor URL - - - Type - PSTextFieldSpecifier - Title - URL - Key - atutorURL - DefaultValue - http://www.example.com/atutor/docs - IsSecure - - KeyboardType - URL - AutocapitalizationType - None - AutocorrectionType - No - - - Type - PSGroupSpecifier - Title - Shindig URL - - - Type - PSTextFieldSpecifier - Title - URL - Key - shindigURL - DefaultValue - http://www.example.com/shindig/php - IsSecure - - KeyboardType - URL - AutocapitalizationType - None - AutocorrectionType - No - - - - diff --git a/mods/atsocial_iphone_app/Settings.bundle/en.lproj/Root.strings b/mods/atsocial_iphone_app/Settings.bundle/en.lproj/Root.strings deleted file mode 100644 index 8cd87b9d6b20c1fbf87bd4db3db267fca5ad4df9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 546 zcmaixOHRW;5JYRuDMndFh#Ua1V1d}N;sVAV2TO?uC3a9aJn*VxFrY}tnon0(S66#J z-d9>G>6W!ur(SDqlp`9nn~*(m%iWnv?yq`Qfp6XbK1?+om~~#r)ZnhkYQU_VbfjuT zHNn`CX<0sd*m1A}>&5sU$akD=GTXJ1e diff --git a/mods/atsocial_iphone_app/TouchJSON/CDataScanner.h b/mods/atsocial_iphone_app/TouchJSON/CDataScanner.h deleted file mode 100755 index 37b3df15f..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/CDataScanner.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// CDataScanner.h -// TouchJSON -// -// Created by Jonathan Wight on 04/16/08. -// Copyright 2008 toxicsoftware.com. All rights reserved. -// - -#import - -// NSScanner - -@interface CDataScanner : NSObject { - NSData *data; - - u_int8_t *start; - u_int8_t *end; - u_int8_t *current; - NSUInteger length; - - NSCharacterSet *doubleCharacters; -} - -@property (readwrite, retain) NSData *data; -@property (readwrite, assign) NSInteger scanLocation; -@property (readonly, assign) BOOL isAtEnd; - -+ (id)scannerWithData:(NSData *)inData; - -- (unichar)currentCharacter; -- (unichar)scanCharacter; -- (BOOL)scanCharacter:(unichar)inCharacter; - -- (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue; -- (BOOL)scanString:(NSString *)inString intoString:(NSString **)outValue; -- (BOOL)scanCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue; // inSet must only contain 7-bit ASCII characters - -- (BOOL)scanUpToString:(NSString *)string intoString:(NSString **)outValue; -- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)set intoString:(NSString **)outValue; // inSet must only contain 7-bit ASCII characters - -- (BOOL)scanNumber:(NSNumber **)outValue; - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/CDataScanner.m b/mods/atsocial_iphone_app/TouchJSON/CDataScanner.m deleted file mode 100755 index 7640978c0..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/CDataScanner.m +++ /dev/null @@ -1,230 +0,0 @@ -// -// CDataScanner.m -// TouchJSON -// -// Created by Jonathan Wight on 04/16/08. -// Copyright 2008 toxicsoftware.com. All rights reserved. -// - -#import "CDataScanner.h" - -#import "CDataScanner_Extensions.h" - -@interface CDataScanner () -@property (readwrite, retain) NSCharacterSet *doubleCharacters; -@end - -#pragma mark - - -inline static unichar CharacterAtPointer(void *start, void *end) -{ - - const u_int8_t theByte = *(u_int8_t *)start; -if (theByte & 0x80) - { - // TODO -- UNICODE!!!! - } -const unichar theCharacter = theByte; -return(theCharacter); -} - -@implementation CDataScanner - -@dynamic data; -@dynamic scanLocation; -@dynamic isAtEnd; -@synthesize doubleCharacters; - -+ (id)scannerWithData:(NSData *)inData -{ -CDataScanner *theScanner = [[[self alloc] init] autorelease]; -theScanner.data = inData; -return(theScanner); -} - -- (id)init -{ -if ((self = [super init]) != nil) - { - self.doubleCharacters = [NSCharacterSet characterSetWithCharactersInString:@"0123456789eE-."]; - } -return(self); -} - -- (void)dealloc -{ -self.data = NULL; -self.doubleCharacters = NULL; -// -[super dealloc]; -} - -- (NSInteger)scanLocation -{ -return current - start; -} - -- (NSData *)data -{ -return(data); -} - -- (void)setData:(NSData *)inData -{ -if (data != inData) - { - if (data) - { - [data autorelease]; - data = NULL; - } - - if (inData) - { - data = [inData retain]; - // - start = (u_int8_t *)data.bytes; - end = start + data.length; - current = start; - length = data.length; - } - } -} - -- (void)setScanLocation:(NSInteger)inScanLocation -{ -current = start + inScanLocation; -} - -- (BOOL)isAtEnd -{ -return(self.scanLocation >= length); -} - -- (unichar)currentCharacter -{ -return(CharacterAtPointer(current, end)); -} - -- (unichar)scanCharacter -{ -const unichar theCharacter = CharacterAtPointer(current++, end); -return(theCharacter); -} - -- (BOOL)scanCharacter:(unichar)inCharacter -{ -unichar theCharacter = CharacterAtPointer(current, end); -if (theCharacter == inCharacter) - { - ++current; - return(YES); - } -else - return(NO); -} - -- (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue; -{ -const size_t theLength = strlen(inString); -if (end - current < theLength) - return(NO); -if (strncmp((char *)current, inString, theLength) == 0) - { - current += theLength; - if (outValue) - *outValue = [NSString stringWithUTF8String:inString]; - return(YES); - } -return(NO); -} - -- (BOOL)scanString:(NSString *)inString intoString:(NSString **)outValue -{ -if (end - current < inString.length) - return(NO); -if (strncmp((char *)current, [inString UTF8String], inString.length) == 0) - { - current += inString.length; - if (outValue) - *outValue = inString; - return(YES); - } -return(NO); -} - -- (BOOL)scanCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue -{ -u_int8_t *P; -for (P = current; P < end && [inSet characterIsMember:*P] == YES; ++P) - ; - -if (P == current) - { - return(NO); - } - -if (outValue) - { - *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease]; - } - -current = P; - -return(YES); -} - -- (BOOL)scanUpToString:(NSString *)inString intoString:(NSString **)outValue -{ -const char *theToken = [inString UTF8String]; -const char *theResult = strnstr((char *)current, theToken, end - current); -if (theResult == NULL) - { - return(NO); - } - -if (outValue) - { - *outValue = [[[NSString alloc] initWithBytes:current length:theResult - (char *)current encoding:NSUTF8StringEncoding] autorelease]; - } - -current = (u_int8_t *)theResult; - -return(YES); -} - -- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue -{ -u_int8_t *P; -for (P = current; P < end && [inSet characterIsMember:*P] == NO; ++P) - ; - -if (P == current) - { - return(NO); - } - -if (outValue) - { - *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease]; - } - -current = P; - -return(YES); -} - -- (BOOL)scanNumber:(NSNumber **)outValue -{ -// Replace all of this with a strtod call -NSString *theString = NULL; -if ([self scanCharactersFromSet:doubleCharacters intoString:&theString]) - { - if (outValue) - *outValue = [NSNumber numberWithDouble:[theString doubleValue]]; // TODO dont use doubleValue - return(YES); - } -return(NO); -} - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/Extensions/CDataScanner_Extensions.h b/mods/atsocial_iphone_app/TouchJSON/Extensions/CDataScanner_Extensions.h deleted file mode 100755 index d8fa671a9..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/Extensions/CDataScanner_Extensions.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// CDataScanner_Extensions.h -// TouchJSON -// -// Created by Jonathan Wight on 12/08/2005. -// Copyright 2005 Toxic Software. All rights reserved. -// - -#import "CDataScanner.h" - -@interface CDataScanner (CDataScanner_Extensions) - -- (BOOL)scanCStyleComment:(NSString **)outComment; -- (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment; - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/Extensions/CDataScanner_Extensions.m b/mods/atsocial_iphone_app/TouchJSON/Extensions/CDataScanner_Extensions.m deleted file mode 100755 index 5f3f00939..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/Extensions/CDataScanner_Extensions.m +++ /dev/null @@ -1,59 +0,0 @@ -// -// NSScanner_Extensions.m -// TouchJSON -// -// Created by Jonathan Wight on 12/08/2005. -// Copyright 2005 Toxic Software. All rights reserved. -// - -#import "CDataScanner_Extensions.h" - -#import "NSCharacterSet_Extensions.h" - -@implementation CDataScanner (CDataScanner_Extensions) - -- (BOOL)scanCStyleComment:(NSString **)outComment -{ -if ([self scanString:@"/*" intoString:NULL] == YES) - { - NSString *theComment = NULL; - if ([self scanUpToString:@"*/" intoString:&theComment] == NO) - [NSException raise:NSGenericException format:@"Started to scan a C style comment but it wasn't terminated."]; - - if ([theComment rangeOfString:@"/*"].location != NSNotFound) - [NSException raise:NSGenericException format:@"C style comments should not be nested."]; - - if ([self scanString:@"*/" intoString:NULL] == NO) - [NSException raise:NSGenericException format:@"C style comment did not end correctly."]; - - if (outComment != NULL) - *outComment = theComment; - - return(YES); - } -else - { - return(NO); - } -} - -- (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment -{ -if ([self scanString:@"//" intoString:NULL] == YES) - { - NSString *theComment = NULL; - [self scanUpToCharactersFromSet:[NSCharacterSet linebreaksCharacterSet] intoString:&theComment]; - [self scanCharactersFromSet:[NSCharacterSet linebreaksCharacterSet] intoString:NULL]; - - if (outComment != NULL) - *outComment = theComment; - - return(YES); - } -else - { - return(NO); - } -} - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/Extensions/NSCharacterSet_Extensions.h b/mods/atsocial_iphone_app/TouchJSON/Extensions/NSCharacterSet_Extensions.h deleted file mode 100755 index eea2067a9..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/Extensions/NSCharacterSet_Extensions.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// NSCharacterSet_Extensions.h -// TouchJSON -// -// Created by Jonathan Wight on 12/08/2005. -// Copyright (c) 2005 Toxic Software. All rights reserved. -// - -#import - -@interface NSCharacterSet (NSCharacterSet_Extensions) - -+ (NSCharacterSet *)linebreaksCharacterSet; - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/Extensions/NSCharacterSet_Extensions.m b/mods/atsocial_iphone_app/TouchJSON/Extensions/NSCharacterSet_Extensions.m deleted file mode 100755 index 566676e7e..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/Extensions/NSCharacterSet_Extensions.m +++ /dev/null @@ -1,27 +0,0 @@ -// -// NSCharacterSet_Extensions.m -// TouchJSON -// -// Created by Jonathan Wight on 12/08/2005. -// Copyright (c) 2005 Toxic Software. All rights reserved. -// - -#import "NSCharacterSet_Extensions.h" - -@implementation NSCharacterSet (NSCharacterSet_Extensions) - -#define LF 0x000a // Line Feed -#define FF 0x000c // Form Feed -#define CR 0x000d // Carriage Return -#define NEL 0x0085 // Next Line -#define LS 0x2028 // Line Separator -#define PS 0x2029 // Paragraph Separator - -+ (NSCharacterSet *)linebreaksCharacterSet -{ -unichar theCharacters[] = { LF, FF, CR, NEL, LS, PS, }; - -return([NSCharacterSet characterSetWithCharactersInString:[NSString stringWithCharacters:theCharacters length:sizeof(theCharacters) / sizeof(*theCharacters)]]); -} - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/Extensions/NSDictionary_JSONExtensions.h b/mods/atsocial_iphone_app/TouchJSON/Extensions/NSDictionary_JSONExtensions.h deleted file mode 100755 index 2aca5d311..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/Extensions/NSDictionary_JSONExtensions.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// NSDictionary_JSONExtensions.h -// TouchJSON -// -// Created by Jonathan Wight on 04/17/08. -// Copyright 2008 toxicsoftware.com. All rights reserved. -// - -#import - -@interface NSDictionary (NSDictionary_JSONExtensions) - -+ (id)dictionaryWithJSONData:(NSData *)inData error:(NSError **)outError; - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/Extensions/NSDictionary_JSONExtensions.m b/mods/atsocial_iphone_app/TouchJSON/Extensions/NSDictionary_JSONExtensions.m deleted file mode 100755 index 76593ad4f..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/Extensions/NSDictionary_JSONExtensions.m +++ /dev/null @@ -1,20 +0,0 @@ -// -// NSDictionary_JSONExtensions.m -// TouchJSON -// -// Created by Jonathan Wight on 04/17/08. -// Copyright 2008 toxicsoftware.com. All rights reserved. -// - -#import "NSDictionary_JSONExtensions.h" - -#import "CJSONDeserializer.h" - -@implementation NSDictionary (NSDictionary_JSONExtensions) - -+ (id)dictionaryWithJSONData:(NSData *)inData error:(NSError **)outError -{ -return([[CJSONDeserializer deserializer] deserialize:inData error:outError]); -} - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONDeserializer.h b/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONDeserializer.h deleted file mode 100755 index c8a89585c..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONDeserializer.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// CJSONDeserializer.h -// TouchJSON -// -// Created by Jonathan Wight on 12/15/2005. -// Copyright 2005 Toxic Software. All rights reserved. -// - -#import - -@interface CJSONDeserializer : NSObject { - -} - -+ (id)deserializer; - -- (id)deserialize:(NSData *)inData error:(NSError **)outError; - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONDeserializer.m b/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONDeserializer.m deleted file mode 100755 index af411e6a8..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONDeserializer.m +++ /dev/null @@ -1,31 +0,0 @@ -// -// CJSONDeserializer.m -// TouchJSON -// -// Created by Jonathan Wight on 12/15/2005. -// Copyright 2005 Toxic Software. All rights reserved. -// - -#import "CJSONDeserializer.h" - -#import "CJSONScanner.h" -#import "CDataScanner.h" - -@implementation CJSONDeserializer - -+ (id)deserializer -{ -return([[[self alloc] init] autorelease]); -} - -- (id)deserialize:(NSData *)inData error:(NSError **)outError -{ -CJSONScanner *theScanner = [CJSONScanner scannerWithData:inData]; -id theObject = NULL; -if ([theScanner scanJSONObject:&theObject error:outError] == YES) - return(theObject); -else - return(NULL); -} - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONScanner.h b/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONScanner.h deleted file mode 100755 index 3210d6592..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONScanner.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// CJSONScanner.h -// TouchJSON -// -// Created by Jonathan Wight on 12/07/2005. -// Copyright 2005 Toxic Software. All rights reserved. -// - -#import "CDataScanner.h" - -@interface CJSONScanner : CDataScanner { - BOOL scanComments; - NSCharacterSet *notQuoteCharacters; - NSCharacterSet *whitespaceCharacterSet; -} - -@property (readwrite, assign) BOOL scanComments; - -- (BOOL)scanJSONObject:(id *)outObject error:(NSError **)outError; -- (BOOL)scanJSONDictionary:(NSDictionary **)outDictionary error:(NSError **)outError; -- (BOOL)scanJSONArray:(NSArray **)outArray error:(NSError **)outError; -- (BOOL)scanJSONStringConstant:(NSString **)outStringConstant error:(NSError **)outError; -- (BOOL)scanJSONNumberConstant:(NSNumber **)outNumberConstant error:(NSError **)outError; -- (void)skipJSONWhitespace; - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONScanner.m b/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONScanner.m deleted file mode 100755 index 837cb8147..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONScanner.m +++ /dev/null @@ -1,435 +0,0 @@ -// -// CJSONScanner.m -// TouchJSON -// -// Created by Jonathan Wight on 12/07/2005. -// Copyright 2005 Toxic Software. All rights reserved. -// - -#import "CJSONScanner.h" - -#import "NSCharacterSet_Extensions.h" -#import "CDataScanner_Extensions.h" - -inline static int HexToInt(char inCharacter) -{ -int theValues[] = { 0x0 /* 48 '0' */, 0x1 /* 49 '1' */, 0x2 /* 50 '2' */, 0x3 /* 51 '3' */, 0x4 /* 52 '4' */, 0x5 /* 53 '5' */, 0x6 /* 54 '6' */, 0x7 /* 55 '7' */, 0x8 /* 56 '8' */, 0x9 /* 57 '9' */, -1 /* 58 ':' */, -1 /* 59 ';' */, -1 /* 60 '<' */, -1 /* 61 '=' */, -1 /* 62 '>' */, -1 /* 63 '?' */, -1 /* 64 '@' */, 0xa /* 65 'A' */, 0xb /* 66 'B' */, 0xc /* 67 'C' */, 0xd /* 68 'D' */, 0xe /* 69 'E' */, 0xf /* 70 'F' */, -1 /* 71 'G' */, -1 /* 72 'H' */, -1 /* 73 'I' */, -1 /* 74 'J' */, -1 /* 75 'K' */, -1 /* 76 'L' */, -1 /* 77 'M' */, -1 /* 78 'N' */, -1 /* 79 'O' */, -1 /* 80 'P' */, -1 /* 81 'Q' */, -1 /* 82 'R' */, -1 /* 83 'S' */, -1 /* 84 'T' */, -1 /* 85 'U' */, -1 /* 86 'V' */, -1 /* 87 'W' */, -1 /* 88 'X' */, -1 /* 89 'Y' */, -1 /* 90 'Z' */, -1 /* 91 '[' */, -1 /* 92 '\' */, -1 /* 93 ']' */, -1 /* 94 '^' */, -1 /* 95 '_' */, -1 /* 96 '`' */, 0xa /* 97 'a' */, 0xb /* 98 'b' */, 0xc /* 99 'c' */, 0xd /* 100 'd' */, 0xe /* 101 'e' */, 0xf /* 102 'f' */, }; -if (inCharacter >= '0' && inCharacter <= 'f') - return(theValues[inCharacter - '0']); -else - return(-1); -} - -@interface CJSONScanner () -@property (readwrite, retain) NSCharacterSet *notQuoteCharacters; -@property (readwrite, retain) NSCharacterSet *whitespaceCharacterSet; -@end - -#pragma mark - - -@implementation CJSONScanner - -@synthesize scanComments; -@synthesize notQuoteCharacters; -@synthesize whitespaceCharacterSet; - -- (id)init -{ -if ((self = [super init]) != nil) - { - self.notQuoteCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"\\\""] invertedSet]; - self.whitespaceCharacterSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; - } -return(self); -} - -- (void)dealloc -{ -self.notQuoteCharacters = NULL; -self.whitespaceCharacterSet = NULL; -// -[super dealloc]; -} - -#pragma mark - - -- (void)setData:(NSData *)inData -{ -NSData *theData = inData; -if (theData && theData.length >= 4) - { - // This code is lame, but it works. Because the first character of any JSON string will always be a control character we can work out the Unicode encoding by the bit pattern. See section 3 of http://www.ietf.org/rfc/rfc4627.txt - const char *theChars = theData.bytes; - NSStringEncoding theEncoding = NSUTF8StringEncoding; - if (theChars[0] != 0 && theChars[1] == 0) - { - if (theChars[2] != 0 && theChars[3] == 0) - theEncoding = NSUTF16LittleEndianStringEncoding; - else if (theChars[2] == 0 && theChars[3] == 0) - theEncoding = NSUTF32LittleEndianStringEncoding; - } - else if (theChars[0] == 0 && theChars[2] == 0 && theChars[3] != 0) - { - if (theChars[1] == 0) - theEncoding = NSUTF32BigEndianStringEncoding; - else if (theChars[1] != 0) - theEncoding = NSUTF16BigEndianStringEncoding; - } - - if (theEncoding != NSUTF8StringEncoding) - { - NSString *theString = [[[NSString alloc] initWithData:theData encoding:theEncoding] autorelease]; - theData = [theString dataUsingEncoding:NSUTF8StringEncoding]; - } - } -[super setData:theData]; -} - -#pragma mark - - -- (BOOL)scanJSONObject:(id *)outObject error:(NSError **)outError -{ -[self skipJSONWhitespace]; - -id theObject = NULL; - -const unichar C = [self currentCharacter]; -switch (C) - { - case 't': - if ([self scanUTF8String:"true" intoString:NULL]) - { - theObject = [NSNumber numberWithBool:YES]; - } - break; - case 'f': - if ([self scanUTF8String:"false" intoString:NULL]) - { - theObject = [NSNumber numberWithBool:NO]; - } - break; - case 'n': - if ([self scanUTF8String:"null" intoString:NULL]) - { - theObject = [NSNull null]; - } - break; - case '\"': - case '\'': - [self scanJSONStringConstant:&theObject error:outError]; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - [self scanJSONNumberConstant:&theObject error:outError]; - break; - case '{': - [self scanJSONDictionary:&theObject error:outError]; - break; - case '[': - [self scanJSONArray:&theObject error:outError]; - break; - default: - - break; - } - -if (outObject != NULL) - *outObject = theObject; -return(YES); -} - -- (BOOL)scanJSONDictionary:(NSDictionary **)outDictionary error:(NSError **)outError -{ -unsigned theScanLocation = [self scanLocation]; - -//[self skipJSONWhitespace]; - -if ([self scanCharacter:'{'] == NO) - { - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-1 userInfo:NULL]; - } - return(NO); - } - -NSMutableDictionary *theDictionary = [NSMutableDictionary dictionary]; - -while ([self scanCharacter:'}'] == NO) - { - NSString *theKey = NULL; - if ([self scanJSONStringConstant:&theKey error:outError] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-2 userInfo:NULL]; - } - return(NO); - } - - [self skipJSONWhitespace]; - - if ([self scanCharacter:':'] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-3 userInfo:NULL]; - } - return(NO); - } - - id theValue = NULL; - if ([self scanJSONObject:&theValue error:outError] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-4 userInfo:NULL]; - } - return(NO); - } - - [theDictionary setValue:theValue forKey:theKey]; - - [self skipJSONWhitespace]; - if ([self scanCharacter:','] == NO) - { - if ([self currentCharacter] != '}') - { - [self setScanLocation:theScanLocation]; - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-5 userInfo:NULL]; - } - return(NO); - } - break; - } - else - { - [self skipJSONWhitespace]; - if ([self currentCharacter] == '}') - break; - } - } - -if ([self scanCharacter:'}'] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-6 userInfo:NULL]; - } - return(NO); - } - -if (outDictionary != NULL) - *outDictionary = theDictionary; -return(YES); -} - -- (BOOL)scanJSONArray:(NSArray **)outArray error:(NSError **)outError -{ -unsigned theScanLocation = [self scanLocation]; - -//[self skipJSONWhitespace]; -if ([self scanCharacter:'['] == NO) - { - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-7 userInfo:NULL]; - } - return(NO); - } - -NSMutableArray *theArray = [NSMutableArray array]; - -[self skipJSONWhitespace]; -while ([self currentCharacter] != ']') - { - NSString *theValue = NULL; - if ([self scanJSONObject:&theValue error:outError] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-8 userInfo:NULL]; - } - return(NO); - } - - [theArray addObject:theValue]; - - [self skipJSONWhitespace]; - if ([self scanCharacter:','] == NO) - { - [self skipJSONWhitespace]; - if ([self currentCharacter] != ']') - { - [self setScanLocation:theScanLocation]; - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-9 userInfo:NULL]; - } - return(NO); - } - - break; - } - [self skipJSONWhitespace]; - } - -[self skipJSONWhitespace]; - -if ([self scanCharacter:']'] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-10 userInfo:NULL]; - } - return(NO); - } - -if (outArray != NULL) - *outArray = theArray; -return(YES); -} - -- (BOOL)scanJSONStringConstant:(NSString **)outStringConstant error:(NSError **)outError -{ -unsigned theScanLocation = [self scanLocation]; - -[self skipJSONWhitespace]; // TODO - i want to remove this method. But breaks unit tests. - -NSMutableString *theString = [NSMutableString string]; - -if ([self scanCharacter:'"'] == NO) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-11 userInfo:NULL]; - } - return(NO); - } - -while ([self scanCharacter:'"'] == NO) - { - NSString *theStringChunk = NULL; - if ([self scanCharactersFromSet:notQuoteCharacters intoString:&theStringChunk]) - { - [theString appendString:theStringChunk]; - } - - if ([self scanCharacter:'\\'] == YES) - { - unichar theCharacter = [self scanCharacter]; - switch (theCharacter) - { - case '"': - case '\\': - case '/': - break; - case 'b': - theCharacter = '\b'; - break; - case 'f': - theCharacter = '\f'; - break; - case 'n': - theCharacter = '\n'; - break; - case 'r': - theCharacter = '\r'; - break; - case 't': - theCharacter = '\t'; - break; - case 'u': - { - theCharacter = 0; - - int theShift; - for (theShift = 12; theShift >= 0; theShift -= 4) - { - const int theDigit = HexToInt([self scanCharacter]); - if (theDigit == -1) - { - [self setScanLocation:theScanLocation]; - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-12 userInfo:NULL]; - } - return(NO); - } - theCharacter |= (theDigit << theShift); - } - } - break; - default: - { - [self setScanLocation:theScanLocation]; - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-13 userInfo:NULL]; - } - return(NO); - } - break; - } - CFStringAppendCharacters((CFMutableStringRef)theString, &theCharacter, 1); -// [theString appendFormat:@"%C", theCharacter]; - } - } - -if (outStringConstant != NULL) - *outStringConstant = theString; - -return(YES); -} - -- (BOOL)scanJSONNumberConstant:(NSNumber **)outNumberConstant error:(NSError **)outError -{ -//[self skipJSONWhitespace]; - -NSNumber *theNumber = NULL; -if ([self scanNumber:&theNumber] == YES) - { - if (outNumberConstant != NULL) - *outNumberConstant = theNumber; - return(YES); - } -else - { - if (outError) - { - *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-14 userInfo:NULL]; - } - return(NO); - } -} - -- (void)skipJSONWhitespace -{ -[self scanCharactersFromSet:whitespaceCharacterSet intoString:NULL]; -if (scanComments) - { - [self scanCStyleComment:NULL]; - [self scanCPlusPlusStyleComment:NULL]; - [self scanCharactersFromSet:whitespaceCharacterSet intoString:NULL]; - } -} - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONSerializer.h b/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONSerializer.h deleted file mode 100755 index f00654d6f..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONSerializer.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// CJSONSerializer.h -// TouchJSON -// -// Created by Jonathan Wight on 12/07/2005. -// Copyright 2005 Toxic Software. All rights reserved. -// - -#import - -@interface CJSONSerializer : NSObject { -} - -+ (id)serializer; - -- (NSString *)serializeObject:(id)inObject; - -- (NSString *)serializeNull:(NSNull *)inNull; -- (NSString *)serializeNumber:(NSNumber *)inNumber; -- (NSString *)serializeString:(NSString *)inString; -- (NSString *)serializeArray:(NSArray *)inArray; -- (NSString *)serializeDictionary:(NSDictionary *)inDictionary; - -@end diff --git a/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONSerializer.m b/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONSerializer.m deleted file mode 100755 index 8cd868646..000000000 --- a/mods/atsocial_iphone_app/TouchJSON/JSON/CJSONSerializer.m +++ /dev/null @@ -1,163 +0,0 @@ -// -// CJSONSerializer.m -// TouchJSON -// -// Created by Jonathan Wight on 12/07/2005. -// Copyright 2005 Toxic Software. All rights reserved. -// - -#import "CJSONSerializer.h" - -@implementation CJSONSerializer - -+ (id)serializer -{ -return([[[self alloc] init] autorelease]); -} - -- (NSString *)serializeObject:(id)inObject; -{ -NSString *theResult = @""; - -if ([inObject isKindOfClass:[NSNull class]]) - { - theResult = [self serializeNull:inObject]; - } -else if ([inObject isKindOfClass:[NSNumber class]]) - { - theResult = [self serializeNumber:inObject]; - } -else if ([inObject isKindOfClass:[NSString class]]) - { - theResult = [self serializeString:inObject]; - } -else if ([inObject isKindOfClass:[NSArray class]]) - { - theResult = [self serializeArray:inObject]; - } -else if ([inObject isKindOfClass:[NSDictionary class]]) - { - theResult = [self serializeDictionary:inObject]; - } -else if ([inObject isKindOfClass:[NSData class]]) - { - NSString *theString = [[[NSString alloc] initWithData:inObject encoding:NSUTF8StringEncoding] autorelease]; - theResult = [self serializeString:theString]; - } -else - { - [NSException raise:NSGenericException format:@"Cannot serialize data of type '%@'", NSStringFromClass([inObject class])]; - } -if (theResult == NULL) - [NSException raise:NSGenericException format:@"Could not serialize object '%@'", inObject]; -return(theResult); -} - -- (NSString *)serializeNull:(NSNull *)inNull -{ -#pragma unused (inNull) -return(@"null"); -} - -- (NSString *)serializeNumber:(NSNumber *)inNumber -{ -NSString *theResult = NULL; -switch (CFNumberGetType((CFNumberRef)inNumber)) - { - case kCFNumberCharType: - { - int theValue = [inNumber intValue]; - if (theValue == 0) - theResult = @"false"; - else if (theValue == 1) - theResult = @"true"; - else - theResult = [inNumber stringValue]; - } - break; - case kCFNumberSInt8Type: - case kCFNumberSInt16Type: - case kCFNumberSInt32Type: - case kCFNumberSInt64Type: - case kCFNumberFloat32Type: - case kCFNumberFloat64Type: - case kCFNumberShortType: - case kCFNumberIntType: - case kCFNumberLongType: - case kCFNumberLongLongType: - case kCFNumberFloatType: - case kCFNumberDoubleType: - case kCFNumberCFIndexType: - default: - theResult = [inNumber stringValue]; - break; - } -return(theResult); -} - -- (NSString *)serializeString:(NSString *)inString -{ -NSMutableString *theMutableCopy = [[inString mutableCopy] autorelease]; -[theMutableCopy replaceOccurrencesOfString:@"\\" withString:@"\\\\" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"\"" withString:@"\\\"" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"/" withString:@"\\/" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"\b" withString:@"\\b" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"\f" withString:@"\\f" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"\n" withString:@"\\n" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"\n" withString:@"\\n" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -[theMutableCopy replaceOccurrencesOfString:@"\t" withString:@"\\t" options:0 range:NSMakeRange(0, [theMutableCopy length])]; -/* - case 'u': - { - theCharacter = 0; - - int theShift; - for (theShift = 12; theShift >= 0; theShift -= 4) - { - int theDigit = HexToInt([self scanCharacter]); - if (theDigit == -1) - { - [self setScanLocation:theScanLocation]; - return(NO); - } - theCharacter |= (theDigit << theShift); - } - } -*/ -return([NSString stringWithFormat:@"\"%@\"", theMutableCopy]); -} - -- (NSString *)serializeArray:(NSArray *)inArray -{ -NSMutableString *theString = [NSMutableString string]; - -NSEnumerator *theEnumerator = [inArray objectEnumerator]; -id theValue = NULL; -while ((theValue = [theEnumerator nextObject]) != NULL) - { - [theString appendString:[self serializeObject:theValue]]; - if (theValue != [inArray lastObject]) - [theString appendString:@","]; - } -return([NSString stringWithFormat:@"[%@]", theString]); -} - -- (NSString *)serializeDictionary:(NSDictionary *)inDictionary -{ -NSMutableString *theString = [NSMutableString string]; - -NSArray *theKeys = [inDictionary allKeys]; -NSEnumerator *theEnumerator = [theKeys objectEnumerator]; -NSString *theKey = NULL; -while ((theKey = [theEnumerator nextObject]) != NULL) - { - id theValue = [inDictionary valueForKey:theKey]; - - [theString appendFormat:@"%@:%@", [self serializeString:theKey], [self serializeObject:theValue]]; - if (theKey != [theKeys lastObject]) - [theString appendString:@","]; - } -return([NSString stringWithFormat:@"{%@}", theString]); -} - -@end diff --git a/mods/atsocial_iphone_app/main.m b/mods/atsocial_iphone_app/main.m deleted file mode 100644 index 939fb7644..000000000 --- a/mods/atsocial_iphone_app/main.m +++ /dev/null @@ -1,17 +0,0 @@ -// -// main.m -// ATutor -// -// Created by Quang Anh Do on 25/05/2010. -// Copyright Quang Anh Do 2010. All rights reserved. -// - -#import - -int main(int argc, char *argv[]) { - - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - int retVal = UIApplicationMain(argc, argv, nil, @"ATutorAppDelegate"); - [pool release]; - return retVal; -} diff --git a/mods/atutor_opencaps/README b/mods/atutor_opencaps/README deleted file mode 100755 index a109a084e..000000000 --- a/mods/atutor_opencaps/README +++ /dev/null @@ -1,179 +0,0 @@ -*********************************** -AtOpenCaps: Atutor-OpenCaps Module -*********************************** - Copyright (C) 2010 - Written by Antonio Gamba-Bari - Adaptive Technology Resource Centre - University of Toronto - - This program is free software. You can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation. - -*********************************** - -MODULE DETAILS: ---------------- -Module Name: AtOpenCaps -version: 1.0 -License: GPL -Languages: English (en), Spanish (es-es) - -AtOpenCaps is an Atutor's module; integrating Atutor with OpenCaps, -an open source web-based captioning tool. - -This module loads media and caption files stored in Atutor's course content -directory and manages all transactions needed to deliver and create caption -files using OpenCaps web captioning editor. - -This module provides a modified version of the OpenCaps web captioning tool -and it is located in the "opencaps" directory. However, for updates and future -compatibility, you must check and download new version from the OpenCaps website. - -This module also includes a version of FlowPlayer for previewing captioned projects. - -For additional updates or documentation about the tools used in this module, -please visit: -* Atutor: http://atutor.ca -* OpenCaps: http://opencaps.atrc.utoronto.ca -* Flow Player: http://flowplayer.org - -For revisions, comments, constructive criticism/feedback, -please post an issue at http://www.atutor.ca -and use the keyword "AtOpenCaps" in your post. -I will try to get back to you as soon as I can. - -Enjoy ! Anto;) - -*********************************** -Acknowledgments -*********************************** -Special thank you to Heidi Valles, Greg Gay, and Harris Wong -for their support and acute help when I found my self lost. - -Additionally, I want to thank "Google Summer Code" -(http://socghop.appspot.com/)for funding this project. - - - - -*********************************** -TABLE OF CONTENTS -*********************************** -1. Installation - 1.1. Setting Directory Permissions - 1.2. Un-installation Notes - 1.3. Known Issues - -2. Using AtOpenCaps - 2.1. Uploading Media Files - 2.2. Creating Projects - 2.3. Start Captioning - 2.4. Playing Captioned Media - -3. The Future of This Module - -*********************************** -1. Installation -*********************************** - -*********************************** -1.1. Setting Directory Permissions -*********************************** -Open Caps requires reading and writing permissions in two directories: - -/ATutor/mods/AtOpenCaps/opencaps/projects -/ATutor/mods/AtOpenCaps/opencaps/conversion_service - -Please set these permissions accordingly. - -*********************************** -1.2. Un-installation Notes -*********************************** -AtOpenCaps uses Atutor database to store matching-pairs of media and caption files. -When removing AtOpenCaps module, the the administrator can decide whether to delete this database or not. - -However, removing this module will NOT delete any media file or -captions already stored in the course content directory. - -*********************************** -1.3. Known Issues -*********************************** -This module was developed at a moment when Atutor is expanding -its compatibility with new media players and captioning media formats. -At the same time, OpenCaps is currently developing new strategies for -communicating with external systems. - -For this reasons, AtOpenCaps module presents the following known issues: - -a) When OpenCaps is loaded for first time. An empty screen shows up. -It is necessary to reload the page and then it will work. - -b) Atutor content rendering class is not ready to display the adequate -tags for flowplayer version flowplayer-3.2.2.swf. Proper handlers are -needed to allow Atutor core code to load the following FlowPlayer plugins: - - - flowplayer.audio-3.2.0.swf - - flowplayer.captions-3.2.1.swf - - flowplayer.content-3.2.0.swf - - flowplayer.content-3.2.0.swf - -*********************************** -2. Using AtOpenCaps -*********************************** - -*********************************** -2.1. Uploading Media Files -*********************************** -To upload a file click on the "Upload Media" tab. This will open Atutor's -File Management utility and allow the user to upload files to the course -content directory. For additional documentation about this utility, -please review "Atutor HandBook": (http://help.atutor.ca/index/index.php). - -*********************************** -2.2. Creating Projects -*********************************** -In order to create a new project, the user must first upload media -files by clicking on the Upload Media tab. - -To Create a new caption Project, click on the "Add Project" tab. -Then, set a name of the project, select one of the available media -files from the list, and select either to create an empty caption file -or type the name of a caption file already uploaded to the course content. - -The user can also specify the width and height of the media file. -This will be use to set the adequate size when playing captioning projects. -If not width or height are set, a default size will be used (320x240) - -Note that if the user selects the option "Select An existing Caption", -the name of the existing caption file must be typed manually. -For example, "my_caption_file.srt" - -*********************************** -2.3. Start Captioning -*********************************** -To start captioning, simply click on "My Caption Projects". -Then, click on the name of the project. This will lunch Open Caps editing tool. - -Note: Once you have finished captioning, remember to click on the link "Finish". -Then, click on the button "Submit Captions to Atutor". - -*********************************** -2.4. Playing Captioned Media -*********************************** -To preview a captioning project, click on the "Preview" tab. -Note that by clicking on this link the last project will be opened. - -Finally, click on the image and the Flow player will be loaded -using the corresponding media and caption file. - -*********************************** -3. The Future of This Module -*********************************** -Although AtOpenCaps version 1.0 provides the basic communication -between OpenCaps and Atutor, the ways in which captioning media can be -played on the web is rapidly evolving. This means that there are many -players out there capable of playing captioned media. - -The future development of this module will include compatibility with -new players as well as a wide range of caption formats. - diff --git a/mods/atutor_opencaps/doc/index.html b/mods/atutor_opencaps/doc/index.html deleted file mode 100755 index e69de29bb..000000000 diff --git a/mods/atutor_opencaps/flowplayer/LICENSE.txt b/mods/atutor_opencaps/flowplayer/LICENSE.txt deleted file mode 100755 index 2a00962f2..000000000 --- a/mods/atutor_opencaps/flowplayer/LICENSE.txt +++ /dev/null @@ -1,721 +0,0 @@ -The Flowplayer Free version is released under the -GNU GENERAL PUBLIC LICENSE Version 3 (GPL). - -The GPL requires that you not remove the Flowplayer copyright notices -from the user interface. See section 5.d below. - -Commercial licenses are available. The commercial player version -does not require any Flowplayer notices or texts and also provides -some additional features. - -======================================================================== - -ADDITIONAL TERM per GPL Section 7 -If you convey this program (or any modifications of it) and assume -contractual liability for the program to recipients of it, you agree -to indemnify Flowplayer, Ltd. for any liability that those contractual -assumptions impose on Flowplayer, Ltd. - -Except as expressly provided herein, no trademark rights are granted in -any trademarks of Flowplayer, Ltd. Licensees are granted a limited, -non-exclusive right to use the mark Flowplayer and the Flowplayer logos -in connection with unmodified copies of the Program and the copyright -notices required by section 5.d of the GPL license. For the purposes -of this limited trademark license grant, customizing the Flowplayer -by skinning, scripting, or including PlugIns provided by Flowplayer, Ltd. -is not considered modifying the Program. - -Licensees that do modify the Program, taking advantage of the open-source -license, may not use the Flowplayer mark or Flowplayer logos and must -change the fullscreen notice (and the non-fullscreen notice, if that -option is enabled), the copyright notice in the dialog box, and the -notice on the Canvas as follows: - -the full screen (and non-fullscreen equivalent, if activated) notice -should read: "Based on Flowplayer source code"; in the context menu -(right-click menu), the link to "About Flowplayer free version #.#.#" -can remain. The copyright notice can remain, but must be supplemented with -an additional notice, stating that the licensee modified the Flowplayer. -A suitable notice might read "Flowplayer Source code modified by ModOrg 2009"; -for the canvas, the notice should read "Based on Flowplayer source code". -In addition, licensees that modify the Program must give the modified -Program a new name that is not confusingly similar to Flowplayer and -may not distribute it under the name Flowplayer. - -======================================================================== - - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. 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 -them 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 prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. 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. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey 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; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If 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 convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU 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 that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - 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. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -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. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: 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 3 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, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/mods/atutor_opencaps/flowplayer/README.txt b/mods/atutor_opencaps/flowplayer/README.txt deleted file mode 100755 index f35bc19f1..000000000 --- a/mods/atutor_opencaps/flowplayer/README.txt +++ /dev/null @@ -1,302 +0,0 @@ -Version history: - -3.2.2 ------ -Fixes: -- Now recognizes following kind of urls as audio clips: 'mp3:audiostreamname' (ulrs with mp3 prefix and no extension) -- Now ignores the duration from metadata if we already got one. Fix required for pseudostreaming -- Fix to reuse buffered data when replaying a clip - -3.2.1 ---------- -- Support for RTMP redirects (tested with Wowza loadbalancing) -- Fixed video size when no size info available in clip metadata - -Fixes: -- Fix to correctly detect if the player SWF name contains a version number and if it does also use the version number -when it automatically loads the controls plugin. - -3.2.0 ------ -- canvas, controlbar and the content plugin backgound color and border color can be now given with rgb() and rgba() CSS style syntax -- Added onMouseOver() and onMouseOut() listener registration methods to the Flowplayer API -- enhancements to RSS playlist. Converted parsing to E4X, yahoo media and flowplayer namespace support. -- added feature to obtain bitrate and dimension information to a new clip custom property "bitrates" for future support for bitrate choosing. -- added getter for playerSwfName config -- if clip.url has the string "mp3:" in it, the clip.type will report 'audio' -- added setKeyboardShortcutsEnabled(), addKeyListener(), removeKeyListener() to FlowplayerBase -Fixes: -- onSeek() was not fired when seeking while paused and when using RTMP. An extra onStart was fired too. -- fireErrorExternal() was not working properly with an error PlayerEvent -- countPlugins() was throwing an error when a plugin was not found -- external swf files were not scaled properly -- the logo was unnecessary shown when going fullscreen if logo.displayTime was being used -- added a loadPluginWithConfig method to FlowplayerBase, accessible from javascript. Fixed double onload callback call. -- now handles cuepoint parameters injected using the Adobe Media Encoder -- showPlugin was not working when config.play was null -- handles 3-part duration values included in FLV metadata, like "500.123.123" -- player wasn't always reaching end of video -- fixed broken buffering: false -- fixed event dispatching when embedding flowplayer without flowplayer.js (=without playlist config field) -- fixed safari crashes when unloading player -- fixed scrubber behaviour with a playlist containing 2 images (or swf) in a row -- fixed errors in logs when using an RSS playlist -- fixed OverlayPlayButton that was showing even if it shouldn't on some cases -- fixed wrong behavior when onBeforeFinish was returning false within playlists -- /!\ Don't use the fadeIn / fadeOut controlbar's API while using autoHide. -- fixed play state button with images -- fixed splash image flickering - -3.1.5 ------ -Fixes: -- The player went to a locked state when resuming playback after a period that was long enought to send the -netConnection to an invalid state. Now when resuming playback on an invalid connection the clip starts again from -the beginning. This is only when using RTMP connections and does not affect progressive download playback. -- Custom netConnect and netStream events did not pass the info object to JS listeners - -3.1.4 ------ -Fixes: -- player did not initialize if the controlbar plugin was disabled and if the play button overlay was disabled with play: null -- works properly without cachebusting on IE -- RSS playlist parsing now respects the isDefault attribute used in mRSS media group items -- Fixed passing of connection arguments - -3.1.3 ------ -- enhancements to RSS playlist parsing: Now skips all media:content that have unsupported types. Now the type attribute -of the media:content element is mandatory and has to be present in the RSS file -- Possibility to pass a RSS file name with playFeed("playlist.rss") and setPlaylist("playlist.rss") calls. -- changes to the ConnectionProvider and URLResolver APIs -- Now automatically uses a plugin that is called 'rtmp' for all clips that have the rtmp-protocol in their URLs. -- Added possibility to specify all clip properties in an RSS playlist - -Fixes: -- the result of URL resolvers in now cached, and the resolvers will not be used again when a clip is replayed -- some style properties like 'backgroundGradient' had no effect in config -- video goes tiny on Firefox: http://flowplayer.org/forum/8/23226 -- RSS playlists: The 'type' attribute value 'audio/mp3' in the media:content element caused an error. -- Dispatches onMetadata() if an URL resolver changes the clip URL (changes to a different file) -- error codes and error message were not properly passed to onEvent JS listeners - -3.1.2 ------ -- The domain of the logo url must the same domain from where the player SWF is loaded from. -- Fullscreen can be toggled by doublclick on the video area. -Fixes: -- Player was not initialized correctly when instream playlists were used and the provider used in the instream clips was defined in the common clip. -- A separator in the Context Menu made the callbacks in the following menu items out of order. Related forum post: http://flowplayer.org/forum/8/22541 -- the width and height settings of a logo were ignored if the logo was a sWF file -- volume control and mute/unmute were not working after an instream clip had been played -- now possible to use RTMP for mp3 files -- Issue 12: cuepointMultiplier was undefined in the clip object set to JS event listeners -- Issue 14: onBeforeStop was unnecessarily fired when calling setPlaylist() and the player was not playing, - additionally onStop was never fired even if onBeforeStop was -- fixed screen vertical placement problems that reappeared with 3.1.1 -- The rotating animation now has the same size and position as it has after initialized - -3.1.1 ------ -- External configuration files -- Instream playback -- Added toggleFullscreen() the API -- Possibility to specify controls configuration in clips -- Seek target position is now sent in the onBeforeSeek event -Fixes: -- The screen size was initially too small on Firefox (Mac) -- Did not persist a zero volume value: http://www.flowplayer.org/forum/8/18413 - -3.1.0 ------ -New features: -- clip's can have urlResolvers and connectionProviders -- Added new configuration options 'connectionCallbacks' and 'streamCallbacks'. Both accept an Array of event names as a value. - When these events get fired on the connection or stream object, corresponding Clip events will be fired by the player. - This can be used for example when firing custom events from RTMP server apps -- Added new clip event types: 'onConnectionEvent' and 'onStreamEvent' these get fired when the predefined events happen on the connection and stream objects. -- Added Security.allowDomain() to allow loaded plugins to script the player -- Added addClip(clip, index) to the API, index is optional -- Possibility to view videos without metadata, using clip.metaData: false -- Now the player's preloader uses the rotating animation instead of a percent text to indicate the progress - of loading the player SWF. You can disable the aninamtion by setting buffering: false -- calling close() now does not send the onStop event -- Clip's custom properties are now present in the root of the clip argument in all clip events that are sent to JS. - -Bug fixes: -- The preloader sometimes failed to initialize the player -- Allow seeking while in buffering state: http://flowplayer.org/forum/8/16505 -- Replay of a RTMP stream was failing after the connection had expired -- Security error when clicking on the screen if there is an image in the playlist loaded from a foreign domain -- loadPlugin() was not working -- now fullscreen works with Flash versions older than 9.0.115, in versions that do not support hardware scaling -- replaying a RTMP stream with an image in front of the stream in the playlist was not working (video stayed hidden). Happened - because the server does not send metadata if replaying the same stream. -- the scrubber is disabled if the clip is not seekable in the first frame: http://flowplayer.org/forum/8/16526 - By default if the clip has one of following extensions (the typical flash video extensions) it is seekable - in the first frame: 'f4b', 'f4p', 'f4v', 'flv'. Added new clip property seekableOnBegin that can be used to override the default. - -3.0.6 ------ -- added possibility to associate a linkUrl and linkWindow to the canvas -Fixes: -- fix for entering fullscreen for Flash versions that don't support the hardware scaled fullscreen-mode -- when showing images the duration tracking starts only after the image has been completely loaded: http://flowplayer.org/forum/2/15301 -- fix for verifying license keys for domains that have more than 4 labels in them -- if plugin loading failis because of a IO error, the plugin will be discarded and the player initialization continues: - -3.0.4 ------ -- The "play" pseudo-plugin now supports fadeIn(), fadeOut(), showPlugin(), hidePlugin() and - additionally you can configure it like this: - // make only the play button invisible (buffering animation is still used) - play: { display: 'none' } - // disable the play button and the buffering animation - play: null - // disable the buffering animation - buffering: null -- Added possibility to seek when in the buffering state: http://flowplayer.org/forum/3/13896 -- Added copyright notices and other GPL required entries to the user interface - -Fixes: -- clip urls were not resolved correctly if the HTML page URL had a query string starting with a question mark (http://flowplayer.org/forum/8/14016#post-14016) -- Fixed context menu for with IE (commercial version) -- a cuepoint at time zero was fired several times -- screen is now arranged correctly even when only bottom or top is defined for it in the configuration -- Fixed context menu for with IE (commercial version) -- a cuepoint at time zero was fired several times -- screen is now arranged correctly even when only bottom or top is defined for it in the configuration -- Now possible to call play() in an onError handler: http://flowplayer.org/forum/8/12939 -- Does not throw an error if the player cannot persist the volume on the client computer: http://flowplayer.org/forum/8/13286#post-13495 -- Triggering fullscreen does not pause the player in IE -- The play button overlay no longer has a gap between it's pieces when a label is used: http://flowplayer.org/forum/8/14250 -- clip.update() JS call now resets the duration -- a label configured for the play button overlay did not work in the commercial version - -3.0.3 ------ -- fixed cuepoint firing: Does not skip cuepoints any more -- Plugins can now be loaded from a different domain to the flowplayer.swf -- Specifying a clip to play by just using the 'clip' node in the configuration was not working, a playlist definition was required. This is now fixed. -- Fixed: A playlist with different providers caused the onMetadata event to fire events with metadata from the previous clip in the playlist. Occurred when moving in the playlist with next() and prev() -- the opacity setting now works with the logo -- fadeOut() call to the "screen" plugin was sending the listenerId and pluginName arguments in wrong order -- stop(), pause(), resume(), close() no longer return the flowplayer object to JS -- changing the size of the screen in a onFullscreen listener now always works, there was a bug that caused this to fail occasionally -- fixed using arbitrary SWFs as plugins -- the API method setPlaylist() no longer starts playing if autoPlay: true, neither it starts buffering if autoBuffering: true -- the API method play() now accepts an array of clip objects as an argument, the playlist is replaced with the specified clips and playback starts from the 1st clip - -3.0.2 ------ -- setting play: null now works again -- pressing the play again button overlay does not open a linkUrl associated with a clip -- now displays a live feed even when the RTMP server does not send any metadata and the onStart method is not therefore dispatched -- added onMetaData clip event -- fixed 'orig' scaling: the player went to 'fit' scaling after coming back from fullscreen. This is now fixed and the original dimensions are preserved in non-fullscreen mode. -- cuepoint times are now given in milliseconds, the firing precision is 100 ms. All cuepoint times are rounded to the nearest 100 ms value (for example 1120 rounds to 1100) -- backgroundGradient was drawn over the background image in the canvas and in the content and controlbar plugins. Now it's drawn below the image. -- added cuepointMultiplier property to clips. This can be used to multiply the time values read from cuepoint metadata embedded into video files. -- the player's framerate was increased to 24 FPS, makes all animations smoother - -3.0.1 ------ -- Fixed negative cuepoints from common clip. Now these are properly propagated to the clips in playlist. -- buffering animation is now the same size as the play button overlay -- commercial version now supports license keys that allows the use of subdomains -- error messages are now automatically hidden after a 4 second delay. They are also hidden when a new clips - starts playing (when onBeforeBegin is fired) -- added possibility to disable the buffering animation like so: buffering: false -- pressing the play button overlay does not open a linkUrl associated with a clip -- license key verification failed if a port number was used in the URL (like in this url: http://mydomain.com:8080/video.html) -- added audio support, clip has a new "image" property -- workaround for missing "NetStream.Play.Start" notfication that was happending with Red5. Because of this issue the video was not shown. -- commercial version has the possibility to change the zIndex of the logo - -3.0.0 ------ -- Removed security errors that happened when loading images from foreign domains (domains other than the domain of the core SWF). - Using a backgroundImage on canvas, in the content plugin, and for the controls is also possible to be loaded - from a foreign domain - BUT backgroundRepeat cannot be used for foreign images. -- Now allows the embedding HTML to script the player even if the player is loaded from another domain. -- Added a 'live' property to Clips, used for live streams. -- A player embedded to a foreign domain now loads images, css files and other resources from the domain where the palyer SWF was loaded from. This is to generate shorter embed-codes. -- Added linkUrl and linkWindow properties to the logo, in commercial version you can set these to point to a linked page. The linked page gets opened - when the logo is clicked. Possible values for linkWindow: - * "_self" specifies the current frame in the current window. - * "_blank" specifies a new window. - * "_parent" specifies the parent of the current frame. - * "_top" specifies the top-level frame in the current window. -- Added linkUrl and linkWindow properties to clips. The linked page is opened when the video are is clicked and the corresponding clip has a linkUrl specified. -- Made the play button overlay and the "Play again" button slightly bigger. - -RC4 ---- -- Now shows a "Play again" button at the end of the video/playlist -- Commercial version shows a Flowplayer logo if invalidKey was supplied, but the otherwise the player works -- setting play: null in configuration will disable the play button overlay -- setting opacity for "play" also sets it for the buffering animation -- Fixed firing of cuepoints too early. Cuepoint firing is now based on stream time and does not rely on timers -- added onXMPData event listener -- Should not stop playback too early before the clip is really completed -- The START event is now delayed so that the metadata is available when the event is fired, METADATA event was removed, - new event BEGIN that is dispatched when the playback has been successfully started. Metadata is not normally - available when BEGIN is fired. - -RC3 ---- -- stopBuffering() now dispatches the onStop event first if the player is playing/paused/buffering at the time of calling it -- fixed detection of images based on file extensions -- fixed some issues with having images in the playlist -- made it possible to autoBuffer next video while showing an image (image without a duration) - -RC2 ---- -- fixed: setting the screen height in configuration did not have any effect - -RC1 ------ -- better error message if plugin loading fails, shows the URL used -- validates our redesigned multidomain license key correctly -- fix to prevent the play button going visible when the onBufferEmpty event occurs -- the commercial swf now correctly loads the controls using version information -- fixed: the play button overlay became invisible with long fadeOutSpeeds - -beta6 ------ -- removed the onFirstFramePause event -- playing a clip for the second time caused a doubled sound -- pausing on first frame did not work on some FLV files - -beta5 ------ -- logo only uses percentage scaling if it's a SWF file (there is ".swf" in it's url) -- context menu now correctly builds up from string entries in configuration --always closes the previous connection before starting a new clip - -beta4 ------ -- now it's possible to load a plugin into the panel without specifying any position/dimensions - information, the plugin is placed to left: "50%", top: "50%" and using the plugin DisplayObject's width & height -- The Flowplayer API was not fully initialized when onLoad was invoked on Flash plugins - -beta3 ------ -- tweaking logo placement -- "play" did not show up after repeated pause/resume -- player now loads the latest controls SWF version, right now the latest SWF is called 'flowplayer.controls-3.0.0-beta2.swf' - -beta2 ------ -- fixed support for RTMP stream groups -- changed to loop through available fonts in order to find a suitable font also in IE -- Preloader was broken on IE: When the player SWf was in browser's cache it did not initialize properly -- Context menu now correctly handles menu items that are configured by their string labels only (not using json objects) -- fixed custom logo positioning (was moved to the left edge of screen in fullscreen) -- "play" now always follows the position and size of the screen -- video was stretched below the controls in fullscreen when autoHide: 'never' -- logo now takes 6.5% of the screen height, width is scaled so that the aspect ratio is preserved - -beta1 ------ -- First public beta release diff --git a/mods/atutor_opencaps/flowplayer/flowplayer-3.2.2.min.js b/mods/atutor_opencaps/flowplayer/flowplayer-3.2.2.min.js deleted file mode 100755 index 723243729..000000000 --- a/mods/atutor_opencaps/flowplayer/flowplayer-3.2.2.min.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * flowplayer.js 3.2.2. The Flowplayer API - * - * Copyright 2010 Flowplayer Oy - * - * This file is part of Flowplayer. - * - * Flowplayer is free software: 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 3 of the License, or - * (at your option) any later version. - * - * Flowplayer 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 Flowplayer. If not, see . - * - * Date: 2010-05-20 17:15:38 +0000 (Thu, 20 May 2010) - * Revision: 480 - */ -(function(){function g(o){console.log("$f.fireEvent",[].slice.call(o))}function k(q){if(!q||typeof q!="object"){return q}var o=new q.constructor();for(var p in q){if(q.hasOwnProperty(p)){o[p]=k(q[p])}}return o}function m(t,q){if(!t){return}var o,p=0,r=t.length;if(r===undefined){for(o in t){if(q.call(t[o],o,t[o])===false){break}}}else{for(var s=t[0];p1){var t=arguments[1],q=(arguments.length==3)?arguments[2]:{};if(typeof t=="string"){t={src:t}}t=i({bgcolor:"#000000",version:[9,0],expressInstall:"http://static.flowplayer.org/swf/expressinstall.swf",cachebusting:true},t);if(typeof o=="string"){if(o.indexOf(".")!=-1){var s=[];m(n(o),function(){s.push(new b(this,k(t),k(q)))});return new d(s)}else{var r=c(o);return new b(r!==null?r:o,t,q)}}else{if(o){return new b(o,t,q)}}}return null};i(window.$f,{fireEvent:function(){var o=[].slice.call(arguments);var q=$f(o[0]);return q?q._fireEvent(o.slice(1)):null},addPlugin:function(o,p){b.prototype[o]=p;return $f},each:m,extend:i});if(typeof jQuery=="function"){jQuery.fn.flowplayer=function(q,p){if(!arguments.length||typeof arguments[0]=="number"){var o=[];this.each(function(){var r=$f(this);if(r){o.push(r)}});return arguments.length?o[arguments[0]]:new d(o)}return this.each(function(){$f(this,k(q),p?k(p):{})})}}})();(function(){var h=document.all,j="http://www.adobe.com/go/getflashplayer",c=typeof jQuery=="function",e=/(\d+)[^\d]+(\d+)[^\d]*(\d*)/,b={width:"100%",height:"100%",id:"_"+(""+Math.random()).slice(9),allowfullscreen:true,allowscriptaccess:"always",quality:"high",version:[3,0],onFail:null,expressInstall:null,w3c:false,cachebusting:false};if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){}})}function i(l,f){if(f){for(key in f){if(f.hasOwnProperty(key)){l[key]=f[key]}}}return l}function a(f,n){var m=[];for(var l in f){if(f.hasOwnProperty(l)){m[l]=n(f[l])}}return m}window.flashembed=function(f,m,l){if(typeof f=="string"){f=document.getElementById(f.replace("#",""))}if(!f){return}if(typeof m=="string"){m={src:m}}return new d(f,i(i({},b),m),l)};var g=i(window.flashembed,{conf:b,getVersion:function(){var f;try{f=navigator.plugins["Shockwave Flash"].description.slice(16)}catch(n){try{var l=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");f=l&&l.GetVariable("$version")}catch(m){}}f=e.exec(f);return f?[f[1],f[3]]:[0,0]},asString:function(l){if(l===null||l===undefined){return null}var f=typeof l;if(f=="object"&&l.push){f="array"}switch(f){case"string":l=l.replace(new RegExp('(["\\\\])',"g"),"\\$1");l=l.replace(/^\s?(\d+\.?\d+)%/,"$1pct");return'"'+l+'"';case"array":return"["+a(l,function(o){return g.asString(o)}).join(",")+"]";case"function":return'"function()"';case"object":var m=[];for(var n in l){if(l.hasOwnProperty(n)){m.push('"'+n+'":'+g.asString(l[n]))}}return"{"+m.join(",")+"}"}return String(l).replace(/\s/g," ").replace(/\'/g,'"')},getHTML:function(o,l){o=i({},o);var n=''}o.width=o.height=o.id=o.w3c=o.src=null;o.onFail=o.version=o.expressInstall=null;for(var m in o){if(o[m]){n+=''}}var p="";if(l){for(var f in l){if(l[f]){var q=l[f];p+=f+"="+(/function|object/.test(typeof q)?g.asString(q):q)+"&"}}p=p.slice(0,-1);n+='"}n+="";return n},isSupported:function(f){return k[0]>f[0]||k[0]==f[0]&&k[1]>=f[1]}});var k=g.getVersion();function d(f,n,m){if(g.isSupported(n.version)){f.innerHTML=g.getHTML(n,m)}else{if(n.expressInstall&&g.isSupported([6,65])){f.innerHTML=g.getHTML(i(n,{src:n.expressInstall}),{MMredirectURL:location.href,MMplayerType:"PlugIn",MMdoctitle:document.title})}else{if(!f.innerHTML.replace(/\s/g,"")){f.innerHTML="

    Flash version "+n.version+" or greater is required

    "+(k[0]>0?"Your version is "+k:"You have no flash plugin installed")+"

    "+(f.tagName=="A"?"

    Click here to download latest version

    ":"

    Download latest version from here

    ");if(f.tagName=="A"){f.onclick=function(){location.href=j}}}if(n.onFail){var l=n.onFail.call(this);if(typeof l=="string"){f.innerHTML=l}}}}if(h){window[n.id]=document.getElementById(n.id)}i(this,{getRoot:function(){return f},getOptions:function(){return n},getConf:function(){return m},getApi:function(){return f.firstChild}})}if(c){jQuery.tools=jQuery.tools||{version:"3.2.0"};jQuery.tools.flashembed={conf:b};jQuery.fn.flashembed=function(l,f){return this.each(function(){$(this).data("flashembed",flashembed(this,l,f))})}}})(); \ No newline at end of file diff --git a/mods/atutor_opencaps/flowplayer/flowplayer-3.2.2.swf b/mods/atutor_opencaps/flowplayer/flowplayer-3.2.2.swf deleted file mode 100755 index 598c3e2a019e9112183a1d5d13822968ab8e54a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 115213 zcmV(#K;*weS5pdia038%+MK-!U>r$xFx)*?&wc6g?Y1pjvUe=Y_8zR*Yb1?q?dn<` z_AZOvnxjWE>(TTuJ!45gz#JP0H-Y6?j)+adnQ#Wea_xo$NPq=#Zk-Pn|e*>Nr3gH#e${ z?E3Mld1&AcDqvhU^YwDAQ8ub7hO;@N*|>dRfR|dxTZPt|^$HbP$e++F`l?=Sm?usS zorHo4`H`YgU(Gh|$ku9=az2a2omf9^mW=$Rwd`g6c(IZ-OShe{0WnXb+^Fbxqzgt) zS0^g^x_Vko+xZEafgo_fZs;A3Ze}s}P~KQQQL7t;W**v9grX?3GYb|`Yvw9tv!vJW zXjU&(jWt$<9g8sex}I$qtq>v((<|BPN;A8n-;tT2G%HMP%r^8p?rv7q(<$}T@X2A; z3XHt%MB8BV7?{61r1AJq+_y<%u4kTk=6OLkOt26B-0q(xCHn8-N5A-AgD~NL9)!`? ziWOt6R>^MYb?tIlU(@F5dd0{V^t$wT_r6_{1b|Ypo?X>XN^xmOQe?NwBRvDL-;^cK zWusgO(_9ScmvI8U8T|2%L6qs6%{{2+8_K9*RP=1M3u+s(Ya41d%9Z$(u`*^!a(HnqY)Yo9S zT5goHmGTSqXt|21dVzH;0pp?9CvXJMW~+sYUJuvmdM#VmsX{lD-`8PeMxaimU@X?N zdEKw+tTjIN>siazs|t_vl&eL6N&)-n&?3e0E4r}3W#Hp5H*`ifM(qOo837`5Io+2}V)%_@v)&ZsneQ09tW-?vTj z2ulu5WzJ=$wDalt8F#tb2;_Mybe=FdGcg-tpPBjj+4(5@URau&o6jsP@TBp~=+c=m zwU19+P%Br>Mz)&Q%}A|YUWM7YtS@fVbe~qxYmJfzYxJd;7SGPk@4H*Cn(96EY}3@$ z2Z-3|ITPm4s1FtN3tpmOp>j1}X%_Uw@~R%2n9NL#YYUmV%zS!rcHX0ojHq6%R4%|= znGK^hg-A1dCc3Jx8ug8ZYPJTXtKmTaFLfi)fMOPnbAT}ghVmZlX<#~iA9QAJ@oWI_ zf}vRy&}^((uLB-o-O9Pl{KDkyjQix!Z~(D$3a6+Ok`Gx(?!h+2vxNe!&Z)B5&;cEy z>GAQ*xVAW}Ei9(bWYpG`FnDxCHSt3=0jbrpsd_0Gq<_zs3yqRnT~|XCJgb*iN{#*P zC8X5cMngAMYDGZ}verxj!iFeeisD0=nZ?Y!HZh-`&U9~CErUnZAOSDJ%B&1J@~OAq zuG%Rn)oz%2yP8mW1Zx_^bk$)pF6%8r5Vn`?;L$);UvE&=C!NtL6_>u6tpL?7Y^V&a zAQe`)TGt!RdKC#44DMK|Tq*QUWr1`7^=}2-OAFKy2YFNr)HR|itGa1IbG;b^l=Z-B zwp=CB5@JgSm#NtWxG=64sd+|qbYlh@yQkCCi=u-x6X{BMrRratoztc=6N}y~2BVa+ zkk3~1X#?X(0XSf80sP;xT8RDRhTRF#VRKsBWef& zjQ)+NJK*~)VEG0t)s+>*&F3CJszO`^)^kUEx~?NLE=VK&vdp? z^41Ng*Q-vCs)HW&Qtqhy0OVS#)%5yU*3?}W)F_{tbr{HMwvx#34;tAbZhC-nCNK^| z9>B+n`@ZQZ1^#g1h8Z80BXaJk!pON{c}E2N3e;T-Jiun+f*Nm$&r}Qk2Z*P*p!&0U z*d0ux?rGq@z(QaOQp!!w!qupejri7B(=8 z(6>feH-|h;+{bX(VV%PMjELkJ2P)u2ny>m{?#~*{x+#wY;d8oNZ2}3y&jlTtS}OH;VCa=^N?KQoU|0TPUyI#8M zioEM(@~)T5yIvvhdZoO}2g&|j`+Faidw*N*JG~3QeKAFjB|J%AS9ecu-;SNT0s(oq zdr#88cbDw;MP)T|U{@e2C-L`S_zkimyA+p4k-duSQ)ESP2NXG|$RR}zD{@5f#1wBr zQMweRTTyxxcdw%KDc&85vQtrZDe`Vb*`p|X6=k0iP?f*|C2&xY4=HlLA|F=dBT8UE zkq4E)Q6+FpkyA?OxDpytXv$S4teI5M09{%1S?{+Ej8)YT_ zW?4!8D*U|_{$2xrZkb6m%D!KR@_qyU-Vc8t0LYKX%KneS z_s8YkFc+VIuTMgGpOT}$BYOjHgulcEzoG;rms`dkDp!^r zg-fDX`(q1;#OjlNf$Auu3+jRp^h}04evI~t8kC@;P){fv@JVto0^N_gB!5f-87Co0 zNvTVgyxq{#9?aD%OYS~d^6h});+}wCiiUT}QZEQc-cV?_EXDT7QukiBv}2zvb?uj> zq$*4C1G1Djh`IN=q`pJ4)Z_C6g3^INzf0PE7~+q}M<9PN*zcD147eqA&@Js7a7p`* zLfR>L&?W6X<_SckVQ6MBe1p%GlHJE8U&`ekO1MM)U7qj>pF8Dt5Boe2chcugdEBRb za?0yIEd`+1!7gv)MoEF9Zj$@~X_s_p=go=m@mr)|N*YK6Z+MQ+r5uuP_4$=C`9Q*d zbR^;Kf36gU4&CPSDre+93E#l}gfe)$6oJz2pfd0Dd6a$fT?x#7w93M8zx0u}9ZLdYAH`S< zCF1}*+bvyK6vZ!M@gBE31nd6l@cCok8`fp@ihC6rQ^IyE%`Qn-i;1LywLAzhXRgln zNxFP>qDvw$U9QNZ(sJ@urNo7E0102S=OA|lzNsgUs^T|5DZ|%>pC=uA`q=OdtMY{% zsa4%okvCJ-P5dpM$1E2UYALbT?>ZwN%j);tFFy|kU-DubkFq9Sa9?;J)tq=ho^Z=& z$^hFto+k zwUoSxvo=5<12UxgJ&<}c<}c0_bE#h{=C63ZcP#-_>B!k@%Z1c0%c)n%qk#Vtx-0c7 z@yMZ1-b*Hk&<0F!EEp>=T+yD_r zG2$?fH~|qmFyc)zk2wi3KKg>jLa7lf)ejB3@mlsq2uIy6kM{-`_DSjLwPoc~h^FxS zs)yo$X%|+nO{~ffl@2c7bal2WUxijemY7@icq5SI>eb@G2~{rbg2=cx;PHMAP*;8E z>17y`ZZwHVgKm!p@;Im z%p^D(RPE)Q+6;W+)@4K+miGgeB)o2qS49lm#gG(6 zJQ4w zd#+(~pE?xf4s#}+Ho>kBCX(B5?2q3lskrmJEPWmZU z*hnLdD8Qtp-YIV)82;l)yN<@YJEW!MqwyoSq;pg*csg(j~7<t$THp8Mpzr8q?If>;mR4t87F4@34ncJ{-NxYtTN3W@vd#G{b7 z-%3Ohq1uT@An|}moJ5R2D4Maxn&H}8@N_Hnp}W^J-eCOlsEC~*3H!WK;=-AUGtwqx%z2)|pXFaleGC9MbDr6k zxL{$MNGbB(coYZ)G~zosZ}FwG6Y`h6Id9I_^S_CvraVcv=a)U$fbXkUuE=>0w8RU4 zKKKLTlJ~=3K)v!ZIUl6-5X6V!F9Ltj1250VmT$ohX2S25r3<$l%g2kiJdsc2;<-fj z7JtGYf9j!Q2{(*KN`C137hW!3n|Qe_Lpeb8im#BNstY#*VY^vQjsnRlR+4?tqz}tE zFLm`ho2gIBur3~oN1V|RfpiUfOJlp4^FfE>z-#8bDPMO+k|6Cfa_V>G?`%Q>bRd51 z<@rRs2MH!LZ6EaP!o)S8iZ9J6vlFgUiFo3#o_Pja3mHEv&%Q*Ce_g`D!c^ET{c7`4VV8(rK9=;uK<1*UFUr6$0nxvf3m0DsQ*dD- z7t4itPd>$Z5(ijploz7ohoJR$B=%At*q}XUGxa5T`IgPp<1%*V;vGk_cK|vZcX`~N zPXSRKc$(1W$kXvh;RizRg6h7XQoggxhb@mk2ovIB0XcpF0=KY$D?SH-CuA0K$6;Di z5f<>oZ-PLO1-$V=2>c$0^Tk0bNPU@ylsHg(+{60)aTosUckg})^lI&yXFC2L(s1bx zxnaoxE2>_3wTuMd!mH)GUoA@*O8tR+VeHz(ugKEG7%cX$%9|K`O>6MAJopwCd>soe z-?sS>QHB$^a$#G#)*tv-5?G0A6R(%0hvM*+`i4w_&4&PNxP?xh5gpDccP=(qpqiLM|2p)3C;Ph#)GkL7>ze%GZ<$@lgzOCn?G3GWv^a%cUY zzcIBI|39y^qAS;iKl$F}?|S~`F3I(tVeeY+>polhx}5s>j`L6c!A0o(8Vdh^hGr6cQ7X5z)FRqz`R z?)moKPyFmpAAiB$KKS0-{`g~$z4R|X_j~V(ePQD8i(dVmdn+R^=zClA&{F#2U--AX zM3xU;4Ia8#_1#_lyItp||K!TUuXca;$i8n&AAh&J@~tcKgSA)u=CJ$kPd)z!e`G$< zb-$$ju=?1)o_PMJ^Dl^e@{1>b~<{&zkB=S zn|}7^S8hr^_|!XGUw^mjk{bM{KYQfXx8L%%y9RPsq`;F;|K#}d=ic*I(*x4O>%JR5 zQ~a0V*_QzCJTLvI>}bSC|6Do!?c%Z5f8#U%{P5{Fyxv#sUw`9k){--y{6Wz%Vjo+J zyy&yP^KSXd_oacSr8~|_&->Rm{r9(`XAV8lbx=C?5C8ASp1kAMbMlQlykGg|_xsfN zr=*Dk&;RB_jUULTYw{zhzdSfB-|&0-9d@mM6npvGo?Mn6`SmaVTJ_@k@{@mX$Jc-M z)nEPT@~-HLNuet5Llf#wW-Mf9C8+z{Cn`7ml$fGZm`foe#|5|rN zzj4>U-}TeR-0gqz7v5LhC1?NPGylD3>DpU=e51ZIbL}hl8vpS04mtD7(gVMLHMJ)F z%lkr7EdAcK`(I!A%zGaE^r`0#?)>(!9NLsd|NSjbz4$Lb`nJ!!_pP6P%{vEw-}j>L zN{{}FH2kgN`bX;z-}Byw@BY?TN`GB@!u2nk(ibOQe6zXd-qm~FvwC;)Z%Vh{`qq@> z7~|LNFu(bMTLw=&dF{Ys&);-CI(KYf@89%Y{qCoye)#?4KfQ9O@#k;dJow%pNIwjC z*vK$t&l`L`{Q1i7y!em%Z$QeWheTR(NKTzvS;SG?zg(#}Wq?-k$tmMgB? z7o~t-|LXL;Z+~a~_AB1AKbL$L9$DJ?l2yt3B{9d?p+9`|oj>`Pw{`vek?($B_e(0P zwZP0f`rqN2``SzL$A9+8N8bFw_n-al`C?^6y5}8-hiZSgcJiC~7cNRYkH7Y_A2~Pl zqn}>7;$8ZvwBvJ)X6{4ZyW)D&cL8;qE9dXM_MTmDz2d!lUQ*7y_S1X!9lPSa^ztA3 zyLWu##@Bu6hj+O?@{kmM>d9T7I&)ay+}!|25Jx!RW!R^~4n%y<*}(?z?c8yuALOZ+JNW*LVD2hvff< z&mZWyxGa^9LWYNaF8Md+qyz7KN#Bn%Ki5hnN&4&)U-caOxGH_^Phb3zy)XE#lp5NU zK7RVOU%UGavHc7GhU>`B`iELH(Z4eM8<0v;Y*X@_kmUF)KmDWM{C@UN-?yU`4c@pJ z`u6zoOP}jHRR4>geWAFx=lvtsUh$I`R^RcUK-*^sN{Wr|sC?{i@A;osed&Ka>V4zp z|GX#u(EI<-&!6`n`^Sp+K?{OngacL!h5$c9(1Q3oumx^x!N+=X`wq0U04rcAtD1kp znKIn-`fvTo#A_ek^=>IRAi4hWu@64>(K%ObQ+jveBX4`<9e-Vrf;%O7_rwP$-u!X- zO`B3-s8G3l;=tcOeCp(%UEBZM;!^Q*C!|Mz{NYbY=l3T5`JTh~HKY?KpZcdi{gwZD z?Ymz3^gldubp|%$@f&QtvoRQgnVs% z_YF^c;&We3zOuYq+8LC5qklc|lgIA;&=b<5HR;6eM_&8LkEMa26!^VekCn#$zId1P zzBfsU-zmW`hQ%<3tYLg1{2PH`RIW;%A<4x@?6d!PqxX-0JRiT(I-S+{$mj2W?$1{S z-zk0LojV`>*2ELOZ|fhvB7b1&EyohSp}*UGIsZ4m{huG*lQ{a*|Jrl&{A-K?I z&IhHyKMp*;a`%O&U-abPUi|pP)3edHzv8`*{q%SL@vduusKBj=Xj1e)XzjQgB9CWvm#Irz60G6(%5GXQl*?=q~GZ_>ue_Ax7x{FkLOLk{yH;lsX@;=Jd*0qk`;B z_}L)l@c>$iwu3n!ru1S%dc6CalWyDG<`kLRz*hAp_s`roIk7POqr4lxf+4>rpt#(= zPyO{bfAq`` zzs|$IFW?^kvmMN`ha2N`w>5m#DCm^{ol}p&XPcQ1x7F!s%LMCIA=u=Co^QfjZP-!F{K0AR04<@eXX_ggYhJJx?_9PDcxWxv1Pb zW@AK)4;7kJR3d;7m&;Ht3$+-dMACTNpUt!75p&=Rb~k7fI4ooZ?Fc9_IAvMY^lZVp z$<bnKM#0?RI;udo{1~RGo7M~E>_Yj4dSFIx!1~v-t6pXqXAN|w z3cb-26U|D+%-40jI-RWoKs{==a5QV`Ks~aJrir;5dSDT4Ysz}1ARlAafgGDy<74;e z8#yCeFYu)wWi^YziV=3=nhu2l3G z_19i$aSO#3nzfoyZ$w1PDALC&O^R{0C)UqVwj9F3ptI9@wHbGOvq^PCOg8k@05+Tk z$Ul~?RIrC=>CnS03)FnJS~VJKPFK;0pv!^At8BflR$6{jP*fYu|6^=#Ed>)tR0$4W35dgY*nmZBrD zL$zYdp1iTj?RZVSPG($$w?hw_Mm2Ev!tBhVaY?U+cx!0Qv$0ud7Uvc`C5Md)Lr3&0EJbh0LWU ztI8@7QH^ln>}X|cr7Bq>9(v5Ej_NR{IwK~!J8zmH z5jSR`~DIxSZl$ZJx08vW3yV=EMmRS<)DBQwKEG)&XY2(+HcnQvBfQ_*tN@Ho{$@eGGC zo3oP%)|E-SvC(Wxe|Er}w6+`2J%33rbYnYa>*FmW<73_S=8^vh)I}i?qiQb@G|0sO z4qqg<;;1?aRku|Zv^(HqGvyZsjh(C=M?@l^5^;98Q}?hwP9Rx1m#v#@XYSI-z!WCl z-oAWV4LOOBmd8GhK`US#5ROH(nq!lSvJx#Csd0wXWP3TZ8TU!HOq5dAL<*6-j26C- zYpR?FeoBYk1nqFyHnM0C3lr38yhyVfEj!1WCeRIQBQiq{8~w1^$ksUlG$RG$tW5x7 zta&r~8t01nDqwZ--Vwvm3TOeci zIq0E&%Kp5O4|p4!U;~`AKTq%AL%D_14I5R$H0pVu4b{SdDH>y#yIA_!Mx!Ps#Z02L zV7gjx3`|g9MY9oy+7X=A5Y3NPYcD;y6+`xJ0V1L}&Mf>wyqP$c{<1ljMN{qFEYdlg zXUoib9MRNb$#@@-r~R(#Bb_ z-udLypvG|p3jtf;77UfFhWZiP&H;6RBF2qo zju#PP-De%+$VQXGk!=fCyQ6G!^fc3zwd{tOZZ-^@$_VV8tRQ5)yHTKQw_)w#Q<7#Y zkw{B|FH2jYkpQmBnleI)q*iQi#%{A62ZX4h7kXLK+vx`EEl7&&io(u{AYk_u_GKCb z!7J|TB=V0~B7Z=)q!P{gv@Fo}*w^m#CUPcZLHYs3}{eZQ^u(<&upi$ghzTpS*K+*oJ$#%}L z5TTbqz*9TjoN)ql1v zFE=)n%Vo0+bq9DlU^~l^Z+NqaEOE1~@V%XvAeU3a7y@DeY>cPa&uR8^BfF{CIsZ*w%HSnPAM_1yiK0$-hCkIgnpbsG z7xLA$>*vMnr8$ zsdr$u$yL&&kh~)DZ?~y(j^TPMmMOora=}$D?CJh+$hqvoNc5VXX)>ri*}E)#ahQtsL#<9091(?$h(XmLwGI*?r_t=PWI)Gxl4H0P zE)2zlAi%WzW&kC8%wpm+u`QC%3>$eCmB59=K1HkBRO$WOFK8PmuH|UAwM4LZ!I&o< zn5}oRcL%Q9fYoKG-n5Fy*~fHe=?bIM76>w5TOxZ3#`sp=A*!{o7d=+UxdC+BS?x2Z zXuYM;fvl)71_&02Xh$Zyb(VzX}O0QnQ|sYG$(tma2-Ox z(y4)X$Jcm}jxXrs%;qIYLu4xjdbCc0e6M{WoDQ$1%DFm70LU`4;p7^Hov`WzAm<-> z3fGQt&ds`l&lx`sl(dK`jVKJ08MkX@DIpDd!{HN@eF3)-F&h{$1EVrnu0oAS5vT0A zN>>XLWxhTpi!(sJfFpA3?>1r{dp1_!*+4sY$^XogGU;${w|qIF) zTi^y^!h;e;SaW0zYF3G1j+H2zZ#fTY+4dPom&I+_^E!Baw#)|f8dadl)-euz`xu9- zkV?GXh=`<79mWyWv3esro^50mOn|7U006-Wh#|t$_M2I)H8#Q`aY5HFDaaSW3bl%) z5RkbESSMyFK=cl`cA%ryNg=h@E(Tf_7Bygi^lxmFo@Z_VAbBcl@(bAkrmamE3hWRJ z8faxlnrtr?^y7d2o#mVv?wT`{r37D^Q&h}_m7_(71< zsb;1YL!AwXQ-(?Mb_g%-gZzqqHX@>28k?xr5{zlBwG#QEBErtv!psK*Qzf!1`qb@& zbxtWJAqtZ>BX&F?O7hIgWFtm0C@qwt_TW--QpSo0Rasj~Rd zsMZn;Xrgp4ov$H7MW-83Q#aFav>2I~Fmf}1wb%(f1tujf>F{ap5MgY?4|0FuBP1;Z z@}fOS@ih(HM7dTe1COK$bPAZOhS4aYLz_zZvYyOuu^fnKPSlH`qR%mi0ZojKVh)$Wj*X@9q<~0{r8gqg>=VsjA*!QvI9vN2qSQUucd;R8{Epew5{`-+}f0o&@7=er)`~PYymq869bPe zXpM=HR%~=b6df(-cx*7vhhE{!9>@bwR1_L!*?xg%VyH1G8%@(Og9)w=Su~i*+GRb~ zmeG%gIjgHUtCr3eo7K8R6pbxZuZAcba!^gbm|kE`uozrL(bnba7gL$g+R-v3=nu6O z&m0_$H@i9@m%>EELQu1o6=2P5RbMC>ARtx+UTu5uV4Guw3v_D5co}aI`p&RvMfcz! zk&CDV>k3H7mQ03HG0PJyS=pnl2Y0CBXy_sBlD@%piAga|j+0$LeT$(<+6=dlVSSfL z5K0K4`1}O6dTD+NmkC6niW8R_jQDPtF=3Vk15t0}n+=ou{qoh>4&5+TR>TQroCO@m zU0ls0Y|{3V83hhx8c#;H=mx|A8xLCo4K@`;Bh2Z+Kmo&nW95e7^8q}f^+q%_!;IE6=%vk)~~ z?5C8=Oyv_T7>kZk^s!M?xQC!9Q6j6axVsDCh4eIH(Qi4)+*LNWn>;TS5+qv`YOYv& zIO{$>cWuYYi7jXIK9elhJm}5~?OGh@oUkTZjI6gt3}lT{6FR?#hypB^1q=1VxI*Uj z3a!bI!zuzzUd%1(&bHMTY@)Fnu?;?UXc7`uA<(qY3O1~q#{m=H$UsJ0F@Pu!DxA9V zIKTOZL%=eFHa3K~bHNEfj2@I7x5%>FX?ZQf;=>)g(>{$owN46+Uaezvc*U>_=mY9) zhaBY5wiqzGY_a$3n&3^CYJ@4m`uNfM47&fUIJSO$z3eD`S4V>~W)Z^=;)!cP4)Ze3 zPzVVgAKPw54mr8ykuf21aYMi^vJV_@iQ{v}BhA=qs|jI16v6q0DZV*!_;c)_&d=yA z)QBG-Rf*#Kj3#F{c5cZtSp*tifW9%qK$5;3hlZngWNJF(9W<(3f$fD`3ZPQ5rRhl& ztm-E7ipON1o+8J{)-u~H7J!PdGKJJajsf{rX?29PTwm)02@;jhNF`~R>Fj9Oudzbv zAuNJfR@FOd{oCw^8P8hh+b0Y-8;`oVQ@gYc?eU|Cj*aPTVa5}EY%McSjc{bXB#9>j|XV)9u+ zm|7`&-L-C6PPb4`?B%u!%q@^fK0}KJZl)w=@ePK7692$Hy)+rbMX-nvIo;c!doY69 zamgh}q8fFf8-3h?)HTa_CyETQIw)%#t02LhH?LRNU?I}X)`gsiXVeS;g=bRZb!&F> zxY1E%LjgGeBa#kLW3ov28-V4&BxN7@iPZy|@E4nyrw_+@LD<<0Zv~s$EjDFFl3B$* zt${~C0n3mo)~0Xjf3|~k1QMo-j63gqq}FoxAj)jaGgaWYasPI3_#h~^q=lW5NYY`# z&QA-DbV8S{V8VbFVuB#GG7ET40`Xi0**h|dNA+3(!MyZ!aC=p?;6QyEF|<8(3hVVV zVoyaNTdO*{!ATD@sbuRQEHX_%5q)fZZ_!?c88UDkF&?IHbaV=xh9eG@7F?;zxgos{ zObv@VuuUx!M%~(FR-9ch!z>45{;Y1c=qKYM*19#Z(yB}9wM+(E$VOsI`xM~1(VS^_ zCwnKJM&uGdwk4OCc=-A{M1IEt2^}3Q`m;2$3yC;=&Do`-eOpXxlJ<(W~&ZSpaJHk$QhiB)AR_3}a%H1#+E6yvTKu~D3 zXN!L1KdHUU`)5=%hzYfQLe18udko;A8Ph@v1qjs!Z6sBl;8clOfk+_-E4=uagKP9IVaM^D!U>x=zGh-=NVCC14%f$BE&L>xBv}DFJJNOJ zp)AZt76Z2h{1uiw$=}i%1QFt|xmn1OgEsuObI2i5bE|2KrDtH_W~!8Z4G8 z6#_LwjDMv-kPhYO^T74^7&<(Q0iSNplTU5Rfdtn!YXaGPL2opWofltp2Ln}pD4SFo zk(LmGoguJ@raR1|!YzTe8d!#CYdiX%?KBj3kLy}b(FG0b`YpC`s~|(@&;}!V#I2Ee zh&_q`gHvlZlv>?D$Hm)NYjT}pP@I8J7I1OR3D4dk&35wbLI1=Kr{7^9Weq$pMj0if z*(G>2gp6p;bdphwsvaBPsAgBoc~Noap=$&3rA-sMwX5S!K}nHG=S9N!WSf5BP{$j- zBQ2SN;zH!)`2J@B_nDWDljd`)&yC?BCQhM z3aT(@ts-azX&$MioMjVCjWfsI>)JSmxuGbd)x!EPLOl>$L4ewV`iT&07TXjoTSeYs z0lss~HTn^LjowQm9c1TY=;d9#-X#nKINX^XX)}onuxk%UWK7FS2~Vr76H&9P)v%4$ zkC$#9MD06bbkwJ{80WQSi#Qo-GvN>^ST%>XYp%nu{a)330yl{;?Uc?D}w1 zL1~d2QQ{=<*dXVgK%7cg)_tPydziEb1vU&kR4#}b@ti1TTX2(cU|0ic#pQl8jK`@W zsjFCC7s!qKC19u-p>wC%8p$box2+p=2(k{#LOiQ)(JT_OXEhT8>Qpb>~OZx$cl5C_~o{{`+huVsv%ipB>~lEw2apru#N_A+rF{S zew9AvIM_|sS3nFmp?M&u$qHmhdFXiVVR z4{O|72hVM~oaQnMO?s6`>f9x#0|tPLxftInC=?G%yJ{X33B01Ju(id~e$6u>5RoGma0mBjLym5O@`*#W4hn z3yZxD3rT40_!!Zg*w+Vpvt6UzlaOXlT#zeU$mT;}bI5@QNyphAH*vJCIP>Y~wVy`9 zVJ_)e+D3X-ob4Bl@-a0=x1$X>$)tc+_z<8WQj7U`oOU7SWWb;~4p0wnZy0Ua4_ju< z%rJ^sqx-5xqg>qZi?se{)6^qj3Zsfr^ry2p<%9^LQgi|s?aD^X_KCr~>abguD01#< zOB%70l1|}_=?n&*RfuD79`v(u;Ch}oMiAmUH&Re!I=VgaYD4BOJmJw>-IgeP;gH(C zT!D>X@3z(9@OGZe7UQ7+$J%s*>m5j6$P|*JWQEzeN0wV1pGFdUfJ8VPyGaW6`odEt~jS=Jkd@wT)1-_7WU=kh04|FP|!wGFt zoJH6v*TJlqhT;#V#70f8~Xk zehz4co$Xeit;-%{w1Q|C$PAvMt*-K(#dZimlH8UZW$^}E-yP3}W^c6Z>O+Baptu-fcQ!$j(#>uc1R4xCA;OsT-wCS;U?z{AWkeD<-o z%@QpJ5TwjzDs^-MplA#zB1{a;4*j~>)Peqt<6%R4PYX-;GP*}@bsc6AyeFv{J$7L}M zFS&wfKU<{|qpiU}pM7wjAKwX@;qn|PU31h@WSs@nq#j+9iBJgxKX^Z4S0!jTM^1CIj%r{nR z3t1e}G}RVC6H|I1nqFPyTP9u?2v{jVjPW>(N8UF*hhJT|q1YAB7IgeNP1y>~Zotf; z;w{YBAI395lP1O%nmP7{qu;2Gp2vNltApL`@n2-ev^y^hAVkdZ>keJJgxlL$N*><6 zkj@$6T9FAG)>YBAfjRn%%qSPS#c4lE$z^j!Ujyk;-^(kWU!0!X$~oNftPSp*uZvy% zuoK9zzeO2C^A{)>JSu4OD6ux|jf-YNUsk*tDwjM!@8Nz(k&aL>&Pc= zEOL)Qj4Q{lAm(D9+{#J7#Hg&(La_|pf>MICg!?uT zt+2>}hFBpR038Nmf>k0&S$^@oQ+%AwR*LD%fTHA962U<{!jj1It@Ud0q0T~1i?|VT z`0?Jqt*F5zi*~Qz{m+ttfTFEHu{OuyZ3>5xw&XA>xk#}Kvwodj(Fqn}Ht_U)_&NfG z4He9wgioLS+h?$WqSnO$3SLK}-U_%=!&OF~q&Bs$VFplAp@bdVfrR-zl4lzVCs+ay zW4c^0E&D0h$%PddupYoH*JG2d;o)Cck-(J^yH_mzGN;8h2vX&Cert!-0_K|2N{F?E zLgKG*`&^2ansSncFmbo1;NnChG1WHqrfeE2xvz zPnWqBu9u0W?a@hb!fZzkc5cR2zzChp=xglk(yQS@R5WI|mjF_PHO=YuJP;Z5PYQe; z;FJzBR)jzW-<+f?g*=Is6`d%r z?jE_GeA_xYNK05e8WSuUH5Q1GSrpnDu`pe##7bE(U`_LZZLAJ#C(OaJN#^^wPuKMd zp0kTE9y+E;+rSj}()RQ67>3IUEyViC#TAYM3i`No4gK?p7Ca_QqGeL zV2Yp>F|buw>{)pqi-~bpjC>gFWAGv+dD$ld!<8=uffy7RXT_{vOW8WRQ7kwk%y_uz zS6$&UZAf#xQbFANg0KWRDAuYty`vIfsBEfvowM3!&m1c_lep(0tXPB#t*3_kuyMRC z7dteyc3nR^BwR!ZWUyxttNZdVDEK3g#RhU-hJEwE9X z`8f+4Z+KQLv0(!mECyyKBtEK-^ums4UgGx} z(W7^W`HiQ9+87#&IH9fW4g+w<>OrJ+41?=*+p$(@&2idHa9;zx4>_qi+tg^siiZMGg{_c zW@a&@SDUM2v~UW6(WQxr%>3lc8RdL>auI%gbLpjp%(yZ)mA)T>-ptH+X5725n4Vws zj%J_`Wo&k4CNs7eno2J~of!y@hc$;+EZ@@HczQA8K?_6Q#Nex;?9XmO(I_TK8lYV{g`|4GFyT;%BXUtJ!tUcFSbAt{B^;od+UBO0t z=+atBv}&pFk75Cb8fmH@{xHI0>|ae)6MRfU!ilB7IP>A%c0doCd!JvYAai^>Mc7-@ zr0nZAoEa77#C+@sWkw|>ACCL`mivMT#Uo;#embczL+F>WOm?@HG>*8YY|!4|oB)eomag+ae}JakTPGnU&)~8oXHe(3Q^3QA)DMJe{Zld8ev0QP4vH z`o{aZeeMoGU2A^qf(yITuz%cNSxyPuIzL2Fc8O1fyf^V$2R>>x5xdmGsDkVH)wWH_ zx@Y=nT(5I&U8Cl2z-;xJ0vJImmz1l}f>UBWrKp1`Coaj?=L)I0`2a zdzw|59j8kiyq)Edn?eIe?yyfjiSBpFrBRNXl!Hiig?6P{j@T)>KZ15Mwpj#HqeGta z#iS~T~VNJ2NDtTsg zEs4bDz(WR72FU|6%lR?i@IqAfmfqw;L?(mVmS3+h$+Zz9pib&>OSIF?!QcMW9Q%DV zZhr~qVj^}P7?X`1amLfFeQnwH1$YFYu{f>5?6TjfaRU@MfcQIe3UOlV-s3y-ki4C- z%5?KD>_)2`EH+jQ2z}lMb%1IT8?XUsJfLO5IJdAfbVz5nWnf6;Znp|enN6MsKdI~b z@WsME9m(*H>)~EF98-^l)fd*${Cg@Ho|J}kbn-wcu zENv`g0qw%@3W&fT2nb~e<`(44Q6E`XaG|$3o4ckof|Uz!1fi^2`kJ9UX*&udzccU` z!Sv3UNU1}*3)*blMe0nE7Tt&jzd!Qv5tcC2#53<=H^LArz53kM?Ji%0X_v#L;!Z(@ z28psFU>m!g-P)lb6R8`$v6pt?B2N9}8*-935x}BG3Y9B(2XlXVswi0r00NO6%k04@ap$9BbPB%_QtwTc zxkg{LSbS}%2B24kZ2RuSy5oq-3|&~{a6#X1Z!G2dcA6ue92}&dQVNZ$5{dwR;4ZkG z-OMFObX14EmY%hO`z&)z(>r*SrSl7QRo)4BL==-g0qxi&+(SZoxQ7#an?NrMpuvUB z%?rUjMDkyb`9tvpj$Z1IqQ2k12fAX#h_{1J@kHf`;$?YsfkB8ghAb|!hRPRA%=I+# zj|Fd$zM=0oOM;A8`qm*aJ$`|VtRc3%am>W#dJSfZT`k`nli*8wQMP%8@M1^XZR#(~CLL&PkPZdKN z+3*ZusQSp$sQTaWz;bf(#hxcxM#%SrJHgeV${^3}vXUM?pPLHbFkpu{Juis;MJq-Io8!o|74m{2`lcGwL>_*uC&5&0l8Z*2-J{ z#p!RZ;=Yiyhsb2Rg zllkSL+O&6nDW%dzmx|YEC6uh&Hxs}nDpw*)NNsHTnISUbPT45raVcR@!qEL0Hb}14 zTf9%Nw#s*t&T&{?tkr>mwBi_RpENKKx~zH8H`dNO|1tdTLrYWX*r0q-d+tNTuME$m z_25*6#iHgOz145yW3=^K?qxL+0JSg1$EQAR%-m4aM+XVKBPGJ_D~b^m-b%T}=wvAK zw45J-VhEKV=hob|>1xWUgLZq6VCLvD=wh~7QL1fKBl^>?rr3zfzr?lIf$j*|c;S)i z8OGpGdh-o~+UOcH$*QW>7)Wpjg99y>;#f-BQ7}Op1++g6Fib022ll|v~hfZ(#*N$1n75YejH z8`o+>0;pMJxIzYI@y_Wdxhd?TVN(dqun6uKxc2h_aXy2 zg&8&ma@FI&x%J=HeXbD?WhJgWXbv}s-Ivr3O|fyhw!hl~R%8L7OomN?TWY-WMjk2` zQg0k1?lh3jNahmCo%ogt{odO()eyZ7l?>Gx2HD7q$G)_y==@Lg$stgeN16#piw zMcad#-uQ93i>dFfEh6ne$#?f7?O6-UI>qXBH8{Ok%wldyZ8ZiG+XzYxV2nvlzAACR zQjDSH1zu7)rWN~5?bNB-?Cv>1LFpGtCI>w-iOc-BU81G^8lh(Rn6#LGIONk`Y^z-B z{Q`b8;zqOp$xHbd?=OCa1s%q0;*fj9gbY{<=ugwB4Zkp%?*VLg6PO6qWbCGVdSB(h z*iC5w*gTY{2<<6v){s`KKHU($c7!ptB@@fKXBD}FBZZ$_#j?X?7(E_V;%Eczb?B`%i(n7%b=31UlYn=?mFPgdxiG9sq0wUd3e`tCVD)q`w2_JO;*`NiBHUT#Q1FMjLm_@qwcYjx zPn_FC5Zud95W8|+zc*dK$S?WZ6dqlM@ixbGbI9*Kic@)P{$5Q2UZh6mCq=Gqh;DO} zF&ZY=B$(h!Ye{zfdUCrnLnivZ=91Bm)s+YCZg_1(ex4EnC zS8nk1&*u6gm!g+C4nwrPPa<-i&hlskt(a~o(&fq8)yHB9Kz=*I&x)b;$%|3dytm;j z5~net8MuuR*VsGo$E3Tpsg^O-Zm^-6R->$%ESK$p4(kN^b@ZEK^^n)%dpj<0OI89Z zbWC(7%gYTH-kDQrIF)ZNmtV3|Q!0Tklxu2#pwpx37 z(OT+4Ql@Yjh8$5Hv0)d#LQb4gE((}(`K%U3t~k{__sBLm*6>8sW!-Kn&zK+$MA9tC zEHLLuU{M@iz!gfp#2%MdmiNcBNE!zo?|#}lrHVk3DH}^CJT|^qU2m$)SS;KZ=r1x# z=_iK#LM(GoLbVa6MvTqfI+b4X37 z8nUpFLNsc7)enpyuyF>x-r>f3#pi?J2YV1yI^L_y*tuI^8jZ&@O{*|(&4wDSJe2ZI z*hq&eU_Ei%1=P)^mqCT4w7yv)j2_tt&|V30FX1yv6}%UjibD5jjAS5U-zFM|>@)!4 zE4$ZqDQYB7e5X>ssnHmWHK{ESmHz!}t6FL}h|S{TXx7zDbY4rlHGjk5Wa_#ZMzpC= zCvMkvNW=;(kG?Ns)l!D874ns_7Z!-?0M-Ft+_}7@G0mMX=2G2K{1A@Px5g~?4z%fv zb~6LOQ&Pf3KNa@Yw7K3zhja~yXQH8T2HX`M2XJA+_IZA4er7e?TDuI8*#UxhI?oA>3C_8xAA6b~f`cj2t(+P9xjhVnD=gaiZ{4pp#uvq1@sI4-TTr*_!CV*$!=2QxtYDplTrxJCw% zLnx)D!A?@K9I%4Yo$y__iqgRdtx1Ktp@b4a+TV1rD_R}ZI%i5OF)4%+OR}(jhDburq_5f zN|S3+LTg1lX`EdG#V$T%0!4K*a~0Qx1}=qg=Up9=pY&3Dl?@$uySg>Ju!Yav+n2H) zp=+$YjjV8r%{L3-N)@rFGeGhNhebX1DO=+}X)pO2D&+!~)syb%bGup$4X+`Nyv4?1 zsX5KDSPK>K_gf(FexxyAMM8%*)=919_4vqob_e|mT!CP@e2MHVvN}^}qjwG3;$-EV zvRrdxmTV$ex1`KFt{m7pj8nsJqe+82)0~V@0rJNFCWG(BU@`}xIS-;vo6Z7aR4OXu zEB<;i?g)3;x|P%;4RCs+G_rwo!;a@c;l_;Q3XI2W08cC7BGA#-=)nfMs`>5MOY!N(`)?|lqORLBLHIqG4@o9ZU~ zO)=14b?4-e!9mNA+%%OlK6LJ&ab)5EC9`u%e{xR=ZQ%lJyYxzYUwFmwNirH4L&}J^ ztF=VksaY2_ZsT_j%|?;A+TrNrGuz~XV+bq1q^(5WnFC#fVNW(!ss0XPLjNoD#5SlKBh-QvPKpCiC>wII?;&)5G#$Mu{X6eB#&#DM5VeLry2g>IGmx~vxanS%_ zU%u?GNtw@tE_3*S4%(J4pzR3PH@9@9_re>Wu}rx-+AO7fP@$mH^G^IB*# zWhBtjqRt$9{_v8>L{`;g;g=sDSIPUYMqem#zl)*7E*!P^5hL8v`-14U=&JhrwV(Kn zwVQaAYPz~{)gDJyQfX0qJb`&32N1`erF25&k`fEtI}{ zZNcD-F3+wK#=r74Z@5l-G|L?Ji0&Z@S~*&-Dlf5O^X`lEq%&2nklT&HrT<*Pgm=ik zPvYN?p$+04UCTqIh#ZYhy~IEXk5aJ(wqd~_DbW17Ny{cn|2C6b?&04E7}=o|mlYB; zqiJEIToIU>)z1F*J-VVbH9;F#^od^vi&Nl@1v69~P(L!_2kRkIUzXGeZ2GWI90p^c zFfxHhK>6N0H^K9me3|Qu>ZWg5=>GjSVW!cSzrcqG@G+w=CnNdG!O*o9wm4Bu@7a?b zcTpQ$Pho>&5c``Vp5YN?stwW1_gL&Cv`yp56#;;K5m3n|d8JGM|>#Oy}vk-W>j z!Q|wxj9Ji(N=3yWw2YxnRB0?xyLfn8lGJvUCvKgWCytGS+L$i@KJyiySpEk07I>E5 zbz?my-BSy`D8k^~9O+-`d&|Qh>7szF^N+N|%y@kwu_T9{yG?HG_*;SnE zj1_>OuMM}Y&ZL0m`PWNUYOrWad(;hli)L)Yhl#^d&KLBO&FfT48;Y!2WiCjjvAP_+ ze^@k7`dvm=YMY)Iw1YdHSjPCX9brlGF+;ZXvi%44QzP}QF~SNDpw`3DrvtWKV(grs z7Cr*V28$eF&e|tr_UCp*yl(_Mwj9kGqKMYs?du-qi}@T5I%*g(?d-Cn=0~F9{2B|z zs~?dHaMJ6fgl8UwAD()-rPx5S~JPAG%s_nBror@X!$(}85$`N z4hjMu4vH0%EKKmCx?`CIYr-6M1cR6#lsx)7%fm-t2t)S`q*j}_>rh27TsyHTy`=2L zpsa&Il>?DE)kcA?c-Ndbz%Hk*S}{f@4XiR=2X14=TTi8PVcX+;H{ai;9VIAfKY@%8 z;zJA8vq`sDwMf>9m~$>Q{6Z64H5hB1$>n7y_RL#Df=D(xrtwI0_f7iQ&a-F3763@7 zz6lwHFRH3hn`#F`_$>+zH4k789@elsr|U{eaCc70H%!67pJEK?-dusNG9CJMR^KvZHC3Fo)Xdl!=XURa3LZT;?9ZIzE1Se?@ z7&Aa`B1s<%W35TJSo(P$((aWiiV{E5{>$k{yfyWLf<~MSKXG|MCF`iPL6ugde8O@p zOa4%?D=ISbqd|x55=)S*5SQRb-hM@-3W~t=pcM~F$64U5YW%Ah%$2i*Q7NCj!-Wt> z%a4Kykj2rW#@Xh=$8t z_Jff$yZ-#uDvUtz)=tCTkc8>COzsapgoA$YDL~s;xKP7BBIzC(1uFL{@_jEsk0NS} zU!FwSPhD)xyBf{C+8iUSNUo^>Hj)B`qW`hi*mha+Xe^7^^?x>0sUa*f@X;l8O zb0Yl}sJe;%vq3haS=!h!vZT%^L*^{4Pwv@7K$RyR932?isin9v))Tm!vu_V6J-HrZ zkXKTw#3>XT4uhzC>0VzPS?85z+8gR1SJLXzZWIw8irmEAE(~^w>Nt%BOC^B>X~JZN zC}@k&fO%j8sjXk+X%AygXmBqd>iCPbx2jtT%)*{ru{s9(E4n=jLka&13?B4wn);m$t5`IaQ zq<<4aRQ3gPMYys=isKDPGg)9Z+JIVp;cP`aLyT-C;u3-xjrX2jw|6Q7~tM` za1;7DT>Gnbd;C<9(=J57JWOoQnE&K37^exxuX=FHSRM7=#IspW9n@##NCN3UNo>PWYt3y%+wGB%a<(tvyG|sY19PJC zhxqnfq&C6y4pEG8>4UKlW#_HbPV8SLusW)2=h-NsNDB4ditt^2xJ$$&bi!iH1JE z{51GhTVWU@H-$^N%-3~;az2OgBZZrSwstk#_(vFYR@`h^Cxwxv_Y2vpKhXSWciR2x zOj*EEpaJ}kLZg4VpntSR&TNU=>m zFpqKPh07u@p)#Y6ryr1Mwwyl@>dzP1M%;ov5`DGKPm1h~aWaK(g=g2K6`C}mrl)Q` zS}-+SLd)hOi_?ftbE9gb>sQ0~2c``)(aCl`PHyZU`v591Mgu1C3)l8j9iArfY42e@rW(UCP6r9=>%+Jv*#YEi4&toV28s1Xd~d--w6>1% zb{Q?El1U8s?m;J1IhVc!BkMoQ-c+SW?)`<$?pK9NouVZA&Innv9HTv(N*>Smtj?Fp zO}M`2`*&>l`Jn?m-|cyXkGpy1(}yoZVL@_A)0LRqXCG*|r$k$><)<_srUvqX|kEev@fkFl?ILLbn3-!1UsZ+-T-Ys*lk`L zC$tMJ_4*c0g(6rgRaQn-fpQ65p@*s5P5k%4MzxwE3Y3B8V}x1b;2IA}^B9(;cRZ!1 zPJ03h+JE;-E%onXe*El13lF8sXBF{iFdTc#du@)cVxBx0_A)fY)VgO4`@#^Kyg`NU z(Gw)nRJ^CD@B1uM6vSpoI?^rqm60lB=)Tn^3Ag$QuVF0{kx_%RYB5oluVj)y*wdc0 z{Z*#P$v*VKh%q@pk+pP|o=y`aYb|8Frfvk^^7mzPj1kZ!V=pATh8=#XWu9IhFt}~V z(r&F1Gd1pNC0!?Q$}9T;Yg1N|;@9uOLe^kcXpuo9xkna}H`VvJUh1)zs~myh+53W- zK<&W0_@l|pNgVF2?o4`xmX~6+&Bw9p_3)YXpxn$6yGwyfX)8^gr1jurU4(Qq%XmKG)dTdj1W&^f4TZqi0F2L zTSSR+RkZA_#V)rc^?1{PFK1Z@$E86QU(HY7gl<m73W{{pvCMpY5WO7(K^_ zM6Fced(Haj29WNefV#-hR&>h+qd|z_U+?bd?zcY0Ga@hHDwXfT1(F*aoX{Cc1E-a> z@b!eha;!OQ{xn@BZ7&WgWNIKzWo!M~Jm2Pe+s!hM$g_>2o7%lB%^NpI;1)m+}C1hxiMOQda|7i8w97#MIr8Z)yc6LCdebX6<~#o(-+z z+}Xz5IS(mKCj=4OKvq=6&mcdelG^vnw_!;e^!c|BnyOq}HgK;x$82y0nHD<0Q^MSH z%k%~vcH@lKl*uC2iU1kkozsaduu2eQ1nZlZQJV5|CL2tl1^A3|dB-cX{zKZ3+s?`U zr*gTOjVclo-Kl|zOF-kCLg+2yTtn`#(1IbtC`d(mSDIuxIR{&-e?{y>)2-I45#$T} zon|#jz^3wBf1Qj+f1R*IUWUK+vGjGOWC{I={sQvoc_eV3x3R%2ta{}-V_uMZmjd9f zo|su^6ZLQ?-X~xm=vW?&8YpBt9gs$iXVNwEvB6+(Del>4K3z9uVTKhdSK2dZ)n|4d z-a>tF8?7v_O^|NgB*!M0?%qGFKWJl9&o;HLcPqhv>m-sA9%ARenR;W_rqA<4H3#=1 zSNDFYa>nsk0E1t}Wxt}{7q<)*sNQD}#~E8C!sV;|w_YvZm#s}L%=c_H;mp=#sC=cy zL}&U_#^{;t{NDZ-A%N_DQ^ z4vkKPCxw}%COB@NO>V-~+~dhK?r*l8a(&M4>-?p( ztP*bZmXM{avZbGoL36#;uZ~6ufe~L#Rw8JB!E_HR8-L|rpUuspy-u&9lzohfoXwG?vd;{#_}m<1@r$H0 z;I;+cOsIpmz?&(IQfA_B87m*T!LQDeB~+teY?{(FpoL^lnHci)OtK}9KUzK8?hM-OPQ3U(W(ZI)egXv2aw*g?Dh zIvONQGA5gRhg@BX=w-eUGwWLAQp*Cmy+wng4RLrD z(310ke&lU8PEzc~qW&qe$!mD!Z)BfQ(LiCrFJH6jF6~oBBOr^6Zo{*Hj%>y{usQ~B z-o`Y@78G`-+3_`7+uQ*@>Zx_kQ~AjWUHX&0qXCqogsO7pxfz&W2r3Oaa*j-9p5Z!? z(X>Dg;QX>>w>z{tx>&czN%Oaf8K{i`!&llZ3iR_KcAe0_3lP0u7NB&{j`Kbhxw9(? znzm7!rJV+4;OPmsR<>|H5vXXDZi6tj6TJKRdr}N4j-K0k>7Ny*8}PZ)MUJ0{&a7TB zq(~^MH=+eKF!~~JKCWa|cSrW_6#e$hqQ5bAPxJV@z7rtJa?0iip zWlCM}CFpHjl=f_!n;O#hwwTIzT8SPhF5(uVTT(5#(&*|h5Gpcfjl%x6%v&SU5_+Ai z3dkGmDPhTa$>$T>!>za=Xl(bdr7Hmy+>3GZ_n66_-YM3<8YnzYyD=WxkLpbH&bEDA z#$`9;Q3vkPpVGt2ROJOc@7-4UxvHE#6>A{g4(w7qHQ}oNYRjL7^~-23c1ZGw*Izka zc6H0!e}6j1z0EHf%UkSj9$C(u!hV_^9`|ai#hkXQlkT!}Ds^sUIY0Ok?Pe4CEB?pZ zD(r`IsG5(E>cd;?W1FXOlyH{?v$^$3CX2uvTfkxnGoHM1nsAf?BE<<%9y|YGDgj^X z{cMcn#KO7t1Z`y<9b#d&PMxcE$X;;RerboR_kio{4j7DJAp(G z`N$Id2q0$FsPemkk>~iakU*_@{I-JAnvr2UnY%4w>U!0pueQ_Vu%r~&r*m>Q^#zyj zM{!TL6hb6q^9hp>_%U$pn)Fw;nC~v(FHqqH^BHzPI6)`B=v?_CPEPqxUkT_>MFOfS-`&i{6^&YF z4ebZUXO;j-)?*E6$wyIgO_*EMv{?9WHJOACG(V~P-qSIXlo#h*XIf)szOR0)#Xsm8 z*>h(;*c&IoZVuF$XHN6o#k_ah7fRi`W0g3XLJ&71M(6(~(-_TAS27-j36JB}(=&r?G z5kIkcLX7g>ycc{^IX$Nt)YY{<47(suM_xnby+8;3l~#ik1Gf8z`%c{9Zp|Lh4_@|0%j zu;F2~>QnXMv2dD%SJLZIE5A^!`B8R*cVOPa#_74bjd!xwV!MUJO}OOuc5(h+)32Gb zt^@hLS_Kg@3zMJa+4`qhN{iZLk9}#&1-%pIpHG&p5Pm)WZThYAI(<%``kE>r4M}7W zM}nr2+o9eF%uGW(-1#p+Y@LOLitZWst4DCf!PK7>7NuM_`t{<<&&Kzy(xl~>EcI9R zrM?WG62*t_Pq0tyeiFKUlj{7v!Z{BG865A^)9r)Wo+>eF=k8tn+LMgW2ZiZV2@Ss| zX5GmG^%ss~iTyropJPK_9kJZ%jRa0}WpA@wH7>05yU85;h3%QElTj}Zx@SPDxv{8C zm$*|wtRk}-Z+_O@ZSC){hqZ;$DQk;m?1~Hz*rn_%1-f?+vu8#`m)dVVkueNj-y^QW z;nxVLk326s`hI9Be0`5A;!|xjCVS5CU_NL=;aF^fKZi~pGfMN&z)mwyqnM9e37z%g zs%kwCcQ~~DG!*5ed?v&syugHeoVK0P@RSQs@KZcuv#~B^Zwjumj~VS#vLHTgFyhu< zvS&f>as!N2EHYf{TL<3O{xP1H{qwd>lNZTuB3E(YbJ-yAay}*^?XEvPAwtjE<0zR61PSo-=x79W@<6FVDe5E*Aa9Qfr>1qoc5e*N%f&>yH zXgG}EuPO0o#TGlgs8MIhzw@Cs1fL3ldMdh}k)F5qw)_M)jgh@HcZI+X@+%{ct9D;4 zOe9;wZL;x=#g3e~eno+f@GGN^E*m0X#X$IV5x91{QU^a%Y#8RnnEZ7Sw<&JRQF6|~ z>u$nzQoFKGFy@gHA^zcf9Z#>CU<6^AkAZ=_sUx-ICr-3Y_1SE z9Y@p&s0B561@j30CLrEJMx~0PljMlb^c{lUx^cx=MZ3I-^z!NP>)HC;x)F0;F>`*Y zT=kpJ^;je5Jwx7pitNUNTb_kOc@X7ITr z<3G43eu_wX9UPnRj5uLd!xWk9%@)}lByl=L^?Hixei;h*-2Doiq#GCbLsB4hBp&1) zvE4mGvL$Mq8{Lj^Ny#ti9(#f?&sDM^`5es;Gnfy#TOU&E6ylO3+NndjNrQHU3x^8V z&rxW@J1#(nRv?xcAsH8wnR1^K>;>rW=0e*dhPy`c_JSVtn{XDH=PN-BxshUTz~n*+ z&B5TJv6EX$tQ1fqNq!|Mexr$C81xJ~EaGw9IB(t$-PbTvwo38G$p+$Qr{ibm;b*7f zXXoJGs)A)MGeM={OZ_O#S!Prk&8?7zsZ4Qdl+3I`w*yPTuJ+D(?REA3b2Ts!M1bWlWv|x7fKS>Q+m^zF{()t!>2S{_8ojhEky2&+yM!UYvMe zslT^Jr7hn3y$ZW}lNB|6$_hP=L0SZ4ml5w7>zeQ@p85qeDDN^R^kE2uvfeZdwn7A^ z!*20XbD&kiY(oU*jS2G(sNB&VJfw^YBMmE)eb@#{^OtE_cSb=3X1@P*o%zlsYz2NP z82Wh$;ZTf^uf#;UU!@`Wk^rZ3G9|8|A;l3Nb+@45p5S96*Znba zoT)h|j;GVnlJ@19bLJ`;P};re$yx5k4e9jkeFF0roaZU6V8Z-)_YMHS-s0f1FY(nt zd|^>CQ+mzd(%?F{Hkn=y&znxwaW3B4`THleq)pw-v5tJ2x)zy_6QJl=V}*TFUQ2Y* z%a_-tQ}tocf=BVOPz+?j%6u zCHSFE{oW$@b5C^CyedpfGYp)ukQsP31po<1O8E@KG!>^$6*CS;R;6E(Iq>qun-1ww zFUstMQqZMDCJQ=IOGENJhg$c;4Fs|Ep^hj-# zo4s9h>k_72HKQzZq@7J0q&v7q&gIAEWJ+ToPWH^+uBjdRn^;>^j>z00yV@G(Cd`3v zEs3LDd_Act!$M^GH@&UMh<4g1qotI{&`M>t{X}3vlZV~yW9J}Wdk7(O^B!E2no)zX zY3|OB^MFUYo)kjUk$>FJ4A*%CPuPK5% zFX?Dyf7Gr^EhQd6;p9^dU=94oVi*fm)>fV+vF0PhRvbx*JIt&sWyrgHCXphd_#>R&Xq2>H4uLhNFm<&no9Y{`BDNtehysWPV$dv{gAi9iFG!wS z2p>l)P$Y|mPwZa{je=%i_Lht$EY3jt03RU1+NzvWfPYHfDT5ButxSUZs#KkVn*|Ks zcd`~>)z+#OV%YHwOd%SJ-NX()$KMQxS5gkQgnlZ&{3Z3aME6#e)AZyJLe^)7DDt`5++c#SXcK zawcWRhrjhox$PMTVSm651Y(T@;*12MzllU#n~49_ivEl9))%o3jH#towBP}dm+{R( z7)dEm57vcnE1o!J({2%85dp_9#={#hK{KMb)Z{+>rr{)mk~6B*;zOn=u+sgGlyd|p zDDSkUoUD=Xj*OU8qmY=vG5wTQ@s^5$ywE@dMG3;rmeXWwFpdzteg|q|Afy{J$cOb9 z5|NZ8ybEp@cgPUpT^$JBNbw1q1wIvm?P3D&hTVuCXm45%y#jt7g6y&Z=Y|QAW96av zzyTVVIfW72z3+G)1i*4YC`x*PcZUe|8=I0ek_@O~%|rH!?V!1QuvG4cTfpNj?gx-X?0`m&->klYm!wsP}l+1;g z4n7h^ETWo2ut9DGUx&C1eiDT(qL_m}L2?KG3GpZRN))w-W-cx+mDV_NjQA4SkEDoY z4)p{T2@D1zELhN#H5nBNJQ89kc()(Ul#&(U8*)7OD8&98kjCY9P7;`AsvOA&eWVFo z1ou_s==Ao6a4i9^f*03v7NQ48y8+7!+eHJqXPu9oG!FLpe;nE9 zSvCy*f-!`30u$QtOpB{)l1eujnPKg&4Bg$L_l(#?K0y(c>4J_>;9+5YB2Kj?eoah;W0-SP@1TRi;7%1iujaf-oXTvL!05UyT@|Unarw-e%Yb z%l-H-4gaUa9lf4L_#-PYrSk};n~hk1=YOO-2?Xa?-(0DWO!fIE%P|@xl>8 zplIMNa1`B@HOq8jY97g+V}Ta?@pc$pP`q_C@W%=%zn`9TD%&JZ1> z+mSx7ortf*pm$aR`*GAcP0U}})W(kBtxLlUozFV@Vov|7NltWo)E3A&HOz07vAQ%$ zKRl#gm|e~h{yK?zy%eXiYpO>gO!^Kc#=hV$0GLkKY4?qjz0?{YT2R3z2a}?ZJd7+M zKrvtiYS`&A8FDwdil_ak9=(%T;~Kl%$Vcv`FsztBXb{X1m|KWXzyE<7_+ZH`8)s+7 z$<`d)c8Q-&MQnAPnK-Pb5kd=?Zh1^c){tbb^&Fy>j;M6Ewas5G9r4J-emFw@_(@3W z2QY~q^HsTu0c8HLx)AvM{vyn3b)yJjvpEW_RlAZi{ud*vfGB^*xp)}EU)}J^bMQz% z!Q3!zQH+SI!~aB(_!1~O7NP8}B*l1j^l!pAzY^gQ-#OIkL_pw;ivS`xAGBmxB$&GpvVK+5Z>)y6P3UlO%>W8B z5@;VzR+u|o(>&&d(V;vrMJQ_Uv=F*}O;dbUqFw9$Ja`a<)sQeO5D^p>AlwM13&#k7 zqw$qIOC{?^cK~6EH^>~-1)&S?gAH0{T?MlzYk*vVBrx5EbAaH6GzhNi=YDa7^#l_z z+lF@IX^gr;J`y$+vEb~mgEb`%|3m`~u_pBkBHVv-A>K)A7m2WnlS+Dc2{7m41Tk*n_rT4!199;g(!U6U5^?X8_DGT8Df+vMN4So{rBCs@y&Ua!IMnaU=_)iq?F|N3;_ zKcDUwguDNjTxN;?s3wGD9jyCKNL^r-fO#WgrYppQiwpNh{_lE?Sm(8ZV&3Z`>VM+gO-Gq$#s-$5 zoH-D=i+My2DF=+nhLcc93Y~=cmYOAs4D(0`uft4v!8* zc}M!K*1io255T!-F`EgAakX;WjanPzxi_7Goy!Pn0sBHEV+oBR8{~;Y_k=$vV?{J& zhRj4n*9UjYKx=C2=YOe#<%XMgp=gA6J7a2ej_5)@@-&5Q#QY82@u#17+%F^m>|t^H zc}Nh|WtcYd02M+U7;)?3v zk$pjYBepnUtcWF0{B^h}&U}u8?WFBD*NepJa8XC#Pn1^}7met`Ic4*?;wFPeiKyWs z>%gDLc)m2Aut!Fwyj^U!n3Go(evJ}d!&gHN7uZeI#vsYHFQyv4;91x!hBLM7*&xkxd0Q~@N)$B z`&bh{FixX$c+8f56Tg8To`Zjt@|CJA)cGKo{n&;yOSIVAhI@8?`Se5kxC{1guoBXJU*DuqqCH`t6= zVN8cQa>Kht9}RLRg}+K7ni~Aao*)&H>nx4u6YEIz<=Fn6HyHo7h4rr(4JZ9862HM5 zptw_ptjN>VVcR2q)EUngINry$UK-D*gwH8A$gW*-J$ZA@XJ6ij=J>?_F*b59POL|? z{maa$cshvUEw=QXOj9SaVmreub1{MF7N6y`M8IAGz-jo*>jJ?GPpa(Y8GFJxk5|$n zc^o}MF$~>sBBs;`+kJp7w1(X(&T{R zoEbLw^X{Fqq-NCfj`9E;xt5rtem7?L`)DUM^Lx2LRgpq7q`X;A3??)3)^RimIz)*z z3`uVaH5V}C3jct-wcp>!;%Euc8}DM9Q+kq^FdYrrad`DOb>el;T4$lRLhU%Ip^PquXU&eo(07y>UL; zjY$vx9jzkoqMfph!cJucMVKwtgIpXv-aH?@ z7;$cy#@nm#+mP?uu{MJ|Il;}ewD^s+pl)Dvu)e9 zG1<0lb9S0++qPXh+vYTr-DC{j&Uwyz{|mqMS@*iW3)feIQW7`366BX5j$vBsCN&Xs zf_SO%_faMuk_>ne_Dm(3oKO(mdUsj%rl#&9>KrvQU#1e}zjGaY z3MZHsUMh7u`5=_X0#UV{O-wf}?cOgHo-#KIM~2DFhglk`7^m98@)0L1WKQ|SM7X7u zM(_3GtYeFNas$$Hi;zB-a0{9AtU|@nv@^>2Biw(2mZvp93a&YOFH*x|@bd~-eOClRT;!xsEMXj?ULHyN-Cc z5M_->ubjtuI|R2JC)rox;KT1Ve3E}{HdzMwX1p<-%B-MB!@Dha4kJ&EQ+P1Nsns?3 zMxK*Df=d8LBJsN{XGx1DdDQLtzl%)rY$Br*4qy{fT;tC8mf#2Jf|prYmJ5cZy>rSq zrEH?-haQCBanXKJz-RuZaK-1nE~N)J<0}2*sNXWIKm<0tk7;2vv|Li{-NiDlhBvn4 zMtRS$Hl&_<-S;UMY)n1~_&2 z9+eLq9D-a5C0!Alh-PzeRu&f*(QQoKK|^p)C_|Kz1W1s|D0gx%#gxLd{iK8<%c+Z_ zGQ&zCRvN}DX_h*SVtcS1n>g&job=9h!~{^l#;?TSCL!+`(o`_iza2r?BA{!2aS%x_ zvx7|L7B=OwCRxf@Kmu8#&(Y*ahF^9bdn5~ma!OgROnQ+l1#Tu;uZMzc7ufA)^s&&0 zUsFJ5lbIN1B+DU^9$p79mJ!eAqnSV{8~IjFlh|fnmzohLX^6HITkN+68v774J`+NS zdP;qjHgd9_dnKt{0ELwT*fv4jgE!&VDNhG8Xuwle?D1%ETKLU5<%`NKJRUKA8ZD9k zidVox5S2Lp<1rAbC`>9c3I+2s&&Ci6$_%@~(SG5R`vm-WV?s*HpZ`V3rNUCln}sDk zTv1ZAurr3RSLzfN%wj>3(Z(cCY?V8G@GC*7e1e-c$slB8E+iZtJ<`cp@I9S7iS*QA zZ`6DWp^Q^lb;Z#y2dZMi=|h7uDL3Av@Mbd-Q8D)UWbD0J(_jt29tvn(l|gpukOjTo zsaUYmm@)BtG1m>oo}}{)a1^aZ^38MU)1JGs4&_HB+f_N@k%oYzZz@@tk!8Q6ctdhq zge_pn$bCc@xtwgI3J2vdUrQI=nXa58ErnEG4!InhJr`;Yz32Z6N1Q#T6Ty5yLV^&^ zDa;(nMFsjFyJmw0-w6|$`{kEa_#x-y0Gk#s@(X#-h~35Yc4u++gcq{mI8P!{@z3?K z{wRdWZ5`kf|1}#x0aPv~ zuBv!4L&gNuPO_p7*8*P@Weu~(nmdG2d=v4lS!HrC)5FDD`-0nu8k5KaE$x*f<17`Y z1hzIsY{K4@@qr}n{VxP+Lfk~Yf_#Sh2sJ18j`{<_6^##?2sQyiHpBw#)}!$#N*ih} zPNapih{v}MMmBp@Y?{KZQ4`w!lcA9^LQr+Z*y`cwmO zeoWF#KPIA;(elGrKJ~HdH==n7K3OQ{ugWFVk}ZayOKA)ibfa(A2=F@5Y&%B7jme(G zH@u)+%Wfr4U`H=KUiW^Ot0+v^_;__u@#=XAc{5Elo*%?qNQT&@W^-C+$bXpvPyi|) z^k1N`_{q;6A^f2}VS*TGkqg5(I^WrLYadDuRY1rs0xzz9l*>-~HU zq!npXoqo`^&ut(oMB5|og^PyF&7;Ktg-N+tARMp9%*6z&R#5@|*P zlMoSSwOfb@+OUh6j_1k<1G@54ah$Tp$#5Ow(Q?Bq{HKoB{^EEzx1vfXR?C$vQ;D)Y zbOq-rFR5;{66fQq9Fsg2&&Eq~!e1@pg2T}RKvb6;A6`{OxiOW>fisQ5#zXahVw1oQ zaW+mvIg+#cNk*Dy|2rPv=85aDEt%%`jBEEXIHoO+>#*nxCrgdpI3M#I-t=;umYv)Sdun9sCbH?2kdHaiB<%e7# zwVKE%Lm!i(EO?enUVF#1U>d=Cd*9(t@ zOan(eNVq6=edABlxH9fj#;txVL=%*2{vb`Vqbra5tx9iUYF(Y?T&Jl_zbiwZ93!78 zz^74m0+0k1XOFXm>!xcnSV6L;b1<}~g)DZR==$Fsa%ha(P~Z@lT?}|0Vi!Cl{mMft zpw2#X1wonWRj_4@7=CsvWbH{a<|NE8PUe?lYoxcNDq?n zu>?zkH{-AKlrsE@ztSe?7CcC}8Qe>u7U;tS>B1rn##N^ezD<+OSS1~EOuFM^O)n}k z;8Q3(c* zMTD-|6L*#t;_1k7NC!+t-`(q0cP>IqAS~2bV zAGYl2VONDQ$cX;q!~<9p{?m*%Su47G zaI%Okd|qn#WmrQ%*iuVC*jkJ5FT>FS$ZX@ZAd|2^RGKy9u`gclJE6KSzTyj1IwaRA)GvPlqIxHJ(aob{zs|7P3uq<*OaQg#- zLjFR!%m<8{-hIf}oXovx%ooN>hv;~Su$}xujib5JDg~^>Gehoe;`ky*s4EevF4dE$ z0ww#;)>Jju;{N`y=RZndpM&%g!{cIey!v!mzu2cm50WY9!7>%a~=6sXa{05%TDC@dg#>3LlO7?oCzRF=aL?h$|UUjfr;I_{$4Sg_?6FPz$O5?HNa`WttaOPC81 z(E<1xR%U!KDNZ!-2)X!bF$Ts2iIE-%ODzseS=eq2Nk%Q!zc_rXHS&)D>wmU?bS0#m z{;HJ7SafUM`H3ki1KV5(yw=sL~1V9XG&fGYDJ44soXbt4l+I*m!&_ zt2_4$L90Y`b3RGQ&CI}Ws}U9^$TaeU6HBHquh%As`5tzd;fx&vGk?w?FNfIU<)XQ! zYv-4_YxLG#OTd9s{61O@HF*+uQKy%^hIu<7$N6KyE}-QupTk=(Ei!gl%uVZvs!naprgO&@zcu*mid~7az7(cTbW6mmzsX~iA)T+9NqyLn zOr-GP_2=-{yGVkA_U*U_%NQ2F!g@0jU_p~7wuK5tdV2a1JtKKzEq!l6j4XX|_DdNs zPqdAfvuH05!?{SR#JuRrtw9p??MrVm!g14t1vPk`Vd_TN;nSqh;t6{S-xc^om-tIU z1)!IleLCpoH)k|S(yQi+5wowkqAcEh>BWy(*LRGLnva#jh+P!(R9BRN(*9FR%TKZ? z6>tH&l`TtYg?2>38Amf>iycPtmNa$oa@o{#Ew`Ts!1N`MhP`po+9{>MV_>RGJk#pCoJHQqul8&=)Wzffxs8Q^0&M|i=y z7%8V}!)UmtKGUb#ZOdFTW7eRN|Yp{cSlUS0UF21g6 z{bB7-H9A#{l#RJ*m~}4f78v}eUXU0-?abdUdFhnN(sA#Sr9rt-HR<^)3`MkGM@O3*aEZ7FpaV3 zOzGYG=bx2EhX3@cN``8hgsMdjcgL!Ef~|cFp6)!Kqq~yKY>lMTR3KMlD$Js$TIBBKvAX2Zkt3TK8hUVD+)3v4oDnu`4L;rY9A`P& zdCdY=g5o`W;=K_gnB0J;4DjiqM?D?*RBIH}+L|O*jLqY}B0LTTWYifEvAs%_@%89w ztQor<6*usnhR(JBnm0rj#AoHJ&elU*4ec2m-DTA4Auu9bs?fRM)~c=%X24_9`U4-G zXKR$$r`=~S{(P7A<=xG0-b>+d5Vn@Z-HBlE`sNH@gVUU^tJ+!vLsO!6VpU7Qp;Yw! zNw=&I*yqv#-=q7Z9n(QG1QISWiR5t6Wf?W|RYL&gp=wnoOn+1lE=jnasI~XR9?##; zQcCGqv14i>TSCKqBpdY*UyU=Bn0;8abVU>U>2$$*S#O<9&N#Hig2U_R`1;MfOz3GN zr|$(ds-`<8v2__eHyw447^?g*9rcd#4H{EM^O*}=KpBuy348Ng?Uz?wYrU74H)p?V z3}mlEbl1z-Wl^fw(x0~<$+`OVGggvoxJ->;S7?{O=(6c70a>N`3qI~WA5MYv3J$iv zTI;vLVozr)orH4Br)b>)_h}8=h++JXfqb=M-L+Q>Ii`#(;rzddd){6zT}-7Hw=w(( zyw=<}_$$iijR~mK54@OhL5`OMdhq7%@bqhH5@~rXltC$HW~p)Jk@)TEK6MUt^w#*q!++fuBN?XSSGn>MhnR#@9&Y50ecxdho z<;~MtA9MfD_Ajl5#tWO$(i|}Rhp|-inaVB82#f0%>}zFNxw3*L4Q#ZQjb{wXYPI3 zx?0c89X6R-S@TP;LeNApnxCHUPhGjT1pLerxq~WkYJNsTia}hAu0WCWME_!sg|}#} z!Q39lweePY4xJ{`)JDsU<&itXgRTYAdA*LDK7vA43>FC$c7x2+6EZOyGuT}}`1s_f zD052H`4Cz8Pk4dH4(Z*84n1+MR)YlwE}wZiT%Orrbq1FQays1UC080ZOHlBv-S7f# zKT`Gir;*0dQ;fbX3`4D!L95_pS$#oM`{V;Y_QgZmUymFIcwzAXz8Q`MZ2kkK9-jE} z7RNt0X_rPP)+p@{k7PM>-$V6o=7=4*xw4Ar+Co;gWj>-%DVv0JJ}R=ljb&{2$~bSzf-1+{Z`b$J(o&}YP=XnDO`+xJ6> z<)=X|Ag^~f2IH!Ehfp zqz>lkeJL(9maty>(S{elqp5GBvQ(J6i>c>&vTo>i@#b`QxedITM{-m;653D0nC@+` zG@M-j;47G%Eo`FJRLxAKn|K)hij)4u7=Y2adsL`l7*jvFry(-84b`f|(hGm{a+r;4 z%-@Q0;rmj~UC9Fqvn zVYH-y61;mN|4fW1+FpMHI+G!G@dp!iLT=k$OAA-`K{mC{D4qc3w)JDu0r`}pD>|DB zjvkfTayd#8C1L*^N-ux&;W~qI)bKc0fE*o8Ok*pj2XldCf$|K`86rp9kr8>E`7p;6 z8g-@3rdOmlh;hnFIKVvvy+sSNkqTRt+6Jp^^Fm2Et@Y}>=1Q*`Uyt#5aA^&vzel(0 zNv{{d9mN(!hwULXSIsb$k*Q}SOLuxJUtz0qn=-|87C&v`RI1t=zM>~lVl#=mq#(dN z(=21Kx3*jh-2bYVvWQrOx?^`_2DXy~x_r9sHwkl%~CAkBcY zGEL!BIUi=Q4ZlLA$0s6e@(4$%{WGmqN9-(pNvwf^UG}x!vla58Gr+ z?h8UYxB2Pj)`0JbT|-)~i}?-zg2S$SW^?0DTIvI}ef@WF<5`NdPV3BqUd#H3Mc%Up zrZ>WrOIjbEmZ{|$uJgKoRble`o~mA3_&GuCk|#V-V=dQJH__pO-LiIzMRx7BJrM|h zs;s@-;IZXUfCxqcZt=t0>VMg2ZqF~vuxhA|7TUC%IY)O-;V~T8gbN?Dgt?S_>bV5W z_J7x7%|6wu-tSSl7}GcG;n>3cj*^vEc1W**I={H+*Z{cPP=!te|KH|_Iq zT<;xX{>T>+Tj)dUVgmC$#o=Vi+Vt+o@S6LSc9>&<^?%86$BD07HDl=P@4TrPSOlTW%{1{%V{wcjU~%d zg!R`Cfm+7$`rJseO0v2Tg(v^KQooyCJ30p=NduV6c#NvHyuZGV8WkG)FOy3oc~Yp=dZ;oNYTK+6j;k+1u^mhTjQi|AzMo2TKFp zVl0ZE8EtxvSOL)hapZ&{bxTSjA}87U8WJn$w;Vmg?|&HQqKZ+t+#hlLjKo6fQe>y| zF&CDa)Hp1eO@dFN)~!(rS(grO^}`nPx(5!O`^f+Tzc9tTOE8p?597wsQxLlQcu@$_Z7i3Xv=w1MfXZDRf&knA`k-Z1njP=WqyZXI?Qbr{JF!ew;fH4_C&YVgTdemVWwEp&G|#)KT?ph_og^*uTQs&Yg-r6A$mirL?uVd2H< z(O*_{lkpKK%nqSxN0xJ%8iv=;o&pS*HCBRG*#nH?0+<(7zV6pTKE~sP9bQUb9=Ee;Ozx z2bV&9A!Pvsb>uBMn!}7*J5nEIrfDVpYbJP{B2d-n!1?_q;9GAq4V(Qg)Aid4^DJzx zNT(CDzll)OjQn`-y?7}o_T&>9ya!|7MEGlXnk35P7N*_w11x$at34nLKI^*?k7C{; z@8S_cdOwFd8%zwXAqD(#Ct3~9hxqD)@i<1mSXqhwpmB^e>a!q$M0ZLy@RdaK8Y(@a z!8klGKu)A#2F<}ZL|3aDq4}9xM%K3>H~kKlvHbT3O`hlg%=?DZ;`iH0pg-=4#k~YVE^2brkKk z_50G7b6z6f43kI+i?!c`VfD7A4j1-gpzK<^elg}IOrBFx*2*zVRLMSh6!KnX$L7~;ppa$3<5PH~sUaTL%8 z&-p5556dTno>K7W(+I(eTemj5>dlXb;I{nA+n36QczJT9Fg$6MJLq=g@P#jx;fz%Z zF$7nHo;KSZj5!MUGUP%Uk6TYKXTkW<=f-=kxBRjlSlJ?)yxcVGYP5a;Gj0XmF?2u( zMKXuqB84AKb9KPoBXr;ir80-y5_DkoLHMidcyp*hBq}-L`wAMM?2l^~5p}erCv`Sy z!S#gIf9uPxFV34$lKl)DNoddUi{dOz7yUCH)s_>A8>Y^HnkHB8}W zEXi&KzZRGS!8+s~$6SI@kEqT1lc&NJB%#MFf=B~%3834iQ!FE+iA0J)Bi}Q;JpKE_ z1MT0?<~|U$^0L7gEKYCqt`5Njy9tFMF0@TGo+mcd-VYuJJimnubM6t7b|g>aF@w?F z5rg4(7H%8yD{vJ(bph(QtpN=hU!f~3U?t}bPY~Tr5GHui}N+mE)mo`eKpdb z(Yz5S8NHn$*wwX~HrO4gzG^~-y#*l_r=QdU(~1@_sHF_ zbOVRuPKAeJeOd3+_YHbp)JWAU?gm`x5B`83`VRLb0e3x9%cH_lnA&1qEqChC0pzx@+OA>@=6`kd**!1V?ykj2~S*3K{I@@qYq4 z)(hyPDqx6mEvT!!`69Sx-~w_|axE+gSQQDD zTpe+p(n%~*_tZ#K=hjM`;!2bxsVgYDXefY2)lmtNt*RW_TjM-nztBrJPUQ!RG&0~O z8KORw#05rghx_Z5i~qq+*WcH&XTRWfHF@fhzg^e`?P~PH-_-0wp{l!t^;Y>Ld5S)< z+`MC3h2#XQ;2Z||&S?-jd@4ZGMSeY}8g`*^Yl1hPNFgmJ$byQF)#WsNd&bGuwe^E@ zd%`Y7&7Dx2>gxjz9j8RBiYnsIyMKbiK^5EZ_f+lgMr*!GTU8a_-@Kx?VGN7BVOTYK zLpG}RhGN%92<$tyG4Iveaeec*3H$V~0mik@FpZiYA(^#*h8R~N;ReM&$J5gVzDP#w zHq`hvIjI4|I;-Cf>MwwjT!+Y3neS(+@mT9@d<7bjVJcOWN#AEKzD(k-sS#kG+QzTW z;dNbUPssZb9j#n^u4-^umB>5=V=x=ir=q`Q2}qY#a%kafaN(N?P!MU^*lMEMOiS4e z9oGpE_Q_Jmdr9Y0A_g|dNJjc`%)Q+Sm$N{asN#mA*2IEkSI0PxsgqEv6ozb8p|WZ0 zCW07yRBK(%(Zt=4Ugw$ zxX-=NzYBV!YpA_E*q1Uuef#!)AwTDvYxJYOjh1IIpOTZ1TkE{sY58n(%K92RBE|!8 zR*k^IfV^|5qu5Zu;bDyxTZnfbiTG=Plc4#ro!}WZztLXwf#g9uV!~eg9szRgX=(f8 z$}^e$S0~n8pzQ~mefaq5pC;s06mVs12fFhlyC_^|!!~)B*DA`0Q`>kOWfSsR&Y^pL zTmId`M#3;~!B7--hwPf{cdy+<@|ZUPa)rJF?a_!3d}aqhb&be2efW7%{`%QkK4+R< zLqUXw%QaDogw?M_IESVV#14|laldP=Lt<}n!pd@!w8VRi1}=kMq=H%_NR{;l`|`Bv zZEi!05^s39xlln_?w&ZR6I;b3sKN@P$bZn+u-CbayyS@+&O=`-#`|oNr?IYiekyL< zOip|yWZ`W4UbqqWk_MwcZUjAQ@x$Vc5rKqt5b?HrTi5g6p$*^F0KPN8)u3Vz*tmEW zir7AW?=?YVx_9fsz|4temF|r?g}rF8qGi>*uJ~12-0En~D(d4-GU$-mQ}0QCT0^Yf zbM6(>K6F`M_WGmM-H1`T-6c|{-KBC}MmAu1JJiSS`Y|%CRzF~Jq7CJsUtjhvxE|BD za2-ET>=H_(&I_h+sV79mZf_{EjpQIqU**oN9@jTVJIXXvyY z@_=z$><--t?X^zE>vu{9@GYDNkH4Gd@~<~DDN7}H&Bsm~d6J5~ z#RwgC5Z|s}lEKBQC^TGN%pV7SWxZqf?QX$AT z;3@ixJ!MLcRA-&adbhiBAr$W}QsvSLUQmsqdyeu<-^%g&6w+&9#6QI>Iua4Y=8B7e zJH^I})^mOa56>DB4=?@qY+9oe$}8&dav63F6A&J*tCQANnTA(k6>E5(lu5WM9m@dT z-_$4S`)LJgT=3xFfMP`#Q85bTDnbu^qx_naU>zg6Wy3&BLD~R8pP>ohrmj)iRS4UH z7^A4! z5biL~l8+?I;)~c#@yR*R%m8VJJnQZ>a!&rcM3A%{ z@Dg3hq?8p_WjT>z(t5A%cmAVARIsY3@=(wK=9li=;N`%QO4IJzeAv#_1=aMW1&VRF zKSaLi!6ZV;gPBB{KJmG{;cHGmo1^&MqD6Soic=gNsn3o`6?4gdh@?QP`41 z^DhL@+i9EVZG3o)WAn?DJa}otn`r5VepPr=Y;C>}!uvx|hs&;QqeKdnQiBsq?lz88 z@7r*^Nn7ZXv=?+==o8~*X0)2+izTtQ$z$X!R5{srkPKfeEFgWt5T|hL$D{Yh5&0mw zdCf7k{FzTDM0x)fupSw$7Ai^XpkG*~yQk3~WR+{zrs1i;I4)Eacc|y1Y$}uol)_&i zrL!c^Ng9>SLkG1AAi72g5V|%A05N20Js>A)9>8y$$tNn>r;?WxUXZ@lwTO^5Rk2{s zFGfrRQOk8V86>$>uq$gfsU0tZ@8um{vnGzZL28Cg?1V3isl2$fnNNSB%y2-d0>NR?_- zh{kGU(8QWVeDjMgF7ii}KD4g{GptZ;286Mi0%T&16$p3D#;O$1TiZfPKQ7t?v{!AI zsxzz=`zUN}IG|hZu}f?5-k78f04+nXrsy`WYf!qJ!^lUk81_*-sqx;HL zFDuo;FB+3wki?vDor+|P^LK_`sV^(q383{!otk7W-Qn&Soahcro$wB9o%qfuxp*)l z};?%qjC8Gy5&F4g~&%Cm^fJK=(w-I-YCZc3OekDiJ^~IoiDW9eOX9R)Y zDwIuC)nLOCvn-C z_Ihxq?GA*F-45i2tsvJngL+OEvvOFQ`V55gnmxpZouJw;WNpO2dTn5raqVXaUoT7j z{QKA$AK0Ow;p4#C60}VM{&=R(S;hzbm|P?y`7@7+<5jQC^*{ zg%tOt2O)m1!TO9aeZ}eLd`dy!MtN%gR`>j#3eAB;<%x*D0>p6d=Z3xC7Muk#&ze*#R>(_w zl_$aq1oEpGR3(AoB>oY~JE+8#@?HW=kL%t0TDZJ0wi*o@-!^n^X}WqY+v1neYipHd zla1fMr=81S)F3U#lL({;_0t}(^=G1qMK754cPcmHJ}px75Vd0v*1SxuPdi5K>*&Nm z@#t?9aS~R(;0hz5ApyMHZ^ereH-LbIwMYo<3l)ZO(Pp{#2TAEaY)j^R_9qvV5S5p0 zPjid17e^bVp6~8=wu?6B>7a)v2C&~d9vJ3b7o7dh2ey0n&Ci&DhCG)NkuIdWldCeS zQ-L+CTJZ~N5s_Xz=cv?ggbhj-!FH_?L3ZsBA$Cm=0k~$1V7gX|Ai7425CZ-n@069Q zvx}JTcs?r-AqCHH^oZahalZ>~T33pYHYwl6uNe0aK)gB!6)UqlCF5E9Ec%?Q{9b<5 z=}>WL)}>9XFgi*ZfaXBCP=Hi9o0(L4JO*_>VS{L&(m}vSEzpP8c6#DPZNw^fk>Scl zNnz}}0NCK&U$sH96z3{w05WanU1sTl=AiO%4s`m+e86Ag0wYxC0uW-!JE|DS&(r)4 zS->c8ZKm^tMQ8KK75Fo>0P=I=_MW9*=5YWs?csgH4eAeZZ>6XjVn@Tc+%>VbHCYg@ zh#2iWOVJP}@^l5^qrWRQVf(va9h6~j_&<%Zu0~M^ooaF5g2d|8Iz9P5C0Thk>cOu7 z%IvdZXrd3PYLb)~)$K&PHy@r&(*?Tm3CFCZcZj!EH?(&a4iw0FP87sQL5Ul4BA7f| zBFae41V93ha#ATC?UH?nTMW%UpAw2$9%LQI`~{Zmy!brbp-^|e8>A~0)r{kSTe5bf zn_Q)fV?Ol2VwWO{iy^rUM*|cKZv&(6iX)SrPFo@3zKP_yHVCEcQ>kQV8zEse3 z`^;<+x5s}OU@!BdN?GwtxinL}xV%&R@WNuz^O>8VF~KK9)|^{LRQw#3A3qEw^&=h< z?1Kkbx^*tCxBJa2=(rgsCg^O6z^)((B4xMDF68<~@Q4*(AXdozEhKmx55;#F57KuU z&#ujMBF>{3=c>&O_O6N@!QxMv5yv9kxHI8}?VS-P1EdR{7N|3h9i$WA4BCiy1M$ZH zvek&HaxzcADn!F8MWWxoOZ!?`>E0F9F)w>9!xOEzrz z`Y!z{F%yhqrXJ&+Kp2!f?Dcc05wc&Oo=a5aVwr7zH{#wEj}PJZjR10yoIupw%cyQ# z{g-bG*}6v0sxN$Ll<1FHwR1L+4mzdS#p zyO_6~=9s0#u!n@|0fRH(!_IMt`2{>_?bg`r0@B21xg~BwhZ)I#NnjtK zy8#)X=NX`8zX!3uQeqH~p+IC+=b>6X)Cce1{M7iU|BZT&!l%u-wDs>g@fmm4L+`k% zLN6^-0BQROlYZw&J#g5H0Gf%bnXOI&v(?Ot{T6Q=jbI+>az?r;%M!b^WSW89PLhe+ zZiE3gC{Fq?*D)R5zgy1d68oU8qbG-|EjQW_e1S5}RU3IwEmljv?ggFStgW)j(&7&< zpl6#Qy}@wE)MHp+|0HuQQH#2r&^bxsQ8!TXokEpH|Bs^E4kzr#8C31ynJ);9OBF0m z6W@+1kV~d0yg}fYVv>?78cD9fjV8{u(mU8g5& zT-6ahLr~vUGY8AL2HZJM0O;B$aOg0tt#>;xwu{FV!c?5r&>`QiZ=pf3P~?~zJSX2k zi0!kE=f-#1&~NM=cdg@%RYCu5QpcR++QFYdrFTG&Gr{AI<^#uI8{JwSdc{%!&`* za?Imo_8oc&pXUFQMUu6u)f*HOTT+VV(j$iH)>;eP}n zszn&J{ncl$X^L|Ub9RWmCQ!F1CpS)@YnCPV&DilQ*0Eo4K#_h{F1D^ev&YKRi!cH* zCXQjW&H1yp8KLcL>?3cE>;pDe_7OKH_JNx-`=|w|Xy7LO>oAFFa`Iod?DZPg3*-pR z3?Fa@svmTYT-zeBfkiHzbK5fpY^3mUm{C{k%|1SGV$fWEc_rQ$^Xxs72Dc`!IZ z68zU8C)*=99JjItVs5?-wHgRoD66gi7-l~Q`^*MIBpY1Af?K_dBdXhaA#Pe?nXdS~ z+3y~_;ScnCvF<{RVBd)Y5EHywuiRq?M0FtFy#rwU^=y6G(MGSG5BTkUI_bDC&D2bU zhdib$%1#RQ5MQx-JBwbLp*nVM81I6MOxiyTxL5%olQtm2JK4d;^$>{GNq~2uEwU){ z&$H^I`wR)Jf4`E=z~Qs&0q+$$DDyh`KyIfL!r^M^VAoLxs-dG&d|}KR`wV!+4$8f1 zE^2I=C|<)45PIY{R}mZh7iSxGY^&08=Jh-U_Sw_``)xMB8rrGA9ES@dH?0?-6yW2O zdffU4R8Y5SJu_+Mwb~f8&7SB!Zr>X&-flmD{^cyu`-CWUBDY?@;RO9~hJ5ASM1@ZG1zVyd}|56Zk4sqLp*ds-+1j?pi0KoU+%7uQMipf;4 zW2r>9S59%>I>ZH1vbYs{{Oo7nQyx3ag(lfgvY zDaMWN&${vO_x?7lo(56nKbnHL64FLqQc?MUVkSsCf>*RL&Co#6(`t%KV(-l#%i`=V ztG}~6zRY4X_Z*^FNk*!E#rwv0Hd~(Sn3kaXXjRi}8vtEi+Gd$2T_qU3%$~!4$_5)e zz6HMxznFk{P8%+pkM&9qsZx3jc^Y?iTUV497Bkc2oWJQ8I}C==SDcsD-<_w{ADy?- zra&SsEJN-rj7P? zK+-qFKk$4gUwVM*%>krMt3eRDCp-||Zir4Tez>{*^exHHU1L0Z%;^w~t_tV9wf%_Kf5H(E6EsD*||gN%_67*B6v~&K+lI9MNjdK3s%{&rJqR zOU^0>TF$Is`OZ!y7s_YID~Hx#Z=eNcXsg3x=adLQ>R1dCxb^cORt9sI9E7=7%wzNe zIc!qy#&w7jO5Z8OrUwp#oo7c&Ce$rM5W%%Va64nmvlGMhn}OA!nd3;0$J_p9tmD9r z9DB!z${y|n$SYkChwV54V0f9(IR(N5v3k%#t@ortboQoR({8H!#KfCkX@|8eB z=YK=t>0J>w`7sZ%dod5)Kb{ZMHIk34dpqAeHF5%Fay}2J^Ei!NVutv~;zLe{KbgEq zrK*bFdo zsn7c91!Bgd&ZXUbvUQ!@gYexfFZ~(pLwOf=LjwlfSc559h#3-l4Z`6&LR%L0XpS6Z zd1d#AK@+=a{o6bot8;d|8L%sUyp#m0EWYdYkjF&O?WQ)n`FH90uHHHg*hF4D$Cj&a zR-OC7YgLg8y;qWBn-Os%UUX`Xu0F+?f;Y}l=RcR$7J_^dm2e#c#0SrB0DlS;5-Ab- z{}lbh=>?`x_^>Lv&IsGat`^?dk#t2aemK9@O{9<#1RPWqNOxbVCURVu?VA}`Hpwmq zf_$)ClYC|?e7&GcVEre=@o(}Wh_3S6=;sR{f}(s7{BNZfAJLYuEl5#f3w&VZm7eCI z5+3HGlM8@-rm?ar7Jad5KQJz8`)5Fh{fr=uzFLq)zXK?>@ABw;ANk(%mgd0nR(thI zC&mrp@0G9@;VSh$ac%+cE_VNJtoCk@Cet$s#QYNh#HnutipAiFH)w8-5z6priL&m^ znElgTOBhT4Bpr16Qn#AC<=%+&xJ4p7t9Owuc$D)9wlCm?4ROiP`LW0=-y@LL{F}h5 zR(Ky7S=(=qc#Ln>57j2j<{8?mb_3D1bYmw($3KXu#o8qDr=_T8>)7S(Vj~dQbutG) z{L6WijBE1>+51ecqY_!XdYuqK_YfJddyWj8^`(Tk>`MmOxnP-26UH|rx*4D6-CZ%L zKKoigpaxh#zW6`dkC3|%-BIrQg2PDq1>AOXA%0i!es%?U;qO4a_;*>nFs_3-O8R+E zWz}@~zbYULo~?Cbf;L&z+(VHm-It!F5 z-fU=hiVSnxi;-b&3B%m*<~%gUO>eF+!#qdP&(JvTdG35iy#FBN(>NN0UWGpCe%~X> zWj>9d*k9;S>P{o*;x7U$^=Yg{{$e423GfGEWF`JmXmXD8WzImq*>WLy1?b)Vm4H3` zRStbKa5ePl<&##u{WU_XwW#gtljeQ>b(qXP{(3>*;85L;am%%(cKr`gMTA{CaR-!dBty zyXZ?=Y&WRm{5^o<{k?!={C%MBcd*ye_mvKUROMq=XJh@tP6y)(=SQ4Le(WeHll^0W zQ+zt@Rr|*siasZVk|)7=jX0PYF7;n(d!dSe1?D4X~Aat=R{k2GBQiZ zoa3K|gc~GbK_p?Bf8n8oCH_Sr;Sw!3|1u;j@~?n$H4?E{h*;`h!$@yoPw>O*v|#)j zv?LhqwQXvw)iE$H~W3%^@MFYr(ys z`AMkh6HIn#>zo3-e^3qBFPQ4mvYjS)ri0QmnBmgx^-Pz}C9^>38~g?_Xm}8tjlz&% z4&b0*F5ut*$qO4A%m*A6EN~U0tHc+&qXK6UC}V=fE;;BDm##CHx|Dn_6G|=@^cCP4 z7pw#v9jpQzAFOt1-O;XJ8LR=NDp(6RHdqJA-AVGKKwU57P^&2cNti0yP7|Ef0kxeR zY;ciu^px1lz}yJ(f?$(N3xBgqH_}@`nJ2oPBLvJ60%i*VbAzpb^Mh?d!H+h$MsMnN zabRu-eO0hSsGoA_4Z}1jOM?vH@}LHArRaP~uoL)-pq3mxr~_OUe8OVS+xG zyJ$TGy8+h)duSyD{{r)F52U>)Yz_7SZVUFiXmr5M1pFY%>EMw2sxbgDDL|s67y~7? zFTnN}W5O6+propou2p99~`;5^`+;DVT|i@>i2muO)G zmjSN?R{(DXR{`$@*8pz^*IkOwHw6DpP;Lab$kl_}w6ubc6=S%>8Upo>V56f}QFzyl zUSN}0VMtFNx`gy)n&R*t1~XD(Wg*srVvLel*HGm7-NO4~I1k*1*?#x10rGoM+%RN@%!K=cqfMdgM9to$z z_TaEPn8t@aK%W@)1U@0`1votH4N7I$2XJ!O7jRtI5A>m7e=lGo!U4dCg#$q!6%GQN z6b=S`KsW^Wm~bfI=x`X|pm4ZHN%aWeQ^JuREx}R1tHROX9~f2w_6w^(nHr7(tPaNl zjts|n#hx*SMl&l6#(T7)CwMQi<>5rH1zQo)N?#dH0%b`!84YHKQ$U{^Rs+rtr-J_v zNEutOIbqs(ku46V178r%0Gt=jM60FYEWl;qY)}@4a{w2G<6U$)j=EeE>T^L_7tVvA zKO&<;L=P8$vLRduxISEj#%sgHz&D0V05^q8Vf+c?mD@t`BGZm=nb+u#sgOK$dr1D6 z3CSPR;d1X)V-nmyR91N88Y^MXx^NYJ$rPEN#OlLx4{Lsk#P)>28jq62wL;)J@1aNR z3uy)qgzJTb4bbv%xDoJ3xC!uJNDm+OhvZIs!_AO+EZpLWbZ{%GkA~X-4~5%3ijzA$ z+T>E6X-t*asnDaBFE4~?ax5fVo+c5Q_c9($kD(JXb1fu;1aOLPvkEK+&i8vNmnv-DA3+?R%+&*4pjPvPUZ79o zhrB?W$`5-%YzjZ(17I>$zbvm>NSCt4axEv?@;^y;YS2JLjo#f}Qu&Sb`maS*6ck z0KE;eSXF9+99QLSklm_Y8|1R=>DSm*PxafdYo4mLVb?uXZ-ZP`jkQ4*8_K7pTb}wv z8+O}M-8Srwr#5TD?t1EzZP-0eRoftQRqZy&M^(8EGFtZ3YshF-s|_+&)oFvARSnu8 zqgBl|$W}w;j8y6ev9nT{uNrMwxvz%ML}KN#R^ek<$V$UlH@TZ1YCYucKKX2mqtwzn=F$LA?kWSpb4Mvu`5>_U*tWN+d@xAc)jMhoiEZpz z=XdKNjZ%AZA!tIE%^`zq_Iv8ftcsc%*jV4Xf5{A=_H;9Rdy z6a$z9tybxiA%Cqt1$}MMtI^A9eJbQ{q&FL;fnlq@L+8_hr1iZzyQ{PAhBX7CdKokQ zz#eGKLi66nY(H=Y8FRqa!PLs<#@ zzOf2wG#INPOC-uOmnsrnBB~^U??%yL7#GSo)j2e&Gpc#ySV{P%FM}9pjVh1 z(WKPegyzNOW{j(c+1q5}O*Ye%w}3dy+zN&{<~E3$Z7wr4^1l`4cAqJ)u^pJlm&rTj zmxY%vH<2&LUSqVlUS?}eiKh4^Vvt^98%&<2k(xV9o&l0F51H(k$!mZgH&2=Dg2`@} z>P|=qV{)y})Yp(|!<~=l97|D=aL%hoS5m3Vu|OpWXSe$%>ua$=ma>a}``9#*kjwbk z15>GNFLYETd8DQ9Ll>j0{Y2&R0gPm{br77NM|RE>@E^tyE3G3w{W`0B6bj&DnZ-6* z+A(;o)ZgV7C|n?ezDJ56hrUV*AdALoSEa!&$4Zx_Aud1etD5vjzQwXnkOx^OF@QfI z-49~ht<$jXZtDzezr#8UU#PdvL6vRRdCX7Rx&Tk9u`a@!_E?uNOS`PgvFb{iVLg;N2uUZaUI-x3j})VYh5`4$cWs__=<=CEFlaUXj1cOF2;K28Hh)7vQw z0&|elB?#1hPEio(1DxU@um(FNL0}AYN`oNQ*BR!-%7Bb?$^-J(n@S)LcPfHF8R6Vf z0(F#Az_ z=?fkSsdB%7846AefjrY00Cna#0|PboE{*{>6gYzeRq=5!U}lWniv{{TXDFolI1;G( zyEr$f+PiE-psMe(#SUBJXd?r1+EHlL4yiwF29@A%hjd?++Obkvr_LB?(T?FbKNgB? zamJzR%?{4*8AlrrHS3)Tpzm}h!YaF*Nl>ZInG9uWohh)*Zl@ajH4e_?I3weLi-YR} zhjn)u4s!ineQFTO1Kepa*ma3bhqxi`3>qm?@0mdu8|2P{z`^cpbTQDK1Kp(W^WiST zscMQ#C#AVATj=U@119%(ah71b6V41w>E`07!PGynh3I{ey9mSV>9WNElX|!~NCnDb zcaO`EcwcncRTmjCUxHD7ky6pmFAbRX8qNyjP|JhB>*K9}Mp&3DF{(0e6%;D>RtL05 z*FbuSw>AizUfwz=U*WBX6}oyGg23(VZG_UL-X`d#ASVcnZr*07=CdvErS9I=fc$V9 zO_gbG5150X0yUvS3ZB)&OG6>)j>|Iv(_dpXn0Axx3YE=KF}NSRX9oGXx$4 z6T}XLgEKxm?_3oWGzjeFmpr31D>5ZYj*%!?~ew>mcV_ zLA7sl`cYS>fz$7WyZywU0P_Y)yraVC66U(3@Ss}aH}Dy5l=!z5_C!kJp2C{#lX#%8 zCl5x*%lxMbd!a<(n^0_Ct?=(Eti>{gUqtc6Z3_Q}!oIju;pH)fwY;V93VeR4 zAx6L0-fFALf2^>VZmaxlg}r^sh|Nd0$=OuP@j6lM4Il3Y}jH=$j?_W}VLl-y7R? zJ_ihM?$P-#7523|I)6f8U+-q{uPf{uLkzwjOneQ$=z zTPp1POHJNNVL59|{<6Z}U2oD~S!=i5rnfPX*U0Rh5hor&Hr6t|EI{| z-%?m^SBL&`UdNse-)1TNABQ@82i!2P(%~t5=8t!H8lRmeIrJCBI!||aj>0}z{>PZajgR~&v0)xWvn@DZ5W zkM2AC7YhGvH?@! z{_z}_|FgnAS>W<2kpE-1%R4FTKXLqAjp83JxIBf=KVEV9PH_L%b(hzp{NIQ;A1dsB z`g!~iil2`3cv4}1s`U6N6bt!ukDmt8g|G1VuM}3q*LeKb3Ql#~J>K0>SP9?d@xee! zaVp}Yfs`TP;?+RPk>Kzd7+?jz;D3Lpdd zVV`$(6*h>U_IWoTgZVk1_W&}4-|~4+AVYb#fcFP7j1LI-9~3s6j|lj06gGlS2>1d> z8Of&yd>xQcd||*hfORxq6Y!4|R>?O9{1b&$@f`vG7i>?wCgA(QFqYQ^{1A|F2;TfK zkn#L@!2d&G6A&W#aS$f*`{2buCh?Mxf2^>{ygcOhP&0-14*4h`)qHx$ixIY_@>L-p z2V@%G67un=n$BxNz7&)hd{@Yq1DVN>hrArfEPg5EDIl}?y^#M=VRLwz{&t}((;qui z=tqdHRNLHzym<#!fOLk%IM)q1)%IQS1!KbuQ*Be}f-XFjDJbNrL>Z?)ou*0LFu#;) zn|C>A$)7M7OC`H-6vnh8v| zKmrPz1e6E?W}|>qvY4kM0T%WEQv(hCfyI7UETp1C#b^+&j6pn`YMV|Dl2SS23|{yT zb*T&lWgaTy$>8?TIQLJf_J869pQe65gY;n>y%mgeHON!i=8eUFPTRa|LEF3*ZSze0 z>%gBE|10PK?x4}8Pm@idZEjE4R4S+-+UJ_|c}7-D>s5620|t}!;;EW~DxUtNbtq%R zHJ^kYY>{iF+grR~H0)h1?EQIJHZ7M-nEA>7NU6kpL4B5U(~6`%Cjotf#y^Ua?NW(K zu%r@$IM6->1`-%cU;vM*Q!f?tC*_`(vu#r^B_?tSRvyM9EIFDd7f9igkVnKqvo*F$ z%uAu!it5q!3#8arVcmc;_HH_pe?7?14?w2#?BtCgm7Ky8Hv`FcAEVp~sObwDx?RWN z1Gj_37>SAArb)ri8O!@LKF$;6xl(0(yjLmknNnrqPQbyQt;$jpcLOPJk_387);h14 z=aq0#vq(xD_EeI7FJQhQ#7^=^gs5ICh2Iji$$|z6VvzI`$+`CfLUXVte@{R9*^*^j zG|D~TDZY-zXp=bPkrA7d5kE&0FpT~_2+MsSM6_gy2V%4>B+0a%!(cy+PmOd))BL6r zbNRzrevwO!^ZCUlw56h&)-2emd1-yB6{ZX#rg>>$i*%r~NVn;{UGqYvt|jZNq>DPo z{9j;=b&7RTzEE19XC;q&H8~9dwDIDMWvEfE(jLKFsmuGcCO*TfOxGj}Lm@I#Bk=sf z(0@vpXP#FhDpFBJVjP!Vk14_Eh6X*RD;XMWN~kbj%1~vaI*fgZoa5VYj%;yJQ}dzr{JlfxzW8`%KsfJ*trq5l%bmK=u)_xZ*Ols*`XWjlt7h|4Xdu~lHrJl38{ z`6Z%#=CSsfZ2OXI`;w@ANr=I=rJ(pyc1=DjrfHQ}d%5RgL`$5DaZJ!K-m2Y8nAoon z`;WmcrYqNMZ!*;7o{4zRfH##hn6rXe5p7mPLmlDyrD3$*p?Ve(I=oI((-ONuS(sZM zW+Q5Q?Ck=bDkaK7363b!lGmewB z#&hhuChcfIlc`v$I<(LcdB^z3JIKzHr9tpFG1SN@#zzh?UN`^-x6RA)HSJZi5eFv9 zT*%GtSCga2I8VwlBzlE1Z6FcLpPO13;~NiS&oGKTf7KL~{+duT8%IRA{pLg7{#5)M za*99%%N>n7P8Drc-=aT%*&1%vJN&bGO$YqzAU~hYZQetRZ#Tuow`9q-KcCwtjHkUs zpOEM7=Xr~H-m}T!eqz6f*KaG5?Y^06`}5Yd$f#ax{~9aUz*D(9_?I^Fmc0EAE){I& zxi^D6H`zCQ`z^{3Qt=uu^#f}B9hqA;_E`*K6Q`+x_B)04@8) zIjcziSs6_GJt&hL8fGIT1myJa8My}r(OAL|z;_mIundTyF0(n9L@Nm9A=xTs^<-cLo7kh4c- zZ+|b*i&oGfPFrN|evQza(>VI?*LWjS{%{qok2j8OCALHb?(!k#YZqsQ&wPXg>poQHt|HMMq*B7lf)asHi>E-To*Zuwr13y&UUkt>>*{%G(2R|Gb~4z zEc zEsJ|tMEQpmLcTPJ=NEIr=)dIUApc5`N|e*&v33d?v=EA1@UmuTUOgzAGc^|B7(XD5 zpFuSEtfMzdYEP2>5Oo~|eA2-a``kSqv8R%&dH5U|aWzlYNr?LqJ!h1}Tbh+cJ`Oi6 z&7vxyX9>q=N_=8-Ahe||q@|*9l!RHf%4iGyp$ZL)MZkvB?2}ocUyET~%m%eY349{= zr&#TIBf^|1el&4nUfcgvDOkzLt+1w#`>EtPv8KuJM9klzQkI2z4aK}(&KkeIF&SM+ zSyoT*S4fEpS%xk@QWVSnChe&o*HbcLpczMAJTesVK0~_^g{DRtmUT_vkLzowpC?md zfBP{RoRYQ2)WVqv9#a2UB>f4++Sk#;mB^L$@+iNP%JYxOdC>w&Y|$CT;F`x;CeYIT zWfX%yjOP2CT>25#)o*ytt<;SODBiQdEYEA{3d0C*N_6nuX~ZOL`FF9-^IZAE6O{+Stpp^oD+T(ia?2B ze*A`)`zBFy-b79*SH^F8l}&`=SY`Ycq}}F{|03m&ja|`1XA)Ido{^N>lzQG42KcFr zd7>=A~pMi^<{;AJ8oqh!19$F+VtYC>lrR2KRV$>_RM zENmvoUHnc;Q-erOk^h*!qFVTDhJ3bdLql4`a1AS%M+=!1RidxIkI8oMgUHA7%8k6y zVRA%>5s~*K>r~-%CuOk?a~AtbJO3Hjpl!PCFIelk)@{Emwv7@$Q5o{*b?K#cTy6c@ zt5qR;Ps8${q&@dXh#_g(1EWZMjko_%te|Ul^>&r=4^V>iz5@1jA~-B<3{U9zw4BA4 zH>G&XKa=7uk5at6QN~L-t5sgGoD;28{+N(Hk-*ap!*c$rmOoZd^2UY9@nQaiFk+jS z{hTB|)A_5ts607h7QwXT%Q(vLy#0C;DH~ts__9bMmq(|F#Bs4oeonE0uAGo9_4!GZ zEfwzIwduTO$tjSV7V#^cSQR7g4iffv3uDQPh62(*(B}N3NA~7FYk`+3xLxDoVh5j8 z@ugGR+Z_@qS@s_{Pc{!|X4}7r#Vq?z+04w1HcTAS2Pu+h^7HmTXHhZEJ1d#ISLd`Q zpLr#dQysETXonS8X=f#sP7aXbef`RGvY%9$317gOy04$9?4;1t#QTwt3P+3cq9&v! zu|=%xUrGoh??jsc24;wXiTzA;k~cL>CkD#2FRb7^0}c>h$(t4?r-z@ALb_}Tb1N&g)UZpm%Ui|BI+`E9p{Ak z7+GG&ak2@%3XrQgc^k6eA53wa?ki6o-->He~~904XPTS$1J&De(cK zvrj&u-S9clYCP6_e1acI%Mg~ow^8CmArT|%B*DGk{LIK|#ofS5?b3|{M5z@@10N~T zjZS9;X8ArfUd^KxjjmPbPzpK8Pq(g%Pxi6-Wxm7oXnGze#p@KHlqi2-ArGc|zudQB zr)W=FD)yyRinMD=K-<5q7i{9uKGjP~3|D9%A5x~&UL@pGB6GF;prGvW^Cl&MtqPWK z3je3Hhv6S_CJO((B?|wUZ1_(~QT&3$>PX^CXp4$pQQr7;N2H4dd&L30?y=;sKu2=8 zNy_frpT?((#@YQlV~7R)A)|3~CRzVWJ(B@@~%tCYf7F-Jm_TJ(bbc?u;v)pGI54x%3 z2C+cIJw*Fwl)`6f)8rxf2XwKK=Fb;5dH+O*t#6RWZV*?#O&2I2#Ao{{{Fk$e^Zb#a zpv(bfP9p_#`_JTMFA1NR>!%-{_R=}~v2Ok*n=wzIL1Ew+#7nD%R0AGu9~z9udJ zsN43rO2OIa+8{#o3lLK{H4SLu80h?^`E&VpcZQ%+vm^7pCr2IuI2-g(ul<@_xL>PHi8MD-2g3h_4&1G> zac6*tJB<e*14oh2JRrMqP$> z^>ikGiTlow?3 zI?oBwSzd(!v^zAMV`H#BOJ|#|8)`JsN;gLRl$OgZuIQrLXaD>hwQUF z`^ay1mT)MWaYhsTSY_0D5n3;Lq`VmA1JSjdxFHo!`l7qiM|0^Vp^|;d2Sxuq8x^D5 zm7KA3wMn4|hXXl_?wF|rV3tneFe zh!PuA=D*&=QrpO~vWaDnDjqgvXlgTwO)9`qjrmlfR8f#HlK&(NJl*7_g-=inI>BjO zp!yG#NxqFETFwNSg<=t7*A3@+;tukcmaJeI@%$I@G!t=Zr1WqctAv{WO+o3ODf@n-E|u$u9vl%1 za*lB+{D~O->W8CG4p+r;tIN={>X$|BnkL(vQCaltC6j&dlF2@Gc~?~L5?%feT^IBb z-o1p2p+m@8pSrG$ucMR7((FN-9@WrnA|!o|LeeApWv3WAei9nl3q=wy?7&1WpDsAh z=`La!Un%Y)mWjKFmQpiXlj%eQ=f1d#+|ILm{HJov4yJM1tLt%~d-)^zL*Bg5`A89m zyAOHhBPrJrJFG)zJKD*biS$QojxFXyG3!H0kUx_BuOX;oXKz83IW1`CmUEVcoaE6B zD-jf7<3Yue49^`8eeIMIc2O1)w(4-`v4+&FPhI(-W}y_1CyS1vzYyI-?(oHiEj%^1jlf&AZzH|ZxKr;I7m%e~fm40A(We^yh#cU9@32?=R-c{M z+}q?C(udM-u*KZwG9fai`d#jS?zva1LTN1~_48~UCiq!a#yLiyMN0`ID#wVp`C6*& zhwLvsZF&#?Iw;RKK5<$=gRG!Gji*GruuQ6L$NgTs!Y6M^nRiJ3#{-3+8;(r`4Eswj+XLAOO&Gy6HEq~B-?DbupI5JkM)Y05g3FLdzW5b zsiT*iVnPXNPDmHIc~W_4T`F(9k;z$!bvaUs@HN0kOXBSb=v)4nypdduDY26xQe&L) zdc@|)-6MrNE2Jo$`RO6xE4f=kdh;M>D-I46OFD^aB30%OmuPH{vyOY5730Q#mHFeO z|1GtV^(kV_d{FZNv3y6o&rtat{%55Rf3!)>2bm9uyTR7vsOjh7mo$dg71 z(~3iP zrk6VReBXcrT@P#w`48<^rZ&=zT8Pq9Q9(5Ihm`rto#lg{{=a8 z&jMMoT)(}~(4m3$ofLXEXY9wFO}clo{E)5$jZRi4b4;QpLk=o2B?+>3yf*IK}%} z@LgGPk(wO$($PHxEwkA?2J$y)lq39R(TgeZQ+_jto{F@AW3^G*#NLmAc-p6ow~g9H zYoom{w`(J{(c9=i7@H$v;VVsndWsZnXbYuO?u+eTWChbDVYyT$u~@{_xlL<#A+6nc zV&&0hl$RezoSv8h44Q)CNZ7ElDC6*GG?tUHqqbq6j8$(}eb8?!z2?pj8>^x_)FVW>l%UJ8y zEo1L1?TCmv^j%t;j-SciAGtq7@))^XouKZ4bNcnQ)&uQ3 zDR4#wA)1`AzM&!0&i^{Hwed!p7=GVb%}S*go>bwzfAJF|TSnh*iTxNJg#ncNjRO!b zq)jj$A+Glk7@<(kCZD$>dgkG1#d!kdoF$m9S1DpH|G$>H@h?lAK^MN{2P=@SitU;h zk2D!uIJ~g(5wbFE;F$W{6W*h=@|+VMe}oJ2RtkBqNAfa{$$Kf{%n)b%oL}9zvCV|K z)o8j(G!3GrC!?`U7CG|jKT|VL)U5e4HM2#{T2b>#R8!xi2tCe>wZqg3W$H;8nq#zB z#}zDzKa%s;QloT}*}g%07ueH{9{2FoO+R{dGk#vUAicfWu89*CYWJDhdYW!BADb(Z zwF)XXhYIV(a`(j=;fPdO8H{ZZqiGe5W^>bM6vl86in`p~#J&;1P|T`$Lj5{CKV1{e zVrzP_?v-3glyfAWX}r3HXJmQG+cmwwu&$wj^x7m$)Bdx*CtfRlp(Sho0&n;DpbGt3 z@uG!f3rEU*AsrQ~&;xNZwpoa5_kS;vKPIyOLxEd_iT*YcxTk6EyzJcV5q@{Uum0?m zJR=s+qcd_b8&9T*X9`=zq&V40Ih=L$Z6bg^myN24y&)ainqqXpbPDI&1yd+=qSoog z#ZJHB@Mo$vimKGZ+-P5Rn=_v;upln|@QAQS91%=9V>Rz!6&N7xeOP&rH+~^uJI)Vw z!Bz^thfuAETc6txj~CZa?G!u(+MS1u8y?mkN3C1XnayLm%;%IJz}*jFg&k=&p2h93{~T`?plvO!Frwv(12<4&R`sw8+3}#5zyj zmExBg@8r{oo-!9VC`7*8L@uKj^6p53TGM6XD};(Sl&a}UR`6blo{XguCE}go(R4I6 z%Xs4>|K`!d6>+F1wdqt(t64l`@x|5e9oi7~heh}=`y@undu0wi2Fw*tT5?|D$pfhJ zRnbf;RNB$w01S@q1nQ$Jfm>4inok!2bSId&CGqEVxp_MtcI-qKKhi<*MC1@X5wYz` zDTYJaJn-kf6_g`&swX{*uqT&MHlfsff!=t>NU!^Ov-MQ6hn&u- z_8T8bVH9?*OH|A)4jtSMudIyU zql1`mnaEtN>rfND_S7KJRb#fcS!)=t6|64=+|S;Yc9oky5oF!$K}1U>x{5e3P7I=X zw#NoPom}lziuWwyg+WxfB~sS$k1=)$9$_qcjB$b#!{U977;j6_WZstYo=pz*)8acN z^hyZ%*25P-68}ZZcj6;UPps!j62)V>9D2CoBji5SPL>{~ndOv&PiZRmpmOzR<4pK` z!3}CSRWL?zW||~xG4-RSIMY{7rIX9$AJ8k+Qz)_wkyAAV{p3_9rJz4xtY843S};<^ zE-+Lsm;^hcO>&4#x96#3Ke;kO`Zpp28j+E5W%kMUbf^|n#T(v3Yw zLaG*ZMCTMyZbs!vvUt@5pY2l0P^z2@`^VJC{*!2R%xh{rg&5`wwTYos!6;%_@L9sb zrWT{9#Ue>lRI4k0^o`;ZVZ1bm9t=m%u1lVK6e*++uqU&@&#OSxjSIWkWUcm(eU zA0I4NW?e|&jV_cp6~-v>e=L&a^_All0Yx(5rU+y2a_hrizgiXY)8c{dV#$oD)|H2M z@DyR?rfXB0*?8BWQ8N)hpo#v@J3_=kZu8x-i?$&(Uj8=&xAqt>iz%C0*(F9 z*Qn&2sp1vJ;Squ^NID75ITh-puHXE#ce*s}9*+)Np*#LKuZ;H$nu+whRXhHhrFHO8Km3gZZy*EHyS)=i$O1tEX58TQ(ME}fv8T$ z`vjCs4MMK0(gX$R%60@>N;&64PM1f^n!H0e-15(O=ZdCsKPs11ciYgNs{Im~BKX@R z?|Ag=C~v5o_sjC+e7#*nz3Vl59@N2dq0%}C$$J_Z&_(hhHurW!c|$zu&3z+JJi|*K zj1d)mY?or_iu3xQ)e z$=o6I{%)g8Xebi*hdm&}fc(7O#vDplfFc2L9_cl0Kd#Tan-^RZV z&FJv~-QuLhB-2&?NiSY37n~$wMp89ZdqUVhx@h}B3}Jf#IYA9#kY<1S{~-kBPLuPR zVo)l2K$?mkj^6TyB#HvZR2I!IrL+~RZbm47Cn(~UzN ztfOjL)Dq=-QATbJQ=+)*Gu68vRu87)o`=O@RNVWpSV_fw4^4mhG1EUurVn7r{cv4b z!NIHJ886k6#|H%ONCjuSj;B$Q;sdF4+Us}@B{@EbO6Rv$feSbPYT z&U+nCd9CtK(exdli#d^5{D9@1^1|o~kwXLVg~)WlV%mon(Oe#s8tgxTQ~ zZx_kpAvMNus3{3pOk+AMk^rwM33%%Hf&>H|dE~5dRP^pQK7(3Dy)B{Mj)~srl=EtQ zgiwaD<4qkbqYh3qm6uTYWMkHmdnJ3Md;0l;=OFBqM5oqc60CR0OT{lM@9=_4UdM~T z&k%mm>-YfpX~G|P9WMYsN%#e?;|<^!2*2TVya)Ui;rG0b*MOfO{F>MCI`B(`U-vqe z`KkCl!pr=Q#lY_pUhH=)1U@nVUg&qc5B_sRzwdSI0{U&jyZ9Y%gMN+h+g``Zz;6(K z+3R=}c)0=ms@Jgy{3SB*BEKUJ)A1|BQ|@=X1)lqa-|{-%0e+qEJ6^}Tz;6}q++p8#bQ5Oydi3DG}hh|#e0p#Yod6qv3Ok+uTv4$KHYfc zL=|S`%)?>>70-%H)BJxpdlNV*t21x3-uWx92(MSvcsHJ_VP5gtwJGoS;HE3FuKi9IU zVBLmal5M!u7wIda#ABQRZTFc+lZB1Jggnk*>`aBv`!15k4+`h{;vVc{K3*Jua(T(!FY|)fTTG+cYD= z&rn-6S7>Fvj2E0PTSwa|D(c@y*1zfoHMc5WrHZ1eR8*CUs!~x^DoU1Q^L_6ro;TmZ zQ^6UPg$(KRz<23PiU^>S5!gwF6<)+F`b;%#-rl5UK6O2DZD&#yx78A-Rc@t%ccarP zodlFKO05*0T?bY0s%^HR#VGplFPex=GHsCz2f1m6@Bw zyDw`mzM!=l1JF@auKSxaDJmeh#EgC0GLt_i9$pAYpHnsJoWJlz`ung*zi60|xZbyw zKyk8RLWkYshV@ikAyWe>{Jla7A2)&LRh{z8ivIfp`Ef_NnR&@BPg47vwJP-uXCKLr zs(67oXT!L&@Pbx2nd)%dMZ*dJ%v+eOJ-H9^sIeyCC+NM$jh?V2vK z_!l$j@V$`U=-A=|QX`Gcz66n(^EBi@Yl{VwczONSqHoLuQ;73g_oV((j_FfLv zDQKr|WDzUQK{Qj%992aH7GYs#9!|7FL@)E4-u}00Zh?(R+C=QnS$OGODrVmtJD-Z_ z{Tdq1refyJu?xf*nX!whm~~a`5~Q7Ut?a}MqrU!@HMs$V@(vXCB}Hrhx2eoB1YSNqhsO+^QpD2SwtyIS*P;DcxzqDhjFF+ z9UKL%bxko^BIWOtzcZqNs@g!u0Sz)Gip551I0(NCo>K?{Q%A3m3)=N?oeQ}vO{c|{ z%lb}cv3;i;B;C(f6v%`r{PDw;^@cQC6onpLAU+$aB;JgrtIeM#;YG!Hvm zu+>#@MoZ-`ilZ)>jtiSAdJvLcnn9EAUumpgN>w3ylH#g+E+JOaedB{?w3d`YKWg~HneFT>WML&nQE2^4+U}YyzQoKa?i# zSY?{47g0*zrD$^_jq5Dba+m+%4aja8Fbb53kk9DxBV9diS-RoR=@X{r> z8H9res^L$4s)0(SeS$OUPg%C=v~G1u>+xTTIjd>Ku}-3aBL$SgILFtEa~xOSQ#DXm zxI`%()7;__bjLIv73P$w)9!N!?Ex*2av-$q#~NPJrfax1zd{1NYWC?maAPxSabIQJ znHt!-!7|TL4nLL(C4^&I>4-L6@}JKO{M?7X8bs*{V>fed@sAJPAhz`v;4h%E|avC(nnfxpN)}vloP@9O?O?O zxX{?rU8h#)8#xTfzFMaizK@%Y$HHOl(OhaNMA^7TH_9Ox=YTEB|Dfduv1a6m50RUQ zrM#5F50KYv9=bn~>Bc)9gOXz4C^W(8z>|!Iw}&x;^xfB3{vnZlr?uq2LLA~lEzmIw z&1CJXWZqWY8;z#eP&N0qMtyK7;bvY+if>PK08v1$zcWV?;=6~wcQZWy!?=rIXh#L%xq*OYkHx`&?)*#Q)>t>i&Ht%aZTVA`X{zzMp16fg6Y80llTs>^wp5`(Gg2>q3s0n#(m48x zrt8o_&o9%$i=jR8VrY2;R*|q38rX;*hirr=%#n;_eL3U~o+2Hp9rskKg&RAGl%d9e zg?KMuAy#ViYy3H91xAkQ?Ir^|PNs|f_)Bs>zK&5^4ay2kAsUOV_F%v=t>V$AL#8kx zAxxCf2hpRNdQVR^nUMYBC52kVB7Tit&9v7q*bbwfsrpn`c9IrL_K_*}a*6@X(3@z4 zR)kwA&eFUT56ghuSY3rG)uvt0R+iWrGX=2g_Y%2j!- zwklOIn=fkqY#v3kx%@5S+g)xR%zPySK{}9oM8Ov)IUrx!bv1bn4k8wqHk)FDyxe4m zS6Hj*liKTf6=KzYVNo=QmzeP0plKG*9qw-8T}0`+RC2i6XRLMEVNivBslJNm55Srf zDq8isLdf0~)nrjQWNe^R(K4FF{Lob^5Gb-XC~J@Y3C6#-Kp+UkO?*0iExd1| zZWh;U7ybLTQMw=#H*3D2>J+(ueYtZd~DgxdIe421bqYdCS5sPgP(u|=r*)ckZz#RsW#$F5V5;9;~9<2)+ z{td(X#^2$kNb_Z*UeSEPsyD61Vb``jhTeKLGNP}6l{CK*PLXGIaRK{`Uh&#i>qPfI z0TR7!gARe1^+>;;+i@dq58p`2hcx+g`esd-1y`QYS#SmKGMY-Wp&ymywXM`)b`pOU z5|KSr$&KauzM-kQX6B(U#RnbP{_Il;MI0>@_YlWD>Wqp2v9F{;Om}de zeWn@+kz4{EBVguuva4D;snap7RAI5NrRR2G zKE&Q3g2S@E#t+IdJSbD56G_U7-+K#d^ucdyxyK#f!p=8h@6r-B?Y@yW=)vz0`K!!v z@ErV}26+pn_$i}LlTu3PeJzki*b052Lp0Y+bB4nG=awEoD;(L1Cmd=-*pUA&8geqY zgxqdqP9@X0ZQH23gq_={tDsSka9pY|*Aa^06q@IhbzDB@=jw&|j)>3BrQX$1Y<`=b zU(C!tb-3u{;q#pV#ra@pKA>aHw0{%IEB+Xp%D_ORhOc^OX@wtmB8D4#CYc|ZVhey& z%E**|sWuQB5q0As?#2qby;54K3kl5JN(zaUsm-S~X~fu0U+f85l0S}p$Y&?)gALkO zTCZ;&)a`o3^}4Ov{-RH3|TntwTIhWT(ZI zX0Px!LZU-}v-c6q|EA*bg2_Y%tipPQ-Sx|bVCrf;zq{Vc?ygr#FW2WDvz5e8@r*}B zq(!t_7~Y9OU@#!@O~g?-Z0>Ib&9U98=Qpfydnc?*h}Sv_qk$ewnBfJeQhJI8C(gG7 zPwBZ2Rans=}G$oM{!|m-XirSNs4T65Ec=(=W7XZIHra1s=7;p?49PlRw% z_X*+8gZ#%_p1-7v&wUYreLhN3e!X<4uTN55h!V>j5fIB4Ytw`T_NCg0_8_9H`{d}? z1${a)0$}>IodG(Xi%<~PYlzj+@Zg|dP1!Dr6042W&(EVi9eOB#MorZOIr`&R`A*zR zQBPz#QpFyff8L;BVY`K#vystuB{XU%qpzqabMO#Do!mL}(&QN28rq1GFoq`9{;t~A5suo|t?{2mD z0e<(W#R~mGuAsOd0FToZJ#^E3dLR|j-%g$4kdwh+F!!nF}-bl3$qFRrK z)jEi3JrRZvBRrSGR|JEXov%WSbzTj4v=5#if<3+ThAzQR)_@QA-~~0{_kHlf8gP#f zUWA3scdt(c3;TH;|Au`PtmvJPQRk#mMqSr+3tPXGem}264CJRc{gzNKST?_JoY!4> zE3=eVmjz<8P^o8l_B8K=Pt&$+*=YgKf2hNxiR)#@Cec05P=S`s-E{`xWt_9<-!tgn ziDE>EVRoB6@`mlK8vAj|na1{BhmO9w(ytIF(PoM6?%A>X$*!>BVz= zy~%Zkh|FB9m4H!T3E0k_=&G_9({}1~b+qpOn zyp5cZ7{g7vuG#T#arX@Tsg_xl=pO!to*9e%bNB)NIG_(dsLNe;bG)q`0zsRpigr9l zMSVZgD=-qZFMmpxy;3QSHi|_3S4ty|;su?4#~8(n`0X%?m+)IQimQRwZWN#5UL^KX zvE$sv(Reo9N^P{`qK%_b@N*%;NFZ#BAdCdU_7GtV5Ozcm#sFbwh|mFqT@i#1AUq!; zl!5R<1fdLs7ej=0AiNYo;NIDdfw1rlwWRkz9M|!0*mc6}$oFxJq(eQ8R>kni32|pr zoQ#)*Jvts2XbUR1^=|gwB-;ma6OD%uhmAu$&>fhFhUf-vO1YWmp8p2cx5qN!BIIX3x zK2TCwJ$mFCv#-3y?5how)Y~h1gfjEfysAg;HU~-??lsQn3Z}3cUC*b;_Uqty`uJdi zVo!V>Z!VCy1UYtN>0_$az$(R|?r+q_9gD`jSsQmT8h4;J?l{E_@Z;XPJT6Fgur}_q zXu7vAj|p1?i5|#$AZk5kXNoruPLTpQOJ&GSTU+?i;)Pio`Z zqv<}?!M+4>pA#D~(35c|YvayE<4y$(!i|Ds_$&foj^T7IlW-`i#-?PEjU>RvJ`Lt|~H`R@c1ce^9$uhw?bs1%w@k0#qz8Zd6zcG0K|Xq#(R zuK&PlTVe3e0)r2`C5YJ|K%Hi#v28M*DK9Xa@N;;XDpm})biqgoOKa;Xu*nbXpujRC z)kIrzS`a=S9)QeAH8bs}lUr@AUqmh@x8&22DQf-tntQC}aG zXs8hIqCs5hy}bLi8_+uHCmL5N%`~Yp(zDww*$p;Mw^0TL^D2QN?KQ}pz!;1+z<^!H zCI!0Lk_!YB*EqSuhT=`WyIWkTejx0P8MWCUjBjlEUM=#SoD$V$ z$8F*X6s)shQZAjLkY`U}e|=SCNt5sKr0RoQSuKd1u$7-m>6CGIw%t@E7RTciwAw84 zc*JyplYPqYQL6k#a>bRRMpIG{jXCt2|A{Nq$zaQScGF$#^s4EuIYl>)NG5n+nUg@aSS*^JfM8w^ zKU-Bw6U-_PK8wvY#poM`h3Hf9Xci8k?E*ORnH!(3H&m6=XfiL)p9*6-t`M!reqg{l z3n!uBVjlps5evXnInVHN<25Om!D^>3k%N1uDcmw!HXDL?JX8OSi|D}{&2_TYa<#fu zQDQwTqw&fuv3#@ejn%%I<9y%dI&9!@p`Z@PbVP1x)ip)iEAo|aVF78*4`o;u&s1thyZS33><~HN+=9*vlEg^aUmwy!{HQe zW56TfEFFnC{%B;5k3>g3#u=p<@S%ZqH%qQNT*q)F`S9p5q^H0hqqNq^PBf+6_}M(D ze}lc2{e?8c?jZUA_WYXN>EMoJL}p_$yUtNC_b@LtY;1YcS*xXu}mz*jYW8R&yhr)q~!g$Nj+$A&K^2(XE+g=^d0c(+sA@B=eq>l&~YB zM1H-44ChBOd}}Fr7Kx?I-9bgv3oGZ zj|rdl0ZR7MJ_>tVb&H=PuSH>DpQEs+!a3CJW;+r}aV5|eN9w?UC1JXiNVk;3bs}8q z;;STHQ`c8+$~*+ehivp(oYwc6?c%H%WwiTOiqAw!cn&2j<9=-w)1Ie!`sXYxXap^$ zY4@yylHyaGzdK9oo!^PFpEG{fjK8pW5Gi{b%3krmRrZFOvN!y% z%iidhy^YJ>hO$?3+1H8zU<=YTWRIrc7iS1SZgCV=-Kuc^eUkUz)eN{&rV9%#jl!O> z=8JNDESf9dv9AqtUBtPr`$M^oMy}6>gMJcqUmw|7PNLs7ga}VyXW1A*cmg}iChpk( zGw9fdlZ$+@>WcZM4}%|*}cX26xAE`CM3Oi->cO~91R0LVujHPV9W?lL3CfT*s^ zG*T?KCoF9R2EGz0Z3PD24G|Uq!HXa)075lHn1%Z8jUdcIefNb34+Eh)g77d9dP0OH zDB_g}!V(nmYKU+e2(N|V4G8a#B-nriuZIYSfbd2H;SgU_g$SLf(}4&=C+hSTpU}9u zo95qVkZf-AzFOBF@%w1aECEO+yuN*&te^%q(KzuW_#+f z6CMsbVLdwGNEqIM@KGZ$-Z0Y?juwwGh^61>nLY(D)0Co9mC`OlH1Ig%T`7{*#Iid0 zABw$%*b`wjW@7L@;qae`upk|YHW_7vvi6@wdVMB({bZQMF0|xS1Ys8j^0P0j!Rva{ zMbzMQn0ys$C5PepsL|O-cJoo*=Mg}eRdvG@>yX3w2*Ns4;6jM77zh`60)B;!mo7#( zVbft+u8X}zxp%iMM!HLe|D?7#xCR?*;NP$TcmTKs*Dj_sx-@)xqOmv~cmE?z^$OE! zXF2f4^bvMr`Stn{@y2rfh`Pq|-;St<(sV;(`OW$feT0S=vEkJO+yP~tOyw5P*Yre6 zvabtLko_W#WkE`st$50;cx~IwO0{i~2~p7XCbYa3m@pr;pZ;2H>rARkMbw4(a#bt| zx28`jF!U&GfAp`|34^(#O-;O#qU?oWl8z>%R8hrrbED%*h5E09v7qXd zeb$7#E>Ojl>=F6~$T&hm`z7W@($9+hD39r}j8j$`})Svn*~= z@8Z1N33l7kY08@=U_F)c<8vqN7-};%8ofA-en&*#8;xEPMqd)q_eGquHUy;l62$g*;7Omkc{1VIP@ntyDVx5U`!5^f5Kg40b7*5thMthV~DjM_|@L z5RM%Fkg+C2Yx_)C+jm86Cvx=FB6?X6Js>wy4BVt>^5sGN!0afN^_pzTg^K7EL3Fmv zrkSR2>^DX1M3Y&B$$H`H?3_d_J6Tr*U3=7oQx5!=R%7{2H3KrgVwTL&#)?iSvkkwQnb`e?R*#t9WkVs@%t>R>@!GWv^n# zUAZUudUht`U%_ks80MB|;_#Yf%3}>YDS@*D7N^UDrYUY&P=F^2VEsr>6ye^Lzp7Q2 zg|NX!D49X>gq6&y(AnZ!yH>rua8>6WU~nEXbZ@Jp*5+jz+TI(S~a)EM2?Gi@)9Qzi7Vea!l>fin&xn;kr}D+)X&ir7ShrpC7QLjDXqC!1MYzeV#!fqp}$PLJje`gXRf|bG5v67?o%r2d@9h!7ZDU>2R7$ZBK))S zDSo$KN+WE=2VL%fW$+TS+z(RCOHFA`K+CPei?_Dbi7B_np5sUO^C{LUc$(*qxE3^_ zlN);eWXAojX0!-5E8)!8Zqlega3=)$JNt5;cDLZp4$AfqB{ECQp(=C1clRU`{K8YE z;q-E^n`$V#e~6!WR`7-azadb|E&qTbi`$&4SKRIt{;Qgs!k5x3!-cvZC9X1YKlD}K zH;x(l#$o1Qof&w=S#A0(1~1`b)Y&v_TT+q^@mbt8yn`fyHAjnQ1JBsCWE7 zb*8Q}Cn+|k$8EV!SA~t}^(K2{t$MkY>@D_L?jQELgZRwWlqZ~CZ6d;`>bo|XUKKY! zndcC_E!9;O2(j3DKK_z&xB?fduz1M*011ezB11_>k%-=C>f)fTa3_60)8j>x-t`&id!7KCH|LqODyo-UAU1djq6dc&FYX|z`RQn$~6^^i^ZO!)nUcc zz1RETt+Wc%9kjA?ojvl3J0 z171-t^nyOk&=+eCz2i9HUNXUS;oy29V7mT}{vS3FEZ1M+zQ+uu7+>~RaA9mb^8%g9 zUhcj+*5WhmxMg1*7`K8A8T+Rec%?F$Q=v?3TQBfY=u(-soy?E2FfOa?>?ljB&3h7U z4UWeu2kiW7CLHKNoJj(nH>Jb8eGIS)E6ma~>_gq0aXm7A-$br3t|)Qdrx_5(?GEGE z!}pp4+V)};UJU>P1>iMViM^=ne(H0?t~K4ZwTOLP#;!%|8=SUpepkHkwi&Uj`X-I6 zZ6`zv-Rve?k+nI%5#Mxu4-J=0$e+_#L1496IKqK{RPsmaD=kOr6>b{hF0zZ;(#Q2a@=89v zOUDAhcmX&b0G<_q69Hg#{otOUuvhyG4lB4jHTcya@N#PKYe8U7YViIb@Mgo{*Mq3<3+yLf9FbDA8#S3B#=}47Yas-tgF?aK=mJ z&MInuIzpANy=d$)V7m21+RcyD$KK^-^A$|@Px|t7f63vcwL^_z-Tmw(A;I|`5fygb zcQ2;|^SjLKE;Ck+3*U>Zk-A-Fim-9;yJl`Doakt~i5`r{US^Tam!NAJd!N``%Z9Y; z3nuTBjSgODiL*UtD&>CQHXF`@_=s3Hf6pl2(o+nv@OGz!r%!it^yI^^_ z$%^8E_Z-+1%bsV(<*=!WD)+K!(n!a3q0uCRO*sl7qXs&(V1L0VRh(jlO(S&+dmRv6 zIm%;y1)q@vpzeC!#P#SgGu~j?(==ff#KIq&Dj96sERX!L*-HI495*58js3DWT1{fl zq#Ep1t){#lDU4N?r*5Xc9IHg2*|CZ;XhfYbGO<(1Dy4R)QE`cIg> zoMxu~9QTUr&HPn`fEbq9L~^Wn)$B-1ZPmejnlyvetg9I~>Cg};B8oizSb~*`9wew2 zmPKXokF;&XA8p$b*|w*{w%K*)RT{p!R=a&fJ=j?G2S?+FaReP2mt$66mwcPXtlq9; zYoW*e1zT|kW=C5p*j#E9jUE;2vDPv*BUfP)86Pw9kAXbEN9OLttj`zT;p>=eUdhe1 zVwYzE%th04J2b5Q6R?GC|9LbknLw!J=V zfKn5$TEga~hKH@}+r*v1sV7ZQ?Vmgo0RMsO@j#)baR|7uZF&4 zut^`pDyI#ajTW6Tn5lj{McmLq!)K{a;i|&^Mz0cj^4)dS%vOV~S>bx9%C_L8TIOe_ zPKV!bT=|kv*y|K-Tb}wVm3bR|w+o}LZhQ7Ng_S1@`<&bf>J940d{RIt#Z_V}zly$T z4VHGR9q2xUx}8`DrD;iOu-Y?+Ws*)4hh^7Y`$aBo#S8M_&%kT#g^EK%!#?i3GrX8? z@vqe03$N6Asx+-K$NFG(>o^EX52s3_3}P-^?+)F@F>n@a4Xd8^MA@3Zr2mI~oz+PO z<88|{6y5l5m79h?l&BPbRBBIL|CE|}KlNj+?V-f*2YuLLHFF5C2NS~|_F+rZ%m;uy zoESdKhb>hz9|ATjF?^;Eds@wW1lUYG51pd}-7w>VOJd!x^QP~d;1#YXRZ|;w16A)D zJfxYS`K*g34CMYkv{iDS<=ZPfoML;0ZrcM^rSyPR7+QMOsgx#JY-+-5n_^X}ZTDO3 z`viZ(yA9q?^PO!IEy|}-nrLN?imd3fQe4X1+jwwqmrRJsucHP1^`1s?(Kpq~Je1&k z#C08W4|gK(i3z2d@8!yUx+|sotjv=MR^?uhD7_|Cxdn4CrAK;4mi9Z-Q+MKor?kg; z)p~Gk*%M^XJ5;s!77h|>aA{_$I$M4`-gMU-csVWZr^x28La|ucf@!ZNemA!=AItZR z)h6Gq=cZXPzSYXzYk{#G$;j78I_?DZUBOg?0-j@xCE(PDz|87CSrN zS8;O_tRT&+GR-IpUIG0ypQX6gZ#n{Hk-PBR#Mqn;I|9dK9{Mffp)z-pvu$beIW4P!uI ztW|h0ReH-|4S#-XDqqbD`|9i?_?D&=##n}CSpN_)g~9w1rGp)T{IxtkB-wDSlAT5K z?5fVT$uvL5TbNxwHctHPI4dTcSrH3jmFZv^++pR2E|7*dhQ>Or(5KK?%*U~oZ*cCQ z)N2~lzwKx6L~SWbyiTl``z+n4s~;xpdj8MMIWgiwpuNkg8eswNe_TK)<^}^BoG_1B*xX z{6~fdkLA>a^C{ovM3?1y#kVnVP6oyL#-yz6yuyJ!G%=e4ZD(EnowlA^;Th& zQW&k|&ep>-&1|c*$IdOZ6!Gnf@7#1=0~0NcGIGSV=W;8&_QcC37sB#)YpvAZVd&P< zz^<}N-D(LA+D9qbM^(j#j8@PhKyv@7qDq7m{Y&&)-fqFpHk?yXs#6mj>Y z@~HGO3p>D1@Dg_1C^VP4k}RA+UvrY>X3R-Ml$$AIbe_xWOdxatL4zgM=G=vPRT$l8 zl;Z{f&;hq}s@bntQp$2ME&5;*h%t7>7$e6(SdOc64=n6cy)TKakLavXDf}Is8bV#? zh5ZK0s+K`h@Ck1FuX^MlV)uy@$dfSpj1_D4N=NlT;B|&|k8m9@!|IiwU7!HFJxq*x zH^r_1Tk$KeL{%z{P638?&@My8Q=Q9Bl|WsYkxo~Y;NtGLS!584JzyC$l+bg+7FC#@ zD$PjY@5~fs02O#kp}8zp?+hN*TX-6`JJ_)xELXUtvwTapM@x$h>s7n~xj7aNxfvGW zjdG+2^h}yF_4Rh)9S182@6MK~*Y`OX@e$Q0>LcnOc}el6gf954MwxXupat0q2tN2q ze2jx{mAQ;ls^Bs@o%XFTFQ?6r0u3|MVw%DiB8MR4l zpYx2|E={LFW|A}*=fprkm%{l1zaWR{gyHq4jlnZ5N@@%l64Txx0<=%;U81Cn*n31s z-4c7y(p283sQml5iz9$wa9ZUjdqngqsTN^^DM3_#snNvPsPhVYbm&Mssb)g6SN8n zcGcVyJh+eZ1cE(#*I%{NjLD8f7nC5xg@uuH1|paYgF+JdA=;XMzo+(Wns{5B~<`;MUy)g5do5el#Boj=-P}z=#p6E=J-I5lj zVF}v{1IEwNx3>f43QR%xwCdtg&t*WKNP zO;+XsxsOte*K`*v$TZ!>0+rs~MSiMU%1Lhr@^nX{`kBoBf=pG68lg*9fkUvV9R5rn%T;U6M28ME)ET&Va~12@Mo6io+$VIgSVmoH7%7g4bId@B;`{yOoXDnpaz7_oY(kW-~O1{$=60?r*NlW8v z^oxDw#H@a?(=2*(#)+BzVrQM0-Y@n!ox?4$)fUW3v*04Sjyjt4nh_WpD;{-xu$Mc> zcG%WfaNY1b5F^+h{WQ{3i9pSsca)|}41;ay9uR18Kb9sap*Sf%79*fg9aaD_e!HL; zO2H~s1Y$5&U{`%B?w;30_JXb03!V-5-V2iN&Gc{kYY4AI_}&e?6$hU1c7SW$hSVFG zB)JFK!549Kg?k&a z&m?2zK7(-gb3=Y?L(A9(3g&im-U}SymfqFK-d~jL-6gHCXZ++~Yi^ zX%c)$3gBn~O#PY@E)qllsqnd92lis0bkhkS@7YgEQLAxlVtHk5;P`bFeeto zok$ixNlLiPYc}y-_+<8rN_|Qk0eh?nPrcKUwICD`+G&+8I+V#`K1z1Vav+_pVp5cXK|0$`~?xDe^B3p(r8!(A-UVzB= zz%THK3YL7OPlNM(ZF|LXsWC~J>Rpp|n2M$f0{SJMUoUb^zrl%DITfE^VuipIcfx8X zsG_9RUZSC?tN-tuW{vEk?^lGQk~WOWUJLtI@d6JC<;3s<71i`A6s4p)^O?UdynSR2UbjOUKPla$&D>hDUG(VqD1&Sh1+dG zVZ`3%ZRrYOFwUa+e4ICxcNoliBkx&m@gialgE2;-?_pg5>s_9>^ZBSdVEOCvS;rL; zsSslbRA*0H)5QUb&%%_3<$@>hU(wt{RAK4N% z0e!PW8%|kD=(`5?%+r=oRXI%=AbgI0A>P8hbPEg4o~F}-FWFC9+?rv_VE{irjB7kh zp%b*J?`%5J>2K~oF+Lwy1|??c;M10LBuDASrkbD)1J3P6V|KPZt%|ZfM#+McJ@w}Ov#vkuk@`E7bB&1ThVBro*K)V=vgrLW0t7a(WH^oo% zm|wzFA2P@Pc+fB5LEdkV@cpZeqj91l!K^*YJKb0@=l0O}oS@!**;d3AI(#Sv zYC1CJ9?;)}ToDZwo6RBKY=(qL{w?AOtF+TD9hG;U(EpSeQeT7jU(TR|bBM)0=hfSf zE9CNA?CL#i=NRSxW|XIV>AT(~E_YtqObCP8&^F1!>s?vP(y-x7l^HnZ+ zc!SNKdko11ZF`=F^l!O*U(fU$Q|%T0KoTlsdhdKcgevD{pqio}Tfwax5SkmKp>^cJ z=Q*x_S?@|x^kU>`>JoEtl3FR-^5T;Yi+90lpRzo*CPW<_t4P81k+%PoIvlgae@Yz= z2C&`sY0c4pgx0*#r#0UItvSjLY0c480ii-J3=7|H3sUGln<{fJ6gxX?s2RZe+!)%3 z2u@Uf%NScNkFl{n*rqT2-ftJr>CnL+V}}+7pd!#|M=T5=!?7X4y+F7(g1{x-7b1)W z!u=71u|ODS2bv7`+rDkJ@mx>eRyOA(Tb|N1XzD#}jQ;kfkz(G!r~2Qr!J0 zZnEv0$*ww;Qs~!xN?6ZM)N^ViVJ8w!!{ESIZN4Mj%gXaj7>zNkOlyY<64Py1P==Z3 z!kBcaGu<}PX0P*j(X<1T#1l~1Ogl75JOTO43K1p&;lT*PBp^H#B1{Cr!x4muKzIbz zg)6B1*qZ8&vGH%%%{+r{hiPv+ym5Za#tm7&P_pO&IfJHQ22Dl2UAFHou#%l($Fein z1mSEO4zaHk{5>&K;O#S;T$XenxgXWKdISRdn6XTU&$5=iwyuQ>yIgZ4Wj?Ho=EU~^2lHyu;{A@+o=sJa2; z8voGp53%w;>~nMXrDK@-b8Yz4>koqG{xsW>sWv*enl2Pdd?eUjSGZUg;pon^~w*m?fPT>oRf|FO`PtN1}V29F@y1$J;RI1l5#FbvN}coC0a zPQ<&V@o8A=7stu`Ug3o@%$6Hx*_pQ--(ksB%Xy20o@eeUo1F_hMO%w>L-~l!B3;>s z;=P~fD^spZZ1_>VjgQ}MHsLeRh6$g3 zz6qbJx;>QTvVO5ADg$#q2ZT8v?7BIvIem$iO%(Am8b;QHKFbs=RZ z)yb&I_`LVz?SY7x}ALP+9gCC4rVP zW8B6AKp3|%#%)UJh$`~@7Zu)O2BPaI=l7AbD&57fMDy>d$VY9V=$E*Pvr`B4Q1fYA zs)*vZ9!`8HtQK7URBrMhi`*kbkx|fN`tm_|?Yef17w%gi>a8R$0npjwoHN9|KC!trl8wZWh3)$s@cx=@R z|Ga!U&r)I7%QTW(gsP{Tn<%#JjsAw5pOh9m@^|{TU5Pgb+9woMY{;8!*p8=NfB5`F z{=YJZ9axW_53$@WHhhn=la_?rAslTNo=9|f(s$ohj{j%se(762zaZgd7bMtSyC+=r z@I!f;!)``dBrFuVjf*7HoH^nw64-8|1NYj}y$>W>rlxf?u8Um=cF`~P-siYXSV`DZ z&&cgbHPs6*7TadS?){b6JA~9h=BN`o3EYlNE}jpR{W=0wKW@c8B9uAiWIsqL6qTQs z;Hf+>LCH&#)6JJ@Ru$$aGRGavC3cb4-&Px&l`nn&b|_X&Nke9PhpkhQe+BDbC!EkW z=#^COrkIy)PpQ6Jqi!hhx0_jqXqk!cH4bp>M{~Jj&?k_M|(+ zyL%{U6=?ty+1))tCm?(yrI2zLchX&`)F)0jPy?v9KJ67g*(-diSNO9?cwofkqlkyO zndj{q3;ZwGz6JiNa%SGrzik-~^%oYEi$b}NMr`=4Qc4LIEwet31C_E`CHuVEsDG=>IR`25By%OwFmFB;b0P1 z&^8oZ{tT*QH+Gh995lj|Ok=BA+N9kBe!t@TV)*$)-AM46w8r*f(&qXrHtbal3bWBE zHD9H;UiIhjDqSzqQ4oHaai?v=7R?U>8_fIg`py!(`CCv&uk=6~O?b$Z2Futu?pj-# zug1Rfn(bSxnx5`uvFf`ZwSNu&1`+Pybtc#cu|gkB|NQKRme~z4mKOghPQEJfX7mq6 z$1Axle0A^!GZaHBH+{WZl7_qNN@Lqr+f6mHEJbMDdqz69-mbOoO~>Xg`{yg@{A`M~ zt+Sy(a)vk{H!#WYCfA5B`-dvIm-u`=z%bTQkdU`*==V1JcumD$3@C<@6~?qzq_*aToczA5&!I3YQ3X;CC_agpz(dbh2zMTN6r z-{7OPAD5ouLdvC~*=_(;K&rnlN=dukpNo4L>a+pWM{43nA|pCMJ(S2Zm}bj1dx^XP z$-ZpI?!mhnQlAs4bBFjYLv&X)If!P2Y}&cL$Ob7rBAsDIcopW|)UqCF@w+@uw70l0 zK_A%i!F4|O#XLoH=XqSrUvTKe$Xs-~gi}th=~6n(_IKU%fdQ39?>{mW(Rb`vl`4pT zw4d@`=dugwuR-P$J(~W~WhhFQ#BzBm)884UQsp;@uzhYzU(IjH`$RlgwlLJhVr;jJ zuu$_$@*+m$gF5#Sg$dj3-{b~}dP7*luS98**)9&?R=qt^X_wY=IRQB&B0>5Iiw!2F z7SeE5rPZR%VYjVqH9?z5OBtv~IgN~ERcKN=UtQTVj^Br^72o@zS!@z9%INj*m)9YkXUA;vBQ3%clx4 z85?XR_Z)8_$8G5xO12ut7;Wg^%}}s$bwf+Tg{}fh8=Vdo`2hpuhth=}y@D%?Nkssz zYY#8bs+dwxjH~jDqRkXA-!DV8e2eHmWW!z1H*7WzqjmP=K|)oyxXy+_5YdSzh$gjc zY2>X#)+rp(bWPuhD&e(*Q(YswK30o0Rp5NeO&=F+`d|OSrZ>eJf`(81|IzHJeg={D zPW__xp0uIS4*D=sBuwCYL6>>1tN;$V|Lt1DVyA3qLVkzW4Xl;RY^uT%+85*^OuMlS z@z4BI5X%s8FqFxQgqVWNn6w;^u1sf|#}}mcneZ~MidA}+=u^wi`VL44t57R^8@Lyl zk@nq-5H;os(lL~$eO0)x|D3P#t|ii9W({faYx;lK_xK_YB4g+5&^_6CTUYEjO!YTr zrkMkOs=+xKJ9ix3qYGz`!$&EZvFWx^%J9+rFe3zLfVNlcO4GO7Ub8FLpVZo3 zwJVu>({0^YaTjcOF#8Er=6fyQi3y$uK{~>nBD6@=!hV^4umlwLN{M{M-aIEV?%^j_`*Aa@Csje$9*Sev(jJe#O(Xx z`u=;+8;ggO|G2oJYdW#qKAV&$LSKEHm2K3=XJ=DNaa5`r#8o+NbPzWhZ+_$BU=@Gj zUm!{O+(OIp)U`;|;$>Tu(hN8b^#e2EJ`|KRtvi-Yb3LJr1pTo%xTOI!@9#@fHBw!f z`_o-6zf_LH2h@AUGep5Mm>AbgO}}3e0+ZnJskVy*$wswZl=>zJ1*i&ft-DYVlr(=g zLIP zML1kuk)Y4c>0S9&nr>`^X@1Y~AP7{#Cw!`Adb9IPRXuq{i# zM8$O6P%ca82+n}T3K7K9LtG^W`L8QCRZE`gQm)yD(lPm5+p2q9KCW))`!^4!Z%7P) zg-cKMdSki*lLy8HCf+XMH7w`MxX;x-EVB`U*kCA8>4KeGlZ0gU zBXQgz!pa^DJF)>-2aLr)Ho{7&+}yKF9y}Tku8a?34L=sgn+7|qK4@nqr1@sH&{|rV z%za{W%1ZX49RqQJ8s#=N!~hg_A-lL~n*_nyBX@j?WOLWdBuy8pppWnw6jA#C_fajK zf-PxrAJjXN8L6p@VZVcKK`0BRPsMTJYq^Mvae151t=@!IAE8bpHb2@sqC@bI6UQ5Yu)b}3xu+UfB_@vB z_2IH_ClX}`Nkq@5?|5~4zHbKC%hHbAjQ#_YG~E|4IAE7PtQP_X+4pRapS?$6E*Aqg zO0LKWO>p6Nrtd$oZ!bdJW>atVVGhinAB(2rN}8)SNzy_hM=s$BQG%DHfo~N24}d^cO^g`YidhvEd>15Mh~?ARA{Y4X8lzG@3IM9`4F67nHEXoAw z7*55YAeR-H{NW=2Yg;A5P%zW+W);^g-596JgYI5DKOM&_&-djT zp5=3Aw6^+)+}zxv21Ten6T*XOp=BNB`V3b%EpqjXq^*4kw)SP=Zu~Kjmvd>~l%+i+ zON&;1U~xeMogE+BJR>N8C$?bsLVYl;R@R&%i&4}nMyi)c#l=Xtx)!z+ur-|YN?Bju zwF>336uGRe$#@Gu>*7SZ@vFG&WoDSU55!AT6uQEPu8-?+-T0NT@uWAF|3=(G;6#Hx zsc%brQrEH3YjnZK#5@TTPkP~RI?I0p3p68$iFqX5YP;SY>J7FH^HMv7c_}=+a1Y)L zQLT6Fm|M6-y0)P$f>uXvGfjsEKb+{qp;*a{j$;eo$emG#W7f?*a|P>a#Qg`AN96(k z!~Si5f=3jlgvI&3B@Q{uP@ z^!8d>V@JH#_4e)k+d7fK&ba@cvjOip52x{-vjOipyU^KISq-(l?}D~BevD8(Nx92#W^f%lX;q%%kb- z?6e~H+`^o6>2ZPydJY_Lt5tj=-5*9v@piRIyj`{GwqE|X-|B@8i42#mXXmD4yk&uq z1^{+NzeUBtM{uit9cmBkE?|otEWbV>?GPKRhP*zZ!RF|T!sh6Zm@$vv_2#Ez+Fh|H z(=la4Y(Y9^+!b4xj_Lmvdp-^i$x~D|ie`FL?T!(;SE2?iN|&BWXVwvcor2n(fGkdD z=A{=UsKW-{GlHu!KTVS~^JJRH@+Ikvx@dY=W+Cmca(m4#O~*19`lRvPRTw}$q5Ej9 zM)t*oo_j}C5>qIDMqHFmj}dmIvQMX#>@#V0rH415F0S0NbY^Kfo#DJPPt%6p#ip)a zN@&Ojz-I(7yE~zB*55CxamHwN|UMWq9M+~O_7?f!>9=t0}f!)@<@$lh^8@w+>m;i+C2*Ly)^n?hL+45^#IylIz zNCVWBS&8eMPj&FIuZGCufc#n*o`mrJNbZx6`|BaXcp$tHK^PB&H@Ub*(EzDh%?*X8 ztheODA?|Ds#Qj&KmA!?`{tVmYt$2Zn?7IhP!%PW54hRSgkX0#jR0ZHSE<=337h+ZT zUWhfA?63P5gE$o*Gc zmVBw^rh{9Y1>4!x+#I%E{|-&jc-l}`W_mZg>puUQ0Loo1TH{mDn{AM#yd zhT?Ts$Rukx63;QTm&EHnWNxt!&UcDj3#Mot?onPG7%-YX2@ zho1a}q>$~pkVJQKW*fuIIJ_w>ER6R=t5)@^CZ3eGYE@Y^yy(O=y{_-KBCpF-42u^~ zDa}lnMul1W+gj75W~Kh>YamPTc`By#i5((BDqiw(px?oO5Ra*sC1xK_D?Fk%${e@I5zY6cAhnh4Nhv}A%l$c<<)DPQ$JuYr zhqScgb#=@nKOAR2RUdIyuoj=MG!&+%S}F}n+bk^m!;H+tG;)~DIUMn6qx|ahA0Uo? zB#9%e@S_1~vk|1tRwivWg0wjnkJFL88J>fG(ejH}`4>bN7S^OoYtzMb=~lxnKAX<3 zPq(a3$I9!|bZla66gDO@yV9OC80r-_5Mp6ty0j@>+?-DQEg>vUmA0faFQ=t2!;Ro= z@|zNwJ?Ts(opI9{FP*8TGkepSed(cAc2hz@CME&s7iTDacc*JJZZ)gLt@O85FFr>< z-?WO`(s*wxZl@m@)}+lz(~FgxzCJ=P>_`vD?o0<)<$p$#3}ym!@Lq9RtGm+q9ciys zr;qH8v{HILoo2B$3OBdvlL-^Vg>bbS`aW1IT-bhGd)A%^F0WpYwC&*jZI5E;K8eQ^ zjSUEW4jh&EgZy(1jl=F}>yNAU2*G-uulk_)_7bfvn79?PJyhBSzKy+sqP8S5TU9r^ zC836~08k?E~t%Kak62$^sU5L%1-#+e}JSnS4C03j&@7p}2bxvr+OM%MYA^`h*oANOyYi_U7V3%g@foldjz zBZUp)6D`U2z;Ksrx}vJJ{$*hYcpcSYPd(cKzL-!tda9W>{pshhiQvqEG)!btGrC|Y zxVcIIi4bRmsstZNq`|CRYIZYkrL!-kf${f*u|2`LZ>QX0F7jYnzD@s5yi38hZvvoJ zV>XqdGSYp?>}#}XCI*dwZ8hsp!&6pb-u0K1 zC*3An{Nm40s5N%fQ3qj)!v%BD6Y6rIwh>l$QR+HacNX>CnNWP6-8x)ZRhu*_vl)_t zBCV7sODvKudQq7%bvl&pHN^<-VP4w~xVP+Y>nJeJ*l$thv*V%2aQxaWxui-4;But?DC zsRGHU`Y~7mlzpo~gMk6dDA||OinKf3MQjVo6jAVYR)>v=cmz+fqg<`R(iFQm9ACS* zCj^Uok6he$_HUbq#XT{yxF^+V@^&b*$aZrp<7}0$F1Wv00_t~49d12-0)IhYSq{g> z71t|Ph|HcJcQfz#)C;6^^Ixg_znr}bd{jl2Ki;=rN%!r?y&>Ikm|@J!#6+3v>Z&vQ z-^c9E_#4}p{f|AnzZsX=`E`EX0egFAb$7=Z*q#0Tb~gk4t>${%1w>?ntHq_Lo!ruPC7?m&2{2rou>u?R0MuTR`*9HVU=(gF_0 zBpdO?MZ_oDh%W=;?RKUG#Y|J|OpB0ds-0am$OhzvGqonl(<~gtUwTA0e=W z0w)nz=!;6BFDZq- zh@mgBp)V$zMpIAla`>ne| zQ?4RE9+0_>K0IHth%8`Ig;lJYh8jn64M=rOk^0tv7}pk~Ynd2du;o~oDdrecvcHV@dU5|i{!Ex6;_KwYpIHz-1)&k_ndErh}fnaw^tB5(A;T=jY%9J6l19=6h^gDs$g zRd##>;;ZfWX2jRn@r{VDwd3m%f7NeWV_J_2*4Y_0A;bD&_Y`FJ#0F$)aW&7=>qm5) zJ08v%BV6|@nd9Nc-CE9QL3p>;*h1lv2)AgBIgNF}QaLS2|Bi?0Y)XGqd!SzPnzez` zC#rE{F}e%UO@5g3fVi#skU~j#18&?U!R^v0#mosfulwOfH^^|H5SiWs>8#D18X|%^ zQ<=22B)9l28|9tcu5Zx4K@ZYV^>$p{^Nv+5OsLlkG0s-r?}YJmYSC?PD#kfPTX1sS zMjQfHnM>ZDZXw2s?VoQi!tSap+CQ%+*mbz!FCnWp{VrmO6e;byuQtwi_nd?xTY3e#h@A_mp2NQD*w}sfWI432mHUHTK6rDz zVWNLQ6mFN^Dm0i_x9dLE{-Pd9+{b-(pOQZ7v3dr-^$zbrenC0JFDoDLE6d?Zhu7)& zkl$C1R6?t2SCPLyDi?%@24vpk%lZ<^&iQftCwfclr5(CqFJD!eeu!1DRyW2llk*7* z?ZSe%2O#qH>eGqUr%)A* zJ%B8^^e$h+1J33LVBh{-aTT`L4{ch}mVI{dZoV}ysk57J&6$tk+p!$AHgycE(E+CyEMeAM%PsC#b|nT-O8iZ_r=TinJG)94Q&NqkPuVSev5^TT&hy z5-vY`AG3}Z$>5~K{{J12c@NM|_=!x|P|O+Rae@dA`Kkx~B(oo%&(dcP%aLF5TlY~X z>GQ*xdtp|CcNIEsG9o@{jZ2l#ysB|#W2Y(=V}!z%SGxlgYUmEoHl5g`4eUzq(KZe2&KC%ga#y)Ca|~5n z=W$CC$Ooo69RLOaD87F9w6dcs&)(u|95p=z+1c8eOCR%L4TiRuaitQ`tZ}t6n{DmH z#5av=B8}pC)*2)z*-jAZ4IWwe@jP9;gq`Oe6sNKMM+mw4?WeZS{nQO`whB#1slC{p zOP}|ZsG5G0K1r2CTh$cx^!TYgWeOZEERHr&Vq z+@T^pHmk*VrVAK>;dcBK;w>s((%?8-sF0t>N@21Peh9CVIEm7Bt}*K?BF&o6#?~^Y ziN$-g;ZaBCf)C(x@%=3OF+z2fdCSJ~gN3`hy7^wQ---^9suS39>0^PAPQULn`+ML$ z=-#$^?63#r4qFjpm!HLgMz4Y&`Bp$U8-X^nHukB{*?cdYU3>8iY=L@5fWkfQNYz#D zEqj(7W!>9d2Qi9!2Yc!uMRDF|QoAao<>iCEle;>tju0wLM1oq9i|_3IJAG~9Wnla&!Kg35P7>a zTvAi=hd%s0Odr=4Kb{Ih1B{Z7Qu6l@l11*Ir5%F1jmJ@W=D060-krE7c~AOmxZxf) z8mkqdYJX4gv?1)O+&8$4iZ_+@hb%0MB2gVOs%Qf#dfJLQq2@+Skx>`s4U5paVfeSk zU0(L}j-DR(y*)jD-qZ6-{?`FZrPRxHDWaw0K(wDQynM;0Kxm^?g}xx$t`=j_(v`37 z&*PD=?Ju%^f+sfm`l~aQcc9ED6_f0bO4NuXCFoEp1B z1lH7(+!~@cBE%x{)IFV|dn||-Eo8ASjp126PR?qYKS^$zFi?&Pf7?|$SqJu+<*~!4 zjpip2etyDlyG;8;Ms?Fv-7RN5Ej;}N{hliAxXTtUlwqlbH7;ns2(44UKUzos+i3L~ z&l_KY)>Dku7)6R~)e;iF?dC<2{!hObFk>J4oI^XmWO;)I`@L;u?1)d1Ba|ODtSiUs z8WY`w-*%TQZ-iAItTLh2%Kj6(v{u5gP(&#Yl*X!-n{Bq8E(k%A5pOV;S)OYg(_)4Z z@2u+rzOmz8N5#W7r5&*-t%S;|i&WNWT2rNqT|?$fi8Ux}ub?o^+R<>2tisRP!}jE_ z>;LC?tpNSy(ieSoHICZ&@O~bXX}mOr3)Ipa$`NyL$~OVL!6_ej16)F@@aP@0!PfTw zeks`a*-EDk60zbECBRMW1#Y|wF$=J==Zf3^KhnQJKgF}_M_@%JsMZ7EWYuE0t`o!c zSDAl?fW3<2@omI#?bDKn0_lx+nJ2*x2b;)(2|uppfw&wZyeSd4^ihF(i%TR^h0#c zEMB^+b9Wc$$UYCMVnaKd=um6U75@=ZbJ@VbY~CYOWSmPmIW5aA{torzHJ?2WhcuJw z;8}!<9HOE*YEesTq@T*pRiWuMpkx$0auj60kM!d{)GjpxrRINCsTnBsyj^M{N-dyi zQ67w!$Uw+_;g5w4ks&q8z=1W&kKDLOz%)Z*W}^SWFA|SPoCq|W2sm61Dv^7>4W$uGd)z0F;ZyuL_q<(^JfQJZ1F=bB zN9tiaRg!)#c~HxY_k-ce-QDD8K|z(rwDF*p+^?k$Y6HquD$5rQZ%fZ^Ob8?WY|xvk zqM*p(EY0C0suMX5YZOG13su!wRVh|g?3K8mWg3Q2x==~g;@XA9s}Ue#zzqpgMlCHe zu)Z%NwD3@@TqfvI^beq&0$)D{Q z*2&efcf=fTT=7|cW|)_&P%nMBq#{gD!TOZc!W>kN=ZjBFlA-J+Sy27Z%v67lSt|?d z3e`>cX9QS_iTcvwG!xBSnqXk|%!!ZlE4k!b6$F&~X|mt^qHfAD(_~fniV8jBv+Nr3 zcEP*Rq{ryTUiUa;-xs$gH*4H>maYbj9Ndlwue~&fTjmb!GHHef_^o7`A51g)mKZn? zD}9N7>|@bgCMH@Bkb92c#~2)ho<7uucIT)fGe0*rrh?{zC)4i79y3&216h3lg9rJ! zb0~8G9UxoY80}uELfx2k=%@JeG~haGLQt6Ra#NrH@qvBIb{B;3O%FEW zf@Otl6$81?1|sv~{KwY}1zAjqPw3~gKvW%L5xdnYocg}(w8mQas2JEygS=_5yU^rL zwfn)TagTWA=y%dkpnW_V;#h`J$5@Bh`sF?83*pu-qKZ*|AzJvXAF`Kx@PV-=B5#;J zAbLR)bLlpJH4|<+)v9YwK z*Q&&cl&^F`5X}Q8s{XI0PB9_jZGChF=ueQ?MCPMJd}!ure-7Q0OFvD0Fv`#E`xAVo zk`=P#NLf-AL=-0a{7nDujBX-1mKcm=c-OBO+XsfgwA?`;y|DRky3$_XH|`-p-I5>z|t? zik1-Zzj4Lcfwdvuf}K0@nJ*vv%%`*vVkPwgKqY%xp~{C-bdf)6v_!J_oHa%uFxzig z8QQ}ALHx5ZG9ogxA_L)TjFLHF%uFq6*)IUsw#|;efcSPhz7X*@R7>f8WZw}T?#KUw zekMd}{}Atos#Ctfo(&t5LYcGS#tUJiJ(Rf+ZoC{eriL#^g}uM!4~aW=sra zj%bY+!^V_Q=3=<?6%taUayy^G-iIWEVe zTt2xM+GzfbQiE~=MkZz5{&S^pb z-7IiC)d~xSyHx0CrEmbIv}QN;_&I8RF>~T$#6H#(xX#I&dFl*gOx)V!ZMc;^$HzuR zTm%c~jEz{|g*YDG#my$KsA;$A_PN|_7X8-2MBEB zG-jx)`PPAh%UReZ02=~y+)Pb(QZ?mNjjXXu)R?2?(CyaDWLpHb9g?FXkb}YNr%LJG z%D&21Kg_B14rg10P6v+B5jqDr@)81sV@5~j3P5x48u}#=@_ixfq0_G0?KADlJ5{I4 z?d@e4Zx5AHMsukyk)N`gbE#H5nckeg%g+Czb&LtTNF*GWpM?e z2@h^O>1_iG*e&Ek%amJH5kCp9x6&7d* z+PmfwzceF=-Ex&bkJl(R?n{h9W+~ttRP86<6-YRwLK>@?rLk7|nXAbm6#LkvWLEnV z{c`Em{)T=^b3bDFS1?PJL%>9)_{)Bm_9JXgOZ`Pv_@#b%_fY}kU5Ll_x|H}U?5Bn9$w+IrnSLq)Y2((xp5$`cRba2Q23k~>k<79Ju`*?B zIuqxGGHG%X`R_Bqs>LR2E~wQfy8KOEW3vYeeI{%3-Pd+UUYf=;jk8W+F~kKu5W?xa zhB%K%lNV9yfcQ$k6Zhljs$tR~0|jMX%gm!plKEL9{zLBl-^kvFe9SL}6I0o#vUdIZ zENopF!rLLG(V{aZqR}~!jVevF(|eFE1jr^u@Lq4y7}U}rIPvtl*(HoH&EON(5$^s+ zMcrQf5rZ%}VzM=;cCn1gQ3rOkZ3~r^CJ!Sx*vrN%W3TvKD9zgkjdhb}0{g%;rOHYZ z;>hBUjGdt8$M`jR@K5B;`ww zjfi})yynE%{M%hTY!z{0SfDZ$H+HVNKmcgnpE37v8 zze(6YOImzsDwFuDel{ztmeYBI$~Sp1asye{C|BO^TdZ5{6=moPH)mR;$(t2PXx2Tx za{YG%!dG6-J$zh+@Cos0;#z=~ZydhFs((U-C>De?fL_AMNEXQm(RZ&W8t>4K~4s>2yEzWCPY$h{RIb*sO z%lj2NmLhRhL?{Cm_?D8s<Tf$)z{RT&OqxDinuv z=B^X`kuU9yJ;e3BQiN_%!%-nGbt8Sw6;nH-cr8DXWW-qz;(Og}J?iVM zWt-#ah&tg_ppsRq*n|^4Nn3#sjJeGG7OoXyZ~GmsVkR!KW+Kdh7%!rwufu9M5o@+y z#1V2hK4sSHPS#tA#9s45o=Zrx=8Tv6CM@OzNQyCk)+jr22`xk${Bq&g;FpSqmQBbF zemO%-pg@S*ANb?zy3~d$$trDkU*&38345d8;#@irF**N6D}RkUD~nuHVVi3Z>;UJ| zTYHUX-X6~a$gOa{BN=ULj`I7bP>gSm(i(&OV0zruJQv`!pvj$2z2oF<D`6_c$FTP}H=*={p7+pWar04bWt6~Dn0 zh5_#F1hYjfUIpVKb7L*-g6VGZ$OLwohujn=l1}Y&a`#GZt&z_Xjp((#?!Xy4!E8j3kCvm=Ng{rnAh zU}7sASlkM`ah%`{0B{Pi_x;Xxwz5z#3+ZW*_&&cAyVq`u|DbBt09(e25$2`mAi8B- zz~lG$vmSo!bqmJ_ZXqS_5kKBOFTf0MZNzq$VY%#hR54y=xp~_vO_rn5Fb&`eJ5C4u z>E|N<+A_FIS_<;8Q*gHFG;nbFz`?$6B&VYSw=fIjY4SFer=~>)fH{RBr@S!aga;~t z=VPAOjEJK~sr)z5w*%Q8k()ZBi47Cs5So*6?Vj|^NNm5~$%dYh)&d_Q9&XmFvRUgQ zqFI(l&j)cj%H7@M<~M1NFkVCX*E5!!Wk9*7qy2vY=}rD0L&cGUgb;L z`+BeTLO|au+xwpmL5;6T#5YEYgDa)?d$rwrQ`@PUuW0!lLFhxv<11^szFh;Sh zXt^OPVNV>ZrBq6Mdd!7$WH}FmtH!aco|CK#D3(I#Xs^fPYj2xL1IpbNtl0Ar#m=FW z!O}=aZfp&P{2^!jtK!5tx0#}?l$v`Qm=CqZ(4X1ofa|k zbe5ck3&>{!eXh0sc0i^J%iF|&B?z`SU#8yxSkH;{HFHW|pSSRU+c*GVBQt@!9O)WQ8X#8eL{B{d?-&Zi6WjUp|EcRXk z>oSv7`m;_=z6TKwr}0(adCd68?*YtSUTN@o~2}Z?fde za`}C$O5Ndlfr#Kf$3mJkVaFmdQC0@r@b{#YI+$b610%E=M?=_I&g=RLaD{)<5d&cL}bPUX0v!Qmdo`N|F#WBf{Jl*rcrt26$d#@=0$5ME&d7KIqyne4aaAoxsEjf zoLQ@=L~+b=$Y{nFskjJO%ik;b^>MQGX*7R&l{bGF2{WrZGBZ`KYFee`|1`5!#X@ky zpN}tA*_a{c|2B)XsYaoQlWzGLMb@V|>-qq!n0`lQ-SdT63-LEpux1;$%~i6^QeF{* z5!);;1$9bvt~tqhYxnLTEseT6N|I9(h%fxKNde3ss_zYkrL6I5qw} zqwzM6IZVqWRt5{X^i_ZQq8nH=tPHwROCz~lA@-`O#HTRbz7v3=SQ+eNkHOXMu7K2W zlP*}}C%q0<*~#VO`=&QnaR z(4YBv5DpOaedcHIgt=*V_h;z-yd9s6?l0K!v54;}A%d|Wg3bWW^tZ|pexDBWQ0nGU zuB99_l@@zZQC9$`T{vno3-Qq|C+!iU@4Br;2GUCJmPYn6^0(U#2dRRCd>?>2z^T@% zJykWO2*$pEt>O0`PsVTZ9cppP%6T>?wyZ+A%e92+*w5`@0$r)HMlAiBu_uGDt!}ct zyg<>Q>Qkz)82i56DbJu&4wiJvGw75<0ZTQP_7PNyeeDCg)C80|%xe}KVVkDHDNljd zrw{FHYmx0pNu!RIgpXNxC6)&pmItu_9p?_SX4?nF*@kuX4IYIP0az+$33!^NsSgOb zQ7Xcz*#RzeID)-BJ=StAG>RA6R#m3v(%1Z@j*jB90`O|}ku_s-=>@>~WB|(6ed|Wg@#4W`BgqSX*Y5%Ho%~*h|EOtU@QAVj%x0fgJNx{9JCZA4X(K z);J=0?%uGEc}igaLtAEn3cTc%xl6`wTVy0hkrC*Ln+s)I6X7Z{KdByh=ysbQl{xf4U1NMiHtPktd3M=g-a}y6r zh{mZ%C0j?nEBzVoq}rW|!}@l*_-(kx-*o%inMfteZB16&EniO0sg7X~GURH`My&br z1>D09M-k4sNaY`(2u~I6)?;3p3Ug|dK!r%>^20S=jHv85yX?o2%3ImprwUzxTzr!1 zU$_{*4P06*%J ztMWRPnPnIiuLg&TkDo@QPf;hfQRw#fIdb!H^NTiH>dxwTyI0X}V;St3%r_@y2ODMw z9kjJFNZK&*%gn5Bpv-71e;#X~9m^#+V%o8s4>^_#zW9Q*5#ZkVV!)&D%QoCPtB&S} z1WhC!0wxU)Da{WtD==53-CYdtO&fd~8Hl2Hcv34O*q4z)`?APR9L04HFO2Oh5hygtIZx1bdGxPI8oVogmM2tv5)mLJ)ba`A8MWfua{Ap6XNGFY z(NlrTOnEf2yk}evxV@gx$^U8uKZ}U_fzSDL?#f!{491*0`g6aF&j{Lxn+7oPGA7Dc z-ROxFy{x{hI%!-vw zMITX8qahQZ*2`SHL?xdJ%Bb9%VqLm3vt8BVxOlMAmXfFLL(KyH&=H-_E& z;{6m*#fX=J%%!)h>{|gy$oLOG4W#x+`rfWmF;+!S0IBV2?5UuVekRzg3EM*3sR_** zH)1u%IYmTej>)$E%^i%&uPhaDn{x`d$|KV{lMQGptvG6}!+@Yu5v_m5|S|zvW zu~C_+xJAP*gM1y)p#Z<^dawSi|tgcn_$Y&(cU6`iQ+TDcn&Vj+b$l4cBrN?KFS55 zEI}YA6x$bnQ)PMo;lU#N_$FAfmY~(dwX%tc0hu2_cRq;i&Lo_BS@^j~;b)^1zNj^R zO5x|+6#i6eyiVaM2w&G4uTZ!h;VW9>1q#39r0@l;@hXLCF$Qq4HkqhYN=Nvh)5wy$= zUBW207Nge?9ThCKK6Fi3AG#({xu#KynG8hsFdg z3qk85Me9S20|sRN0uLKO>z;00P~Ou$>Zl&{zccTEe4Y;4)b>o!>1H3#1>r@xqu#`A zeja~tiWnb+Pp1m@w+zFivEjNBYh_Px6SydQ9^O$tR0wz7B5Y)?k0>?OAs88e3t~mO zaf=-8=`q-URL~{Na*C39D##9I3ln8YADd)g_r>*vi9=zPyXt*ecw*2k%!}mV6`24a z7f_wVANt_~;NsI9)Q)eH`CCZ1jm{fNtXYR8()OUs?{Y63$W0Sj(r3$H3*~BdB;MYJ|iTFZ=%IUi|GF*y7O$oveStYEiK*6d+ zc@fIA!Cntz(}I>r&IUOdlLIolK?2VOE%EC%J@KE$W(>@%pk-^eRNAo$@;HfF?!H*9LY-#|HKOAV35mwpy$3E^9Joz#;8FuJ zISkyKlDRuK2tzwq0&+pKAs1AdbHT2BtiXr!dBu<2^s$>hcH`qg{y4vPb8dtFx7 zG$3Q5x&=XxxMOU5N(T?wqQQFE^yvMr%u{;fSSxLZV$49=SiNzam9|qcW+H7IsOp7a zU*&*>#r11*q-f!6Fs)xdhVE@~{aRwJUx~57>On&?F}y7Vze{~Elh~}rXLMs$)R-ML zvQcAB^bvRF8NG3WZfpu=Cg_dRbYpJRm=`tXM~&yB#)7EvLey9oH5NsU7o)~i^$~w& zn%+1?H#(xmOHpHS)L0TVmQvXBh&MAuZ=9^>C>QM=ll8_KI^?k^JVS4sPT`k46rQd( zK1bnAAqqdIH$JNy%c9B2y76)}IbAoFb9e>+eTDz7j3#I3#wz~1np4*B-?g0oRsOq< z|E}l18~E#M{C6Y&-Nb)i=f9iz?-u^M6@PyoNj&kAd=N<6J6##772(_Zy7?^UmGU;Kjl zf@&630ggX$z)E49FjVf~8?N3=PSAU$J*U?bmc8>$r+kEHrHIX-99-7nSjm-tLw0R# zJ=IdgfdMRot;L{IcFQE-ZbcJmSc7S+8(=QPuh&nAiIS8)>}BJfv`Nz1Z@|xWL;k zvD_iBOn0fQrkP9cRgu?BZ3FMJAz1X4MH!^8*w=#Aiwk9ja4F zbKb;Bsz{;{V%;u=@NJP+1TFMFEew9Ojb%?Z7ZkFWU>R0|v?hB)!O9(!JQq<5mj z_Vi7C3#pxbQ{P5vSKrikklG!DkA=r*6c$&cyS%NPX3@fZ7sR!@iNQ(CuFelVtc z`=WEK^hjCgwrsfJmg$M?eSdXf?CU;5v zAjLf;@lzD{mc)-!+?P2-f6Fo_>2G=F1ZsVssgXVS98=SW;M-8+D~n^|3iqfwr$)hR z$3dGskAXZ7+3}-@e_+QC@)Ly}KZW>*cKkTMO>o6@lrnZl0U~SUaG7#YWi1^P%EGE0 zlm_gQhfwmE9Y2ZqaXWqj@e}rPbXZMK!iM#co#ik;G6d~cmt*{3P+Wj>lEVLCK;~gw z>6eVknP4wVs%KE}ti8~kQKhY*bG_0|a@xne(l&D1C%w`>;k5I`sb)$<9vhH3jhZf$ zU~;iHCKvGiQV>s#?1>@RWm;ZR*+$_R;u_Bo*H}z{PNW~F^y8)J(=D&6rtMV~89$(m zA8CaWPWTfSw>OM*hUU7`Y}SNq9eN zh7-i$0iyX46iTluhp;u)rg)Ev>xz+Vz^^&vb$dLwC$Fi7DX%h;%>grUF=!@71kxiE z{2i$@TnxHW1#D}>Lr#~ctg1v@g71NvL-Be22%xfuZ?0NGkg)k{bmPTfcP>rf^90@) z-cO293pw}Z0EGMWqQW=jEtvWERh4D8?m=tUI!p1!D-ut|&haQQ73X zk>uV;tR>`RTLdEl$$gRdD=dW58loO6+h^Ysqm7X7>vLaB@b>bxp}c6it_nA$l)f)& zC9!ULb>_N?3(01_NlOQUu~BSX#oS@zG3M#2a!=h`2Yj|d*< z&1?6`?|^!*0b%HKKZcDM5bmQgU6slz8^B_{n<_ho`^e-H3x`|6Xws z+!=AWF9sc>LQad1xklX2WS5e-(-h7W+Cm`8hs7u3U{qY#&~&iF_O!r7QOKH>`{lI!rvaG_n3hk4tZDg7$g;tDn2uoooN0wu(D5PL z@!Et?FNc@UhQ7+-<*%hrr_q2kF@znE7WKx(dg79^;gZvlTC6uN)s6k3%u>B^g>F2M zSpnv0Qb_KV$;EndsScS+T4LOA;pz7wo>Z1HC z+05=)D4aeJN&ZzEeaPSMsK+T|TBz6F{9LHd-u%RX%owz5I`@jS5*BhPe)SK<+8ZAi zaDX~%?%_wgCj+_klL7gN_jEvz=92;Wh&Pj<_*Gu-i)piZrHTDxHrIf4B1x;*NG1MM z0QclsS||J}JDYtbfdA7YDr@}N)CkxYoD+B zFi$R~PY&RJE1hcJR@uD15>729@gTb9r8ZYGit$4c1*r+bxIG}=8yMRf2*p=o6XJS6 z4GfchTVfSTY6KS(6($dqb3{=53e6=jpt?Xiq7akObUPJ43W$pfPY%>LWLb_+?-QS9 z$3>5pLIE8z)*M7lxVmDJ{4OmqA4I;KCVy+uskSMD4dF;m9YvWe zKhNtzkRJO(o7H?iAeM*~;4n7?XenA5z#dG2w2`0OahoB0D5Snc0C+W%0p$#L19R z1_M4Xpx9qzneDy$;;hx^H+m(Xvy$KJ)kPm$$vb#Bf;>>Mc_Bx759Bp>TA5|4nc4%# z<8R%RycWrC_l2<*Fy7(J*r(BX812|aRcU^h4YcnHK|8b68ktX`@XMJs&g1OMeI^bv zxWl_3-+@I}zUQ$_e~)*;<|!AyD2hv+MC40^%|b)i8Jpl%gta!xb%|NXx_V8O375GO zF!y&ep?q6n^QpwF{U@vfGaA=fX;1$AJ1n6qiYN;8|bCr9z zJ2&HzDz?DoXz!9Q-_7@RqeRZQ7KQ6pYJPzwJqzjOo{D=Uxa$I3U2S}Rz*$0}s|49m z%i@R29l1h$SpZ^p8v=E)UF8aj=PUY47&jzJ>jJg4b@35C7B{d!N&<%2;XF*K^-V7q z{TDx4j_si{gaiEJ)^g+Lhbpv6Nc&ORXM%WpA4jM`xA$()m$iiJvnExZTjg+cg`}h` zA2D9Qv7!#^S}wgRz=xXRX@gQ(=++**FUj#PPsBec4sW|udn;1%unLPbKaUED1eV#g zxbMV=^8E6z12RpJ%?;TeFy6yq*;}I8_f|mO8oXl#w#xN=Tfj^-wGH#JZVfJN3%6xrjJDEQ@*;NMuRydQI;$N z$c8fKkCZzg^9Gx4cA}Ijem?}i58M;)1kBh9tQGqC%Mxzk=fig@1JR~rMf_+82PY{`O#7e5D+TV3V-z8TkT@DC@j&rA;vzO< zQ#}!~T~K@!g0XMi9?X0If)(`TWXMCcJ&5Y^0i(I9kbcLRHO5wC3ziOV;&C%q4Tszf zkGq>6AMDPtTkAr=mDmwza_8ea0?tH>V$%2m-l>qs&7R}ASl%kuoihu0S*SooltOH0 z0L?!ga(me>_w8`O@YrAv>V^3!;j;JJ&|OD`F*D$5ehj+8KK8%Vi&d8s*voI+8z`L@CCe2t^>VK(A$z%5*%!PoQZkSSe{C*BCe-Ut-G8IN6Uwme7}^ z!A`k+bRp*_yrn&j{UzN_ldCHbo9|Pae?bd@Fx}i4FostlU0(Vip`|LHHAYlrMKZ6* zU4cBEHTe93;K&L-FLwo!gI3^bEis5e4^k)>{ZEIKe|HLtO~+$e6K=_Pvbhh z#*tYEzWP&}cio5Ce}%VaOx)PsfJ0i^-iOjx?VJaZ^BV63Ul(zd?vUnDD41NQv&+`& zp6SrQXpS-?oz8)*Cli z;SGA@E-SnX6g4tzJ)Z8+&Gbp^aIImN@Rn|A=(l#|^SzxewRTbVJZ0yX)kC3t!y(#x zkY=V%Mv^;qe$F5>^>B|`?0 zF3m@8C)~Fa=l?dhueK7zvO&++qFuXmlYgmD9>1G84@w+Pln+? zQQ9(d7bhq`io=HqRRb3$-?Lqq5URtZ`SbO#tVAQy!GyD&V#$AQgF*CKXqw>Z9KKAp z3STDdB0KE#y4(-2*(R$l2vSp{n4n?gh8vLQ1_Z4Jz*Bj4XcurlEpW%1+So9*BnXPN?Uq_|2J%|e53xG-*nS-De%<5LbX(S)`E7K zu+qjI;M4xxveQP;(SD#;kQ))v9LL+S4>x&f(DU&tKBbAh2C$7**ah>I>+6J-HPl## z8aL<#OlIZ@sis|AQ$=Y_fDCd*>Ep6Al|mAM{}WkoCl~ydEchKL@t5(+13^=S+6qmc zeEeX@1vu{tIC#nlduS1Z`nO4aQTd0|B?VolqaZC0l+akv`TBogcdDQl%3VOYpwmHU zqn_NV8Zf=Gn0I_;p(D zdH*pWbBN!h!Zt@VDO^0od;sobau^3K=rHdMlyEX1pj>+xvf9-mue4m2JQ%2P&aY8A zc$e>~ui=L%8|ZNWo%+Qh%`@CTkJ7(E|4BSw8jnyVT{N3(1@~dJRWZAm4O>11&)V!_ zvqEK00P>u$#V>a1HU3N|cK5kqT+66JM3l{jIvn%DwEp{7I7=R%hrlRGb@P4jL(<1x z3Fh$Q?&Jp{b{g`YuINIRYIK#5Tssq>GKnGh+Au_su2em-a}kFzrm8~-u_U}~H|FC= z%u5W!l8Tpwr#?>nB$7TK!EP`?_+zF0;5z~zXhor*D|Ra21a8{BB??hxr3Mm`ojPTcwN|OGGeDe z?s{dG^0KlL8ct;w*lfzhh@VmI)+=l<)*SPB3@-3Z zBlT9|zJ~i8&G&UDy8H!c=QMBGIV~6ys$wI(?BoRDM;!51uhUFli?DB71X8P=c%u$9 zpADq1N376|NbIwSL$cT<-wW~c0Xu&&7jzaALrT+!D24dP0p}N_o@4;$IO%iZ%_5H8 zRasvO@k_X@;yx}E&CNX@cDdyh6tzA1U_LfcSDGK}F5u~a$Y?T-Xjj5n8o`D;oi4MG z;&+h+VOaY6H8!Imkn%vkb@}tuSxR%4pP2{~sDN;OAlZoTh^&M_dsUMg6qq%pRAnjH z9CZkUL^9$cwKl%b&x5>P3^HCCx#p}Q_CYUK%|NGC5^<_J}ZCA06B)Fn1em3}H( z@lUq(EX0u^{)t>D7FCs`@|s**4<50%O^uQ@zQ0)GU%aVY$$Iaut5^Q_SYAOzR$Zb}W4}8=>+YCngHthHs!Di~ zy}_#(Qx$}t=I|sAKZEek-SP2JHsKV8M&2LWw^*kGxy0Fkp){NgD48=Nvbc(4S43=y zh@A@v25Jd2P!PDE5ETs6aAiQ|Bkb@?!}fLAvM}E3er#8CU0#=6BdAX_JmJVR2Xpb3 zAWOyEmJ8P?EVFeZkW1fyV9bjZx%BX$yyt#7Y`s00nK40l+6l6IlqYH&4NoY|PYB;G z&B5j;;-i9S=5k(p*Z|L%Ae&dGUo-V=G?yMJ<0CnaM{@=aOw-o`#xg&;p~XGx&9vcZBjw52&{ zL7XKZ=IQ_}Cmsn`GIsyL76ZIe0wq~x#@2cj29$!<+>j8QNevm=Y1TLbK&Qr$S?dL8 zcmqfw*cN1K2_@A5Ai!{y)amJ-emeV+BE*+h3H|dMmiW;szFA_672F_UD0+2Rk>at0 zF|w`Ue!ovPe}xT&tq+V2%F?OBA;iqo5&n&T7((H-TnCJ=CXa?KenfgTTvS517BKOiNr+%qqt;galBy^8B2I zdR{A`x{<#R)om=EEhfsT(Lz(>@94{>uqC3gC2R@SO^Q|z8lhzV9?$S$OEd3XXy(0A z1x;;4BASnN>rTstFpK@~?&--D?ng&%4?}UlAawsUZ}zgL(i|fuNoe`4#ijA9 zRjlO)rs|DwuY20@LA2V6?6(597badVzIeNd8C49S`Em2BOdL z!O|u{SSv^;mI*;Ru}lhr#wXJf($0jpBMjNtTT$}0s$@H{4x7M{NW;R3_MptSlMch4 zvL|dE@)&f;367|&vQpsndX=#*;SWo~M@qs+OTx!`pW2TXTRBy>aul_4Hd=9_ z*viwzRxY7dwkeqod_Pmt%Co#Fv1H`3VDhf?m9X)a3Sk3W_MWqQb{Ts1zX!drvG$>kjvDmWbWXncV%a*dBehKE6 zdHMi&KC>cNsD{UJIa?f#PfIX;1(;qbrI@R|yYgDG!s)WYF;wAl6uVwh;SJ`pe=6@t zEv#1u#gu*(6LC!t9AyD~WdG8uQh0WDw!zT(jA(pqkU74C#RJS|VVGrJ?PP1Yx%BFw zv6ZI!t3he;gyP#o9LzsYUYoZTmU3HdOSuK(O;3kqiD+HW(cWU2QhYVo(qdWIr$~CY z$F{r3(e%uyG`2`pZs+-)w?Cz3Mm71d04um=ff^$X$a6R~BZ`~Z-&#g^Uk&C{yFK~z ztmv>3e1<{anQM4ctSFQ(mtGS@K4V7(*LTHZyBTlvhhP3#bymLRP z;lT8NFoTl6ZOgolEoKXGe3^!fBeR=}8*f*ovQdPZ+^MnUxh79$7iPiR^!1IPFbley z!)yy^cTk%7*~CmN9mY2X=`c<#%xghoS5=c_3Hjo9YY>fmN|Tco&(mYIa#zuTMb3=B z6;#;z)SRfXyQ+Apwxp=&E|e zC99R1v#jQ@J;<(hbMfuG`Hs`<1^#Kxvg=Af1xLP{7((hgGxG)p_8HAy)V3pGyjEPF zcVm5?pp`6g&)Oef$H$3wd^_Tk?D!VMCu@Dy8A^o~vNamS1lcREpOdy&i6G;Llou)!Jft2J2oSeO-e*;7-$wbjD4>*R>CG20gv8HQ(p|IZ`n51a!)}}%;+jzGs+ojbg2<}DjYaHB% zV2Fe7A?V`Zegv;@u>%O6;o$oS9)=SP z*{*z!wwFaw5EM0WvrFjVcJ=faCvX)hG#zJZw3n7&b6F~CFh}iX+wQhecifs=*X4$S z`|`wWHs21z_4JKxRHt8zg4hgi<>F zXGR`@shBV|Qm?+uYJ@>*G#1X&Nn@G{NK`TU&QC zk{!{1rF~ymTkpoOi3d`mmw|)J*x354N@;AJpJ-o-QoD?2l@7j@=8MZk(E%{AjxBqW z*s}3lMI9v??M0&}SdIRU=sIq58G)i^SNHqPSGJ9FQ{9WB=_OHPB2{0(Wvs-d(H6Gm zEuo_0(Gx9JSCmxOt5Y(fQ;emWFwOQ+712Q1vM4N~zZ`YAhB%f-Ve@-M)ZunJUWvjA z_{ylGY=~o3)ZuYDW)+vT)pAK2OG{b~tJUn1B`wP9gvOg8=r_e^{YS`4kmt-qRI;mH(0Z7Uy9ANJc8mFo_L)Mv%UkEAMOTtLRd}ce2 zi`~?6CepWt6BZ(C*x^hu{j^>=k=AIZ1RQfJv~Tt)dseR;BvCQ*+=kSe=$BRS6-_wZ zy9rkEnJ-R0+dKKkqQTE|uV3Ofo%e&)m8#5ru8MQrg%-y41|9YEbBKQg5CkaO$Gw5R z=&+j638c^Hrd)2HpwluXoRSHOmJ$i4Wr7ofii8hkf(t%Qk#JllxV1kJ2}fjt2W&SI zj>&|ZmtN)Tzoey?TKbngJ%8Q%-!Db;7ZfRet)%#IMDg7q-WN1m6>K4~7(%Cx4>iZ| zeG#YqfOVigkv#iRX73WGq2?ZppY{+R`MJ{}jd>%OIT~bDD*7r^sb18eWyh-JM}y+w zwS$wWGUGh;?y(@&@t1(754S6?M!#Hd=xN1L9QptlE-q=o62?}uT5y6U>q%y{mTDfV z?ML8mShw#Zf#64sAb!(V^%}>(_;pAETd^Ad!1%ffw@irN&;eY3tD9mi0uDjBNPy@%>7b>zq5&a}@^ zofAWKP7c+%UPE=R?@*m98LG9thU#2#s9x&|OaILq8>%1JU4aMQQD)507 zn&NP+|1XAXd~vwWV7NAx?1q~(T)5nB9}qs3S0A6@(03UJ#OuLavOYam&)h)a*EOfK z>1?Lxb3Sz)shb(hFrfQs(6}ZKyk>PJJGs9RY_9LD>oyq-FVeBALC3Ie?a#p1*Qe*m z#1SDR)``Tdj&7s_<>x_#Qgx9!OJ|U=;mAs8-U#9*b_?$VzeDv`f_N9z#li6sBI1dT z(7IlQ(SW%}irk<+{4AK>?8zD%VPAv7Yd!LONbMpx^M*pX^HOkbE`2>1Ok$f`i#s&AJuC(_?V1C>d`Ku~L^NA2-;`SPmKR8DDX!aVZFJONHR9_;@+E zl>MUu)6W=f?y`D(ExOUT6dWe>ZYa~|)=h42(DbE8w%Xy?&WFKjIY`a7$P$->HO_h5 zV5>22aK>-QjKl4Wz*B&BINoGt;{lne?&T4R-Qyz_ z%U%2qo7uVnW^1QbbQgg^TxwkfV0a;S{FWv~fQ^y2AT?{W-jYS$tT76K%M@rs;5yHf zx3!`T6drWkF!xGYi=^#faP`ng(?9MIf~$NO_y#h(utqnXB%s{_n!B-iT6 zSM=1gp~S)fn^&)UM5&7{47e)311Vr=P1U9jc@pyiloQ%piISZ(BpDuJr2Y~bj1m?4`cefWM@X$IMXL4@rIwNU8f^zR zp<=6aexOl;cL^Q8YJrYt@2fV-aAH<+2j2q(a^ECP{)evW^ToeFttDdV6@6KGo&?~2l#W&f-r=s{+6hBi^{OlJLKgXT&KTC;EHtLILk2P?AZ_@kt_w2AwINu#s zhh6S96st;rU$%zgyaol9+j?~|obv%NENhnQM05m1>&rD9KXcYRW30u14JvQSLV{=Lqb(|9n4yUqzde1hQPO*sqq+? zPr1>$4RQ%<14DMDy%YTrl)&hoRRN3gy24|tD<6fsB_@#Xl;kd(w|){!eJ`rx=*a1}E{we%T4hU29fyNo zV8U(lK`YswOrmzulB^|gq-ySwl7s_CoZJK#GS^tTMAiWsp@In ze$x)Y@u7|fz@K0qd5D{;z;zckC@5WYg7 zUxyFczXVkFL@_@Em7`qZdCIUf#HGxJ=R>Z{{1848&;?(XV?hWX@w%fI&4?}v!P^3& zdkYxqNxCHiv`w zQR5hx&o}%6hOFo4I5wch^yZK;Rq4R|;A@1}La~*aG8DIPR(v(Zaqr7R^!K^DZ|}^d z*M)?7E-X%n$~Xn}!AJFmkTLNVnU*ysQ70o))|h;YG|`P~QToa%yTaT7B6!&j0j2cz zC@zyr+c;mh#ZjKu?U%&`)(BWCuQO=?R-=nvDCy#bdM_EJ?fAY(hv92%>*$(XdV2`} ziw=6RwCax1$V(-7EH1%gNnbo>5gyx6&r;pqvX|*p0BaiX$Y*wj2$^>lD1PFlyXh&uj zo7kq8S=fesVAux4zG%90zgzWQzXlxp$4u9Ht6trzTes@oy7wa!J3L&jCbkp_!i4QPe&@d9{T#L!_@gJ+SvZT^vuJj30V>+zVZjE?s1iS%yyamIt(kvPY_|&9< zEdNSz(X<-U@HiGq8l`_v_zjlh&G)~i6T4`RCbIaK!M_eelZakLZ3fF9!WX9vyfEKk zBz72D;&q?iGz?VhewD%?=B5*E^dFsFT~cwfUc1#uY%Q%QQ@B~Gm{S$kaJM4-jyHyP z@lMTl107mh%+_ON(C}3~lG*Eu*|c_UtG&LMT^7@CtG&VWR|d z7I~{tyUs|gGqm_DXMxskG!h$$OxvGF*pPu)M|-YJ%W@iY8`4IO!j1mKwus&YgW$04 zSo?Jc*zBnE1Q3KGeWSmzd~Rb9b|g?~Zc~UKEjBd`8(vWzVz*VrZu|z_fFe#~pe6p> zDE&C~)FTEbic2rkdD_3-oi$qw{5{@+lX&VWs9X{?_A}eH&85aWB7+~FtEa}nkdI5O zTixsfM6BoOsWG_eaBJsGN9k-Q)t;}Xx-iq)JS)82bYIuMip!umQTe*Q!(}ygMcn67 zZ(?d60*Fo%&!uQO)g3V7FAPW>Fzfc4@#jQpzggF1#;1x@msz*hj87D)y=L7JGd^9U zjzDE}H@J$*e<;d^M?gTya$xT}D4%q|^&JJ!RMjEPJ0ayhPFD{)h(syONgcsr0-kjFwW{Ki2;&b|0EPW#ansTWJYx{+*!N z8^UztqlNg5GI*hN@)IZ7G}&oWceKD|P8ZhO8PheK#i^Nweb|-G-j>{jknFU1{*(hE}LluT7|`e!HWl+1d;bhG}>$?BC^Ek%HX zDJ#Apnodxp#ryxcj%<8kI2^@|7)xJKbBJ3Hclhyz(X15r?xpXHFS-L11*^$0#D&J1+H9A_|tT`)M*#NUoK`X!u%4vFecqs)uG$w8x41LX#~ zMq2DdD_9%px&yhAwUMp~6|Hhb;{8}8-mfBXPhY;!Z&Y7lVqf94zQQMcg8bxkI2 zW_7OX;g*ijG}iaJCMej1*n>cs``d1gil`r(<3m5YRDuFxi ztQ-!BKStg4FuX=pISb>OK-66)`jT1Z-T8uA8#sH#S41(c41mrUEj~<|OMF=|n`mjt zY&q)87P;hb8Ih&m7S+77Fxhip{5=U5MR%IvA-DF`Da`7i@%Onf?36&VSb687W_LmM ze2p3Y9-3bB|2F-nK$;R-;-MlRM3-1L08a_Ec!qSwT}y5uH3R<8*U0ui{8QSm4Q3NT zy{WTyVI&7_P^G|5dtwe7BI|Nya*U94{3D{V@sB0#!a4LZpZSNd8WwGC!`kiB#;|p; zWOUkqB_k+v4r@>K8d5Rq3h(8(U`bw}ZY0m(-v!kgRVeVSVNv#9?e z9qZ8@ita(TO{ar2lw5qiQxbYVl8!tP{;C4z0Izg_1Jwa!@3 z;dKu>-fI7XBhYO8_fb_o8(+oczcl?4R_z**NfT;;zgPru~^^+3QY18UcL{_ zK@)C@EgWNp(=p~G3`m_c>rTO1*eSE_tQpf&XU)1EGv-V6n02SkSXt_{S=VjG{HboU zuGfqOQ@v*02{TrnI$_owGh-F0V`klPGgg^8Zq}WF6^S!u-BB~vFLe|rpD9)ezdzM- zhUJLr)Z5glFVWxUEzhd~>lVXqed@Apg208ag6HxXh z)!L6^2KP-Z&i7^$+X8y?!<{)rnTV846mw&~W&F-X-lbE`^~6fzt8z*;XoAQk zCsyj|9DQzTB8GLk<(?#{)iV{+>HSOm1!46C8{{z4Y~d=ubkTWCp>qkL^L3zeh6kN5 zTerAUeL+Zcz9wkC&jF-gS)i1gStlO?COYzH@O51ysISvR7T4_X2GkuH2U<5Y`HCnD zy#huR!icbNODA6!dgy;-#+M}-zoCrbGUJj6-{WRTuy7pI9ZCK#f&H#5G$|Cm>y|>v zmxT``F~h?>B4bR|*ylMK?O_weWF_gD1yYx;Xl*lj`n!86>KM9ohs;c>wNRe}t}o+9MLnj&}_ z)J`QbRWnuiQd0yH)sya-LQYyLB`57{?&=T;!IbAZ1ThWU;XVxAu`dT;1`jrK_)`P8 z>V#W{lGv*yu{oByqlHlNcihUqvG)WK|12t}C3V@9T`u+xrcsmgg{GQ~X$FflsMf}4 z$*ANg>P8uEiz|s zb~KBoiR7z-ZR=RN^SF?PNg`E_G!(KeC6>4?Go4A!;`;Nr$U_QIe<8ox-X^5UU}|!U z)bwyLLltLm#rYQ4zVEA!ZH=OU8iV5S$%Q{f#Iy#QH#x8=gPR5J^D;y;lD`uW$Gyo5 z^J}V?@-e#nJ{pJQJi)UfO8{`6Z@D^1bA+S~3yXWu96|9#mhN|k`z@<@?Y`I(e%mTu z%`fqUmwHh3jt9=WE{Qp=NX$|qF_Ssq-R29aB>t)iUSNgg4+blq zVWUQYhi)@t)aZZ8@7SU6Kg!P}^wd&;-?G#KF;ahIx#jr7N!yDBo>2@*&Ipv1CcJTL z!t?;muE2?iRuV<+f1q|cqUpcT-m@V0pTV|E9T90gA$uDx1ZbhK z=bGjLO!R{+jJ!DDeOB1Z!eo6ed8SH-!*LnSCXQ9 z9cTU=>c}Xh6Bay(;_8&DYFI62tFT%=upqo1;G`!nRH5{Tx1^rq)Q>C(M+_H6@<()_bw!~N*eN$%38mLn)ZrhTFc zRtQSdx{C$KC%X;ZYgutDh#u zNpsCrEN^X7_$biVSe!6JrVd>_2%aOL6;n_b);P3Hwa3%dF*1!hO8u*M+ z0}X&|j^=Ca_{`v%@xIiDD7TUOu3qMC;@S1LJf@g5^^#oFD{6sH*{LR4+Wt@wo%~27 z_X}U`Y}%b>GY#5oDKpoev@Lf?+iF4JUz+y0<(DR`GwjEAwxrvWLfIPOQ$@D%uw7*q zFD*Kx*7C6Thk?4?U!N8#VQS)>sgHxDuG(T+OCc&q-z1Q$xcJW{L!``DrZ&S!yNKta;K0;AyGicILsOrjwf&YO zNTm$9*`sV~J42N_F+pe}2-}6DMcidU2E`iAl-C}0J(N(bV$%?W@aNhJx@5;36PxXT zNc`AlG56k{^7$<|CbSCIfgm00RY_SSE&8*2;k3O=*jM^ht07?<%><|#BzskF9O^hup}=dPb96F#O6I<%>xEMf1*$6h`M70UI_1?MPjGWtw-JS2q7%q8C3*^ zs_c$3tW2Pov?r>-a}q4{hnXX+3F}~x)Ana#mV8^7RRw1*XS4bgp|$h{uekIOiJ(JF zneN4Inh9j6tbr?W`Ur%VS7+E=W~OrPH_G0DJ4~xAC{@!2H~(mOKn<2;ePdPgaQcdk zm`C4_wz7$>!Us3a${0*e8H2$vNrUr0#_L)-R$hoOw8lVUhtSOj;C8@@?~OJFcv{VX zD_`#Vlu%=UI`3-?DBLyVDjlozfPU99zWX?0L9y^#?km2|SOBd-)gYJ2Hu|ZHa}!Gg zx^(N@+324s?b>V6u0jD15sorx{woYhuJY#{*;qlDGnTC)6*C4Sa?DctV``{b$z595 z#-W7M;8(fZrCJxg$^k2|jHdz-$E~8y_6b5tMdjDf{vkpW1^6rP#YEk`eX%WCvMD z!Mh!P;?g1bg-^1b&uk~HfG%6L+r(g8so|SzFGUbfT#C@v<2;E|oXVda7rg>KUp&*{$AdL6e^8awq8Wxng`b;^%>4_^YbD z9Qgyf_3t^l^=Y8|3(rP%!791#+6Q{Q7lkfbu5qY+#3yX>u}W`g;&x8F%*QxGC1!^v zxA?&8U9lY9AtX0!1#@^6t3J@b_DZDwYUHsi5jM-Ey5$()ZYV1(i>1_F-qeVYyCX_le}^ zK8)|p;xTF;o%V2m{?fgvyQcQm_i1k(PldlX@P?*oh>>G|`sAq8Gg`$Ri~XRAgZn8lU>3GjGgVl#t5!Z3gc z0*_~5L`%AjG;XOiQj2A>j5Cu-X34(qaWYkT$wPiXQkB3Gn$6|YXd*gdk<5qPiHgWUj%~*UgHaR(l5@WT4vaRorm1~zrW*mTdQOi|}6}xDa zBgE@jt8U*O8EK;Cb4Q?+dew9w^SPKXMM;$HT5Mu`0)g_mX~U|PbbCgxRLo*dC%D-D zSgl~?9_;D6V$3l0TH#jgSdet=qHT(q*}Rn%k)$d1BU6#tV|_>36(QmLv7<9>Vd|tk zp0i4^O4Z8ObLf+SP>yoD3PDurS+iIxi0Vwe{Ge>@xh9TRNhVhnx@|oz(ORQ@Q!nq- z^&K&jSatS}c*jTG7BegQLFD>qWHLSxcfFv+Td@<#ZmwYcX4ri2U-B(BCp~%cO<^P13^ZCOczmvU!1^>4nv!5|cYp-JJ2cnwM>-nOUnWcHHYV8*DqMFom=;;Cb zQ|~3zMkQuc^^%xiK{n1LM!)p=#|ys(=1FDW6ggYjwTk&(gdRVJ9xqvWVfyCGVkNPQ zh30oG%M^OK!>QwVzE~rSD+;FMO{r>^>SWwR|LV-w8d1STD7VUsOroe z==x4o)M^gr-zb)ZyX{%6m$IVjT|*04Ap6V-7jstGu3Dxks=<4fSucsXqlLhlS>Gv^ zS15>{6KcCfvFA@7@t(9@EtYq@$$B|Qb@93GmWAzG6*g`Pz0`pef|rFO5jrMYS=Y$x z7IQL{PL+C}RV7clQZ3rz>a!H4pQX^@#?|C}WwGZjbUYn&-0x)Afzx!`)^i2dZ9n;0 zs+htSihWQK3Mm9L6}?^)vxeRD1<~nCSoY&&^t*ocA4B^5ZVicwuxk z-B`0~MZ)wNMN_1UZwpP&=a(@zqAaSlz6|Eqo^O_gPNQz;3L@{rEL+Y&^R{vs+&ytd zx-%zNG`p>fJ2Fpk6w4jQV>&FDi+i|ioyxdTBSTXiz!&zV+DI0n0%>*L6u zYWHFpdjii)aaXukRrslki!z`WF`xa#a)biCa&DL6oGLG>1S$4y54nEj>iMdu*9c4OVYc>G;;Of0M@?_c zu5WZ<7`X>)7CsselGq6T&GqGV@m3vE705MD!e-UE}wmPLVo!VTT z&&;J()|L|+3GZSmlUQF*t;>t^Q|iXzN@87g4om-LSpy)5$e6^h(Zym zf`XNc`6+2Sa;fs^=_E2ADAtbJPP?<2OeWSdiIugDR{~8Yxw*XTF-3XDE+{Ly zU6A!`?QFX-JQvMIqOx|mH{DUXwYB9<%y%YnFR{AeKbDO=>v=fc_E_m{U53f3Ra(I) z@iDJ^l8dX0>AO8G`*#Gs?Fh%1x6(YxTCMF+4FAt(+I0IPh2w!E-rF+T*|Lywt{T;; zQ#cG^CCtPAuomtKhr?&X7f%nI9#&a69)3|}eHXp&!`b1plJ|$;{W+*0fybvomoL~I z2=##P>%c+cAahCO;Nh~DOFpgyxZ1(hPOf%wHOQfxOCj#*<%9DYu7nE$F&<= zd!B2b;c$~{(;Pm_wOd@f&9xb>y}&zXIo#pe9EW)h2@XjP3moopSmfFghnF}kb8Urd zs~l2XTjSd2xVFwA&0&LUn;h0SA*qi9?wy7MH3VY8-41bq>4SyT@Ul!vTl4IeebO7dU*8!sR!tpTBj|}}VkW_rLlw=Pr2Lf1c zTJzH6qsdQGz*TmaR1Z;db3#CkNSv6`97K0CzncT34w`_bPMW%0|3C^7Mt7(+vmPA1 zI8M=K7>RDzKS2L9?Kqac(>_0(k>D&a=m%dwI(L5b<^^Dv@Q)%-L}I5ek>LTxIJ+#d zGlPr`v0-2xBaC&iE9B@^U_DWKwZ2B~jsoi(1LhkC)*X{rG!860L1L3MO)++zJqK*y z264~J?BZvDUAZZ-k!fI;KP$1mTfk1;2G%trv2!m-Z1_cVc$QqaBeC;yzykBgfSdrP zC1rMDL1vM=_*WcTl-boK#=`6+VCpik&c_Ak$^n1 ztf+Ii6d7cxTT;VV4Pl`h#?)vr^*SJ%y2u`fusvEjhr7`b_TJTo5#0@O5{(|Fwg92H zEUW%Yjrhyazs4KJKfY zYvjosAYdwv;Y7EyMlO|aQUa+UwnpP|A==pDOPm!3w)7>PJ=CK)Wmq>_+Qz`v&SRsn zv;$cswIMapJ}pe3F98|dTEQ^4{YJ52jHcd{4!3>AgN8BgkY2-V7>VX;sbLHw+1MHy z`ZFvIL17TX+YT7zhH;zLF;Q&8a~=BEGDeRW7{$chvoK^egbl+56O}J;HQ6{DnDI_S>0*;on6=n$u<|=4}7oZA^lDo9cFoxRvgs#m~FW zt)QKtf_B!(kpbfijdPQghwJZ>|J_uTUc!w!p}z+d`&WSWLe!lK76#9155+m)R_{4Nr2cLg zv)D9;PoJ4yl8m~Nd6FD*RvgB7mDy%k)yC|T4jcoSOy@9cfU~H$`=rcsCjrbs4P-lsu z3(B~LTt6M}QR0?DK5}6xlKcRGFdZixADnUo@o_ZB>Zo&$bYf1~+9T*=tgVK)WPAv} zX;V8-hWi|~kiRM0wtaz8%yIj$aBYG9`F3=RM2>gvB72Eg&0$9lQy&4PW}q1@RrT_* z<{)0FO>*d%9BvaHX``>S(N~XcE}=@anY7VIfScDqXc-H?5#-I6br5929zkUj;46CI?jsO4v diff --git a/mods/atutor_opencaps/flowplayer/flowplayer.captions-3.2.1.swf b/mods/atutor_opencaps/flowplayer/flowplayer.captions-3.2.1.swf deleted file mode 100755 index b2588a3f9c2fd5a1c447a1ee49fce63382f4c570..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8327 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 R#moPES{{{u;&eh>xyQ@sEH diff --git a/mods/atutor_opencaps/flowplayer/flowplayer.content-3.2.0.swf b/mods/atutor_opencaps/flowplayer/flowplayer.content-3.2.0.swf deleted file mode 100755 index 33498f439a672f1af5db513941f5799eef42e398..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4301 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 diff --git a/mods/atutor_opencaps/flowplayer/flowplayer.controls-3.2.1.swf b/mods/atutor_opencaps/flowplayer/flowplayer.controls-3.2.1.swf deleted file mode 100755 index 61874403f1656107bceae27dcd02546e6d92d262..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35736 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 Fm_KMxI`Sq$aSC3$D+M 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 diff --git a/mods/atutor_opencaps/images/index.html b/mods/atutor_opencaps/images/index.html deleted file mode 100755 index e69de29bb..000000000 diff --git a/mods/atutor_opencaps/images/poster.jpg b/mods/atutor_opencaps/images/poster.jpg deleted file mode 100755 index 8a4f29359410d961eda9fe7cf5cdc4c5bb6f522d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20035 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 id where to show the result - document.getElementById(elementToUpdate).innerHTML=xmlHttp.responseText; - } -} - -function GetXmlHttpObject() -{ -var xmlHttp=null; -try - { - // Firefox, Opera 8.0+, Safari - xmlHttp=new XMLHttpRequest(); - } -catch (e) - { - //Internet Explorer - try - { - xmlHttp=new ActiveXObject("Msxml2.XMLHTTP"); - } - catch (e) - { - xmlHttp=new ActiveXObject("Microsoft.XMLHTTP"); - } - } -return xmlHttp; -} \ No newline at end of file diff --git a/mods/atutor_opencaps/include/basic.js b/mods/atutor_opencaps/include/basic.js deleted file mode 100755 index 037af4523..000000000 --- a/mods/atutor_opencaps/include/basic.js +++ /dev/null @@ -1,31 +0,0 @@ - \ No newline at end of file diff --git a/mods/atutor_opencaps/include/classes/ATOC_Debug.php b/mods/atutor_opencaps/include/classes/ATOC_Debug.php deleted file mode 100755 index d789a7157..000000000 --- a/mods/atutor_opencaps/include/classes/ATOC_Debug.php +++ /dev/null @@ -1,52 +0,0 @@ - Noting in $_SESSION '; - } else { - - echo '

    Displaying PHP $_SESSION and $_COOKIE variables

    '; - echo '

    $_SESSION vars

    '; - while ($var = each($_SESSION)) - { - printf ("Key %s = %s
    ", $var['key'], $var['value']); - } - } - - if (count($_COOKIE) == 0) - { - echo '
    No cookies set'; - } else { - - echo '

    $_COOKIE vars

    '; - while ($var1 = each($_COOKIE)) - { - printf ("Key %s = %s
    ", $var1['key'], $var1['value']); - } - } - echo '

    '; - } // end _seeAlSessionVars - -} // end AtOpenCapsDebug class -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/include/classes/ATOC_Json.php b/mods/atutor_opencaps/include/classes/ATOC_Json.php deleted file mode 100755 index 14499ad9d..000000000 --- a/mods/atutor_opencaps/include/classes/ATOC_Json.php +++ /dev/null @@ -1,46 +0,0 @@ -$varName = $varValue; - } - - /** - * @desc addProjectData - * @param String $theProjectData - */ - public function addProjectData($theProjectData) - { - - $this->results[]=$theProjectData; - } - -} // end class -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/include/classes/ATOC_ProjectManager.php b/mods/atutor_opencaps/include/classes/ATOC_ProjectManager.php deleted file mode 100755 index 599253e1f..000000000 --- a/mods/atutor_opencaps/include/classes/ATOC_ProjectManager.php +++ /dev/null @@ -1,326 +0,0 @@ -START method: _loadProjects()'; - - global $db; - - $myProjects = array(); - $myGetMediaObj = new OcJsonFileProject(); - - $sql = "SELECT * FROM ".TABLE_PREFIX."atopencaps_mod WHERE login = '".$theLogin."' AND courseId = ".$theCourseId; - $sqlWhere = ''; - - if($theId!=0) - { - $sqlWhere .= ' AND id = '.$theId; - } - - $sqlOrder = ' ORDER BY id DESC'; - $sql .= $sqlWhere.$sqlOrder; - //echo "

    ".$sql.'

    '; - - $result = mysql_query($sql, $db); - $num_affected = mysql_affected_rows($db); - - if ($ocAtSettings['debugMode'] && $num_affected==0) - { - $ocAtSettings['messages'] = '

    _loadProjects(): no data to load

    '; - } - - // get all project data into an array. - $myCounter = 0; - while ($row = @mysql_fetch_assoc($result)) - { - //$existing_accounts[$row['public_field']]; - $myProjects[$myCounter]['id'] = $row['id']; - $myProjects[$myCounter]['login'] = $row['login']; - $myProjects[$myCounter]['courseId'] = $row['courseId']; - $myProjects[$myCounter]['name'] = $row['name']; - $myProjects[$myCounter]['mediaFile'] = $row['mediaFile']; - $myProjects[$myCounter]['captionFile'] = $row['captionFile']; - $myProjects[$myCounter]['timeStamp'] = $row['timeStamp']; - $myProjects[$myCounter]['width'] = $row['width']; - $myProjects[$myCounter]['height'] = $row['height']; - - $myCounter++; - //echo "
    ID: ".$row['id']; - } // end while - - return $myProjects; - - } // _loadProjects() - - - /** - * @desc _createCcFile - * @param String $theMediaFile - * @return String $theCaptionFile - */ - public function _createCcFile($theMediaFile) - { - global $ocAtSettings; // - - $theNewFileName = ''; - $bol=false; - $theCaptionFile = ''; - $theCaptionFilePath = ''; - $theCaptionFilePathFull = ''; - $i = 0; - - while (!$bol) - { - $ccNameTemp = explode('.',$theMediaFile); - //print_r($ccNameTemp); - if ($i==0) - { - $theCaptionFile = $ccNameTemp[0].'.'.$ocAtSettings['defaultCcExt']; - } else { - $theCaptionFile = $ccNameTemp[0].'_'.$i.'.'.$ocAtSettings['defaultCcExt']; - } - - // fix path - $theCaptionFilePath = str_replace('/',$ocAtSettings['dirSep'],$theCaptionFile); - - $theCaptionFilePathFull = AT_CONTENT_DIR.$_SESSION['course_id'].$ocAtSettings['dirSep'].$theCaptionFilePath; - - if (!file_exists($theCaptionFilePathFull)) - { - $bol=true; - } - $i++; - - } // end while - - file_put_contents($theCaptionFilePathFull, ''); - return $theCaptionFile; - - } // end createNewCcFile - - - /** - * @desc Set Active Project - * @param int $theId - * @param string $theLogin - * @param int $theCourseId - * @param string $theSessionId - */ - public function _setActiveProject($theId, $theLogin, $theCourseId, $theSessionId) - { - global $db, $ocAtSettings; // load AT db object - - // split id - $temId = explode('-',$theId); - - if($theId!=0 && $theLogin!='' && $theCourseId!=0 && $theSessionId!='') - { - $sql = "UPDATE ".TABLE_PREFIX."atopencaps_mod SET sessionId='$theSessionId'"; - $sql .= " WHERE id = $theId AND login='$theLogin' AND courseId=$theCourseId"; - $result = mysql_query($sql, $db); - $num_affected = mysql_affected_rows($db); - //echo '
    '.$sql; - $result = null; - } - - } // end _setActiveProject - - - /** - * @desc Add/Edit/Delete captioning Project. - * @param int $theId - * @param string $theLogin - * @param int $theCourseId - * @param string $theName - * @param string $theMediaFile - * @param string $theCaptionFile - * @param int $theWidth - * @param int $theHeight - * @param int $theAction - */ - public function _addEditProject($theId, $theLogin, $theCourseId, $theName, $theMediaFile, $theCaptionFile, $theWidth, $theHeight, $theAction='') - { - - global $db, $ocAtSettings; // load AT db object - - if ($theAction=="deleteProject") - { - $sql = "DELETE FROM ".TABLE_PREFIX."atopencaps_mod"; - $sql .= " WHERE id = $theId AND login='$theLogin'"; - - } else if ($theId != 0) - { - // UPDATE - $sql = "UPDATE ".TABLE_PREFIX."atopencaps_mod SET name='$theName', mediaFile='$theMediaFile', captionFile='$theCaptionFile', width='".$theWidth."', height='".$theHeight."'"; - $sql .= " WHERE id = $theId AND login='$theLogin'"; - - } else { - - // create caption file if does not exist - if($theCaptionFile=='') - { - $theCaptionFile = $this->_createCcFile($theMediaFile); - } - - // INSERT - $sql = "INSERT INTO ".TABLE_PREFIX."atopencaps_mod (`login`, `courseId`, `name`, `mediaFile`, `captionFile`, `width`, `height`) VALUES"; - $sql .= "('".$theLogin."', ".$theCourseId.", '".$theName."', '".$theMediaFile."', '".$theCaptionFile."', '".$theWidth."', '".$theHeight."')"; - - } - - //echo $sql; - // run SQL - $result = mysql_query($sql, $db); - $num_affected = mysql_affected_rows($db); - $result = null; - - } // end addProject() - - /** - * @desc _getProjecDataJson - * @param unknown_type $theId - * @param unknown_type $theBaseUrl - * @return unknown - */ - public function _getProjecDataJson($theId, $theBaseUrl) - - { - global $db, $ocAtSettings; - - // split id - $temId = explode('-',$theId); - - $myProjects = array(); - $myGetMediaObj = new OcJsonFileProject(); - - $sql = "SELECT * FROM ".TABLE_PREFIX."atopencaps_mod WHERE id = $temId[0] AND sessionId ='$temId[1]'"; - - $result = mysql_query($sql, $db); - $num_affected = mysql_affected_rows($db); - - // debug - if ($ocAtSettings['debugMode'] && $num_affected==0) - { - echo "

    _getProjecDataJson() function reported that: there are no Captioning Projects matching the criteria -
    SQL: ".$sql.'

    '; - } - - // get all project data into an array. - $myCounter = 0; - while ($row = mysql_fetch_assoc($result)) - { - // build object to JSON - $myGetMediaObj->setVars('id',$theId); - $myGetMediaObj->setVars('login',$row['login']); - $myGetMediaObj->setVars('title',$row['name']); - - $rex1 = '/(http:|https:)/i'; - - if (preg_match($rex1, $row['mediaFile'])) - { - $myGetMediaObj->setVars('mediaFile',''.$row['mediaFile']); - $myGetMediaObj->setVars('captionFile',$theBaseUrl.'content/'.$row['courseId'].'/'.$row['captionFile']); - - } else if ($ocAtSettings['contentUrlType']== 0) { - $myGetMediaObj->setVars('mediaFile',$theBaseUrl.'get.php/'.''.$row['mediaFile']); - $myGetMediaObj->setVars('captionFile',$theBaseUrl.'get.php/'.''.$row['captionFile']); - - } else if ($ocAtSettings['contentUrlType']== 1) { - $myGetMediaObj->setVars('mediaFile',$theBaseUrl.'content/'.$row['courseId'].'/'.$row['mediaFile']); - $myGetMediaObj->setVars('captionFile',$theBaseUrl.'content/'.$row['courseId'].'/'.$row['captionFile']); - - } - - $myGetMediaObj->setVars('timeStamp',$row['timeStamp']); - $myGetMediaObj->setVars('returnFormat',$ocAtSettings['ccReturnFormat']); - - } // end while - - $jsonFile = json_encode($myGetMediaObj); - - return $jsonFile; - - - } // _getProjecDataJason() - - - /** - * @desc _saveCaptionData - * @param String $theId - * @param String $theCcData - * @param int $theWidth - * @param int $theHeight - */ - public function _saveCaptionData($theId,$theCcData,$theWidth,$theHeight) - { - global $db, $ocAtSettings; - - $temId = explode('-',$theId); - - $sql = "SELECT * FROM ".TABLE_PREFIX."atopencaps_mod WHERE id = $temId[0] AND sessionId ='$temId[1]'"; - - $result = mysql_query($sql, $db); - $num_affected = mysql_affected_rows($db); - - $row = mysql_fetch_assoc($result); - - if ($row['captionFile']!='') - { - // fix path - $theCaptionFilePath = str_replace('/',$ocAtSettings['dirSep'],$row['captionFile']); - - $theCaptionFilePathFull = AT_CONTENT_DIR.$row['courseId'].$ocAtSettings['dirSep'].$theCaptionFilePath; - - file_put_contents($theCaptionFilePathFull, $theCcData); - - // update metadata - if ($theWidth!='' && $theHeight!='') - { - $sqlUpdateMetadata = "UPDATE ".TABLE_PREFIX."atopencaps_mod SET width='".$theWidth."', height='".$theHeight."'"; - $sqlUpdateMetadata .= " WHERE id = $temId[0] AND sessionId ='$temId[1]'"; - //$sqlUpdateMetadata .= " AND login='$theLogin'"; - //echo '
    '.$sqlUpdateMetadata; - $result1 = mysql_query($sqlUpdateMetadata, $db); - $result1 = null; - } - $result = null; - - //return '

    Data Saved in : '.$row['captionFile'].'

    '; - return '

    Data Saved in : '.$theCaptionFilePathFull.'

    '; - } - - } // _saveCaptionData() - - -} // end class -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/include/classes/ATOC_ServerFiles.php b/mods/atutor_opencaps/include/classes/ATOC_ServerFiles.php deleted file mode 100755 index 3e69b7c61..000000000 --- a/mods/atutor_opencaps/include/classes/ATOC_ServerFiles.php +++ /dev/null @@ -1,65 +0,0 @@ -directoryToArray($directory. $sep . $file, $recursive)); - } - //add if add only known files - if (preg_match($rex, $file)) - { - //$file = $directory . $sep . $file; - $array_items[] = preg_replace("/\/\//si", $sep, $file); - //echo '
    '.$file; - } - - } else { - if (preg_match($rex, $file)) - { - $file = $directory . $sep . $file; - //$file = $sep . $file; - $file = str_replace(AT_CONTENT_DIR.''.$_SESSION['course_id'].$sep, '', $file); - $file = str_replace('\\', '/', $file); - $array_items[] = preg_replace("/\/\//si", $sep, $file); - //echo '
    '.$file; - } - } - } - } - closedir($handle); - } - return $array_items; - } // end directoryToArray - -} // end class ServerFiles -?> diff --git a/mods/atutor_opencaps/include/config.inc.php b/mods/atutor_opencaps/include/config.inc.php deleted file mode 100755 index 640d6e0ab..000000000 --- a/mods/atutor_opencaps/include/config.inc.php +++ /dev/null @@ -1,54 +0,0 @@ - \ No newline at end of file diff --git a/mods/atutor_opencaps/include/index.html b/mods/atutor_opencaps/include/index.html deleted file mode 100755 index e69de29bb..000000000 diff --git a/mods/atutor_opencaps/include/vitals.inc.php b/mods/atutor_opencaps/include/vitals.inc.php deleted file mode 100755 index 7a9de3a56..000000000 --- a/mods/atutor_opencaps/include/vitals.inc.php +++ /dev/null @@ -1,134 +0,0 @@ - This Module only works when you are working on a particular course."'; -$ocAtSettings['lang']['atoc_projectDeleted'] = 'Project Deleted'; -$ocAtSettings['lang']['atoc_projectUpdated'] = 'Project Updated'; -$ocAtSettings['lang']['atoc_projectCreated'] = ' New Project Created'; -$ocAtSettings['lang']['atoc_debugModeActive'] = '******** Debug Mode is Active ******** '; -$ocAtSettings['lang']['atoc_backToContentLinkAlt'] = 'Back To: Content'; -$ocAtSettings['lang']['atoc_myCaptionProjectsLink'] = 'My Caption Projects'; -$ocAtSettings['lang']['atoc_uploadMediaLink'] = 'Upload Media'; -$ocAtSettings['lang']['atoc_addProjectLink'] = 'Add Captioning Project'; -$ocAtSettings['lang']['atoc_captionEditorLink'] = 'Caption Editor'; -$ocAtSettings['lang']['atoc_previewLink'] = 'Preview'; -$ocAtSettings['lang']['atoc_helpLink'] = 'Help'; -$ocAtSettings['lang']['atoc_noIframeSupportedError'] = 'This option will not work correctly.
    Unfortunately, your browser does not support inline frames.'; -$ocAtSettings['lang']['atoc_noMediaFileFound'] = 'There are NO media files in the course content Directory'; -$ocAtSettings['lang']['atoc_uploadMediaMsg'] = 'Upload Media in order to start a captioning Project.'; -$ocAtSettings['lang']['atoc_projectName'] = 'Project Name'; -$ocAtSettings['lang']['atoc_mediaName'] = 'Media File'; -$ocAtSettings['lang']['atoc_mediaWidth'] = 'Width'; -$ocAtSettings['lang']['atoc_mediaHeight'] = 'Height'; -$ocAtSettings['lang']['atoc_newCaptionFileMsg'] = 'Create a new Caption File'; -$ocAtSettings['lang']['atoc_existCaptionFileMsg'] = 'Select An existing Caption'; -$ocAtSettings['lang']['atoc_addProjectButtonLabel'] = 'Add Captioning Project'; -$ocAtSettings['lang']['atoc_projectsNotFoundError'] = 'No Projects found'; -$ocAtSettings['lang']['atoc_saveProjectButtonLabel'] = 'Save'; -$ocAtSettings['lang']['atoc_deleteProjectButtonLabel'] = 'Delete'; -$ocAtSettings['lang']['atoc_editProjectLink'] = 'Edit'; -$ocAtSettings['lang']['atoc_previewProjectLink'] = 'Preview'; -$ocAtSettings['lang']['atoc_htmlCode'] = 'HTML Code'; -*/ - - -// Spanish -/* -$ocAtSettings['lang']['atoc_notActiveCourseError'] = '"Nota: Para poder usar este módulo Ud. debe ser in instructor/Profesor.
    Este módulo solo está activo cuando el se está tramajando en un curso"'; -$ocAtSettings['lang']['atoc_projectDeleted'] = 'Se ha borrado el Proyecto Seleccionado'; -$ocAtSettings['lang']['atoc_projectUpdated'] = 'El projecto ha sido Actualizado'; -$ocAtSettings['lang']['atoc_projectCreated'] = ' Se ha Creado un nuevo Proyecto'; -$ocAtSettings['lang']['atoc_debugModeActive'] = '******** El modo Debug/depuración está activo ******** '; -$ocAtSettings['lang']['atoc_backToContentLinkAlt'] = 'Ir a Contenido'; -$ocAtSettings['lang']['atoc_myCaptionProjectsLink'] = 'Mis Proyectos'; -$ocAtSettings['lang']['atoc_uploadMediaLink'] = 'Adicionar Archivos'; -$ocAtSettings['lang']['atoc_addProjectLink'] = 'Crear Nuevo Proyecto'; -$ocAtSettings['lang']['atoc_captionEditorLink'] = 'Editar Subtítulos'; -$ocAtSettings['lang']['atoc_previewLink'] = 'Vista Previa'; -$ocAtSettings['lang']['atoc_helpLink'] = 'Ayuda'; -$ocAtSettings['lang']['atoc_noIframeSupportedError'] = 'Su Navegador no soporta iframes.
    Se recomienda actualizar el navegador de Internet'; -$ocAtSettings['lang']['atoc_noMediaFileFound'] = 'NO se han encontrado archivos de video/audio en el directorio del curso'; -$ocAtSettings['lang']['atoc_uploadMediaMsg'] = 'Suba archivos para iniciar un proyecto de Subtítulos.'; -$ocAtSettings['lang']['atoc_projectName'] = 'Nombre del Proyecto'; -$ocAtSettings['lang']['atoc_mediaName'] = 'Archivo (video/audio)'; -$ocAtSettings['lang']['atoc_mediaWidth'] = 'Ancho'; -$ocAtSettings['lang']['atoc_mediaHeight'] = 'Alto'; -$ocAtSettings['lang']['atoc_newCaptionFileMsg'] = 'Crear un nuevo archivo de Subtítulos'; -$ocAtSettings['lang']['atoc_existCaptionFileMsg'] = 'Usar un archivo de Subtítulos existente'; -$ocAtSettings['lang']['atoc_addProjectButtonLabel'] = 'Crear un nuevo Proyecto de Subtítulos'; -$ocAtSettings['lang']['atoc_projectsNotFoundError'] = 'No se han encontrado Proyectos'; -$ocAtSettings['lang']['atoc_saveProjectButtonLabel'] = 'Guardar'; -$ocAtSettings['lang']['atoc_deleteProjectButtonLabel'] = 'Borrar'; -$ocAtSettings['lang']['atoc_editProjectLink'] = 'Editar'; -$ocAtSettings['lang']['atoc_previewProjectLink'] = 'Vista Previa'; -$ocAtSettings['lang']['atoc_htmlCode'] = 'Código HTML'; -*/ - -// look for Win OS file structure -if (preg_match('/WIN/', PHP_OS)) -{ - $ocAtSettings['serverOs'] = 'win'; -} - -if ($ocAtSettings['serverOs']=='win') -{ - $ocAtSettings['dirSep'] = "\\"; - -} else { - $ocAtSettings['dirSep'] = "/"; -} - -// if project id active is isset -if (isset($_GET['id']) && $_GET['id']!='') -{ - $_SESSION['ATOC_activeProjectId']= $_GET['id']; -} - -// set session active id -if (!isset($_SESSION['ATOC_activeProjectId'])) -{ - $_SESSION['ATOC_activeProjectId'] = ''; -} - -// get actions variables -if(isset($_POST['action'])) -{ - $ocAtAction = $_POST['action']; -} else { - - // get actions variables - if(isset($_GET['action'])) - { - $ocAtAction = $_GET['action']; - } else { - - $ocAtAction = ''; - } -} -$ocAtSettings['atWebPath'] = ''; -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/index.php b/mods/atutor_opencaps/index.php deleted file mode 100755 index 8612c446a..000000000 --- a/mods/atutor_opencaps/index.php +++ /dev/null @@ -1,418 +0,0 @@ -_addEditProject($_POST['id'],$_SESSION['login'],$_SESSION['course_id'],$_POST['name'],$_POST['mediaFile'],$_POST['captionFile'],$_POST['width'],$_POST['height'],$ocAtAction); - - if ($ocAtAction=='deleteProject') - { - $ocAtSettings['messages'][]= $ocAtSettings['lang']['atoc_projectDeleted']; - } else { - $ocAtSettings['messages'][]= $ocAtSettings['lang']['atoc_projectUpdated']; - } - - $ocAtAction=''; -} - -// addProject: if step 1 -if ($ocAtAction=='addProject' && $_POST['step']=='1') -{ - if($_POST['ccOption']==0) - { - $captionFile = ""; - - } else { - $captionFile = $_POST['captionFile']; - } - - // run Project Manager Class - $myProjectManager = new ATOCProjectManager(); - $myProjectManager->_addEditProject(0, $_SESSION['login'], $_SESSION['course_id'], $_POST['projectName'], $_POST['mediaFile'], $captionFile,$_POST['width'],$_POST['height']); - $ocAtAction=''; - $ocAtSettings['messages'][] = $ocAtSettings['lang']['atoc_projectCreated'].':
    '.$_POST['projectName'].''; - -} // end step 1 - -if($ocAtSettings['ocWebPath'] == '') -{ - $ocWebPath_replace = str_replace('index.php','opencaps/',$_SERVER['SCRIPT_NAME']); - $ocAtSettings['ocWebPath'] = 'http://'.$_SERVER['HTTP_HOST'].''.$ocWebPath_replace; -} - -if ($ocAtSettings['debugMode']) -{ - echo '

    '.$ocAtSettings['lang']['atoc_debugModeActive'].'

    '; -} -?> - - - - - -
    - 0) - { - echo '
    '; - - for($i=0;$i'.$ocAtSettings['messages'][$i].'

    '; - } - echo '
    '; - } - - // show AT vars - if($ocAtSettings['showAtVars']) - { - AtOpenCapsDebug::_seeAlSessionVars(); - } - ?> - -
    - - _loadProjects($_SESSION['login'],$_SESSION['course_id'],0); - $activeProjectId = $myOcProjects[0]['id']; - - // get the last project - $myProjectManager = null; - } - - - // set active session ID - $myProjectManager = new ATOCProjectManager(); - $myProjectManager->_setActiveProject($activeProjectId,$_SESSION['login'],$_SESSION['course_id'],$_SESSION['token']); - $activeProjectId .= '-'.$_SESSION['token']; - - if($ocAtSettings['debugMode']) - { - // testing service before sending data - $theServiceUrl = AT_BASE_HREF.'mods/AtOpenCaps/service.php?id='.$activeProjectId.'&action=getMedia'; - $theJson = file_get_contents($theServiceUrl); - $media_info = json_decode($theJson); - $JsonDebug = ''; - $JsonDebug .= ' -

    Open Caps service: getMedia

    -
    - -
    - '; - echo $JsonDebug; - } // end debug - - - $ccEditorHtml = '
    - -
    '; - - echo $ccEditorHtml; - - - } // end if ccEditor - - else if ($ocAtAction=='fileManager') - { - echo '
    '; - echo ' - -
    -'; - } - - else if ($ocAtAction=='preview') - { - $myProjectManager = new ATOCProjectManager(); - $myPreviewProject = $myProjectManager->_loadProjects($_SESSION['login'],$_SESSION['course_id'],$_GET['id']); - - // set width and height - if ($myPreviewProject[0]['width']=='') - { - $playerWidth=320; - - } else { - $playerWidth = $myPreviewProject[0]['width']; - } - - // set width and height - if ($myPreviewProject[0]['height']=='') - { - $playerHeight=240; - - } else { - $playerHeight = $myPreviewProject[0]['height']; - } - - $playerHtml = ' -
    '; - $playerHtml .=' - -
    -'; - echo $playerHtml; - - } - - else if ($ocAtAction=='addProject') - { - ?> -
    -
    - directoryToArray($theServerDir, true); - - // if not media files found - if (count($myFileArray)==0) - { - echo '

    '._AT('atoc_noMediaFileFound').'

    '; - echo '

    '._AT('atoc_uploadMediaMsg').'

    '; - } else { - //echo "

    Select one of the available media files:

    "; - ?> -

    : - -

    -

    : - -

    -

    - : - : -

    -

    - -
    - - : - -

    -

    - - - -

    - - -
    -
    -My Projects"; - echo '
    '; - // run Project Manager Class - $myProjectManager = new ATOCProjectManager(); - $myOcProjects = $myProjectManager->_loadProjects($_SESSION['login'],$_SESSION['course_id'],0); - //print_r($myOcProjects); - - if (count($myOcProjects)==0) - { - echo '

    '._AT('atoc_projectsNotFoundError').'.

    '; - echo '

    '._AT('atoc_addProjectLink').'

    '; - } else { - //echo '
    Total Projects: '.count($myOcProjects); - - $myProjectsHtml = ''; - $myProjectsHtml .= ' -

    - - - - - - - - - '; - // load project in a table - $flip = 1; - for ($i=0; $i - - - - - - - - '; - - } else { - $myProjectsHtml .= ' - '. - ' - - - - - - '; - } // end if edit project - - } // end for - - - $myProjectsHtml .= ' -
    '._AT('atoc_projectName').''._AT('atoc_mediaName').''._AT('atoc_captionName').'  
    - -
    '._AT('atoc_mediaWidth').': -
    '._AT('atoc_mediaHeight').': -
    - -
    '.$myOcProjects[$i]['mediaFile'].' '.$myOcProjects[$i]['captionFile'].' ['._AT('atoc_editProjectLink').']['._AT('atoc_previewProjectLink').']
    -
    - '; - echo $myProjectsHtml; - - } // end if not projects found - - echo '
    '; - } // end listing - - // if about/help - else if ($ocAtAction == 'atOcAbout') - { - $atOc_readme = file_get_contents('README'); - $atOc_readme = str_replace(chr(13),'
    ',$atOc_readme); - $atOc_readme = str_replace(chr(32),' ',$atOc_readme); - $atOc_readme = str_replace(chr(9),'   ',$atOc_readme); - $atOcAboutHtml = '
    -

    '.$atOc_readme.'

    - -
    - '; - echo $atOcAboutHtml; - - } // end if about/help - ?> - -
    - - \ No newline at end of file diff --git a/mods/atutor_opencaps/index_admin.php b/mods/atutor_opencaps/index_admin.php deleted file mode 100755 index df245e9da..000000000 --- a/mods/atutor_opencaps/index_admin.php +++ /dev/null @@ -1,23 +0,0 @@ - - -

    Please login as an instructor to access this module

    - - - diff --git a/mods/atutor_opencaps/index_instructor.php b/mods/atutor_opencaps/index_instructor.php deleted file mode 100755 index c2eab5978..000000000 --- a/mods/atutor_opencaps/index_instructor.php +++ /dev/null @@ -1,16 +0,0 @@ - - diff --git a/mods/atutor_opencaps/module.css b/mods/atutor_opencaps/module.css deleted file mode 100755 index e98b45bd4..000000000 --- a/mods/atutor_opencaps/module.css +++ /dev/null @@ -1,47 +0,0 @@ -div#AtOpenCaps { - -} - -div#ATOC_playerPreview { - border: 0px solid #ccc; - margin-right: auto; - margin-left: auto; - float: left; -} - -div#ATOC_preview_code { - border: 1px solid #ccc; - padding: 10px; - margin-right: auto; - margin-left: auto; - background-color: #efefef; - color: #444; - margin-top: 30px; - margin-bottom: 30px; - float: right; -} - - -div#Abase { - border: 1px solid #ccc; - padding: 10px; - width: 95%; - margin-right: auto; - margin-left: auto; - background-color: #efefef; - color: #444; - margin-top: 30px; - margin-bottom: 30px; - float: right; -} - -.ATOC_projecLink { - font-size: 1.5em; -} - -.ATOC_labels { - font-size: 1.1em; - text-align: center; - padding: 1em 1em; - -} \ No newline at end of file diff --git a/mods/atutor_opencaps/module.php b/mods/atutor_opencaps/module.php deleted file mode 100755 index 5743fb3a3..000000000 --- a/mods/atutor_opencaps/module.php +++ /dev/null @@ -1,90 +0,0 @@ -getPrivilege()); -//define('AT_ADMIN_PRIV_ATOPENCAPS', $this->getAdminPrivilege()); - -// Add menu item into "Manage" => "Content" -$this->_pages['mods/_core/content/index.php']['children'] = array('mods/AtOpenCaps/index.php'); - - -/******* - * create a side menu box/stack. - */ -//$this->_stacks['AtOpenCaps'] = array('title_var'=>'AtOpenCaps', 'file'=>'mods/AtOpenCaps/side_menu.inc.php'); -// ** possible alternative: ** -//$this->addStack('OpenCaps', array('title_var' => 'OpenCaps', 'file' => './side_menu.inc.php'); -//$this->addStack('OpenCaps', array('title_var' => 'OpenCaps', 'file' => 'side_menu.inc.php'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_group_tool = $_student_tool = 'mods/AtOpenCaps/index.php'; - -/******* - * add the admin pages when needed. - -if (admin_authenticate(AT_ADMIN_PRIV_CMSMS_FEUSERS, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/AtOpenCaps/index_admin.php'); - $this->_pages['mods/AtOpenCaps/index_admin.php']['title_var'] = 'Captioning'; - $this->_pages['mods/AtOpenCaps/index_admin.php']['parent'] = AT_NAV_ADMIN; -} - */ - -/******* - * instructor Manage section: - */ -//$this->_pages['mods/AtOpenCaps/index_instructor.php']['title_var'] = 'AtOpenCaps'; -//$this->_pages['mods/AtOpenCaps/index_instructor.php']['parent'] = 'tools/index.php'; -// ** possible alternative: ** -// $this->pages['./index_instructor.php']['title_var'] = 'AtOpenCaps'; -// $this->pages['./index_instructor.php']['parent'] = 'tools/index.php'; - - - - -// adding module to content edit page -//$this->_pages['mods/AtOpenCaps/index_mystart.php']['title'] = 'edit_content_opencaps'; -//$this->_pages['mods/AtOpenCaps/index_mystart.php']['parent'] = 'mods/_core/editor/edit_content.php'; -//$this->_pages['mods/AtOpenCaps/index_instructor.php']['guide'] = 'instructor/?p=content_edit.php'; - - -// ADD TO CONTENT -$this->_pages['mods/_core/content/index.php']['children'] = array('mods/AtOpenCaps/index.php'); - - -/******* - * student page. - */ -// this not working for some reason; and breaking the shift of AT language compatibility -//$this->_pages['mods/AtOpenCaps/index.php']['title_var'] = _AT('atoc_moduleName'); - -$this->_pages['mods/AtOpenCaps/index.php']['title_var'] = 'Captioning'; -$this->_pages['mods/AtOpenCaps/index.php']['img'] = 'mods/AtOpenCaps/images/AtOpenCaps.png'; - - -/* public pages */ - //$this->_pages[AT_NAV_PUBLIC] = array('mods/AtOpenCaps/index_public.php'); - //$this->_pages['mods/AtOpenCaps/index_public.php']['title_var'] = 'AtOpenCaps'; - //$this->_pages['mods/AtOpenCaps/index_public.php']['parent'] = AT_NAV_PUBLIC; - -/* my start page pages */ -//$this->_pages[AT_NAV_START] = array('mods/AtOpenCaps/index_mystart.php'); -//$this->_pages['mods/AtOpenCaps/index_mystart.php']['title_var'] = 'AtOpenCaps'; -//$this->_pages['mods/AtOpenCaps/index_mystart.php']['parent'] = AT_NAV_START; - -function AtOpenCaps_get_group_url($group_id) { - return 'mods/AtOpenCaps/index.php'; -} -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/module.sql b/mods/atutor_opencaps/module.sql deleted file mode 100755 index ec4ed9737..000000000 --- a/mods/atutor_opencaps/module.sql +++ /dev/null @@ -1,77 +0,0 @@ -CREATE TABLE `atopencaps_mod` ( - `id` int(10) unsigned NOT NULL auto_increment, - `login` varchar(100) character set utf8 NOT NULL, - `courseId` int(10) unsigned NOT NULL, - `name` varchar(255) character set utf8 NOT NULL, - `mediaFile` varchar(255) character set utf8 NOT NULL, - `captionFile` varchar(255) character set utf8 default NULL, - `timeStamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, - `width` varchar(255) default NULL, - `height` varchar(255) default NULL, - `sessionId` varchar(255) default NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; - -# Module Language - EN -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_moduleName','Captioning',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_notActiveCourseError','Note: In order to use this module you MUST login as an instructor.
    This Module only works when you are working on a particular course.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_projectDeleted','Project Deleted',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_projectUpdated','Project Updated',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_projectCreated',' New Project Created',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_debugModeActive','******** Debug Mode is Active ******** ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_backToContentLinkAlt','Back To: Content',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_myCaptionProjectsLink','My Caption Projects',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_uploadMediaLink','Upload Media',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_addProjectLink','Add Captioning Project',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_captionEditorLink','Caption Editor',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_previewLink','Preview',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_helpLink','Help',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_noIframeSupportedError','This option will not work correctly.
    Unfortunately, your browser does not support inline frames.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_noMediaFileFound','There are NO media files in the course content Directory',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_uploadMediaMsg','Upload Media in order to start a captioning Project.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_projectName','Project Name',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_mediaName','Media File',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_captionName','Caption File',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_mediaWidth','Width',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_mediaHeight','Height',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_newCaptionFileMsg','Create a new Caption File',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_existCaptionFileMsg','Select An existing Caption',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_addProjectButtonLabel','Add Captioning Project',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_projectsNotFoundError','No Projects found',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_saveProjectButtonLabel','Save',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_deleteProjectButtonLabel','Delete',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_editProjectLink','Edit',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_previewProjectLink','Preview',NOW(),''); -INSERT INTO `language_text` VALUES ('en', 'AtOpenCaps','atoc_htmlCode','HTML Code',NOW(),''); - -# Module Language - ES -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_moduleName','Subtítulos',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_notActiveCourseError','Nota: Para poder usar este módulo Ud. debe ser in instructor/Profesor.
    Este módulo solo está activo cuando el se está tramajando en un curso',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_projectDeleted','Se ha borrado el Proyecto Seleccionado',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_projectUpdated','El projecto ha sido Actualizado',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_projectCreated',' Se ha Creado un nuevo Proyecto',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_debugModeActive','******** El modo Debug/depuración está activo ******** ',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_backToContentLinkAlt','Ir a Contenido',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_myCaptionProjectsLink','Mis Proyectos',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_uploadMediaLink','Adicionar Archivos',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_addProjectLink','Crear Nuevo Proyecto',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_captionEditorLink','Editar Subtítulos',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_previewLink','Vista Previa',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_helpLink','Ayuda',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_noIframeSupportedError','Su Navegador no soporta iframes.
    Se recomienda actualizar el navegador de Internet',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_noMediaFileFound','NO se han encontrado archivos de video/audio en el directorio del curso',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_uploadMediaMsg','Upload archivos para iniciar un proyecto de Subtítulos.',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_projectName','Nombre del Proyecto',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_mediaName','Archivo (video/audio)',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_captionName','Archivo de Subtítulos',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_mediaWidth','Ancho',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_mediaHeight','Alto',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_newCaptionFileMsg','Crear un nuevo archivo de Subtítulos',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_existCaptionFileMsg','Usar un archivo de Subtítulos existente',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_addProjectButtonLabel','Crear un nuevo Proyecto de Subtítulos',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_projectsNotFoundError','No se han encontrado Proyectos',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_saveProjectButtonLabel','Guardar',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_deleteProjectButtonLabel','Borrar',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_editProjectLink','Editar',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_previewProjectLink','Vista Previa',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', 'AtOpenCaps','atoc_htmlCode','Código HTML',NOW(),''); diff --git a/mods/atutor_opencaps/module.xml b/mods/atutor_opencaps/module.xml deleted file mode 100755 index 90d4d2fe8..000000000 --- a/mods/atutor_opencaps/module.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - AtOpenCaps - AtOpenCaps is a module that integrates Atutor with OpenCaps, an open source web-based captioning tool. This module uses media and caption files stored in Atutor's course content directory and manages all transactions needed to deliver caption files to Open Caps editor and retrieve updated captions. This module also includes a version of FlowPlayer for playing captioned projects. - - - - Antonio Gamba Bari - antonio.gambabari@utoronto.ca - - - http://atutor.ca - GPL - - 1.0 - 2010-08-10 - beta - See details in README file. - - diff --git a/mods/atutor_opencaps/module_install.php b/mods/atutor_opencaps/module_install.php deleted file mode 100755 index 7fc2e338b..000000000 --- a/mods/atutor_opencaps/module_install.php +++ /dev/null @@ -1,80 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/module_uninstall.php b/mods/atutor_opencaps/module_uninstall.php deleted file mode 100755 index 8e9f44395..000000000 --- a/mods/atutor_opencaps/module_uninstall.php +++ /dev/null @@ -1,49 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/about.txt b/mods/atutor_opencaps/opencaps/conversion_service/about.txt deleted file mode 100755 index a6e487e29..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/about.txt +++ /dev/null @@ -1,26 +0,0 @@ -Caption Format Conversion Service - -Written by: -Antonio Gambabari -antonio.gambabari@utoronto.ca - -This version: -November 2009 - -Supported import formats: -Timed Text (DFXP) -QTtext -SubRip -JSON for OpenCaps - -Supported export formats: -Timed Text (DFXP) -DVD STL -MicroDVD -QT text -SAMI -SubRip -SubViewer -JSON for OpenCaps - -To use the conversion service on its own, go to (opencaps url)/conversion_service/ in your browser. \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/imported/index.html b/mods/atutor_opencaps/opencaps/conversion_service/imported/index.html deleted file mode 100755 index e69de29bb..000000000 diff --git a/mods/atutor_opencaps/opencaps/conversion_service/imported/noname.JSON b/mods/atutor_opencaps/opencaps/conversion_service/imported/noname.JSON deleted file mode 100755 index c41593a3e..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/imported/noname.JSON +++ /dev/null @@ -1 +0,0 @@ -{"collectionName":"","txtStylesGlobal":[],"captionCollection":[{"inTime":"00:00:00.000","outTime":"00:00:23.196","caption":"ok lang is ok","textStyles":[]},{"inTime":"00:00:29.594","outTime":"00:01:40.218","caption":"adfsdafsda","textStyles":[]},{"inTime":"00:01:46.299","outTime":"00:02:06.786","caption":"afdsfs","textStyles":[]}]} \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/imported/noname.srt b/mods/atutor_opencaps/opencaps/conversion_service/imported/noname.srt deleted file mode 100755 index 0805c5888..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/imported/noname.srt +++ /dev/null @@ -1,12 +0,0 @@ -1 -00:00:00,000 --> 00:00:23,196 -ok lang is oku000alove yoy php.flash - -2 -00:00:29,594 --> 00:01:40,218 -adfsdafsda - -3 -00:01:46,299 --> 00:02:06,786 -afdsfs - diff --git a/mods/atutor_opencaps/opencaps/conversion_service/imported/noname.txt b/mods/atutor_opencaps/opencaps/conversion_service/imported/noname.txt deleted file mode 100755 index 72c0502f7..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/imported/noname.txt +++ /dev/null @@ -1,19 +0,0 @@ -{QTtext}{font: Tahoma}{plain}{size:18}{textColor: 45824,45824,45824}{backColor: 0,0,0}{justify:center}{timeScale: 1000}{timeStamps:absolute}{keyedtext:on}{language:0}{height:114}{width:334}{textEncoding:0} -[00:00:00.000] -hola anto -[00:00:15.390] -[00:00:21.174] -22222222*******2222222 -[00:00:37.041] -[00:00:39.556] -33333333*******3333333 -[00:01:04.672] -[00:01:07.436] -4444444444*******44444444 -[00:01:12.210] -[00:01:15.982] -5555555*******5555555 -[00:01:21.263] -[00:01:21.377] -6666666666************666666666666 -[00:01:25.500] diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_DFXP_format.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_DFXP_format.php deleted file mode 100755 index 9962b7970..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_DFXP_format.php +++ /dev/null @@ -1,282 +0,0 @@ -toString(); - - // get xml collection - $myXmlTagCollection = $myXmlParse->getCollection(); - - //include_once('CaptionCollection.php'); - $myCcCollection = new CaptionCollection(); - - foreach ($myXmlTagCollection as $xmlTagObj) - { - //echo '
    Begin Time: '.$xmlTagObj->getTagAttribute('BEGIN'); - //echo '
    End Time: '.$xmlTagObj->getTagAttribute('END'); - //echo '
    Caption:'.$xmlTagObj->getTagValue(); - - $txtStylesArr = Array(); - $newCaption = new Caption($xmlTagObj->getTagAttribute('BEGIN').'0',$xmlTagObj->getTagAttribute('END').'0',$xmlTagObj->getTagValue(),$txtStylesArr); - - // add captions to the collection - $myCcCollection->addCaption($newCaption); - - } // end for - - //$myCcCollection->toString(); - - return $myCcCollection; - - } // end importCC() - - /** - * Exports a CaptionCollection object into a string - * - * @param CaptionCollection $theCollection A CaptionCollection Object - * @return String $captionString The caption as a String - */ - public function exportCC($theCollection) - { - $ttCaption = ''; - - $myCollection = $theCollection->getCollection(); - - // add header - $ttCaption .= $this->getTTHeader(); - - // Caption counter - $capCount = 0; - - foreach ($myCollection as $captionObj) - { - $capCount++; - - // adding caption number - for debug purpuses - //$captionObj->getCaption() = "[CAP no. $capCount]" . " ". $captionObj->getCaption(); - - // adapt \n character to
    - //$fixCap = "[CAP no. $capCount] : ". CcUtil::ccNewLineToBr($captionObj->getCaption(),'
    '); - $fixCap = "". TxtFileTools::ccNewLineToBr($captionObj->getCaption(),'
    '); - - // convert qt to TT time format - $ttTimeIn = $this->timeQtToTT($captionObj->getInTime()); - $ttTimeOut = $this->timeQtToTT($captionObj->getOutTime()); - - // ading TTcaptions - $ttCaption .= "".$this->getTTCaption($ttTimeIn,$ttTimeOut,$fixCap,$captionObj->getTextStyles()); - - // show caption object - //$captionObj->toString(); - - } // end foreach - - // close TT file - $ttCaption .= $this->getTTClose(); - - return $ttCaption; - - } // end exportCC() - - /** - * Verify if the caption file is a QText caption file - */ - public function checkFormat($theCCString) - { - $isValid = false; - $patternCheck = "/({(QTtext)})/"; // RegExp to look for QText - preg_match_all($patternCheck,$theCCString,$patternFound); - - if(count($patternFound)>0) - { - $isValid = true; - } - - return $isValid; - - } // end checkFormat() - - /* - * Here functions to re-define - */ - public function getName() - { - return 'Timed Text (TT) Authoring Format 1.0 – Distribution Format Exchange Profile (DFXP)'; - } - - public function getAbout() - { - return 'This is the most comprehensive caption format ever !! - XML based. - Additional information at W3-dfxp'; - } - - public function getVersion() - { - return '1.0'; - } - - public function getFileExtension() - { - return 'dfxp.xml'; - } - - public function getIdPattern() - { - $idPattern = '/(1 begining

    - - $ttCaption = ""; - - // Find if text alignment in $txtStyles array - if (isset($txtStyles['text-align'])) - { - if ($txtStyles['text-align']=='right') - { - // Add right alignment style - $ttCaption = ' -

    '.$caption.'

    '; - } - else if ($txtStyles['text-align']=='left') - { - // Add right alignment style - $ttCaption = ' -

    '.$caption.'

    '; - } - else if ($txtStyles['text-align']=='center') - { - $ttCaption = ' -

    '.$caption.'

    '; - - } - - } else { - // no text style, creates a plain caption - $ttCaption = ' -

    '.$caption.'

    '; - - } // end if - - - - return $ttCaption; - -} // end getTTCaption() - -/** - * Converts QT time to TT Time; drops last right number on the time format - * @return String $ttTime TT time format 00:01:10.28" - * @param String $qtTime QT time Format; "00:01:10.280" - */ -private function timeQtToTT($qtTime) -{ - $ttTime = substr($qtTime, 0, 11); // returns "d" ; - return $ttTime; -} // end timeQtToTT - -/// TT Header -private function getTTHeader() -{ -// common vars -$textFont = "Arial"; -$textFontWeight = "normal"; -$textFontStyle = "normal"; -$textSize = "12"; -$textJustify = "center"; - -// unique vars -$capTitle = 'This is a sample SAMI 1.0 caption'; -$textHtmlColor = "white"; -$bgHtmlColor = "black"; -$capLangName = "English"; -$capLangCode= "EN-US-CC"; - -$capTT_header = ' - - - - - -'; - return $capSAMI_header; -} // end getSamiHeader() - - -// SAMI Close -private function getSamiClose() -{ -$capSAMI_close = ' - -'; - return $capSAMI_close; -} - - - -} // end CCsami Class -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_Scc_format.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_Scc_format.php deleted file mode 100755 index b7b231757..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_Scc_format.php +++ /dev/null @@ -1,149 +0,0 @@ -Based on the SCC convertion class by Colin McFadden at
    - * http://blog.lib.umn.edu/mcfa0086/discretecosine/2008_10.html'; - */ - - $ccExport = ''; - - $myCollection = $theCollection->getCollection(); - - // include SCC external convertor - include("include/classes/ext_SccConvert_class.php"); - - $startTC = "00:00:00:00"; - - //create a SCC captionConvert instance - $sccCaptions = new captionConvert($startTC); - - - // Building Sami caption - foreach ($myCollection as $captionObj) - { - - //$capCount++; - - $beginTime = $captionObj->getInTime(); - $captionContents = $captionObj->getCaption(); - - // clean any xml style - $toSearch = array('','','','','','','
    ','
    ','
    ','\n',chr(10)); - $toReplace = ''; - $captionContents = str_replace($toSearch,$toReplace,$captionContents); - - // add SCC captions - $sccCaptions->addCaption($beginTime, $captionContents); - - //$fixCap = CcUtil::ccNewLineToBr($captionObj->getCaption(),'
    '); - - } // end for each caption - - // ading caption to String - $ccExport .= ''.$sccCaptions->outputCaptions(); - - - return $ccExport; - - } // end exportCC() - - /** - * Verify if the caption file is a SAMI caption file - */ - public function checkFormat($theCCString) - { - - } // end checkFormat() - - /* - * Here functions to re-define - */ - public function getName() - { - return 'SCC - Scenarist Closed Caption'; - } - - public function getAbout() - { - return 'This caption format is one of the standards in the TV industry.
    SCC is used by M4V movies targeted for the Apple iPhone, iPod Touch and iPod Nano.
    As documented in http://ncam.wgbh.org/mm/m4vcaps.html'; - } - - public function getVersion() - { - return '1.0'; - } - - public function getFileExtension() - { - return 'scc'; - } - - public function getIdPattern() - { - $idPattern = '/(Scenarist_SCC V1.0)/'; - - return $idPattern; - } - - public function allowsTextStyles() - { - return '0'; - } - - public function template() - { - $ccTemplate = ' -Scenarist_SCC V1.0 - -00:00:00:00 942c 942c - -00:00:00:-21 94ae 94ae 9420 9420 10d0 10d0 a8c4 d629 2020 57e5 ece3 ef6d e520 f4ef 2061 2080 13d0 13d0 64e5 6def 6e73 f4f2 61f4 e9ef 6e20 efe6 2061 e3e3 e573 73e9 62ec e520 1370 1370 76e9 64e5 efae 2054 e5f8 f420 bc62 3e62 efec 6420 54e5 f8f4 2020 942f 942f - -00:00:02:00 94ae 94ae 9420 9420 10d0 10d0 a8c4 d629 2020 5468 e973 20e9 7320 6120 e3ef 6d6d e5f2 e3e9 61ec 2080 13d0 13d0 e6ef f220 c7f2 6170 e56e 75f4 7320 e3e5 f2e5 61ec 2c20 942f 942f - -00:00:04:03 94ae 94ae 9420 9420 10d0 10d0 a8c4 d629 2020 f7e9 f468 2061 6464 e564 20e3 ecef 73e5 6420 13d0 13d0 e361 70f4 e9ef 6e73 2020 942f 942f - -00:00:05:06 94ae 94ae 9420 9420 10d0 10d0 a8c4 d629 2020 616e 6420 64e5 73e3 f2e9 70f4 e976 e520 76e9 64e5 ef2c 2020 13d0 13d0 2075 73e9 6e67 2073 70e5 e5e3 6820 7379 6ef4 68e5 73e9 7320 1370 1370 f4e5 e368 6eef ecef 6779 ae20 942f 942f - -00:00:08:03 94ae 94ae 9420 9420 10d0 10d0 a8c4 d629 2020 c4e5 7075 f479 20c2 61f2 6ee5 7920 46e9 e6e5 2080 13d0 13d0 e56e f4e5 f273 2020 20f4 68e5 20cd 6179 62e5 f2f2 7920 1370 1370 d368 e5f2 e9e6 e6a7 7320 4fe6 e6e9 e3e5 2c20 942f 942f - -00:00:11:02 94ae 94ae 9420 9420 10d0 10d0 a8c4 d629 2020 f7e9 f468 2061 20f4 f261 7920 e3ef 6ef4 61e9 6ee9 6e67 2020 13d0 13d0 f468 e520 c7f2 6170 e56e 75f4 7320 62f2 e561 6be6 6173 f4ae 2080 942f 942f - -00:00:12:28 94ae 94ae 9420 9420 10d0 10d0 a8c4 d629 2020 d368 e5f2 e9e6 e620 c16e 6479 2054 6179 ecef f220 e973 2080 13d0 13d0 ece5 616e e96e 6720 20ef 6e20 f468 e520 e6f2 ef6e f420 efe6 2068 e973 2080 1370 1370 64e5 736b 2c20 942f 942f - -00:00:15:21 94ae 94ae 9420 9420 10d0 10d0 a8c4 d629 2020 f2e5 6164 e96e 6720 f468 e520 6ee5 f773 7061 70e5 f2ae 2080 942f 942f - -'; - - return $ccTemplate; - } - - -} // end Scc Class -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_SubRipSrt_format.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_SubRipSrt_format.php deleted file mode 100755 index 4ff92f002..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_SubRipSrt_format.php +++ /dev/null @@ -1,204 +0,0 @@ -'.chr(10).''.$counter; - - // split each line of the single caption - $captionParts=split(chr(10),$singleCaption); - - // add captions if minimal time and caption are set - if (isset($captionParts[1]) && isset($captionParts[2])) - { - $counter++; - $timeMark = ''; - $captionLines = ''; - - // fix milisecond separator "," by "." - $captionParts[1] = str_replace(',','.',$captionParts[1]); - - // get time marks on line 2 - $timeMark = split('-->',$captionParts[1]); - - // get time in and out - $timeIn = trim($timeMark[0]); - $timeOut = trim($timeMark[1]); - - $captionLines = $captionParts[2]; // add caption line 1 - - // if caption has two lines - if (count($captionParts)==4) - { - $captionLines .= ''.chr(10).$captionParts[3]; // add a new line + caption line 2 - } - - // Create a caption Object - $theNewCaption = new Caption($timeIn,$timeOut,$captionLines,$txtStyles); - - // add caption to CaptionCollection - $myCollection->addCaption($theNewCaption); - - - //echo ''.chr(10).'IN: '.$timeIn.'****'.' OUT:'.$timeOut; - //echo ''.chr(10).''.$captionLines; - } - - } // end foreach - - return $myCollection; - - } // end importCC() - - /** - * Exports a CaptionCollection object into a string - * - * @param CaptionCollection $theCollection A CaptionCollection Object - * @return String $captionString The caption as a String - */ - public function exportCC($theCollection) - { - - $ccExport = ''; - - $myCollection = $theCollection->getCollection(); - - // fix time Srt Time Format - $toSearch = array('.'); - $toReplace = array(','); - - $srtCounter = 0; - - foreach ($myCollection as $captionObj) - { - - $srtCounter++; - - // fix QT time to SRT format, replace "." by "," - $srtInTime = $captionObj->getInTime(); - $srtInTime = str_replace($toSearch,$toReplace,$srtInTime); - - $srtOutTime = $captionObj->getOutTime(); - $srtOutTime = str_replace($toSearch,$toReplace,$srtOutTime); - - $srtCaption = $captionObj->getCaption(); - $srtCaption = str_replace('
    ',chr(10),$srtCaption); - $srtCaption = str_replace('
    ',chr(10),$srtCaption); - - $ccExport .= "$srtCounter\n".$srtInTime." --> ".$srtOutTime."\n".$srtCaption."\n\n"; - - } // end foreach - - // Fix if there are more than the two empty line separator (standard) - $ccExport = str_replace(chr(10).chr(10).chr(10),chr(10).chr(10),$ccExport); - - return $ccExport; - - } // end exportCC() - - /** - * Verify if the caption file is a QText caption file - */ - public function checkFormat($theCCString) - { - $isValid = false; - $patternCheck = "/({(QTtext)})/"; // RegExp to look for QText - preg_match_all($patternCheck,$theCCString,$patternFound); - - if(count($patternFound)>0) - { - $isValid = true; - } - - return $isValid; - - } // end checkFormat() - - /* - * Here functions to re-define - */ - public function getName() - { - return 'SubRip - Srt'; - } - - public function getAbout() - { - return '???'; - } - - public function getVersion() - { - return '???'; - } - - public function getFileExtension() - { - return 'srt'; - } - - public function getIdPattern() - { - $idPattern = '/([0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}) (-->) ([0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3})/'; - //$idPattern = '/([0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3})/'; - //$idPattern = ''; - //$idPattern .= '/'; // start pattern - - //$idPattern .= '([0-9]{2}\n)'; - - //$idPattern .= '/'; // end pattern - - return $idPattern; - } - - public function allowsTextStyles() - { - return '0'; - } - - public function template() - { - $ccTemplate = ' -1 -00:00:42,360 --> 00:00:48,360 -With this device we can -give anything an attitude. - -2 -'; - - return $ccTemplate; - } -} // end SubRipSrt -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_SubViewer_format.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_SubViewer_format.php deleted file mode 100755 index 56f38ea62..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/cc_SubViewer_format.php +++ /dev/null @@ -1,117 +0,0 @@ -getCollection(); - - foreach ($myCollection as $captionObj) - { - // add in time - $ccExport.= chr(10).$captionObj->getInTime(); - - $ccExport.= ','; - - // add out time - $ccExport.= $captionObj->getOutTime(); - - // fix caption to subViewer v. 1 - $fixCaption = str_replace(chr(10),'',$captionObj->getCaption()); - $fixCaption = str_replace('
    ','',$fixCaption); - - // add caption - $ccExport.= chr(10).$fixCaption.chr(10); - - } // end foreach - - return $ccExport; - - } // end exportCC() - - /** - * Verify if the caption file is a srt caption file - */ - public function checkFormat($theCCString) - { - - } // end checkFormat() - - /* - * Here functions to re-define - */ - public function getName() - { - return 'SubViewer - Sub'; - } - - public function getAbout() - { - return '????'; - } - - public function getVersion() - { - return '???'; - } - - public function getFileExtension() - { - return 'sub'; - } - - public function getIdPattern() - { - $idPattern = '/([0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{2})(,)([0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{2})/'; - - return $idPattern; - } - - public function allowsTextStyles() - { - return '0'; - } - - public function template() - { - $ccTemplate = ' -00:04:35.03,00:04:38.82 -Hello guys... please seat down... - -00:05:00.19,00:05:03.47 -M. Franklin,[br]are you crazy? - -???? -[00:00:00] -caption 1 - using Bold style? -[00:00:02] - -'; - - return $ccTemplate; - } - -} // end SubViewer Class -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/index.html b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/ccformats/index.html deleted file mode 100755 index e69de29bb..000000000 diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_CaptionCollection_class.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_CaptionCollection_class.php deleted file mode 100755 index 1fa47fbef..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_CaptionCollection_class.php +++ /dev/null @@ -1,120 +0,0 @@ -captionCollection[] = $theCcObject; // this a php-based approach... java will need a push/count solution - - } // end addCaptions() - - /** - * Sets all the Global text style attributes - * @param Array $theGlobalStyles Array containing all the global text styles - */ - public function setTxtStylesGlobal($theGlobalStyles) - { - $this->txtStylesGlobal = $theGlobalStyles; - } - - /** - * Sets the value of a single Global text style attribute - * @param String $theAtt Attribute name - * @param String $theValue Attribute Value - */ - public function setTxtStylesGlobalAtt($theAtt,$theValue) - { - $this->txtStylesGlobal[$theAtt]=$theValue; - } // end setTxtStylesGlobalAtt() - - /** - * Sets the collection Name - * - * @param String $theCollectionName - */ - public function setCollectionName($theCollectionName) - { - $this->collectionName = $theCollectionName; - } - - /** - * Gets Collection Name - * - * @return String $collectionName - */ - public function getCollectionName() - { - return $this->collectionName; - } - - /** - * Returns this CaptionCollection object - * - * @return CaptionCollection - */ - public function getCollection() - { - return $this->captionCollection; - } - - public function toString() - { - $ccCount=0; - echo '

    Collection Name: '.$this->getCollectionName().'

    '; - echo 'Total Captions Found: '.count($this->captionCollection); - - if (count($this->txtStylesGlobal)!=0) - { - echo '

    [Global] Styles'; - - foreach ($this->txtStylesGlobal as $txtStyleName => $txtStyleValue) - { - echo '
    -----'.$txtStyleName.' = '.$txtStyleValue; - } - } - - echo '

    Printing Captions in the collection... '; - - foreach ($this->captionCollection as $captionObj) - { - $ccCount++; - - // call Caption's toString(); - echo '

    '.$ccCount; - $captionObj->toString(); - - } // foreach end - - } //toString() end - -} // end CaptionCollection Class -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_CaptionFormat_class.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_CaptionFormat_class.php deleted file mode 100755 index d903b9eb1..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_CaptionFormat_class.php +++ /dev/null @@ -1,69 +0,0 @@ - \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_Caption_class.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_Caption_class.php deleted file mode 100755 index 8ec7e5990..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_Caption_class.php +++ /dev/null @@ -1,156 +0,0 @@ -inTime = $theInTime; - $this->outTime = $theOutTime; - $this->caption = $theCaption; - $this->textStyles= $theTextStyles; - } // __construct() end - - // SET Functions - - /** - * Sets value of caption IN time - * @param String $theInTime - * @return void - */ - public function setInTime($theInTime) - { - $this->inTime = $theInTime; - } - - /** - * Sets value of caption OUT time - * @param String $theOutTime - * @return void - */ - public function setOutTime($theOutTime) - { - $this->outTime = $theOutTime; - } - - /** - * Sets value of a caption (multiple lines allowed) - * @param String $theCaption - * @return void - */ - public function setCaption($theCaption) - { - $this->caption = $theCaption; - } - - /** - * Sets value of Caption text style attribute - * @param String $theAtt Attribute name - * @param String $theValue Attribute Value - */ - public function setTextAtribute($theAtt,$theValue) - { - $this->textStyles[$theAtt]=$theValue; - } - - // GET Functions - - /** - * Gets value of Caption IN Time - * @return String inTime Caption - */ - public function getInTime() - { - return $this->inTime; - } - - /** - * Gets value of Caption OUT Time - * @return String outTime Caption - */ - public function getOutTime() - { - return $this->outTime; - } - - - /** - * Gets value of Caption text - * @return String inTime Caption text - */ - public function getCaption() - { - return $this->caption; - } - - /** - * Gets text style array - * @return Array $theTextStyles Txt Styles Array - */ - public function getTextStyles() - { - return $this->textStyles; - } - - - /** - * Gets value of Caption text style attribute - * @param String $theAtt Attribute name - * @return String $Value Attribute Value - */ - public function getTextAtribute($theAtt) - { - return $this->textStyles[$theAtt]; - } - - /** - * Print all values of the Caption as a String - */ - public function toString() - { - echo "
    In Time: ". $this->getInTime().""; - echo "
    Out Time: ". $this->getOutTime().""; - echo "
    Caption: ". $this->getCaption().""; - - if (count($this->textStyles!=0)) - { - if (count($this->textStyles)==0) - { - //echo '
    ----(NO text styles found)'; - } else { - - echo '
    ------[Caption] Styles: '; - - // Display all text attributes in the caption - foreach ($this->textStyles as $styleName=>$styleValue) - { - echo '
    -----'.$styleName.' = '.$styleValue; - } // foreach end - }// end if - - } //if end - - }// toString() end - - // return this caption object - public function getThisCaption() - { - return $this; - } -} // end class Caption -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_CcService_class.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_CcService_class.php deleted file mode 100755 index ccd8ba5b3..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_CcService_class.php +++ /dev/null @@ -1,57 +0,0 @@ -ccResult = $theCcResult; - $this->ccSourceURL = $theCcSourceURL; - - $this->ccStringTarget = ''; - $this->ccTypeTarget = $theCcTypeTarget; - $this->ccSourceFileName = $theFileName; - - $this->_startService(); - } - - private function _startService() - { - global $rosettaCCSettings; - - // download remote caption file - $myCCString = file_get_contents($this->ccSourceURL); - - $myCCString = stripslashes($myCCString); - - // Start a convertion Manager Instance - $myCcManager = new ConversionManager($myCCString,$this->ccTypeTarget,$this->ccSourceFileName); - - // get the Caption Target URL - $ccTargetUrl = $myCcManager->getCcTargetUrl(); - - if($this->ccResult==0) - { - // get the target file as a String - $ccTargetString = TxtFileTools::fileToString($ccTargetUrl); - echo $ccTargetString; - } - else if ($this->ccResult==1) - { - echo $rosettaCCSettings['uploadDir'].'/'.$ccTargetUrl; - } - - - } -} -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_ConversionManager_class.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_ConversionManager_class.php deleted file mode 100755 index 6c26954b3..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_ConversionManager_class.php +++ /dev/null @@ -1,246 +0,0 @@ -ccTypeTarget = $theTarget; - $this->ccSourceFileName = $theFileName; - $this->ccTypeSource = ''; // initialize $ccTypeSource = '' - - // load caption formats - $this->ccFormats = CcUtilVital::ccFormatsLoad(); - - /* - * run detection function on imported caption string - * Note: the type of the source caption is not a parametter. This means that for stability - * purposes the conversion tool MUST identify the format. Otherwhise, many unexpected and - * incorrect conversions may occur - */ - $this->ccTypeSource = $this->_ccAutoDetect($theCaption); - - // proceed only if caption format is detected - if($this->ccTypeSource!='') - { - //echo '

    Caption format Detected: '.$this->ccTypeSource.''; - - /* - * Invoques import function in caption format subclass - * Note: here we know the name of the Caption format class from the $this->ccTypeSource (the value assigned by the autodetection function) - */ - $ccSourceObj = new $this->ccTypeSource(); - - // get a CaptionCollection Object - $this->ccImportedCollection = $ccSourceObj->importCC($theCaption); - - //echo '

    Uploaded Caption file was loaded into a CaptionCollection'; - - // Initialize exported collection string - $this->ccStringTarget = ''; - - // run export function - $this->ccStringTarget = $this->_ccExport(); - - // print target format in a form for debuging purposes only - //echo '
    '; - - //$this->_ccExport(); - - // verify if the Target format has been provided - if ($this->ccStringTarget!='') - { - // Save collection in DB as serialized string - //DbTools::collectionInBdSave($this->ccImportedCollection, $theFileName); - - // FINALLY !! if all goes right save exported caption into a file - $theConvertedFile = $this->_saveExported(); - // display player test option - //PlayerTools::displayPlayerOp($theConvertedFile); - - // force downlaod: only when no comments or debuging mode - //TxtFileTools::downloadFile($theConvertedFile); - - // set the relative path of the target caption file - $this->ccTargetUrl = $theConvertedFile; - - } - - - } else { - echo 'The format of source Caption was not recognized.'; - }; - - // return $ccSourceFormat - - }// end __construct() - - public function getCcTargetUrl() - { - return $this->ccTargetUrl; - } - - /** - * Gets the file name without extension of a file - * - * @param String $theFilename Name of the file - * @return String $targetFileName - */ - private function _buildExportFileName() - { - $targetFileName = substr($this->ccSourceFileName, 0, -3); - return $targetFileName; - } - - private function _saveExported() - { - //global $rosettaCCSettings; - // build the proper name to save converted caption - $theCCname = $this->_buildExportFileName().$this->ccTargetExt; - - //$fullFileUrl = $rosettaCCSettings['uploadDir'].'/'.$theCCname; - - // save exported collection in a file - TxtFileTools::stringToFile($theCCname,$this->ccStringTarget); - - // return the generated file name - return $theCCname; - - // download the generated caption file - //CcUtil::downloadFile($fullFileUrl); - - } - - /** - * Gets a CaptionCollection object and return the target caption file as string - * - * @return unknown - */ - private function _ccExport() - { - $ccTargetString = ''; - - //echo '

    ...creating an object of the target format: '.$this->ccTypeTarget; - //echo '

    I AM a '.$ccObjExp->getName().' Object'; - - if ($this->ccTypeTarget!='0') - { - // create an instance of the target Caption Format - $ccObjExp = new $this->ccTypeTarget(); - - // get the extension of the target Caption - $this->ccTargetExt = $ccObjExp->getFileExtension(); - //echo '
    The extension of the Target Caption is: '. $this->ccTargetExt; - - // call export method in caption format instance - $ccTargetString = $ccObjExp->exportCC($this->ccImportedCollection); - - } // end if - - //echo '
    Target Collection:
    '.$ccTargetString; - return $ccTargetString; - } // end _ccExport() - - /** - * Import caption as a sting and return a Caption Collection - * @param String $theCaption Caption file as a String - * @param String $theCcFormatClassName The class name of the caption source - * @return CaptionCollection $importedCollection Return a Caption Collection Object - */ - private function _ccImport($theCaption,$theCcFormatClassName) - { - // Create an instance of the source Caption Format - $myCcSourceObj = new $theCcFormatClassName(); - - // import the caption into a CaptionCollection Object - return $myCcSourceObj->importCC($theCaption); - - } // _ccImport() end - - /** - * Auto detect format of a caption string using the unique pattern provided by each caption format - * @param String $theCaption Caption file as a String - * @return String $formatfound Return detected caption format or '' if not found - */ - private function _ccAutoDetect($theCaption) - { - //echo '
    Total Formats to Auto-detect: '.count($this->ccFormats); - - $formatfound = ''; - - // instanciate each caption format sub-class and call getIdPattern() - foreach ($this->ccFormats as $ccId) - { - // testing here a polymorphic behaviour - //echo '
    .....Detecting format: '.$ccId; - $theCcIdPattern = ''; - $ccObj = new $ccId(); // Create an instance of a caption format - $theCcIdPattern = $ccObj->getIdPattern(); // get the pattern identifying the caption format - //echo '
    ***** '.$ccId.' = '.$theCcIdPattern; - - // look for the pattern in the caption string - if (preg_match($theCcIdPattern,$theCaption)==1) - { - //echo '
    !! Caption Format Dettected!! ***** '.$ccId.' = '.$theCcIdPattern; - //echo '
    Caption Format Dettected: '.$ccId.''; - - // set the detected format - $formatfound = $ccId; - - return $formatfound; - break; // stop detecting caption format - } - - } // foreach end - - return $formatfound; - - } // _ccAutoDetect() end - - public function getCaptionFormats() - { - return $this->ccFormats; - } - - public function getImportedCollection() - { - return $this->ccImportedCollection; - } - - -} // class end -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTag.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTag.php deleted file mode 100755 index 2068a3911..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTag.php +++ /dev/null @@ -1,162 +0,0 @@ -tagName = $theTagName; - $this->tagType = $theTagType; - $this->tagLevel = $theTagLevel; - $this->tagValue = $theTagValue; - $this->tagAttrib = $theTagAtrib; - - } // __construct() end - - public function getTagValue() - { - return $this->tagValue; - } - - public function getTagAttribute($attribName) - { - if (isset($this->tagAttrib[$attribName])) - { - return $this->tagAttrib[$attribName]; - } else { - return ''; - } - - } - - /** - * Adds a value to the xml tagValue - * - * @param String $theTagValueAdded The value to be added - */ - public function addToTagValue($theTagValueAdded) - { - $this->tagValue .= $theTagValueAdded; - } - - /** - * Adds a child xml tag as a value to other parent tag value. - * - * @param String $theTagAdded The tag yo be - * @param String $theTagState - */ - public function addChildTagAsValue($theTagAdded,$theTagState,$theTagValue) - { - - // add
    Tag - if (($theTagAdded=='BR') && ($theTagState=='complete')) - { - $this->tagValue .= '
    '.$theTagValue; - } - - // open and close Bold tag - if (($theTagAdded=='B') && ($theTagState=='complete')) - { - $this->tagValue .= ''.$theTagValue.''; - } - - // open and close Italics tag - if (($theTagAdded=='I') && ($theTagState=='complete')) - { - $this->tagValue .= ''.$theTagValue.''; - } - - if (($theTagAdded=='U') && ($theTagState=='complete')) - { - $this->tagValue .= ''.$theTagValue.''; - } - - } // end addChildTagAsValue - - - /** - * Adds an attribute and value to the XML tag - * - * @param String $attName - * @param String $attValue - */ - public function addAttribute($attName,$attValue) - { - $this->tagAttrib[$attName] = $attValue; - - } // end addAttribute() - - /** - * Set the state of the XML tag - * - * @param Boolean $theState True or False - */ - public function setTagState($theState) - { - $this->tagState = $theState; - - } // end setTagState() - - /** - * Print all values of the XML tag as a String - */ - public function toString() - { - // check if the tag is ready to show - if ($this->tagState==true) - { - echo "

    Tag Name: ". $this->tagName; - echo "
    Tag Type: ". $this->tagType; - echo "
    Tag Level: ". $this->tagLevel; - echo "
    Tag Value: ". $this->tagValue; - - // print data if the tag has attributes - if (count($this->tagAttrib!=0)) - { - echo '
    Tag Attributes: '; - - // Display all tag attributes; name and value - foreach ($this->tagAttrib as $attribName => $attribValue) - { - echo '
    ------'.$attribName.' = '.$attribValue; - } // foreach end - - } else { - echo '
    NO Attributes found.'; - } //end if attributes - - // end if is tag is ready - } else { - echo '

    --- ops!! The XML tag is not ready .... Showing NO data'; - } // end if XML tag is ready - - }// toString() end - - -} // end class XmlParse -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTagCollection.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTagCollection.php deleted file mode 100755 index 7e1da6362..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTagCollection.php +++ /dev/null @@ -1,38 +0,0 @@ -xmlTagCollection[] = $theXmlTagObject; - } - - public function getXmlTagCollection() - { - //echo '

    XmlTagCollection Class -> getXmlTagCollection()
    Tot in XmlTagCollection: '.count($this->xmlTagCollection); - return $this->xmlTagCollection; - } - - /** - * Print all values of the XML tag object - */ - public function toString() - { - echo "

    Total ".$this->xmlTagCollection." Tags = ".count($this->xmlTagCollection).""; - - // Display all tag attributes in the tag - foreach ($this->xmlTagCollection as $xmlTagObject) - { - $xmlTagObject->toString(); - } // foreach end - - }// toString() end - -} // end class XmlTagCollection -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTagTrace.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTagTrace.php deleted file mode 100755 index 9f2660518..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTagTrace.php +++ /dev/null @@ -1,242 +0,0 @@ -xmlString = $theXmlString; - - // set the tag to trace and the starting level - $this->tagToTrace = $theTagToTrace; - $this->tagToTraceLevel = $theTagToTraceLevel; - - // create XML tag Collection - $this->myXmlCollection = new XmlTagCollection(); - - // start tracing - $this->traceXmlTag($theXmlString); - } // __construct() end - - /** - * Returns the XML tag Collection - * - */ - public function getCollection() - { - //get from here of from XmlTagCollection collection object??? - return $this->myXmlCollection->getXmlTagCollection(); - //return $this->myXmlCollection; - //echo '
    From ' - - - }// end getCollection() - - /** - * Creates an XML parcer and Iterates through array - * - * @param unknown_type $theXmlString - */ - private function traceXmlTag($theXmlString) - { - // create XML parser - $p = xml_parser_create(); - - // parse XML data into array - xml_parse_into_struct($p, $theXmlString, $xmlVals, $xmlIndex); - - // free XML parser - xml_parser_free($p); - - // initialize XML object ???? - //$myXmlTag = new XmlTag() - - - // start looping xml array - for($i = 0; $i < count($xmlVals); $i++) - { - // initialize XML data - $theTagName=''; - $theTagType=''; - $theTagLevel=''; - $theTagValue=''; - $theTagAtrib = Array(); - - // verify data before adding - if (isset($xmlVals[$i]['tag'])) - { - $theTagName = $xmlVals[$i]['tag']; - } - - if (isset($xmlVals[$i]['type'])) - { - $theTagType = $xmlVals[$i]['type']; - } - - if (isset($xmlVals[$i]['level'])) - { - $theTagLevel = $xmlVals[$i]['level']; - } - - if (isset($xmlVals[$i]['value'])) - { - $theTagValue = $xmlVals[$i]['value']; - } - - if (isset($xmlVals[$i]['attributes'])) - { - $theTagAtrib = $xmlVals[$i]['attributes']; - } - - // set xml data - $this->setXmlData($theTagName,$theTagType,$theTagLevel,$theTagValue,$theTagAtrib); - - - } // end for loop xml array - - } // end traceXmlTag() - - /** - * Recieves Xml data from each tag and determines if values should be collected - * this to trace

    and

    tags - * - * @param String $theTagName - * @param String $theTagType - * @param String $theTagLevel - * @param String $theTagValue - * @param String $theTagAtrib - */ - private function setXmlData($theTagName,$theTagType,$theTagLevel,$theTagValue,$theTagAtrib) - { - - //echo '
    '.$this->tagToTrace; - - // verify also if the level is lower !!!! - - //echo '
    '.$theTagName; - // verify if this data is from the xml tag being traced/collected - if ($theTagName == $this->tagToTrace) - { - - //echo '
    '.$theTagName.' TAG IS THE SAME'; - //echo '
    Value: '.$theTagValue.''; - - - // if tag is complete. The tag has NO children - if ($theTagType=='complete') - { - // create a XmlTag object - $this->xmlTag = new XmlTag($theTagName,$theTagType,$theTagLevel,$theTagValue,$theTagAtrib); - - // tracing this tag is done. - $this->xmlTagState = true; - - $this->xmlTag->setTagState(true); - - //echo '
    '.$theTagName.' TAG is complete !!!'; - - //$this->xmlTag->toString(); - - // add to collection - $this->myXmlCollection->addXmlTagObject($this->xmlTag); - - // reset temp object - $this->xmlTag = null; - - } // end if complete - - // if tag is open. tag do have children - else if ($theTagType=='open') - { - // create a new XmlTag object - $this->xmlTag = new XmlTag($theTagName,$theTagType,$theTagLevel,$theTagValue,$theTagAtrib); - - // tracing this tag is NOT done. - $this->xmlTagState = false; - - //echo '
    '.$theTagName.' TAG is Open !!!'; - - } // end if - - // if tag cdata. Getting data of the traced Tag, after any children data - else if ($theTagType=='cdata') - { - // add value to traced tag - // OJO !! This skips any child value - $this->xmlTag->addToTagValue($theTagValue); - - // tracing this tag is NOT done. - $this->xmlTagState = false; - //echo '
    '.$theTagName.' TAG is cdata!!!'; - - - } // end if - - // if tag close. Getting data of the traced Tag is done - else if ($theTagType=='close') - { - // add value of traced tag - $this->xmlTag->addToTagValue($theTagValue); - - // tracing this tag is NOT done. - $this->xmlTagState = true; - - $this->xmlTag->setTagState(true); - //echo '
    '.$theTagName.' TAG is close!!!'; - - //add to collection - $this->myXmlCollection->addXmlTagObject($this->xmlTag); - - // reset temp object - $this->xmlTag = null; - - } // end if - - - }// end if tracing xml tag - - /* - * if the tag is a children. the tagToTraceLevel is lower than the current TagLevel - * this for all tags like
    , , , , or even for inside our traced tag - */ - if ($this->tagToTraceLevel<$theTagLevel && (isset($this->xmlTag))) - { - // adding children data to tag as value - $this->xmlTag->addChildTagAsValue($theTagName,$theTagType,$theTagValue); - - } // end if - - - } // end setXmlData() - - /** - * Print all values of the XML tag as a String - */ - public function toString() - { - $this->myXmlCollection->toString(); - - - }// toString() end - -} // end class XmlTagTrace -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTagTraceManager.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTagTraceManager.php deleted file mode 100755 index d4957164e..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/core_XmlTagTraceManager.php +++ /dev/null @@ -1,174 +0,0 @@ -xmlDataString = $theXmlString; - - // create a caption Collection - $myCaptionCollcton = new CaptionCollection(); - $this->captionCollection = $myCaptionCollcton; - - // start loopXmlData - $this->loopXmlData(); - - } // end constructor - - /** - * Parses an XML string into an myltidimentional array - * - * @param String $theXmlString The xml file as string - * @return Array $xmlInArray - */ - public function loopXmlData() - { - // create XML parser - $p = xml_parser_create(); - - //xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); - - xml_parse_into_struct($p, $this->xmlDataString, $vals, $index); - - // free parser - xml_parser_free($p); - - - // create a Xmlparse Object tracing for

    tags at level 4 (this the case of DFXP files) - $myXmlParse = new XmlParse('P','4'); - - - // start looping xml array - for ($i = 0; $i < count($vals); $i++) - { - $myXmlParse->setXmlData(); - - - // *************************************** GET CAPTION DATA ---- START - - // if P tag is complete - if($ccBuild == 3) - { - // get caption value - $ccText = $vals[$i]['value']; - - // get attributes array - $capAttrib = $vals[$i]['attributes']; - - // get time in and out of the caption - $ccTimeIn = $capAttrib['BEGIN']; - $ccTimeOut = $capAttrib['END']; - - $newCaptionDone = 1; - - $newCaption = new Caption($ccTimeIn,$ccTimeOut,$ccText,$noStyles); - //$new - //$countCC++; - - } else if($ccBuild == 1) { - - - - // if there are other tags inside P - } else if (($ccBuild == 2) && isset($vals[$i]['value'])) { - - // add other parts of the caption text - $ccText .= $vals[$i]['value']; - - // if is the end of the caption - } else if (($ccBuild == 4) && isset($vals[$i]['value'])) { - - // add other parts of the caption text if is set - $ccText .= $vals[$i]['value']; - } - - - // *************************************** GET CAPTION DATA ---- END - - // just print each tag info - echo '
    Tag: '.$vals[$i]['tag']; - echo '
    Type: '.$vals[$i]['type']; - echo '
    Level: '.$vals[$i]['level']; - - if(isset($vals[$i]['attributes'])) - { - foreach ($vals[$i]['attributes'] as $theAtt => $theVal) - { - //echo '
    Attributes: '.$vals[$i]['attributes']; - echo '
    ------ '.$theAtt.': '.$theVal; - } - } - - if(isset($vals[$i]['value'])) - { - echo '
    Value: '.$vals[$i]['value']; - } - - echo '


    '; - } // end for - - - - - - - - - - - - - - - - - - /* - echo "Index array\n"; - echo "Total in array Index: ".count($index)."\n"; - print_r($index); - echo "\nVals array\n"; - echo "Total in array vals: ".count($vals)."\n"; - print_r($vals); - */ - - - - /* - foreach($vals as $val) - { - $totInArr = count($val); - echo '
    tot in Val = '.$totInArr; - //echo '
    Val = '.$val; - foreach ($val as $theVal) - { - echo '
    the val = '.$theVal; - - } // end for 2 - - } // end for 1 - */ - - - //return $vals; - - } // end loopXmlData() - - /** - * Print class Data - * - */ - public function toString() - { - echo '
    xmlDataString: '.$this->xmlDataString; - echo '
    tagToTrace: '.$this->tagToTrace; - echo '
    tagToTraceLevel: '.$this->tagToTraceLevel; - - } -} // end XmlManager class -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/index.html b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/index.html deleted file mode 100755 index e69de29bb..000000000 diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/static_CcUtilVital_class.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/static_CcUtilVital_class.php deleted file mode 100755 index aeb19f52b..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/static_CcUtilVital_class.php +++ /dev/null @@ -1,61 +0,0 @@ - \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/static_TimeUtil_class.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/static_TimeUtil_class.php deleted file mode 100755 index 27379b909..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/static_TimeUtil_class.php +++ /dev/null @@ -1,186 +0,0 @@ -=$anHour) - { - // get only the int value - $myHours = intval($miliSecTime/$anHour); - - // set the tot milliseconds left after removing number of hour(s) - $myMiliSecTime -= ($myHours*$anHour); - - // set the current hours add leading 0 if needed - if ($myHours<10) - { - $timeArray['hour'] = '0'.$myHours; - } else { - $timeArray['hour'] = ''.$myHours; - } - } else { - $timeArray['hour'] = '00'; - } - - // Is time mark at least a minute? or rather, how many minutes are left? - if($myMiliSecTime>=$aMin-1) - { - // get only the int value - $myMins = intval($myMiliSecTime/$aMin); - - // set the milliseconds left after removing total of minute(s) - $myMiliSecTime -= ($myMins*$aMin); - - // set the current minutes and add leading 0 if needed - if ($myMins<10) - { - $timeArray['min'] = '0'.$myMins; - } else { - $timeArray['min'] = ''. $myMins; - } - } else { - $timeArray['min'] = '00'; - } - - // does it have seconds, or rather, how many seconds are left - if($myMiliSecTime>=$aSec) - { - // get only the int value - $mySec = intval($myMiliSecTime/$aSec); - - // set the milliseconds left after removing total of seconds - $myMiliSecTime -= ($mySec*$aSec); - - // set the current number of seconds in time array, and add leading 0 if needed - if ($mySec<10) - { - $timeArray['sec'] = '0'.$mySec; - } else { - $timeArray['sec'] = ''.$mySec; - } - } else { - $timeArray['sec'] = '00'; - } - - // here a fix for adding leading zeros to milliseconds (e.g. 1=001, 10=010) - if($myMiliSecTime>0) - { - $tempMilliSec = 0 + (0.001 * $myMiliSecTime); - $tempMilliSecArray = explode('.',$tempMilliSec); // split using '.' as separator - $myMiliSecTimeString = ''. $tempMilliSecArray[1]; // get only the decimal value as a string - - // add one zero after the sting value if $myMiliSecTimeString has 2 character - if (strlen($myMiliSecTimeString)==2) - { - $myMiliSecTimeString .= '0'; - } - // add two zeros after the sting value if $myMiliSecTimeString has 1 character - else if (strlen($myMiliSecTimeString)==1) - { - $myMiliSecTimeString .= '00'; - } - - // set millisecodns - $timeArray['msec'] = $myMiliSecTimeString; - } else { - $timeArray['msec'] = '000'; // no milliseconds left - } - - // concatenate values - $qtTimeString = ''.$timeArray['hour'].':'.$timeArray['min'].':'.$timeArray['sec'].'.'.$timeArray['msec']; - - return $qtTimeString; - - } // end samiToQtTime() - - /** - * Converts QT time to miliseconds format (Accepted by SAMI 1.0 and other CCformats) - * @return int $samiTime Time in miliseconds format; 1000 = 1. sec - * @param String $qtTime QT time Format; (e.g. "00:01:10.280") - */ - static public function timeQtToSami($qtTime) - { - // Known patterns: 1, 2, or 3 decimals for millisecond definition - $pattern_time_000 = "\[([0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3})\]"; - $pattern_time_00 = "\[([0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{2})\]"; - $pattern_time_0 = "\[([0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{1})\]"; - $pattern_selected = ''; - - // If pattern is 3 digit - if(preg_match('/'.$pattern_time_000.'/',$qtTime)) - { - $pattern_selected = $pattern_time_000; - } - // If pattern is 2 digit - if(preg_match('/'.$pattern_time_00.'/',$qtTime)) - { - $pattern_selected = $pattern_time_00; - } - // If pattern is 1 digit - if(preg_match('/'.$pattern_time_0.'/',$qtTime)) - { - $pattern_selected = $pattern_time_0; - } - - $t1 = 0; // hours (e.g. [01]) - $t2 = 0; // minutes (e.g. [12]) - $t3 = 0; // seconds (e.g. [01.123]) - - $qtTimeParts = split(':',$qtTime); // split QT time mark into an array - - $t1 += $qtTimeParts[0]; // adding hours - $t2 += $qtTimeParts[1]; // adding minutes - $t3 += $qtTimeParts[2]; // adding seconds and miliseconds - - // millisecond equivalents - $t1 *= 3600000; // 1 hour = 60*60*1000 - $t2 *= 60000; // 1 minute = 60*1000 - $t3 *= 1000; // 1 second = 1*1000 - - // get time in milliseconds - $samiTime = $t1 + $t2 + $t3; - - return $samiTime; - - } // end timeQtToSami() - - - - /******************************** - * still working on more time functions - *********************************/ - -} // end TimeUtil -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/static_TxtFileTools_class.php b/mods/atutor_opencaps/opencaps/conversion_service/include/classes/static_TxtFileTools_class.php deleted file mode 100755 index 3f51d659c..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/classes/static_TxtFileTools_class.php +++ /dev/null @@ -1,107 +0,0 @@ -
    Target Caption File saved in: '.$theFileName.' [Download Caption]'; - - return $fullFileUrl; - - } // stringToFile - - /** - * Loads a Caption File and return it as String - * @param $theFileName The full URL of the file - * @return $ccString The caption file as String - */ - static public function fileToString($theFileName) - { - global $rosettaCCSettings; - - $ccString = file_get_contents($rosettaCCSettings['uploadDir'].'/'.$theFileName); - - /* - clean malformed pattern for ANSI files: - This is harmless for any well formed caption. - fixing captions saved in win notepad - */ - $toSearch = array(chr(13).chr(10)); - $toReplace = array(chr(10)); - $contents = str_replace($toSearch,$toReplace,$ccString); - - return $ccString; - } - - /** - * Forces a browser to download a file stored in the server - * @param $exfile The full URL of the file - */ - static public function downloadFile($exfile) - { - // verify if the file exists - if (file_exists($exfile)) - { - header('Content-Description: File Transfer'); - header('Content-Type: application/octet-stream'); - header('Content-Disposition: attachment; filename='.basename($exfile)); - header('Content-Transfer-Encoding: binary'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Pragma: public'); - header('Content-Length: ' . filesize($exfile)); - //header("Content-type: $type"); ???????? - ob_clean(); - flush(); - readfile($exfile); - exit; - - } // end if - - } // end downloadFile() - - /** - * Replaces all
    tags in a string with chr(10) characters - * - * @param String $theHtmlString The string containign
    HTML tags - * @return unknown - */ - static public function ccBrToNewLine($theHtmlString) - { - $a = array(chr(10)); - $b = array('
    ','
    ','
    ','
    ' ); - $stringWithBreakLines = str_replace($a, $b, $theHtmlString); - return $stringWithBreakLines; - } - - /** - * Replaces the break line character "char(10)" by a specified character - * - * @param String $theCaption The caption containing char(10) characters as line separators - * @param char $theChar The String used to replace the break line character - * @return unknown - */static public function ccNewLineToBr($theCaption, $theChar) - { - $a = ''.chr(10); - $b = $theChar; - $newString = str_replace($a, $b, $theCaption); - return $newString; - } - -} // end class TxtFileTools -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/config.inc.php b/mods/atutor_opencaps/opencaps/conversion_service/include/config.inc.php deleted file mode 100755 index 15f3ad80d..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/include/config.inc.php +++ /dev/null @@ -1,41 +0,0 @@ -get_magic_quotes_gpc = 1'; -} else { - $rosettaCCSettings['get_magic_quotes_gpc'] = 0; - //echo '
    get_magic_quotes_gpc != 1'; -} - - - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/conversion_service/include/index.html b/mods/atutor_opencaps/opencaps/conversion_service/include/index.html deleted file mode 100755 index e69de29bb..000000000 diff --git a/mods/atutor_opencaps/opencaps/conversion_service/index.php b/mods/atutor_opencaps/opencaps/conversion_service/index.php deleted file mode 100755 index 9860796b8..000000000 --- a/mods/atutor_opencaps/opencaps/conversion_service/index.php +++ /dev/null @@ -1,71 +0,0 @@ - - -RosettaCCService - - - - -
    - cc_url - CaptionUrl: - -
    - cc_result - Type of Result: - - if 0 returns a caption string, if = 1 returns the URL where target caption is - found
    - cc_target - Type of Target Caption: - -
    - cc_name - Name of the Caption: - -
    - -
    - - -'; -echo $htmlForm; -} -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/editor.php b/mods/atutor_opencaps/opencaps/editor.php deleted file mode 100755 index 0e8a9d9e3..000000000 --- a/mods/atutor_opencaps/opencaps/editor.php +++ /dev/null @@ -1,123 +0,0 @@ - - - - -
    - -
    - - - - - - - - - - -
    -
    -
    /
    -
    - -
    -
    -
    - -
    Previous Clip
    -
    Next Clip
    - -
    - - Play -
    - -
    - -
    -

    - -
    - - -
    - -
    - -
    - - -
    -

    - Add previous space to clip - -
    - -
    -

    - - Add next space to clip -
    - -
    -
    -
    -
    -
    - -
    -
    - Go to start of clip  - Step back .033 second  - Step back .100 second -
    - -
    - Step forward .100 second  - Step forward .033 second  - Go to end of clip -
    - -
    - - Play Clip  - Last play -
    -
    -
    -
    -
    -
    - -
    - -
    - -
    -
    -
    - - \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/error_log b/mods/atutor_opencaps/opencaps/error_log deleted file mode 100755 index 9b610fa9b..000000000 --- a/mods/atutor_opencaps/opencaps/error_log +++ /dev/null @@ -1 +0,0 @@ -[15-Aug-2010 23:56:54] PHP Warning: Cannot modify header information - headers already sent by (output started at /home/filoa3/public_html/a2/ATutor/mods/AtOpenCaps/opencaps/include/classes/project_class.php:186) in /home/filoa3/public_html/a2/ATutor/mods/AtOpenCaps/opencaps/include/classes/system_class.php on line 94 diff --git a/mods/atutor_opencaps/opencaps/export.php b/mods/atutor_opencaps/opencaps/export.php deleted file mode 100755 index d3020cc75..000000000 --- a/mods/atutor_opencaps/opencaps/export.php +++ /dev/null @@ -1,77 +0,0 @@ -remoteUpdate($_SESSION['rid']); - $this_system->putCaps($this_proj->id); -} else if (isset($_POST['format'])) { - $this_proj->exportCaption($_POST['format']); -} - -require(INCLUDE_PATH.'header.inc.php'); - -?> - - - -
    -
    - - -

    Send Captions to

    -

    If you are finished captioning this project, use the button below to update the system with your caption file.

    -

    - - -

    Export Caption File

    -

    You may export your captions in a variety of formats. Choose a format to receive a download of that caption file:

    - - - - -

    Export Transcript

    -

    Coming soon.

    - - - -

    Export Complete Project

    -
      -
    • Complete Package - .zip of original movie, caption file, SMIL file (layout in preview), and accessible html player
    • -
    - -
    - -

    Close

    -

    Once you have exported your work to save it, you may now Close this project.

    -
    - diff --git a/mods/atutor_opencaps/opencaps/help.php b/mods/atutor_opencaps/opencaps/help.php deleted file mode 100755 index 7203a379a..000000000 --- a/mods/atutor_opencaps/opencaps/help.php +++ /dev/null @@ -1,25 +0,0 @@ - - -
    -

    Coming soon...

    - -
    - \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/images/application_edit.png b/mods/atutor_opencaps/opencaps/images/application_edit.png deleted file mode 100755 index fb2efb8775442af862ef0ef111f371e5857928d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 703 zcmV;w0zmzVP)FxeKF=OosmQ6jmTLP{}-6iF>nO8f(+aY2!Xm^*5Av6NhR zD0!Nar%`rnu~v@R4hO^8&iS41=VQN>+65QO>m_E!|B#IbuI^pAy5?9WYjHC`6;s8j z!_-hy%sJEya}KAD$C|Z-~!ZLFQctG09Uhp@QPcl?mU}7$E{?cz}t3fC%LK?;}5+keI!OTyHb6 z@j}nbBm-HHT&CJnb^IYBAVSCka_RdNzT74;XDve?FCx*eM2ky^TZSvCN4lf#zADBt{VLMZ58~8Xlk&tIj2}J+_M1=n24SuBB zC|kIW{HG=&F(WrHgY=^pRBSp=QTYN)m5{Hh{2@SBTQi04uPMk>dS9PrQdx|l%yhmz zOH#Sz0@1`YLTX0HPj&aS)SnFM)H&2CwbI1q`b)fRK1k<-HpW#}^Sv*{jiIgdH9W>t zQ6<#EFflVmJF;g{aA;S(kLP%K=NdiTT|X03N>|n%ZExo<#LO72ZdK{vlG)|{vIVoS lXs&IrKfQB(9TL{7iX$V@PAta(9$|8b7D6wp-IURZdO^p#W zhGj%3h}IwkopYY&+|PAgc}vbAem;r__Cgn?7OtN?KmKI17sC;NJK>JG5gvFrVTMN# zW|%vN_vh}?(%S8}PbcQ9@iXId`-X{dTVVoMbkJeoYg zZe4x6LQzFH#h^6;2oKD`3ETs7$J)T!z`_|=FnatD=0;HwL7^lRK_n3h@B_uHVGm~Ku92vAS`gf?5Br# z8{9Z~kHXz3lDn}(5=ayYND`_NGav5KA9U$9znOkFMd9ugsm+;f5|St+frNR>{r5M? zxnXQ%jM1ZG)Va%*SCi!2P^2)Y=l}vFAwaUKcgHXPW0kkyS9ex(J9 zLu@IU7soQkH&;No%bTEi-Lr>D_AI6iV#?A3~B^FfP%5GR1nd|DqtT_3=slpZLAdaE7%DZ zq7q}81xXPN76HNi^JdngC8_mhYI?w^U( z2gw6K?&>VvIx{ig&f_gAfExg@R2*<~)WC4e95q8rugZ<6&Z+ic)U*Onzk&oo-0>i| zIATHwf=EC_k<7^~keAhcD{H`r6aW_ify}`K%$&?2NJcK8;%KOhO|6b#^*;~+_kTbl z;Odxw3lN0NvI;PYFxpfMsWxLE%Z0^vw@I-i#zYz>Ufg_xS!EE)l=cip0Fkc0GbiElsF znK^ijVHt@UnK|0x!SlPMyan7K-~PV!>fW=oV5*oJs*0JRDPew=cw&P?(*;Eu5;d~( zYlq(NDUO%dUjxW~rt#|X#V_sY_PH1n-EQ~u$EWMFd)E6M=kt$dKcrzwpH{xkji3Jo X7}OeR*sz>k00000NkvXXu0mjfdXfo6 diff --git a/mods/atutor_opencaps/opencaps/images/arrow_right.png b/mods/atutor_opencaps/opencaps/images/arrow_right.png deleted file mode 100755 index b1a1819238c6de8f9e50988f4151261fa6ba64ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 349 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 b1@G?wx(0*AsWg{l00000NkvXXu0mjfIK9F$ diff --git a/mods/atutor_opencaps/opencaps/images/clip_next.png b/mods/atutor_opencaps/opencaps/images/clip_next.png deleted file mode 100755 index ce378bc4a1f53710174229752819a3e761d1f067..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3243 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 diff --git a/mods/atutor_opencaps/opencaps/images/clip_rightedge.png b/mods/atutor_opencaps/opencaps/images/clip_rightedge.png deleted file mode 100755 index 36acc97ccc21c93ed284f94079ad11d5af5c3710..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3084 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 diff --git a/mods/atutor_opencaps/opencaps/images/ffwd.png b/mods/atutor_opencaps/opencaps/images/ffwd.png deleted file mode 100755 index 20d3350c185d68ca3e0db6880bcab057680fa9f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3353 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 Hu0mjf2&(G2 diff --git a/mods/atutor_opencaps/opencaps/images/logo.png b/mods/atutor_opencaps/opencaps/images/logo.png deleted file mode 100755 index a0ddbb0584e6cb299071632655ec826d331afba9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2148 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 LNkvXXu0mjf90!wr diff --git a/mods/atutor_opencaps/opencaps/images/pause.png b/mods/atutor_opencaps/opencaps/images/pause.png deleted file mode 100755 index b8f02e63afeabdcedc83b57f8d371cd1f6b960c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3554 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 diff --git a/mods/atutor_opencaps/opencaps/images/play.png b/mods/atutor_opencaps/opencaps/images/play.png deleted file mode 100755 index aee4018991b79792bfe57d4e0a5fa0d5f3f540fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3483 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 diff --git a/mods/atutor_opencaps/opencaps/images/rewind2.png b/mods/atutor_opencaps/opencaps/images/rewind2.png deleted file mode 100755 index 9fd790847d070e1dbd7fdec6b59162a252b28af1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3297 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 BOOpTq diff --git a/mods/atutor_opencaps/opencaps/images/slider-bg-2.png b/mods/atutor_opencaps/opencaps/images/slider-bg-2.png deleted file mode 100755 index 2fb763d66dd0790f2897944b4f215303a1b9997e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 365 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 m*7M6#3}fA6zulBOJpTd&*i6`<2gkMm0000 - - - - - - OpenCaps - An online inclusive media editor - - - - - - - - - - - - - -
    - Logout -
    - - Error:
    '; - foreach ($_SESSION['errors'] as $errmsg) { - echo $errmsg.'
    '; - } - echo '
    '; - unset($_SESSION['errors']); - } - if (isset($_SESSION['feedback'])) { - echo ''; - unset($_SESSION['feedback']); - } - if (isset($_SESSION['notices'])) { - echo '
    Notice:
    '; - foreach ($_SESSION['notices'] as $nmsg) { - echo $nmsg.'
    '; - } - echo '
    '; - unset($_SESSION['notices']); - } \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/classes/captionCollection_class.php b/mods/atutor_opencaps/opencaps/include/classes/captionCollection_class.php deleted file mode 100755 index 5ba4d877f..000000000 --- a/mods/atutor_opencaps/opencaps/include/classes/captionCollection_class.php +++ /dev/null @@ -1,125 +0,0 @@ -captionCollection[] = $theCcObject; // this a php-based approach... java will need a push/count solution - - } // end addCaptions() - - /** - * Sets all the Global text style attributes - * @param Array $theGlobalStyles Array containing all the global text styles - */ - public function setTxtStylesGlobal($theGlobalStyles) - { - $this->txtStylesGlobal = $theGlobalStyles; - } - - /** - * Sets the value a single Global text style attribute - * @param String $theAtt Attribute name - * @param String $theValue Attribute Value - */ - public function setTxtStylesGlobalAtt($theAtt,$theValue) - { - $this->txtStylesGlobal[$theAtt]=$theValue; - } // end setTxtStylesGlobalAtt() - - /** - * Return this object - * - * @return CaptionCollection - */ - public function getCollection() - { - return $this->captionCollection; - } - - public function toString() - { - $ccCount=0; - echo '

    Printing a Rosetta Collection

    '; - echo 'Total Captions Found: '.count($this->captionCollection); - - echo '

    [Global] Styles'; - if (count($this->txtStylesGlobal)==0) - { - echo ' (NO text styles found)'; - } - - foreach ($this->txtStylesGlobal as $txtStyleName => $txtStyleValue) - { - echo '
    -----'.$txtStyleName.' = '.$txtStyleValue; - } - - echo '

    Printing Captions in the collection... '; - foreach ($this->captionCollection as $captionObj) - { - $ccCount++; - // building a new to string - /* - - echo "
    In Time: ". $captionObj->getInTime().""; - echo "
    Out Time: ". $captionObj->getOutTime().""; - echo "
    Caption: ". $captionObj->getCaption().""; - - // display text styles - foreach ($captionStylesFound as $txtStyle) - { - $captionObj-> - //$textStyles[] = $txtStyle; - } - */ - // call Caption's toString(); - echo '

    '.$ccCount; - $captionObj->toString(); - - } // foreach end - - } //toString() end - -} // end CaptionCollection Class -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/classes/caption_class.php b/mods/atutor_opencaps/opencaps/include/classes/caption_class.php deleted file mode 100755 index 8070e5ca4..000000000 --- a/mods/atutor_opencaps/opencaps/include/classes/caption_class.php +++ /dev/null @@ -1,27 +0,0 @@ -caption = $theCaption; - $this->textStyles= $theTextStyles; - - } -} - - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/classes/clip_class.php b/mods/atutor_opencaps/opencaps/include/classes/clip_class.php deleted file mode 100755 index 24eed2d9c..000000000 --- a/mods/atutor_opencaps/opencaps/include/classes/clip_class.php +++ /dev/null @@ -1,65 +0,0 @@ -clips[] = $clip; - } - -} - -/* an actual clip */ -class clip { - public $inTime; - public $outTime; - public $duration; - - public $inTimeMilli; - public $outTimeMilli; - public $durationMilli; - - // should these two be in a caption object? - public $caption_text; - public $captionStyles = array(); - - //public $description; - - function __construct($in, $out, $caption) { - $intime = new time($in, false); - $this->inTime = $intime->formatted; - $this->inTimeMilli = $intime->ms; - - $outtime = new time($out, false); - $this->outTime = $outtime->formatted; - $this->outTimeMilli = $outtime->ms; - - $this->durationMilli = $this->outTimeMilli - $this->inTimeMilli; - $dur = new time($this->durationMilli, true); - $this->duration = $dur->formatted; - - $this->caption_text = $caption; - } -} - - - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/classes/db_class.php b/mods/atutor_opencaps/opencaps/include/classes/db_class.php deleted file mode 100755 index 80ca44132..000000000 --- a/mods/atutor_opencaps/opencaps/include/classes/db_class.php +++ /dev/null @@ -1,90 +0,0 @@ -connect(); - } - - private function connect() { - - require(INCLUDE_PATH.'config.inc.php'); - $this->db = @mysql_connect(DB_HOST . ':' . DB_PORT, DB_USER, DB_PASSWORD); - if (!$this->db) { - $_SESSION['errors'][] = 'Unable to connect to database.
    '; - } - if (!@mysql_select_db(DB_NAME, $this->db)) { - $_SESSION['errors'][] = 'Connection established, but database "'.DB_NAME.'" cannot be selected.
    '; - } - - if (isset($_SESSION['errors'])) { - include(INCLUDE_PATH."basic_header.inc.php"); - include(INCLUDE_PATH."footer.inc.php"); - exit; - } - - return true; - } - - /* adds a new proj to the db, returns proj id */ - public function addProj($proj) { - - $sql = "INSERT INTO projects VALUES (0, $_SESSION[mid], '$proj->name', '$proj->media_loc', 0, NOW())"; - if (!$result = mysql_query($sql, $this->db)) { - $_SESSION['errors'][] = 'Database error - could not add project.'; - return false; - } - return mysql_insert_id(); - } - - public function updateProj($proj) { - $sql = "UPDATE projects SET name='".$proj->name."', video_file='".$proj->media_loc."' WHERE project_id=".$proj->id; - if (!$result = mysql_query($sql, $this->db)) { - $err = 'Database error
    '; - exit; - } - return true; - } - - - - /*public function getProjInfo($id) { - global $db; - - $sql = "SELECT name, video_file, layout_preset, last_accessed FROM projects WHERE project_id=".intval($id); - $result = mysql_query($sql, $db); - - if ($row = mysql_fetch_assoc($result)) { - return $row; - } - } - - public function getMovie() { - global $db; - - $sql = "SELECT video_file FROM projects WHERE project_id=".intval($_SESSION['pid']); - $result = mysql_query($sql, $db); - - if ($row = mysql_fetch_assoc($result)) { - return 'projects/'.$_SESSION['pid'].'/movies/'.$row['video_file']; - } - - }*/ -} - - - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/classes/index.html b/mods/atutor_opencaps/opencaps/include/classes/index.html deleted file mode 100755 index e69de29bb..000000000 diff --git a/mods/atutor_opencaps/opencaps/include/classes/project_class.php b/mods/atutor_opencaps/opencaps/include/classes/project_class.php deleted file mode 100755 index e8fd25567..000000000 --- a/mods/atutor_opencaps/opencaps/include/classes/project_class.php +++ /dev/null @@ -1,503 +0,0 @@ -clip_collection = new clipCollection(); - } - - /* create a new project */ - function createNew($name, $media, $captions) { - global $this_db; - - $this->name = $name; - $this->layout = 0; - - //enter into db - $this->id = $this_db->addProj($this); - - if (isset($_SESSION['errors'])) { - header("Location:start.php"); - exit; - } - - $_SESSION['pid'] = $this->id; - - //make project folder - if (!file_exists('projects/'.$this->id.'/')) { - @mkdir('projects/'.$this->id.'/'); - @copy('projects/index.html', 'projects/'.$this->id.'/index.html'); - } - - // if uploaded - if (is_array($media)) { - $this->media_loc = 'projects/'.$this->id.'/'.$media['name']; - - if ( !move_uploaded_file($media['tmp_name'], 'projects/'.$this->id.'/'.basename($media['name'])) ) { - $_SESSION['errors'][] = "Problem uploading media file - can't copy file to server. The file may exceed file size limits. Try a smaller file or contact your server administrator."; - - $this->delete($this->id); - return; - } - - // if URL - } else { - $this->media_loc = $media; - } - - //convert caption file to quicktime & save - if (!empty($captions['tmp_name'])) { - - $this->importCaptions($captions); - } - - //save reference file - $json = json_encode(get_object_vars($this)); - $this->saveJson($json, $this->id); - $this_db->updateProj($this); - - return $this->id; - } - - /* open user project */ - function open($pid) { - global $this_db; - $sql = "UPDATE projects SET last_accessed=NOW() WHERE project_id=$pid AND member_id=$_SESSION[mid]"; - if (!$result = mysql_query($sql, $this_db->db)) { - echo 'Database error: '.mysql_error(); - exit; - } - - $_SESSION['pid'] = $pid; - } - - - /* save uploaded media - returns location of file */ - function saveMedia($upload) { - $dir = 'projects'; - if (!move_uploaded_file($file['tmp_name'], $dir.'/'.basename($file['name'])) ) { - //$err = "Problem uploading file - can't copy file to server. The file may exceed file size limits. Try a smaller file or contact your server administrator."; - } - } - - /* list the current user's projects */ - function printUserProjects($pageNum) { - global $this_db, $stripslashes, $addslashes; - - if (!isset($pageNum)) - $pageNum = 1; - - $projsPerPage = 20; - - //printing page numbers - $sql = "SELECT project_id FROM projects WHERE member_id=".intval($_SESSION['mid']); - $result = @mysql_query($sql, $this_db->db); - $numrows = @mysql_num_rows($result); - - $maxPage = ceil($numrows/$projsPerPage); - - $nav = 'Page: '; - for($page = 1; $page <= $maxPage; $page++) { - if ($page == $pageNum) { - $nav .= " $page "; - } else { - $nav .= ' '.$page.' '; - } - } - - if ($maxPage > 1) - echo $nav."

    "; - - $offset = ($pageNum - 1) * $projsPerPage; - $sql = "SELECT * FROM projects WHERE member_id=".intval($_SESSION['mid'])." ORDER BY last_accessed DESC LIMIT $offset, $projsPerPage"; - $result = @mysql_query($sql, $this_db->db); - - - if ($numrows == 0) { - echo "No projects yet."; - } else { - echo '
      '; - while ($row = @mysql_fetch_assoc($result)) { - echo '
    • (Delete)
    • '; - } - echo '
    '; - echo "
    "; - - } - } - - function saveJson($json, $pid) { - global $stripslashes; - - $json_path = INCLUDE_PATH.'../projects/'.$pid.'/'; - - if (!file_exists($json_path)) - mkdir($json_path); - - // addede by ANTO - /////////////////////////////////////////// - if (get_magic_quotes_gpc()) - { - $json = stripslashes($json); - - } - // second test using regexp - $validJsonRegExp = '/"clips":\[/'; // can be better tho - if (!preg_match($validJsonRegExp, $validJsonRegExp)) - { - $json = str_replace('\"','"',$json); - } - //end added by ANTO - /////////////////////////////////////////// - - - if (!@file_put_contents($json_path.'opencaps.json', $stripslashes($json))) { - echo 'Could not create project file.'; - } - } - - function importCaptions($capfile, $upload=true) { - global $page, $remote_systems; - - // added by anto - if (OC_DEBUG_MODE_ON) - { - $ocAtDebugMsg = '*************************'; - $ocAtDebugMsg .= '
    '; - $ocAtDebugMsg .= 'importCaptions() - class: project'; - $ocAtDebugMsg .= '
    '; - $ocAtDebugMsg .= '
    Session ID: '.$_SESSION['pid']; - $ocAtDebugMsg .= '
    $this->id: '.$this->id; - $ocAtDebugMsg .= '

    '; - $ocAtDebugMsg .= '*************************'; - ///echo $ocAtDebugMsg; - $_SESSION['feedback'][] = $ocAtDebugMsg; - } - - $page = explode('/',$_SERVER["SCRIPT_NAME"]); - $page = end($page); - - $page_len = strlen($page)+1; - - $ccollection = new clipCollection() ; - - //save - if ($upload) { - if( !move_uploaded_file( $capfile['tmp_name'], INCLUDE_PATH.'../projects/'.$this->id.'/'.basename($capfile['name'])) ) { - $_SESSION['errors'][] = "Problem uploading caption file - can't copy file to server."; - $this->delete($this->id); - return; - } - - $base_url = substr('http://'.$_SERVER["SERVER_NAME"].$_SERVER["SCRIPT_NAME"], 0, -$page_len); - $caption_file = urlencode('../projects/'.$this->id.'/'.basename($capfile['name'])); - - } else { - /* system - matterhorn */ - $page_len += strlen("include/"); - $base_url = substr('http://'.$_SERVER["SERVER_NAME"].$_SERVER["SCRIPT_NAME"], 0, -$page_len); - - $uri = substr($capfile, strlen($remote_systems[$_SESSION['rid']]['url'])); - $caps = matterhornAuth($_SESSION['rid'], $uri); - $caption_file = INCLUDE_PATH.'../projects/'.$this->id.'/'.'captions.xml'; - @file_put_contents($caption_file, $caps); - } - - $convert_url = $base_url.'/conversion_service/?cc_url='.$caption_file.'&cc_result=0&cc_target=JSONcc&cc_name=noname.___'; - $json_captions = json_decode(@file_get_contents($convert_url)); - - if (!empty($json_captions) && $json_captions != "The format of source Caption was not recognized.") { - - foreach ($json_captions->captionCollection as $clip) { - $this_clip = new clip($clip->inTime, $clip->outTime, trim($clip->caption)); - $ccollection->addClip($this_clip); - } - - $_SESSION['feedback'][] = "Captions imported successfully."; - $_SESSION['feedback'][] = "id: ".$this->id; - - } else { - $_SESSION['errors'][] = "Problem uploading caption file - the format is incorrect, or unsupported."; - } - - $this->clip_collection = $ccollection; - - //save reference file - $json = json_encode(get_object_vars($this)); - - - // changed by ANTO - $this->saveJson($json, $_SESSION['pid']); - - return; - - } - - - function exportCaption($format) { - - if ($format == "all") { - $this->export_pkg(); - - } else if ($format == "json") { - $cappath = INCLUDE_PATH.'../projects/'.$this->id.'/'.'opencaps.json'; - //make a copy of the json that has the proj name as prefix - - - } else { - $base_url = substr('http://'.$_SERVER["SERVER_NAME"].$_SERVER["SCRIPT_NAME"], 0, -10); - - $convert_url = $base_url.'conversion_service/?cc_url='.urlencode('../projects/'.$this->id.'/opencaps.json').'&cc_result=0&cc_target='.$format.'&cc_name=noname.___'; - $formatted_captions = @file_get_contents($convert_url); - if (!empty($formatted_captions)) { - $formatted_captions = trim($formatted_captions); - $cappath = INCLUDE_PATH.'../projects/'.$this->id.'/'.str_replace(' ', '_', $this->name).'_'; - - switch($format) { - case "DFXP": - $cappath = $cappath.'captions.dfxp.xml'; - break; - - case "DvdStl": - $cappath = $cappath.'captions.stl'; - break; - - case "MicroDvd": - $cappath = $cappath.'captions.sub'; - break; - - case "MPlayer": - $cappath = $cappath.'captions.MPsub'; - break; - - case "QTtext": - $formatted_captions = $formatted_captions."\r\n".'['.$this->duration.']'; /* white cap background hack */ - $cappath = $cappath.'captions.txt'; - break; - - case "RealText": - $cappath = $cappath.'captions.rt'; - break; - - case "Sami": - $cappath = $cappath.'capscribe.smi'; - break; - - case "SubRipSrt": - $cappath = $cappath.'captions.srt'; - break; - - case "Scc": - $cappath = $cappath.'captions.scc'; - break; - - case "SubViewer": - $cappath = $cappath.'captions.sub'; - break; - } - - @file_put_contents($cappath, $formatted_captions); - } - } - export_file($cappath); - exit; - } - - function delete($proj_id) { - global $this_db; - - if (deleteDir('../projects/'.$proj_id."/")) { - $sql = "DELETE from projects WHERE project_id=".$proj_id." AND member_id=".$_SESSION['mid']; - $result = mysql_query($sql, $this_db->db); - } else { - //echo "Project could not be deleted."; - } - } - - function preview($layout) { - $this->layout = $layout; - - //send this to the conversion service - $base_url = substr('http://'.$_SERVER["SERVER_NAME"].$_SERVER["SCRIPT_NAME"], 0, -20); - $json_url = urlencode($base_url.'projects/'.$this->id.'/opencaps.json'); - $request = $base_url."conversion_service/?cc_url=".$json_url."&cc_result=0&cc_target=QTtext&cc_name=noname.___"; - - //create the qt-text file - $qt_text = @file_get_contents($request)."\r\n".'['.$this->duration.']'; - @file_put_contents('../projects/'.$this->id.'/captions.txt', $qt_text); - - //send the embed height back as a response - $eheight = $this->get_smil('save'); - if ($eheight >= 100) - echo $eheight; - else - echo '100'; - } - - - function get_smil($method="") { - $layout = $this->layout; - - $contents = @file_get_contents(INCLUDE_PATH.'../projects/layouts/smil_'.$layout.'.mov'); - $contents = str_replace("%rootwidth%", $this->media_width, $contents); - - $vid_file_name = end(explode('/',$this->media_loc)); - - if ($this->media_loc == 'projects/'.$this->id.'/'.$vid_file_name) - $contents = str_replace("%video%", $vid_file_name, $contents); - else - $contents = str_replace("%video%", $this->media_loc, $contents); - - $contents = str_replace("%duration%", $this->duration, $contents); - $contents = str_replace("%width%", $this->media_width, $contents); - $contents = str_replace("%height%", $this->media_height, $contents); - - $contents = str_replace("%capwidth%", $this->media_width-10, $contents); - - if ($layout == 0) { //cap below - $contents = str_replace("%rootheight%", $this->media_height+85, $contents); - $obj_height = $this->media_height+100; - $contents = str_replace("%captop%", $this->media_height+10, $contents); - $contents = str_replace("%capheight%", 135, $contents); //affects font size - - } else if ($layout == 1) { //cap bottom - $contents = str_replace("%rootheight%", $this->media_height, $contents); - $obj_height = $this->media_height+30; - $contents = str_replace("%captop%", $this->media_height-75, $contents); - $contents = str_replace("%capheight%", 135, $contents); - - } else { //caption only - $contents = str_replace("%rootheight%", 85, $contents); - $obj_height = 155; - $contents = str_replace("%captop%", 10, $contents); - $contents = str_replace("%capheight%", 135, $contents); - } - - if ($method == "save") { - $proj_smil = INCLUDE_PATH.'../projects/'.$this->id.'/smil_'.$layout.'.mov'; - @file_put_contents($proj_smil, $contents); - return $obj_height; - } else { - return $contents; - } - } - - function export_pkg() { - //create zipfile - $zip = new ZipArchive(); - - $proj_name = str_replace(' ', '', $this->name); - $proj_name = str_replace("'", '', $proj_name); - $zipfile = $proj_name.".zip"; - if ($zip->open(INCLUDE_PATH.'../projects/'.$this->id.'/'.$zipfile, ZIPARCHIVE::CREATE)!==TRUE) { - exit("cannot open <$zipfile>\n"); - } - - $zip->addEmptyDir($proj_name); - - //add smil - $contents = $this->get_smil(); - $zip->addFromString($proj_name.'/smil.mov', $contents); - - //create player from template - $contents = file_get_contents(INCLUDE_PATH.'../projects/player_template.php'); - $contents = str_replace("%width%", $this->media_width, $contents); - $contents = str_replace("%height%", $this->media_height+135, $contents); - - //add player - $zip->addFromString($proj_name.'/player.html', $contents); - - //add captions - $zip->addFile(INCLUDE_PATH.'../projects/'.$this->id.'/captions.txt', $proj_name.'/captions.txt'); - - //add movie if not a URL - if (current(explode('/', $this->media_loc)) == "projects") { - $media_name = end(explode('/', $this->media_loc)); - $zip->addFile($this->media_loc, $proj_name.'/'.$media_name); - } - - $zip->close(); - //export_file(INCLUDE_PATH.'../projects/'.$this->id.'/'.$zipfile); - unlink(INCLUDE_PATH.'../projects/'.$this->id.'/'.$zipfile); - exit; - } - - function editName($name) { - global $addslashes, $this_db; - - $this->name = $addslashes($name); - - //save reference file - $json = json_encode(get_object_vars($this)); - $this->saveJson($json, $this->id); - $this_db->updateProj($this); - } - -} - - -/* utility functions */ - -/* force download of a file in browser */ -function export_file($exfile) { - if (file_exists($exfile)) { - header('Content-Description: File Transfer'); - header('Content-Type: application/octet-stream'); - header('Content-Disposition: attachment; filename='.basename($exfile)); - header('Content-Transfer-Encoding: binary'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Pragma: public'); - header('Content-Length: '.filesize($exfile)); - ob_clean(); - flush(); - readfile($exfile); - } -} - -/* delete a directory and its contents */ -function deleteDir($dir) { - $dh = @opendir($dir); - while ( $file = @readdir($dh) ) { - if ( $file != '.' || $file != '..') { - @unlink($dir.$file); - //if ( ! @unlink ( $dir . '/' . $obj ) ) deleteDir ( $dir . '/' . $obj, true ) - } - } - @closedir ($dh); - if (@rmdir($dir)) - return true; - else - return false; -} - - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/classes/system_OcAtutor_class.php b/mods/atutor_opencaps/opencaps/include/classes/system_OcAtutor_class.php deleted file mode 100755 index 65d535fef..000000000 --- a/mods/atutor_opencaps/opencaps/include/classes/system_OcAtutor_class.php +++ /dev/null @@ -1,37 +0,0 @@ - Encoded Data sent to Server:
    '.$encoded.'
    '; - } - } // end putCaps - - } // end class -} -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/classes/system_class.php b/mods/atutor_opencaps/opencaps/include/classes/system_class.php deleted file mode 100755 index 2d320d16b..000000000 --- a/mods/atutor_opencaps/opencaps/include/classes/system_class.php +++ /dev/null @@ -1,328 +0,0 @@ -system_id = $system_id; - $this->name = $systems[$system_id]['name']; - $this->base_url = $systems[$system_id]['url']; - $this->type = $systems[$system_id]['type']; - - $this->username = $systems[$system_id]['username']; - $this->password = $systems[$system_id]['password']; - - $this->get_url = $this->base_url."?action=getMedia"; // url for receiving media info - $this->put_url = $this->base_url."?action=putCaps"; // url for sending captions back - $this->returnFormat = 'DFXP'; - } - - function openProject($id) { - global $this_proj, $supported_ext; - - $media_info = $this->getMedia(); - - if (!empty($media_info)) { - - //check if correct format - $ext = explode(".", $media_info->mediaFile); - $ext = end($ext); - - if (!@in_array($ext, $supported_ext)) { - $_SESSION['errors'][] = "Media file format not supported."; - include(INCLUDE_PATH."basic_header.inc.php"); - include(INCLUDE_PATH."footer.inc.php"); - exit; - } - - //populate project vars - $this_proj->name = $media_info->title; - $this_proj->media_loc = $media_info->mediaFile; - $this_proj->clip_collection = new clipCollection(); - - //import existing captions, if any - if (!empty($media_info->captionFile)) - $this->importSystemCaptions($media_info->captionFile); - - //save working file - $json = json_encode(get_object_vars($this_proj)); - $this_proj->saveJson($json, $this_proj->id); - - } else { - $_SESSION['errors'][] = "Could not open project - no response from server."; - include(INCLUDE_PATH."basic_header.inc.php"); - include(INCLUDE_PATH."footer.inc.php"); - exit; - } - - // set user as guest - $_SESSION['valid_user'] = true; - $_SESSION['mid'] = '99999'; - - header('Location:editor.php'); - exit; - - return; - } - - - function getMedia() { - global $this_proj; - - //get json - switch ($this->type) { - case 'matterhorn': - $media_info = json_decode($this->matterhornAuth('/opencaps/rest/'.$this_proj->id)); - - //convert naming - $media_info->mediaFile = $media_info->mediaURL; - $media_info->captionFile = $media_info->DFXPURL; - unset($media_info->mediaURL); - unset($media_info->DFXPURL); - break; - - case 'atutor': - $media_info = json_decode(@file_get_contents($this->get_url.'&id='.$this_proj->id)); - break; - - default: - $media_info = json_decode(@file_get_contents($this->get_url.'&id='.$this_proj->id)); - break; - } - return $media_info; - } - - function putCaps($id, $format="SubRipSrt") { - global $this_proj, $base_url, $systems; - - //convert captions to required format - $convert_url = $base_url.'conversion_service/index.php?cc_url='.urlencode('../projects/'.$_SESSION['pid'].'/opencaps.json').'&cc_result=0&cc_target='.$format.'&cc_name=noname.txt'; - $formatted_captions = trim(@file_get_contents($convert_url)); - - if (OC_DEBUG_MODE_ON) - { - $ocAtDebugMsg = '*************************'; - $ocAtDebugMsg .= '
    '; - $ocAtDebugMsg .= 'putCaps() - class: system'; - $ocAtDebugMsg .= '
    '; - $ocAtDebugMsg .= '
    ID: '.$_SESSION['pid']; - $ocAtDebugMsg .= '
    '; - $ocAtDebugMsg .= '
    Conversion Service URL:
    '.$convert_url; - $ocAtDebugMsg .= '
    '; - $ocAtDebugMsg .= '
    Caption Data:
    '.$formatted_captions; - $ocAtDebugMsg .= '
    '; - $ocAtDebugMsg .= '
    Base Url: '.$base_url; - $ocAtDebugMsg .= '

    '; - $ocAtDebugMsg .= '*************************'; - $_SESSION['feedback'][] = $ocAtDebugMsg; - } - - //send captions - if (!empty($formatted_captions)) { - - switch ($this->type) { - case 'matterhorn': - $uri = '/opencaps/rest/'.$this_proj->id.'/TimedText/'; - $response = matterhornAuth($this->id, $uri, $formatted_captions); - break; - - default: - /* - * ANTO APPROACH - */ - // load and call atutor class - include_once('system_OcAtutor_class.php'); - OcAtutor::putCaps($systems[ACTIVE_SYSTEM]['url'],'putCaps',$_SESSION['pid'],$formatted_captions); - break; - } - /* - * ANTO: this stuff is too accurate, really tells nothing about the success to the action (e.g. was the file updated?): - * - */ - if (empty($response)) { - $_SESSION['feedback'][] = "Successfully updated server."; - } else { - $_SESSION['errors'][] = "Could not update remote server."; - - } - - - - } else { - $_SESSION['errors'][] = "Could not convert captions to required format."; - } - - return true; - - } - - function importSystemCaptions($capfile) { - global $base_url, $this_proj; - - $ccollection = new clipCollection() ; - - //get captions - switch ($this->type) { - case 'matterhorn': - $uri = substr($capfile, strlen($remote_systems[$_SESSION['rid']]['url'])); - $caps = matterhornAuth($_SESSION['rid'], $uri); - $caption_file = INCLUDE_PATH.'../projects/'.$this->id.'/'.'captions.xml'; - @file_put_contents($caption_file, $caps); - break; - - case 'atutor': - $caption_file = $capfile; - break; - - default: - break; - } - - $convert_url = $base_url.'/conversion_service/?cc_url='.$caption_file.'&cc_result=0&cc_target=JSONcc&cc_name=noname.___'; - $json_captions = json_decode(@file_get_contents($convert_url)); - - if (!empty($json_captions) && $json_captions != "The format of source Caption was not recognized.") { - - foreach ($json_captions->captionCollection as $clip) { - $this_clip = new clip($clip->inTime, $clip->outTime, trim($clip->caption)); - $ccollection->addClip($this_clip); - } - - $_SESSION['feedback'][] = "Captions imported successfully."; - - } else { - $_SESSION['errors'][] = "Problem with caption file - the format is incorrect, or unsupported."; - } - - $this_proj->clip_collection = $ccollection; - - //save reference file - $json = json_encode(get_object_vars($this_proj)); - $this_proj->saveJson($json, $this->id); - return; - - } - - - /* digest auth for matterhorn systems */ - function matterhornAuth($uri, $content='') { - global $this_proj; - - $username = $this->username; - $password = $this->password; - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - - curl_setopt($ch, CURLOPT_URL, $systems[$rid]['url'].$uri); - curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); - curl_setopt($ch, CURLOPT_USERPWD, $username.':'.$password); - curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-Requested-Auth: Digest")); - - if ($content == "media") { - curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); - - $temp_file = 'projects/'.$this_proj->id.'/media'; //use tempname(); - $fh = fopen($temp_file, 'w'); - curl_setopt($ch, CURLOPT_FILE, $fh); - curl_exec($ch); - curl_close($ch); - fclose($fh); - return $temp_file; - - } else if (!empty($content)) { - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $content); - } - - $response = curl_exec($ch); - $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - - curl_close($ch); - - return $response; - } - - - /* list a system's available projects */ - function printProjects($pageNum=1) { - - //check if connected - if (!@file_get_contents($this->url)) { - echo "Can't connect to remote server."; - return; - } - - $projsPerPage = 20; - - $uri = "/opencaps/rest/list/processed.json"; - $remote_media = json_decode(matterhornAuth($rid, $uri)); - - $numrows = $remote_media->total; - $maxPage = ceil($numrows/$projsPerPage); - - $nav = 'Page: '; - for($page = 1; $page <= $maxPage; $page++) { - if ($page == $pageNum) { - $nav .= " $page "; - } else { - $nav .= ' '.$page.' '; - } - } - - if ($maxPage > 1) - echo $nav."

    "; - - $offset = ($pageNum - 1) * $projsPerPage; - - $uri = "/opencaps/rest/list/processed.json?count=90&startPage=".($pageNum-1); - - //$remote_media = $remote_systems[$rid]['url']."/opencaps/rest/list/processed.json?count=$projsPerPage&startPage=".($pageNum-1); - - $_SESSION['rid'] = $rid; - $remote_media = json_decode(matterhornAuth($rid, $uri)); - - if (!empty($remote_media->results)) { - echo '
      '; - foreach($remote_media->results as $rm) { - echo '
    • '; - } - echo '
    '; - echo "
    "; - } else { - echo "No projects yet."; - } - } - -} - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/classes/time_class.php b/mods/atutor_opencaps/opencaps/include/classes/time_class.php deleted file mode 100755 index ba4c45868..000000000 --- a/mods/atutor_opencaps/opencaps/include/classes/time_class.php +++ /dev/null @@ -1,209 +0,0 @@ -ms = $t; - $this->formatted = $this->timeFormatted($t); - } else { - $this->ms = $this->timeMilli($t); - $this->formatted = $t; - } - } - - - /* - * Functions written by Antonio for the conversion service - */ - - /** - * Converts milliseconds time mark into 00:00:00:000 format (QT native format) - * - * @param int $miliSecTime A time format in miliseconds (e.g. 26070) 1000 = 1 second - * @return String $qtTimeString A QT mark in 00:00:00:000 format - */ - static public function timeFormatted($miliSecTime) - { - $qtTimeString = ''; - // milliseconds holder - $myMiliSecTime = $miliSecTime; - - // basic constant knowledge, values in milliseconds - $anHour = 3600000; // 60*60*1000 - $aMin = 60000; // 60*1000 - $aSec = 1000; // 1 * 1000 - - // temp holders for to store equivalent hh, mm, sec, milisec - $myHours = 0; - $myMins = 0; - $mySec = 0; - //$myMsec = 0; /// not using it.!!! - - // initialize timeArray - $timeArray = array(); - $timeArray['hour'] = ''; - $timeArray['min'] = ''; - $timeArray['sec'] = ''; - $timeArray['msec'] = ''; - - // parsing millisecodns QT time format 00:00:00.000 - - // is time mark at least an hour? - if($miliSecTime>=$anHour) - { - // get only the int value - $myHours = intval($miliSecTime/$anHour); - - // set the tot milliseconds left after removing number of hour(s) - $myMiliSecTime -= ($myHours*$anHour); - - // set the current hours add leading 0 if needed - if ($myHours<10) - { - $timeArray['hour'] = '0'.$myHours; - } else { - $timeArray['hour'] = ''.$myHours; - } - } else { - $timeArray['hour'] = '00'; - } - - // Is time mark at least a minute? or rather, how many minutes are left? - if($myMiliSecTime>=$aMin-1) - { - // get only the int value - $myMins = intval($myMiliSecTime/$aMin); - - // set the milliseconds left after removing total of minute(s) - $myMiliSecTime -= ($myMins*$aMin); - - // set the current minutes and add leading 0 if needed - if ($myMins<10) - { - $timeArray['min'] = '0'.$myMins; - } else { - $timeArray['min'] = ''. $myMins; - } - } else { - $timeArray['min'] = '00'; - } - - // does it have seconds, or rather, how many seconds are left - if($myMiliSecTime>=$aSec) - { - // get only the int value - $mySec = intval($myMiliSecTime/$aSec); - - // set the milliseconds left after removing total of seconds - $myMiliSecTime -= ($mySec*$aSec); - - // set the current number of seconds in time array, and add leading 0 if needed - if ($mySec<10) - { - $timeArray['sec'] = '0'.$mySec; - } else { - $timeArray['sec'] = ''.$mySec; - } - } else { - $timeArray['sec'] = '00'; - } - - // here a fix for adding leading zeros to milliseconds (e.g. 1=001, 10=010) - if($myMiliSecTime>0) - { - $tempMilliSec = 0 + (0.001 * $myMiliSecTime); - $tempMilliSecArray = explode('.',$tempMilliSec); // split using '.' as separator - $myMiliSecTimeString = ''. $tempMilliSecArray[1]; // get only the decimal value as a string - - // add one zero after the sting value if $myMiliSecTimeString has 2 character - if (strlen($myMiliSecTimeString)==2) - { - $myMiliSecTimeString .= '0'; - } - // add two zeros after the sting value if $myMiliSecTimeString has 1 character - else if (strlen($myMiliSecTimeString)==1) - { - $myMiliSecTimeString .= '00'; - } - - // set millisecodns - $timeArray['msec'] = $myMiliSecTimeString; - } else { - $timeArray['msec'] = '000'; // no milliseconds left - } - - // concatenate values - $qtTimeString = ''.$timeArray['hour'].':'.$timeArray['min'].':'.$timeArray['sec'].'.'.$timeArray['msec']; - - return $qtTimeString; - - } // end samiToQtTime() - - /** - * Converts QT time to milliseconds format (Accepted by SAMI 1.0 and other CCformats) - * @return int $samiTime Time in miliseconds format; 1000 = 1. sec - * @param String $qtTime QT time Format; (e.g. "00:01:10.280") - */ - static public function timeMilli($qtTime) - { - // Known patterns: 1, 2, or 3 decimals for millisecond definition - $pattern_time_000 = "\[([0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3})\]"; - $pattern_time_00 = "\[([0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{2})\]"; - $pattern_time_0 = "\[([0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{1})\]"; - $pattern_selected = ''; - - // If pattern is 3 digit - if(preg_match('/'.$pattern_time_000.'/',$qtTime)) - { - $pattern_selected = $pattern_time_000; - } - // If pattern is 2 digit - if(preg_match('/'.$pattern_time_00.'/',$qtTime)) - { - $pattern_selected = $pattern_time_00; - } - // If pattern is 1 digit - if(preg_match('/'.$pattern_time_0.'/',$qtTime)) - { - $pattern_selected = $pattern_time_0; - } - - $t1 = 0; // hours (e.g. [01]) - $t2 = 0; // minutes (e.g. [12]) - $t3 = 0; // seconds (e.g. [01.123]) - - $qtTimeParts = explode(':',$qtTime); // split QT time mark into an array - - $t1 += $qtTimeParts[0]; // adding hours - $t2 += $qtTimeParts[1]; // adding minutes - $t3 += $qtTimeParts[2]; // adding seconds and miliseconds - - // millisecond equivalents - $t1 *= 3600000; // 1 hour = 60*60*1000 - $t2 *= 60000; // 1 minute = 60*1000 - $t3 *= 1000; // 1 second = 1*1000 - - // get time in milliseconds - $samiTime = $t1 + $t2 + $t3; - - return $samiTime; - - } - -} -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/classes/user_class.php b/mods/atutor_opencaps/opencaps/include/classes/user_class.php deleted file mode 100755 index 84b063a64..000000000 --- a/mods/atutor_opencaps/opencaps/include/classes/user_class.php +++ /dev/null @@ -1,125 +0,0 @@ -id = $id; - - if ($id = 99999) - $this->username = "guest"; - else - $this->username = $username; - - $this->valid = false; - - //default $preferences - } - - public function login($username, $password) { - global $this_db; - $row = ''; - $result = ''; - - //check if user exists in db with this password - if (isset($username, $password)) { - /*if (version_compare(PHP_VERSION, '5.1.0', '>=')) { - session_regenerate_id(TRUE); - }*/ - - if ($username=="guest" && $password=="guest") { - $this->valid = true; - $this->id = '99999'; - $this->username = $username; - - $_SESSION['valid_user'] = true; - $_SESSION['mid'] = $this->id; - $_SESSION['username'] = $this->username; - - return; - } - - - $username = addslashes($username); - $password = addslashes($password); - - //$sql = "SELECT member_id, login, SHA1(CONCAT(password, '-', '".DB_PASSWORD."')) AS pass FROM members WHERE login='$this_login' AND SHA1(CONCAT(password, '$_SESSION[token]'))='$this_password'"; - - $sql = "SELECT member_id, login, password FROM members WHERE login='$username' AND password='$password'"; - $result = mysql_query($sql, $this_db->db); - - if ($row = mysql_fetch_assoc($result)) { - - $this->valid = true; - $this->id = intval($row['member_id']); - $this->username = $row['login']; - - $_SESSION['mid'] = $this->id; - $_SESSION['username'] = $this->username; - $_SESSION['valid_user'] = true; - - $sql = "UPDATE members SET last_login=NOW() WHERE member_id=$_SESSION[mid]"; - mysql_query($sql, $this_db->db); - - $_SESSION['feedback'][] = 'Successfully logged in.'; - - } else { - $this->valid = false; - $this->id = 0; - $this->username = ''; - $_SESSION['errors'][] = 'Invalid login.'; - } - header('Location:start.php'); - exit; - } - - //create cookies - } - - /* checks if a user is logged in and valid */ - public function authenticate() { - if ($this->valid) { - return true; - } - - return false; - } - - public function logout() { - unset($_SESSION['valid_user']); - unset($_SESSION['member_id']); - unset($_SESSION['errors']); - $_SESSION['feedback'][] = 'Successfully logged out.'; - - header('Location: index.php'); - exit; - } - - public function savePrefs() { - - } - - public function getPrefs() { - - } - -} - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/config.inc.php b/mods/atutor_opencaps/opencaps/include/config.inc.php deleted file mode 100755 index dd248b342..000000000 --- a/mods/atutor_opencaps/opencaps/include/config.inc.php +++ /dev/null @@ -1,48 +0,0 @@ - \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/footer.inc.php b/mods/atutor_opencaps/opencaps/include/footer.inc.php deleted file mode 100755 index 2bd0eea29..000000000 --- a/mods/atutor_opencaps/opencaps/include/footer.inc.php +++ /dev/null @@ -1,30 +0,0 @@ - - -
    - - - -'; - print_r($_SESSION); - echo ''; */ -?> - - - - \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/header.inc.php b/mods/atutor_opencaps/opencaps/include/header.inc.php deleted file mode 100755 index 5645040c5..000000000 --- a/mods/atutor_opencaps/opencaps/include/header.inc.php +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - OpenCaps - An online inclusive media editor - - '; - - //IE - } else if (preg_match('/msie/i', $userAgent)) { - echo ''; - - //Opera - } else if (preg_match('/opera/i', $userAgent)) { - echo ''; - } - ?> - - - - - - - - - - - - -
    -

    OpenCaps - a free, online caption editor

    - -
    - name; ?> -
    -
    - - - Error:
    '; - foreach ($_SESSION['errors'] as $errmsg) { - echo $errmsg.'
    '; - } - echo '
    '; - unset($_SESSION['errors']); - } - if (isset($_SESSION['feedback'])) { - echo ''; - unset($_SESSION['feedback']); - } - if (isset($_SESSION['notices'])) { - echo '
    Notice:
    '; - foreach ($_SESSION['notices'] as $nmsg) { - echo $nmsg.'
    '; - } - echo '
    '; - unset($_SESSION['notices']); - } - ?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/index.html b/mods/atutor_opencaps/opencaps/include/index.html deleted file mode 100755 index e69de29bb..000000000 diff --git a/mods/atutor_opencaps/opencaps/include/matterhorn.inc.php b/mods/atutor_opencaps/opencaps/include/matterhorn.inc.php deleted file mode 100755 index 8c98d2127..000000000 --- a/mods/atutor_opencaps/opencaps/include/matterhorn.inc.php +++ /dev/null @@ -1,61 +0,0 @@ -id.'/media'; //use tempname(); - $fh = fopen($temp_file, 'w'); - curl_setopt($ch, CURLOPT_FILE, $fh); - curl_exec($ch); - curl_close($ch); - fclose($fh); - return $temp_file; - - } else if (!empty($content)) { - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $content); - } - - $response = curl_exec($ch); - $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - - curl_close($ch); - - return $response; - -} - - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/vitals.inc.php b/mods/atutor_opencaps/opencaps/include/vitals.inc.php deleted file mode 100755 index 319a76de3..000000000 --- a/mods/atutor_opencaps/opencaps/include/vitals.inc.php +++ /dev/null @@ -1,140 +0,0 @@ -owner = &$this_user; - - if (isset($_SESSION['pid'])) - $this_proj->id = $_SESSION['pid']; - - if (!empty($this_proj->id)) - setVals(); -} - -function setVals() { - global $this_proj, $stripslashes; - - $json = json_decode($stripslashes(@file_get_contents(INCLUDE_PATH.'../projects/'.$_SESSION['pid'].'/opencaps.json'))); - - $this_proj->id = $json->id; - $this_proj->name = $json->name; - //$this_proj->prefs = $json->prefs; - - $this_proj->media_loc = $json->media_loc; - $this_proj->media_height = $json->media_height; - $this_proj->media_width = $json->media_width; - $this_proj->duration = $json->duration; - $this_proj->layout = $json->layout; - - $this_proj->caption_loc = $json->caption_loc; - $this_proj->clip_collection = $json->clip_collection; - -} - -/* - * check for valid project - -if ($page != "index.php" && $page != "login.php" && $page != "logout.php" && $page != "register.php" && $page != "start.php" && $page != "adminTasks.php") { - if (!isset($_SESSION['pid']) && empty($_SESSION['pid'])) { - echo "Project not loaded."; - exit; - } -} -*/ - - -//check if using firefox -/*if(!strstr($_SERVER['HTTP_USER_AGENT'], "Firefox")) { - $_SESSION['errors'][] = "At this time, Capscribe Web requires a Firefox browser."; - include(INCLUDE_PATH.'basic_header.inc.php'); - include(INCLUDE_PATH.'footer.inc.php'); - exit; -}*/ - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/include/workflow.php b/mods/atutor_opencaps/opencaps/include/workflow.php deleted file mode 100755 index 18111b81a..000000000 --- a/mods/atutor_opencaps/opencaps/include/workflow.php +++ /dev/null @@ -1,94 +0,0 @@ -printUserProjects($_GET['page']); - else - $this_proj->printUserProjects(1); - -} else if ($_GET['task'] == "print_projs_remote") { - if (isset($_GET['page'])) - $this_system->printProjects($_GET['page']); - else - $this_system->printProjects(); -} else if ($_GET['task'] == "open_proj") { - $this_proj->open($_GET['pid']); - -} else if ($_GET['task'] == "open_proj_remote") { - $this_proj->openRemote($_GET['pid']); - -} else if ($_GET['task'] == "proj_delete") { - $this_proj->delete($_GET['pid']); -} - - -/* - * load json file into a project - */ -if ($_GET['task'] == 'get_json') { - $json_path = '../projects/'.$this_proj->id.'/'; - echo $stripslashes(@file_get_contents($json_path.'opencaps.json')); - -/* - * save project into json file - */ -} else if ($_POST['task'] == 'save_json') { - $this_proj->saveJson($_POST['json'], $_POST['pid']); - -/* - * preview - create smil & qttext files based on layout - */ -} else if ($_GET['task'] == "preview") { - $this_proj->preview($_GET['layout']); - -/* export */ -} else if ($_GET['task'] == "export") { - $exfile = $this_proj->exportCaption($_GET['format']); - export_file($exfile); - -/* start tabs */ -} else if ($_GET['task'] == "get_tabs") { - - if (isset($systems)) { - echo ''; - } -} - - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/index.php b/mods/atutor_opencaps/opencaps/index.php deleted file mode 100755 index baa8e1ebf..000000000 --- a/mods/atutor_opencaps/opencaps/index.php +++ /dev/null @@ -1,54 +0,0 @@ -id = $_GET['id']; - $_SESSION['pid'] = $this_proj->id; - - //check which system is pinging opencaps - if (isset($systems) && ACTIVE_SYSTEM != '') { - - /*$ref_url = substr($_SERVER['HTTP_REFERER'], 0, -(strlen($_SERVER['SCRIPT_FILENAME']))); - - echo $_SERVER['HTTP_REFERER'].' '.$_SERVER['HTTP_HOST'].'
    '; - echo $systems[2]['url'].' '.$ref_url; - exit; - - foreach ($systems as $key=>$sys) { - if (strpos($sys['url'], getenv("HTTP_REFERER"))) { - $sys_id = $key; - } - }*/ - - $this_system->openProject($this_proj->id); - - - } else { - $_SESSION['errors'][] = "External system URL not recognised. Make sure to add this system to the OpenCaps config file."; - header("Location:start.php"); - exit; - } - //$_SESSION['rid'] = $rid; - //$this_proj->openRemote($this_proj->id, true); - -} else { - header("Location:start.php"); - exit; -} - -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/install/config_template.php b/mods/atutor_opencaps/opencaps/install/config_template.php deleted file mode 100755 index 7e77f23a9..000000000 --- a/mods/atutor_opencaps/opencaps/install/config_template.php +++ /dev/null @@ -1,44 +0,0 @@ - \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/install/index.html b/mods/atutor_opencaps/opencaps/install/index.html deleted file mode 100755 index e69de29bb..000000000 diff --git a/mods/atutor_opencaps/opencaps/install/oc_schema.sql b/mods/atutor_opencaps/opencaps/install/oc_schema.sql deleted file mode 100755 index 138f728c5..000000000 --- a/mods/atutor_opencaps/opencaps/install/oc_schema.sql +++ /dev/null @@ -1,31 +0,0 @@ --- -------------------------------------------------------- - --- --- Table structure for table `members` --- - -CREATE TABLE IF NOT EXISTS `members` ( - `member_id` mediumint(9) unsigned NOT NULL AUTO_INCREMENT, - `login` varchar(20) NOT NULL, - `password` varchar(40) NOT NULL, - `name` varchar(255) NOT NULL, - `email` varchar(100) NOT NULL, - `last_login` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`member_id`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; - --- -------------------------------------------------------- - --- --- Table structure for table `projects` --- - -CREATE TABLE IF NOT EXISTS `projects` ( - `project_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `member_id` mediumint(8) unsigned NOT NULL, - `name` varchar(255) NOT NULL, - `video_file` varchar(255) NOT NULL, - `layout_preset` tinyint(3) unsigned NOT NULL, - `last_accessed` datetime NOT NULL, - PRIMARY KEY (`project_id`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; diff --git a/mods/atutor_opencaps/opencaps/js/AC_QuickTime.js b/mods/atutor_opencaps/opencaps/js/AC_QuickTime.js deleted file mode 100755 index b40e932c7..000000000 --- a/mods/atutor_opencaps/opencaps/js/AC_QuickTime.js +++ /dev/null @@ -1 +0,0 @@ -/* File: AC_QuickTime.js Abstract: This file contains functions to generate OBJECT and EMBED tags for QuickTime content. Version: <1.2> Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Copyright å© 2006-2007 Apple Computer, Inc., All Rights Reserved */ /* * This file contains functions to generate OBJECT and EMBED tags for QuickTime content. */ /************** LOCALIZABLE GLOBAL VARIABLES ****************/ var gArgCountErr = 'The "%%" function requires an even number of arguments.' + '\nArguments should be in the form "atttributeName", "attributeValue", ...'; /******************** END LOCALIZABLE **********************/ var gTagAttrs = null; var gQTGeneratorVersion = 1.2; var gQTBehaviorID = "qt_event_source"; var gQTEventsEnabled = false; function AC_QuickTimeVersion() { return gQTGeneratorVersion; } function _QTComplain(callingFcnName, errMsg) { errMsg = errMsg.replace("%%", callingFcnName); alert(errMsg); } function _QTIsMSIE() { var ua = navigator.userAgent.toLowerCase(); var msie = /msie/.test(ua) && !/opera/.test(ua); return msie; } function _QTGenerateBehavior() { return objTag = ''; } function _QTPageHasBehaviorObject(callingFcnName, args) { var haveBehavior = false; var objects = document.getElementsByTagName('object'); for ( var ndx = 0, obj; obj = objects[ndx]; ndx++ ) { if ( obj.getAttribute('classid') == "clsid:CB927D12-4FF7-4a9e-A169-56E4B8A75598" ) { if ( obj.getAttribute('id') == gQTBehaviorID ) haveBehavior = false; break; } } return haveBehavior; } function _QTShouldInsertBehavior() { var shouldDo = false; if ( gQTEventsEnabled && _QTIsMSIE() && !_QTPageHasBehaviorObject() ) shouldDo = true; return shouldDo; } function _QTAddAttribute(prefix, slotName, tagName) { var value; value = gTagAttrs[prefix + slotName]; if ( null == value ) value = gTagAttrs[slotName]; if ( null != value ) { if ( 0 == slotName.indexOf(prefix) && (null == tagName) ) tagName = slotName.substring(prefix.length); if ( null == tagName ) tagName = slotName; return ' ' + tagName + '="' + value + '"'; } else return ""; } function _QTAddObjectAttr(slotName, tagName) { // don't bother if it is only for the embed tag if ( 0 == slotName.indexOf("emb#") ) return ""; if ( 0 == slotName.indexOf("obj#") && (null == tagName) ) tagName = slotName.substring(4); return _QTAddAttribute("obj#", slotName, tagName); } function _QTAddEmbedAttr(slotName, tagName) { // don't bother if it is only for the object tag if ( 0 == slotName.indexOf("obj#") ) return ""; if ( 0 == slotName.indexOf("emb#") && (null == tagName) ) tagName = slotName.substring(4); return _QTAddAttribute("emb#", slotName, tagName); } function _QTAddObjectParam(slotName, generateXHTML) { var paramValue; var paramStr = ""; var endTagChar = (generateXHTML) ? ' />' : '>'; if ( -1 == slotName.indexOf("emb#") ) { // look for the OBJECT-only param first. if there is none, look for a generic one paramValue = gTagAttrs["obj#" + slotName]; if ( null == paramValue ) paramValue = gTagAttrs[slotName]; if ( 0 == slotName.indexOf("obj#") ) slotName = slotName.substring(4); if ( null != paramValue ) paramStr = '' + _QTAddObjectParam("src", generateXHTML); var embedTag = ''; } // return the object/embed as a string function QT_GenerateOBJECTText() { var txt = _QTGenerate("QT_GenerateOBJECTText", false, arguments); if ( _QTShouldInsertBehavior() ) txt = _QTGenerateBehavior() + txt; return txt; } function QT_GenerateOBJECTText_XHTML() { var txt = _QTGenerate("QT_GenerateOBJECTText_XHTML", true, arguments); if ( _QTShouldInsertBehavior() ) txt = _QTGenerateBehavior() + txt; return txt; } function QT_WriteOBJECT() { var txt = _QTGenerate("QT_WriteOBJECT", false, arguments); if ( _QTShouldInsertBehavior() ) document.writeln(_QTGenerateBehavior()); document.writeln(txt); } function QT_WriteOBJECT_XHTML() { var txt = _QTGenerate("QT_WriteOBJECT_XHTML", true, arguments); if ( _QTShouldInsertBehavior() ) document.writeln(_QTGenerateBehavior()); document.writeln(txt); } function QT_GenerateBehaviorOBJECT() { return _QTGenerateBehavior(); } function QT_ReplaceElementContents() { var element = arguments[0]; var args = []; // copy all other arguments we want to pass through to the fcn for ( var ndx = 1; ndx < arguments.length; ndx++ ) args.push(arguments[ndx]); var txt = _QTGenerate("QT_ReplaceElementContents", false, args); if ( txt.length > 0 ) element.innerHTML = txt; } function QT_ReplaceElementContents_XHTML() { var element = arguments[0]; var args = []; // copy all other arguments we want to pass through to the fcn for ( var ndx = 1; ndx < arguments.length; ndx++ ) args.push(arguments[ndx]); var txt = _QTGenerate("QT_ReplaceElementContents_XHTML", true, args); if ( txt.length > 0 ) element.innerHTML = txt; } \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/js/editor.js b/mods/atutor_opencaps/opencaps/js/editor.js deleted file mode 100755 index 677a01e82..000000000 --- a/mods/atutor_opencaps/opencaps/js/editor.js +++ /dev/null @@ -1,883 +0,0 @@ -/* - * OpenCaps - * http://opencaps.atrc.utoronto.ca - * - * Copyright 2009 Heidi Hazelton - * Adaptive Technology Resource Centre, University of Toronto - * - * Licensed under the Educational Community License (ECL), Version 2.0. - * You may not use this file except in compliance with this License. - * http://www.opensource.org/licenses/ecl2.php - * - */ - -/* GLOBALS */ - -var proj = proj || {}; - -var MIN_CLIP_DUR = 400; - -var clip_playing = false; - -var movie = movie || {}; -var clip = clip || {}; -var movieObj = movieObj || {}; - -num_clips = 0; -clips = new Array(); - -this_location = new Object; - -var json; -var inClip; - - -/* ****** */ -tab = 'clips'; -lastplay = 0; -new_flag = 0; -clocktimer = 0; -curTime = 0; -clipTime = 0; -curClip = 0; -curIn = 0; -lastLoc = 1; - -pace = 0; -timer = 0; -numclips = 0; -marker = ""; -clip_marker = ""; - -//set values in seconds -onemin = 60; -onehr = onemin*60; - -/* clip vars */ -temp_in = 0; -temp_out = 0; -temp_caps = ''; -dur = 0; -extend = false; - - -/*************************************** initialize */ - -$(document).ready(function () { - $("#movie-controls").css("visibility", "hidden"); - $("#clip-controls").css("visibility", "hidden"); - $("#make-clip").css("visibility", "hidden"); - $("#clip-info").css("visibility", "hidden"); - - $.get("include/workflow.php", { task: 'get_json' }, function(json) { - if (json) { - proj = JSON.parse(json); - startEditor(); - } - }); - - $("#caption-text").keyup( function(event) { - //if ($("#caption-text").text() != this_location.caption_text) { - $("#makeclip").removeAttr("disabled"); - temp_caps = 1; - //} - }); -}); - - -function confirmDelete(clipnum) { - if (confirm("Are you sure you want to delete Clip "+clipnum+"?")) { - deleteClip(clipnum); - } -} - -function startEditor() { - movieObj = document.mymovie; - - //register listeners - RegisterListener('qt_play', 'mymovie', 'mymovie_embed', startTimeline); - RegisterListener('qt_pause', 'mymovie', 'mymovie_embed', pauseTimeline); - RegisterListener('qt_ended', 'mymovie', 'mymovie_embed', pauseTimeline); - - /* show or hide side bar action */ - $("#show_hide_caps").click(function() { - if ($("#info-tab").css("display") == "none") { - $("#info-tab").show(); - $("#info-container").css("margin-left", "71%"); - $("#movie-container").css("width", "70%"); - - $(this).html('

    Clips hide clips

    '); - } else { - $("#info-tab").hide(); - $("#info-container").css("margin-left", "97%"); - $("#movie-container").css("width", "96%"); - - $(this).html('show clips'); - } - }); - - /* hide clip side bar */ - $("#info-tab").hide(); - $("#info-container").css("margin-left", "97%"); - $("#movie-container").css("width", "96%"); - $("#show_hide_caps").html('show clips'); - - - $("#editor-tab").addClass('current'); - $("#clips-subtab").addClass('current'); - - /* global proj related vars */ - if (proj.clip_collection) - num_clips = proj.clip_collection.clips.length; - - interval = window.setInterval("QTStatus()",100); -} - -function QTStatus() { - try { - if (movieObj.GetPluginStatus() == "Complete") { - window.clearInterval(interval); - $("#movie_status").html(""); - setDisplay(); - } else { - $("#movie_status").html("Loading media..."); - } - } catch (err) { - } -} - -function setDisplay() { - $("#movie-controls").css("visibility", "visible"); - $("#clip-controls").css("visibility", "visible"); - $("#make-clip").css("visibility", "visible"); - $("#clip-info").css("visibility", "visible"); - - $("#source-file").text(movieObj.GetURL()); - - $("#duration").text(getFormattedTime(movieObj.GetDuration())); - dur = parseInt(movieObj.GetDuration()/movieObj.GetTimeScale()*1000); - - var mysize = movieObj.GetRectangle().split(','); - - /* set if audio file: min 250x100 */ - if (mysize[3] >= 1) - proj.media_height = mysize[3]; - else - proj.media_height = 1; - - if (mysize[2] >= 250) - proj.media_width = mysize[2]; - else - proj.media_width = 250; - - proj.duration = getFormattedTime2(dur); - clips = proj.clip_collection.clips; - - $("#m_timeline").slider({ - min: 0, - max: dur, - - stop: function(e, ui) { - $("#m_timeline").slider("value", ui.value); - }, - - slide: function(e, ui) { - $("#c_timeline").slider("value", ui.value); - moveMovieAll(ui.value); - } - }); - - //$("#show_hide_caps").html('hide clips Clips'); - - pace = dur / parseInt($("#m_timeline").css("width")); - - //isn't it always 0? - if (movieObj.GetTime() > 0) { - curTime = calcTime(movieObj.GetTime()); - } else { - curTime = getFormattedTime2(0); - } - - $("#current-time").text(curTime); - $("#clip-time").text(curTime); - - curTime = getMilliseconds(curTime); - $("#makeclip").attr("disabled","disabled"); - - saveJson(); -} - -function moveMovie(time) { //time in milliseconds - movieObj.SetTime(time*movieObj.GetTimeScale()/1000); - setCurClip(time); - - $("#current-time").text(getFormattedTime2(time)); - - clipTime = parseInt(time - this_location.inTimeMilli); - $("#clip-time").text(getFormattedTime2(clipTime)); - - curTime = time; -} - -function moveMovieAll(time) { //time in milliseconds - movieObj.SetTime(time*movieObj.GetTimeScale()/1000); - setCurClip(time); - - $("#c_timeline").slider("value", time); - $("#m_timeline").slider("value", time); - $("#current-time").text(getFormattedTime2(time)); - - clipTime = parseInt(time - this_location.inTimeMilli); - $("#clip-time").text(getFormattedTime2(clipTime)); - curTime = time; -} - -function startTimeline() { - /*if (getMilliseconds(calcTime(movieObj.GetTime())) == curTime-1) { - movieObj.SetTime((curTime*movieObj.GetTimeScale()/1000)+50); - }*/ - runTimer(); - - this_location_dur = getMilliseconds($("#out-time").text())-getMilliseconds($("#in-time").text()); - clip_pace = this_location_dur / parseInt($("#c_timeline").css("width")); - - updateMovieMarker(curTime); - updateClipMarker(curTime); -} - -function pauseTimeline() { - clearTimeout(clocktimer); - clearTimeout(marker); - clearTimeout(clip_marker); -} - -function updateMovieMarker(time) { - $("#m_timeline").slider("value", time); - marker = setTimeout("updateMovieMarker(curTime)", pace); -} - -function updateClipMarker(time) { - $("#c_timeline").slider("value", time); - clip_marker = setTimeout("updateClipMarker(curTime)", clip_pace); -} - -function runTimer() { - curTime = calcTime(movieObj.GetTime()); - - $("#current-time").text(curTime); - curTime = getMilliseconds(curTime); - - clipTime = parseInt(curTime - getMilliseconds($("#in-time").text())); - - if ( curTime==dur || curTime>getMilliseconds($("#out-time").text()) || curTime= dur) { - clip.pressStop(); - moveMovieAll(getMilliseconds($("#out-time").text())); - return; - } else { - setCurClip(curTime); - } - } - $("#clip-time").text(getFormattedTime2(clipTime)); - clocktimer = setTimeout("runTimer()",1); -} - -function setClipTimeline(cdur, cin, cout) { - //console.log('setClipTimeline', cin, cout); - - //destroy the old slider set up and create the new one - $("#c_timeline").slider("destroy"); - - $("#c_timeline").slider({ - min: cin, - max: cout, - - stop: function(e, ui) { - $("#c_timeline").slider("value", ui.value); - }, - slide: function(e, ui) { - $("#m_timeline").slider("value", ui.value); - moveMovieAll(ui.value); - } - }); -} - -function loadClips() { - $('#numclips').text(num_clips); - clips_html = ''; - - if (num_clips > 0) { - for (var i in clips) { - - //previous space - if (clips[parseInt(i)-1] == undefined && clips[i].inTimeMilli>0) { - space_dur = getFormattedTime2(clips[i].inTimeMilli-1); - clips_html += '
    Space before Clip 1'+ space_dur +'
    '; - } else if ( clips[parseInt(i)-1] != undefined && (clips[i].inTimeMilli != parseInt(clips[parseInt(i)-1].outTimeMilli)+1)) { - space_dur = getFormattedTime2(clips[i].inTimeMilli - clips[parseInt(i)-1].outTimeMilli -2); - clips_html += '
    Space after Clip '+i+''+ space_dur +'
    '; - } - - //clip - html_caption = clips[i].caption_text.replace(/\n/g, "
    "); - clips[i].name = 'Clip '+(parseInt(i)+1); - clips_html += '
    '+clips[i].name+'
    ' + html_caption + '
    '+ clips[i].duration + '
    in: ' + clips[i].inTime + '
    out: '+ clips[i].outTime +'
    '; - - //last space - if (clips[parseInt(i)+1] == undefined && clips[i].outTimeMilliSpace after Clip '+(parseInt(i)+1)+''+ space_dur +'
    '; - } - i++; - } - - $("#info-tab").html(clips_html); - } else { - //no clips - clips_html = '
    Space'+ $("#duration").text() +'
    '; - $("#info-tab").html(clips_html); - - new_flag = true; - } - setCurClip(curTime); -} - -/* - * As the movie plays (or the playhead is moved), figure out what clip it's on - */ -function setCurClip(time) { - - this_location = {}; - inClip = false; - var asterisk = ''; - - if (temp_in) { - this_location.inTime = temp_in; - this_location.inTimeMilli = getMilliseconds(temp_in); - } else { - this_location.inTime = $("#in-time").text(); - this_location.inTimeMilli = getMilliseconds(this_location.inTime); - } - if (temp_out) { - this_location.outTime = temp_out; - this_location.outTimeMilli = getMilliseconds(temp_out); - } else { - this_location.outTime = $("#out-time").text(); - this_location.outTimeMilli = getMilliseconds(this_location.outTime); - } - - if (extend == true) { - if( (temp_in && time < getMilliseconds(temp_in)) || (temp_out && time > getMilliseconds(temp_out) )) { - resetClipWork(); - extend = false; - } else { - return; - } - } else { - lastLoc = curClip; - } - - if (num_clips == 0) { - //no clips - this_location.name = "Space"; - - asterisk = "#space0"; - if (!temp_in) { - this_location.inTimeMilli = 0; - this_location.inTime = getFormattedTime2(this_location.inTimeMilli); - } - if (!temp_out) { - this_location.outTimeMilli = dur; - this_location.outTime = getFormattedTime2(dur); - } - - this_location.caption_text = ""; - curClip = 0; - $("#makeclip").val("Make Clip"); - - } else { - for (var i in clips) { - if (time < clips[i].inTimeMilli && clips[parseInt(i)-1] == undefined) { - //first space - this_location.name = "Space before Clip 1"; - - asterisk = "#space0"; - - if (!temp_in) { - this_location.inTimeMilli = 0; - this_location.inTime = getFormattedTime2(this_location.inTimeMilli); - } - if (!temp_out) { - this_location.outTimeMilli = parseInt(clips[i].inTimeMilli)-1; - this_location.outTime = getFormattedTime2(this_location.outTimeMilli); - } - - this_location.caption_text = ""; - curClip = 0; - $("#makeclip").val("Make Clip"); - - break; - } else if ( (clips[parseInt(i)+1] == undefined || time < clips[parseInt(i)+1].inTimeMilli) && time > clips[i].outTimeMilli) { - - //space - this_location.name = "Space after Clip "+ parseInt(parseInt(i)+1); - - if (!temp_in) { - this_location.inTimeMilli = clips[i].outTimeMilli+1; - this_location.inTime = getFormattedTime2(this_location.inTimeMilli); - } - - if (!temp_out) { - if (clips[parseInt(i)+1] == undefined) - this_location.outTimeMilli = dur; - else - this_location.outTimeMilli = clips[parseInt(i)+1].inTimeMilli-1; - - this_location.outTime = getFormattedTime2(this_location.outTimeMilli); - } - - this_location.caption_text = ""; - curClip = parseInt(i)+1; - asterisk = "#space"+curClip; - - $("#makeclip").val("Make Clip"); - - break; - } else if (time >= clips[i].inTimeMilli && time <= clips[i].outTimeMilli) { - //clip - curClip = parseInt(i)+1; - this_location = clips[i]; - inClip = true; - $("#makeclip").val("Update Clip"); - - asterisk = "#clip"+curClip; - break; - } else { - //console.log("skipping this one", i, clips[i].inTimeMilli, clips[i].outTimeMilli); - } - } - } - - // 'you are here' asterisk - $("#space"+lastLoc).text(""); - $("#clip"+lastLoc).text(""); - - $(asterisk).html(" current space"); - - // in and out times - if (!temp_in) - $("#in-time").text(this_location.inTime); - if (!temp_out) - $("#out-time").text(this_location.outTime); - - //duration - this_location.durationMilli = this_location.outTimeMilli - this_location.inTimeMilli; - this_location.duration = getFormattedTime2(this_location.durationMilli); - $("#clip-duration").text(this_location.duration); - - - // moved into a different clip or space - if ($("#clip-name").text() != this_location.name || (new_flag && !temp_in && !temp_out && !temp_caps)) { - - //caption text - $("#caption-text").val(this_location.caption_text); - - // user was working on a new clip but it gets reset when moving out of current clip - if (temp_in || temp_out || temp_caps) { - resetClipWork(); - } - - //move scroll bar to clip - if (curClip>2) - $("#info-tab").scrollTop(curClip*70); - else - $("#info-tab").scrollTop(0); - - // update the clip timeline and move the playhead - setClipTimeline(this_location.durationMilli, this_location.inTimeMilli, this_location.outTimeMilli); - } - - // name - $("#clip-name").text(this_location.name); -} -/*************************************** movie controller buttons */ - -movie.normPlay = function() { - if ($("#playButton").attr("src") == "images/play.png") { - movieObj.Play(); - $("#playButton").attr("src", 'images/pause.png'); - $("#clip-playButton").attr("src", 'images/pause.png'); - - } else { - movie.pressStop(); - } -} - -movie.pressPlay = function() { - movieObj.Play(); - $("#pressButton").attr("src", 'images/pause.png'); -} -movie.pressStop = function() { - movieObj.Stop(); - $("#playButton").attr("src", 'images/play.png'); - $("#clip-playButton").attr("src", 'images/play.png'); - - $("#pressButton").attr("src", 'images/pressplay.png'); -} - - -/*************************************** clip controller buttons */ - -clip.normPlay = function() { - if ($("#clip-playButton").attr("src") == "images/play.png") { - lastplay = curTime; - movieObj.Play(); - $("#clip-playButton").attr("src", 'images/pause.png'); - $("#playButton").attr("src", 'images/pause.png'); - clip_playing = true; - } else { - clip.pressStop(); - } -} - -clip.pressPlay = function() { - lastplay = curTime; - moveMovie(curTime); - movieObj.Play(); - $("#clip-pressButton").attr("src", 'images/pause.png'); - clip_playing = true; -} -clip.pressStop = function() { - movieObj.Stop(); - var max = $("#c_timeline").slider("option", "max"); - if (curTime > max) - moveMovie(max-1000); - - $("#clip-playButton").attr("src", 'images/play.png'); - $("#playButton").attr("src", 'images/play.png'); - $("#clip-pressButton").attr("src", 'images/pressplay.png'); - clip_playing = false; -} - -function getIndex( myarray, item ) { - for (var i=0; i 1) { - //go to prev space (prev clip's out time +1) - if (clips[curClip-2].outTimeMilli+1 != clips[curClip-1].inTimeMilli) { - moveMovieAll(clips[curClip-2].outTimeMilli+1); - - //if no space, go to prev clip - } else { - moveMovieAll(clips[curClip-2].inTimeMilli); - } - - //if in a space, go to prev clip - } else if (!inClip && curClip>0) { - moveMovieAll(clips[curClip-1].inTimeMilli); - //if in first space or clip, go to start - } else { - moveMovieAll(0); - } -} -clip.next = function() { - //if in a clip - if (inClip && clips[curClip] != undefined) { - - //go to next space (next clip's out time +1) - if (clips[curClip].inTimeMilli != clips[curClip-1].outTimeMilli+1) { - moveMovieAll(clips[curClip-1].outTimeMilli+1); - - //if no space, go to next clip - } else { - moveMovieAll(clips[curClip].inTimeMilli); - } - - //if in a space, go to next clip - } else if (!inClip && clips[curClip] != undefined) { - moveMovieAll(clips[curClip].inTimeMilli); - - //if at the end - } else if (clips[clips.length-1] != undefined) { - if (clips[clips.length-1].outTimeMilli == dur) - moveMovieAll(clips[clips.length-1].inTimeMilli); - else - moveMovieAll(clips[clips.length-1].outTimeMilli+1); - } - -} - -clip.goToStart = function() { - moveMovieAll(getMilliseconds($("#in-time").text())); -} -clip.goToEnd = function() { - moveMovieAll(getMilliseconds($("#out-time").text())); -} -clip.stepBack = function(step) { - if (curTime >= step && (curTime-step >= getMilliseconds($("#in-time").text())) ) - moveMovieAll(curTime - step); -} -clip.stepForward = function(step) { - if ( curTime+step <= getMilliseconds($("#out-time").text()) ) - moveMovieAll(curTime + step); -} - -clip.lastPlay = function() { - moveMovieAll(lastplay); -} - -/*************** making a clip */ - -clip.newInTime = function() { - var clip_dur = 0; - clip_dur = this_location.outTimeMilli-curTime; - if (clip_dur <= MIN_CLIP_DUR) { - alert("Too few frames to make a clip!"); - } else { - $("#in").css("color","red"); - $("#in-time").css("color","red"); - $("#clip-duration").css("color","red"); - $("#makeclip").removeAttr("disabled"); - $("#clip-duration").text(getFormattedTime2(clip_dur)); - - //old_in = getMilliseconds($("#in-time").text()); - - temp_in = getFormattedTime2(curTime); - $("#in-time").text(temp_in); - - setClipTimeline(clip_dur, curTime, this_location.outTimeMilli); - moveMovieAll(curTime); - - /*if (new_flag) - $("#in-undo").html("cancel in-time"); - else if (inAClip()) - $("#in-undo").html("cancel in-time"); - else - $("#in-undo").html("cancel in-time"); - */ - } -} - - -clip.newOutTime = function() { - if (curTime != getMilliseconds($("#out-time").text())) { - var clip_dur = 0; - - if (temp_in) { - clip_dur = curTime-getMilliseconds(temp_in); - } else { - clip_dur = curTime-getMilliseconds($("#in-time").text()); - } - - if (clip_dur <= MIN_CLIP_DUR) { - alert("Too few frames to make a clip!"); - } else { - - $("#out").css("color","red"); - $("#out-time").css("color","red"); - $("#clip-duration").css("color","red"); - $("#makeclip").removeAttr("disabled"); - $("#clip-duration").text(getFormattedTime2(clip_dur)); - - temp_out = getFormattedTime2(curTime); - $("#out-time").text(temp_out); - - setClipTimeline(curTime - getMilliseconds($("#in-time").text()), getMilliseconds($("#in-time").text()), curTime); - moveMovieAll(curTime); - - /*if (new_flag) - $("#out-undo").html("cancel out-time"); - else if (inAClip()) - $("#out-undo").html("cancel out-time"); - else - $("#out-undo").html("cancel out-time"); - */ - } - } -} - -clip.addPrevSpace = function() { - - //if the current clip's inTime is > 0 and also not equal to the prev clip's outTime - if (inClip && clips[curClip-1].inTimeMilli > 0 && ( clips[curClip-2]==undefined || clips[curClip-1].inTimeMilli != clips[curClip-2].outTimeMilli) ) { - - var newin = 0; - - //make clip start = last clip's end - if (clips[curClip-2] != undefined) { - newin = clips[curClip-2].outTimeMilli + 1; - } else { - newin = 0; - } - temp_in = getFormattedTime2(newin); - var oldout = getMilliseconds($("#out-time").text()) - var caption_text = $("#caption-text").val(); - - //set new temp values - $("#in-time").css("color","red"); - $("#in-time").text(temp_in); - - $("#clip-duration").css("color","red"); - $("#makeclip").removeAttr("disabled"); - $("#makeclip").val("Update Clip"); - - //$("#caption-text").val(caption_text); - $("#clip-duration").text(getFormattedTime2(oldout - newin)); - - extend = true; - setClipTimeline(oldout - newin, newin, oldout); - moveMovieAll(curTime); - //$("#in-undo").html("cancel in-time"); - } -} - -clip.addNextSpace = function() { - - if (inClip && clips[curClip-1].outTimeMilli < dur && (clips[curClip]==undefined || clips[curClip-1].outTimeMilli != clips[curClip].inTimeMilli)) { - var newout = 0; - //make clip start = last clip's end - if (clips[curClip] != undefined) { - newout = clips[curClip].inTimeMilli - 1; - } else { - newout = dur; - } - temp_out = getFormattedTime2(newout); - - var oldin = getMilliseconds($("#in-time").text()) - var caption_text = $("#caption-text").val(); - - //set new temp values - $("#out-time").css("color","red"); - $("#out-time").text(temp_out); - - $("#clip-duration").css("color","red"); - $("#makeclip").removeAttr("disabled"); - $("#makeclip").val("Update Clip"); - - //$("#caption-text").val(caption_text); - $("#clip-duration").text(getFormattedTime2(newout - oldin)); - - extend = true; - setClipTimeline(newout - oldin, oldin, newout); - moveMovieAll(curTime); - //$("#out-undo").html("cancel out-time"); - } -} - -/****** making/updating and saving clips **/ - -movie.saveClip = function() { - var caption_text = $("#caption-text").val(); - var clipnum = 0; - - // button should be disabled but double check that at least one time has changed, or caption text has changed - //if (temp_in || temp_out) { - resetClipWork(); - - if (!temp_in) { - temp_in = $("#in-time").text(); - } - if (!temp_out) { - temp_out = $("#out-time").text(); - } - - this_location.inTime = temp_in; - this_location.outTime = temp_out; - this_location.inTimeMilli = getMilliseconds(temp_in); - this_location.outTimeMilli = getMilliseconds(temp_out); - - this_location.durationMilli = this_location.outTimeMilli - this_location.inTimeMilli; - this_location.duration = getFormattedTime2(this_location.durationMilli); - this_location.caption_text = caption_text; - - if($("#makeclip").val() == "Make Clip") { - num_clips++; - - if (num_clips > 0) { - //add to clips list - clips[num_clips-1] = this_location; - - //sort clips by inTimeMilli - clips.sort(function (a,b) { return a.inTimeMilli-b.inTimeMilli}); - - } else { - clips = new Array(); //clips - clips[0] = this_location; - - new_flag = 0; - } - } else { - clips[curClip-1] = this_location; - } - - //loadClips(); - - var move_to = getMilliseconds(temp_out) + 1; - if (move_to < (dur - MIN_CLIP_DUR) ) { - setTimeout("moveMovieAll("+move_to+")", 500); - } else { - setTimeout("moveMovie(curTime)", 500); - } - - - temp_in = ''; - temp_out = ''; - - saveJson(); - //} -} - -function deleteClip(clipnum) { - num_clips--; - clips.splice(clipnum-1, 1); - saveJson(); -} - -function saveJson() { - //save file - json = JSON.stringify(proj); - - $.post("include/workflow.php", { task: 'save_json', json:json, pid:proj.id }, function(data) { - if (!data) { - loadClips(); - } else { - alert(data); - } - - } ); - - var d = new Date(); - - var curr_hour = d.getHours(); - var curr_min = d.getMinutes(); - - $("#last-saved").text('Last saved at '+curr_hour + ":" + ((curr_min < 10) ? "0" : "") + curr_min); -} - -/****************reset UI */ - -function resetClipWork() { - $("#in").css("color","black"); - $("#out").css("color","black"); - $("#in-time").css("color","black"); - $("#out-time").css("color","black"); - $("#clip-duration").css("color","black"); - temp_in = 0; - temp_out = 0; - temp_caps = ''; - - extend = false; - $("#makeclip").attr("disabled","disabled"); - $("#in-undo").html(""); - $("#out-undo").html(""); - -} - - diff --git a/mods/atutor_opencaps/opencaps/js/export.js b/mods/atutor_opencaps/opencaps/js/export.js deleted file mode 100755 index e81e01fa7..000000000 --- a/mods/atutor_opencaps/opencaps/js/export.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * OpenCaps - * http://opencaps.atrc.utoronto.ca - * - * Copyright 2009 Heidi Hazelton - * Adaptive Technology Resource Centre, University of Toronto - * - * Licensed under the Educational Community License (ECL), Version 2.0. - * You may not use this file except in compliance with this License. - * http://www.opensource.org/licenses/ecl2.php - * - */ - -$(document).ready(function () { - $("#export-tab").addClass('current'); -}); - -function set_format(chosen_format) { - document.forms[0].format.value = chosen_format; - document.forms[0].submit() ; -} \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/js/index.html b/mods/atutor_opencaps/opencaps/js/index.html deleted file mode 100755 index e69de29bb..000000000 diff --git a/mods/atutor_opencaps/opencaps/js/jquery/GPL-LICENSE.txt b/mods/atutor_opencaps/opencaps/js/jquery/GPL-LICENSE.txt deleted file mode 100755 index 11dddd00e..000000000 --- a/mods/atutor_opencaps/opencaps/js/jquery/GPL-LICENSE.txt +++ /dev/null @@ -1,278 +0,0 @@ - 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/mods/atutor_opencaps/opencaps/js/jquery/MIT-LICENSE.txt b/mods/atutor_opencaps/opencaps/js/jquery/MIT-LICENSE.txt deleted file mode 100755 index 965a83130..000000000 --- a/mods/atutor_opencaps/opencaps/js/jquery/MIT-LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -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/mods/atutor_opencaps/opencaps/js/jquery/jARIA.js b/mods/atutor_opencaps/opencaps/js/jquery/jARIA.js deleted file mode 100755 index cd4868646..000000000 --- a/mods/atutor_opencaps/opencaps/js/jquery/jARIA.js +++ /dev/null @@ -1 +0,0 @@ -(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/mods/atutor_opencaps/opencaps/js/jquery/jquery-1.2.3.js b/mods/atutor_opencaps/opencaps/js/jquery/jquery-1.2.3.js deleted file mode 100755 index 5899bd415..000000000 --- a/mods/atutor_opencaps/opencaps/js/jquery/jquery-1.2.3.js +++ /dev/null @@ -1 +0,0 @@ -(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=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-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]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">"});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
    "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
    ","
    "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--){div=div.lastChild}if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=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*",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 im[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=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=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=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=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("
    ").append(res.responseText.replace(//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;ithis.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/mods/atutor_opencaps/opencaps/js/jquery/jquery-1.2.6.js b/mods/atutor_opencaps/opencaps/js/jquery/jquery-1.2.6.js deleted file mode 100755 index 88e661eec..000000000 --- a/mods/atutor_opencaps/opencaps/js/jquery/jquery-1.2.6.js +++ /dev/null @@ -1,3549 +0,0 @@ -(function(){ -/* - * jQuery 1.2.6 - New Wave Javascript - * - * Copyright (c) 2008 John Resig (jquery.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $ - * $Rev: 5685 $ - */ - -// Map over jQuery in case of overwrite -var _jQuery = window.jQuery, -// Map over the $ in case of overwrite - _$ = window.$; - -var jQuery = window.jQuery = window.$ = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context ); -}; - -// A simple way to check for HTML strings or ID strings -// (both of which we optimize for) -var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/, - -// Is it a simple selector - isSimple = /^.[^:#\[\.]*$/, - -// Will speed up references to undefined, and allows munging its name. - undefined; - -jQuery.fn = jQuery.prototype = { - init: function( selector, context ) { - // Make sure that a selection was provided - selector = selector || document; - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this[0] = selector; - this.length = 1; - return this; - } - // Handle HTML strings - if ( typeof selector == "string" ) { - // Are we dealing with HTML string or an ID? - var match = quickExpr.exec( selector ); - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) - selector = jQuery.clean( [ match[1] ], context ); - - // HANDLE: $("#id") - else { - var elem = document.getElementById( match[3] ); - - // Make sure an element was located - if ( elem ){ - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id != match[3] ) - return jQuery().find( selector ); - - // Otherwise, we inject the element directly into the jQuery object - return jQuery( elem ); - } - selector = []; - } - - // HANDLE: $(expr, [context]) - // (which is just equivalent to: $(content).find(expr) - } else - return jQuery( context ).find( selector ); - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) - return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector ); - - return this.setArray(jQuery.makeArray(selector)); - }, - - // The current version of jQuery being used - jquery: "1.2.6", - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - // The number of elements contained in the matched element set - length: 0, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == undefined ? - - // Return a 'clean' array - jQuery.makeArray( this ) : - - // Return just the object - this[ num ]; - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - // Build a new jQuery matched element set - var ret = jQuery( elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - // Return the newly-formed element set - return ret; - }, - - // Force the current matched set of elements to become - // the specified array of elements (destroying the stack in the process) - // You should use pushStack() in order to do this, but maintain the stack - setArray: function( elems ) { - // Resetting the length to 0, then using the native Array push - // is a super-fast way to populate an object with array-like properties - this.length = 0; - Array.prototype.push.apply( this, elems ); - - return this; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - var ret = -1; - - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem && elem.jquery ? elem[0] : elem - , this ); - }, - - attr: function( name, value, type ) { - var options = name; - - // Look for the case where we're accessing a style value - if ( name.constructor == String ) - if ( value === undefined ) - return this[0] && jQuery[ type || "attr" ]( this[0], name ); - - else { - options = {}; - options[ name ] = value; - } - - // Check to see if we're setting style values - return this.each(function(i){ - // Set all the styles - for ( name in options ) - jQuery.attr( - type ? - this.style : - this, - name, jQuery.prop( this, options[ name ], type, i, name ) - ); - }); - }, - - css: function( key, value ) { - // ignore negative width and height values - 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] ) - // The elements to wrap the target around - 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 ) { - // Do the clone - var ret = this.map(function(){ - if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) { - // IE copies events bound via attachEvent when - // using cloneNode. Calling detachEvent on the - // clone will also remove the events from the orignal - // In order to get around this, we use innerHTML. - // Unfortunately, this means some modifications to - // attributes in IE that are actually only stored - // as properties will not be copied (such as the - // the name attribute on an input). - var clone = this.cloneNode(true), - container = document.createElement("div"); - container.appendChild(clone); - return jQuery.clean([container.innerHTML])[0]; - } else - return this.cloneNode(true); - }); - - // Need to set the expando to null on the cloned set if it exists - // removeData doesn't work here, IE removes it from the original as well - // this is primarily for IE but the data expando shouldn't be copied over in any browser - var clone = ret.find("*").andSelf().each(function(){ - if ( this[ expando ] != undefined ) - this[ expando ] = null; - }); - - // Copy the events from the original to the clone - 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 the cloned set - 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 ) - // test special case where just one selector is passed in - 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 this.pushStack( jQuery.unique( jQuery.merge( - this.get(), - typeof selector == 'string' ? - jQuery( selector ) : - jQuery.makeArray( selector ) - ))); - }, - - is: function( selector ) { - return !!selector && jQuery.multiFilter( selector, this ).length > 0; - }, - - hasClass: function( selector ) { - return this.is( "." + selector ); - }, - - val: function( value ) { - if ( value == undefined ) { - - if ( this.length ) { - var elem = this[0]; - - // We need to handle select boxes special - if ( jQuery.nodeName( elem, "select" ) ) { - var index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type == "select-one"; - - // Nothing was selected - if ( index < 0 ) - return null; - - // Loop through all the selected options - for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { - var option = options[ i ]; - - if ( option.selected ) { - // Get the specifc value for the option - value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value; - - // We don't need an array for one selects - if ( one ) - return value; - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - - // Everything else, we just grab the value - } else - return (this[0].value || "").replace(/\r/g, ""); - - } - - return undefined; - } - - if( value.constructor == Number ) - value += ''; - - 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 = jQuery.makeArray(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[0] ? - 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 === undefined ) { - var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); - - if ( data === undefined && this.length ) - data = jQuery.data( this[0], key ); - - return data === undefined && 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; - - // execute all scripts after the elements have been injected - if ( jQuery.nodeName( elem, "script" ) ) - scripts = scripts.add( elem ); - else { - // Remove any inner scripts for later evaluation - if ( elem.nodeType == 1 ) - scripts = scripts.add( jQuery( "script", elem ).remove() ); - - // Inject the elements into the document - callback.call( obj, elem ); - } - }); - - scripts.each( evalScript ); - }); - } -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -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 ); -} - -function now(){ - return +new Date; -} - -jQuery.extend = jQuery.fn.extend = function() { - // copy reference to target object - var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; - - // Handle a deep copy situation - if ( target.constructor == Boolean ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target != "object" && typeof target != "function" ) - target = {}; - - // extend jQuery itself if only one argument is passed - if ( length == i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) - // Extend the base object - for ( var name in options ) { - var src = target[ name ], copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) - continue; - - // Recurse if we're merging object values - if ( deep && copy && typeof copy == "object" && !copy.nodeType ) - target[ name ] = jQuery.extend( deep, - // Never move original objects, clone them - src || ( copy.length != null ? [ ] : { } ) - , copy ); - - // Don't bring in undefined values - else if ( copy !== undefined ) - target[ name ] = copy; - - } - - // Return the modified object - return target; -}; - -var expando = "jQuery" + now(), uuid = 0, windowData = {}, - // exclude the following css properties to add px - exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i, - // cache defaultView - defaultView = document.defaultView || {}; - -jQuery.extend({ - noConflict: function( deep ) { - window.$ = _$; - - if ( deep ) - window.jQuery = _jQuery; - - return jQuery; - }, - - // See test/unit/core.js for details concerning this function. - isFunction: function( fn ) { - return !!fn && typeof fn != "string" && !fn.nodeName && - fn.constructor != Array && /^[\s[]?function/.test( fn + "" ); - }, - - // check if an element is in a (or is an) XML document - isXMLDoc: function( elem ) { - return elem.documentElement && !elem.body || - elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; - }, - - // Evalulates a script in a global context - globalEval: function( data ) { - data = jQuery.trim( data ); - - if ( data ) { - // Inspired by code by Andrea Giammarchi - // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html - 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 ) ); - - // Use insertBefore instead of appendChild to circumvent an IE6 bug. - // This arises when a base node is used (#2709). - head.insertBefore( script, head.firstChild ); - 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 ]; - - // Compute a unique ID for the element - if ( !id ) - id = elem[ expando ] = ++uuid; - - // Only generate the data cache if we're - // trying to access or manipulate it - if ( name && !jQuery.cache[ id ] ) - jQuery.cache[ id ] = {}; - - // Prevent overriding the named cache with undefined values - if ( data !== undefined ) - jQuery.cache[ id ][ name ] = data; - - // Return the named cache data, or the ID for the element - return name ? - jQuery.cache[ id ][ name ] : - id; - }, - - removeData: function( elem, name ) { - elem = elem == window ? - windowData : - elem; - - var id = elem[ expando ]; - - // If we want to remove a specific section of the element's data - if ( name ) { - if ( jQuery.cache[ id ] ) { - // Remove the section of cache data - delete jQuery.cache[ id ][ name ]; - - // If we've removed all the data, remove the element's cache - name = ""; - - for ( name in jQuery.cache[ id ] ) - break; - - if ( !name ) - jQuery.removeData( elem ); - } - - // Otherwise, we want to remove all of the element's data - } else { - // Clean up the element expando - try { - delete elem[ expando ]; - } catch(e){ - // IE has trouble directly removing the expando - // but it's ok with using removeAttribute - if ( elem.removeAttribute ) - elem.removeAttribute( expando ); - } - - // Completely remove the data cache - delete jQuery.cache[ id ]; - } - }, - - // args is for internal usage only - each: function( object, callback, args ) { - var name, i = 0, length = object.length; - - if ( args ) { - if ( length == undefined ) { - for ( name in object ) - if ( callback.apply( object[ name ], args ) === false ) - break; - } else - for ( ; i < length; ) - if ( callback.apply( object[ i++ ], args ) === false ) - break; - - // A special, fast, case for the most common use of each - } else { - if ( length == undefined ) { - for ( name in object ) - if ( callback.call( object[ name ], name, object[ name ] ) === false ) - break; - } else - for ( var value = object[0]; - i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} - } - - return object; - }, - - prop: function( elem, value, type, i, name ) { - // Handle executable functions - if ( jQuery.isFunction( value ) ) - value = value.call( elem, i ); - - // Handle passing in a number to a CSS property - return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ? - value + "px" : - value; - }, - - className: { - // internal only, use addClass("class") - 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; - }); - }, - - // internal only, use removeClass("class") - 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(" ") : - ""; - }, - - // internal only, use hasClass("class") - has: function( elem, className ) { - return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; - } - }, - - // A method for quickly swapping in/out CSS properties to get correct calculations - swap: function( elem, options, callback ) { - var old = {}; - // Remember the old values, and insert the new ones - for ( var name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - callback.call( elem ); - - // Revert the old values - 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, style = elem.style; - - // A helper method for determining if an element's values are broken - function color( elem ) { - if ( !jQuery.browser.safari ) - return false; - - // defaultView is cached - var ret = defaultView.getComputedStyle( elem, null ); - return !ret || ret.getPropertyValue("color") == ""; - } - - // We need to handle opacity special in IE - if ( name == "opacity" && jQuery.browser.msie ) { - ret = jQuery.attr( style, "opacity" ); - - return ret == "" ? - "1" : - ret; - } - // Opera sometimes will give the wrong display answer, this fixes it, see #2037 - if ( jQuery.browser.opera && name == "display" ) { - var save = style.outline; - style.outline = "0 solid black"; - style.outline = save; - } - - // Make sure we're using the right name for getting the float value - if ( name.match( /float/i ) ) - name = styleFloat; - - if ( !force && style && style[ name ] ) - ret = style[ name ]; - - else if ( defaultView.getComputedStyle ) { - - // Only "float" is needed here - if ( name.match( /float/i ) ) - name = "float"; - - name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); - - var computedStyle = defaultView.getComputedStyle( elem, null ); - - if ( computedStyle && !color( elem ) ) - ret = computedStyle.getPropertyValue( name ); - - // If the element isn't reporting its values properly in Safari - // then some display: none elements are involved - else { - var swap = [], stack = [], a = elem, i = 0; - - // Locate all of the parent display: none elements - for ( ; a && color(a); a = a.parentNode ) - stack.unshift(a); - - // Go through and make them visible, but in reverse - // (It would be better if we knew the exact display type that they had) - for ( ; i < stack.length; i++ ) - if ( color( stack[ i ] ) ) { - swap[ i ] = stack[ i ].style.display; - stack[ i ].style.display = "block"; - } - - // Since we flip the display style, we have to handle that - // one special, otherwise get the value - ret = name == "display" && swap[ stack.length - 1 ] != null ? - "none" : - ( computedStyle && computedStyle.getPropertyValue( name ) ) || ""; - - // Finally, revert the display styles back - for ( i = 0; i < swap.length; i++ ) - if ( swap[ i ] != null ) - stack[ i ].style.display = swap[ i ]; - } - - // We should always get a number back from opacity - 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 ]; - - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { - // Remember the original values - var left = style.left, rsLeft = elem.runtimeStyle.left; - - // Put in the new values to get a computed value out - elem.runtimeStyle.left = elem.currentStyle.left; - style.left = ret || 0; - ret = style.pixelLeft + "px"; - - // Revert the changed values - style.left = left; - elem.runtimeStyle.left = rsLeft; - } - } - - return ret; - }, - - clean: function( elems, context ) { - var ret = []; - context = context || document; - // !context.createElement fails in IE with an error but returns typeof 'object' - 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 += ''; - - // Convert html string into DOM nodes - if ( typeof elem == "string" ) { - // Fix "XHTML"-style tags in all browsers - 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 + ">"; - }); - - // Trim whitespace, otherwise indexOf won't work as expected - var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div"); - - var wrap = - // option or optgroup - !tags.indexOf("", "" ] || - - !tags.indexOf("", "" ] || - - tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && - [ 1, "", "
    " ] || - - !tags.indexOf("", "" ] || - - // matched above - (!tags.indexOf("", "" ] || - - !tags.indexOf("", "" ] || - - // IE can't serialize and - - -

    Login

    - -

    To start a new captioning project or to return to an ongoing project, please login below. If you are new here, quickly register with us!

    - - -
    - -

    Capscribe logo

    - -
    -
    -
    -
    -
    -
    -
    - -
    -
    - - - \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/logout.php b/mods/atutor_opencaps/opencaps/logout.php deleted file mode 100755 index 777b50cac..000000000 --- a/mods/atutor_opencaps/opencaps/logout.php +++ /dev/null @@ -1,32 +0,0 @@ - \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/preview.php b/mods/atutor_opencaps/opencaps/preview.php deleted file mode 100755 index 79700d8b0..000000000 --- a/mods/atutor_opencaps/opencaps/preview.php +++ /dev/null @@ -1,45 +0,0 @@ - - - - -
    -
    -
    - -
    - - -
    -

    Layout Presets

    -
    -
    -
    -

    -
    -
    -
    -
    - -
    - diff --git a/mods/atutor_opencaps/opencaps/projects/12-d0679f0984ba38ffc572d0d9718091d37059d5b6/opencaps.json b/mods/atutor_opencaps/opencaps/projects/12-d0679f0984ba38ffc572d0d9718091d37059d5b6/opencaps.json deleted file mode 100755 index 2f8a98a21..000000000 --- a/mods/atutor_opencaps/opencaps/projects/12-d0679f0984ba38ffc572d0d9718091d37059d5b6/opencaps.json +++ /dev/null @@ -1 +0,0 @@ -{"id":"12-d0679f0984ba38ffc572d0d9718091d37059d5b6","name":"ttttttttttt","media_loc":"http://localhost/php/_myphp/__phpOO/ATutor_Devel/_at2/ATutor/content/1/antoOC/movie1.mov","media_height":"182","media_width":"287","duration":"00:00:26.693","caption_loc":null,"clip_collection":{"clips":[],"global_caption_styles":[]},"layout":null,"owner":{"id":"99999","username":"guest","name":null,"preferences":[],"valid":false}} \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/projects/3-d0679f0984ba38ffc572d0d9718091d37059d5b6/opencaps.json b/mods/atutor_opencaps/opencaps/projects/3-d0679f0984ba38ffc572d0d9718091d37059d5b6/opencaps.json deleted file mode 100755 index a1efe7484..000000000 --- a/mods/atutor_opencaps/opencaps/projects/3-d0679f0984ba38ffc572d0d9718091d37059d5b6/opencaps.json +++ /dev/null @@ -1 +0,0 @@ -{"id":"3-d0679f0984ba38ffc572d0d9718091d37059d5b6","name":"sdfsdf","media_loc":"http://localhost/php/_myphp/__phpOO/ATutor_Devel/_at2/ATutor/content/1/ram40.mov","media_height":"150","media_width":"272","duration":"00:03:03.125","caption_loc":null,"clip_collection":{"clips":[{"inTime":"00:00:00.000","outTime":"00:00:23.196","duration":"00:00:23.196","inTimeMilli":0,"outTimeMilli":23196,"durationMilli":23196,"caption_text":"ok lang is oku000alove yoy php.flash","captionStyles":[],"name":"Clip 1"},{"inTime":"00:00:29.594","outTime":"00:01:40.218","duration":"00:01:10.624","inTimeMilli":29594,"outTimeMilli":100218,"durationMilli":70624,"caption_text":"adfsdafsda","captionStyles":[],"name":"Clip 2"},{"inTime":"00:01:46.299","outTime":"00:02:06.786","duration":"00:00:20.487","inTimeMilli":106299,"outTimeMilli":126786,"durationMilli":20487,"caption_text":"afdsfs","captionStyles":[],"name":"Clip 3"}],"global_caption_styles":[]},"layout":null,"owner":{"id":"99999","username":"guest","name":null,"preferences":[],"valid":false}} \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/projects/index.html b/mods/atutor_opencaps/opencaps/projects/index.html deleted file mode 100755 index 6a2361656..000000000 --- a/mods/atutor_opencaps/opencaps/projects/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/projects/layouts/smil_0.mov b/mods/atutor_opencaps/opencaps/projects/layouts/smil_0.mov deleted file mode 100755 index ad736151b..000000000 --- a/mods/atutor_opencaps/opencaps/projects/layouts/smil_0.mov +++ /dev/null @@ -1 +0,0 @@ -SMILtext [region="captionregion"] {background-color:black; } \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/projects/layouts/smil_1.mov b/mods/atutor_opencaps/opencaps/projects/layouts/smil_1.mov deleted file mode 100755 index 857886520..000000000 --- a/mods/atutor_opencaps/opencaps/projects/layouts/smil_1.mov +++ /dev/null @@ -1 +0,0 @@ -SMILtext \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/projects/layouts/smil_2.mov b/mods/atutor_opencaps/opencaps/projects/layouts/smil_2.mov deleted file mode 100755 index 6bd201209..000000000 --- a/mods/atutor_opencaps/opencaps/projects/layouts/smil_2.mov +++ /dev/null @@ -1 +0,0 @@ -SMILtext \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/projects/opencaps.json b/mods/atutor_opencaps/opencaps/projects/opencaps.json deleted file mode 100755 index 0e4bc21d7..000000000 --- a/mods/atutor_opencaps/opencaps/projects/opencaps.json +++ /dev/null @@ -1 +0,0 @@ -{"id":"3-d0679f0984ba38ffc572d0d9718091d37059d5b6","name":"sdfsdf","media_loc":"http://localhost/php/_myphp/__phpOO/ATutor_Devel/_at2/ATutor/content/1/ram40.mov","media_height":"165","media_width":"283","duration":"00:03:03.125","caption_loc":null,"clip_collection":{"clips":[{"inTime":"00:00:00.000","outTime":"00:00:23.196","duration":"00:00:23.196","inTimeMilli":0,"outTimeMilli":23196,"durationMilli":23196,"caption_text":"ok lang is ok","captionStyles":[]},{"inTime":"00:00:29.594","outTime":"00:01:40.218","duration":"00:01:10.624","inTimeMilli":29594,"outTimeMilli":100218,"durationMilli":70624,"caption_text":"adfsdafsda","captionStyles":[]},{"inTime":"00:01:46.299","outTime":"00:02:06.786","duration":"00:00:20.487","inTimeMilli":106299,"outTimeMilli":126786,"durationMilli":20487,"caption_text":"afdsfs","captionStyles":[]}],"global_caption_styles":[]},"layout":null,"owner":{"id":"99999","username":"guest","name":null,"preferences":[],"valid":false}} \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/projects/player_template.php b/mods/atutor_opencaps/opencaps/projects/player_template.php deleted file mode 100755 index 1dc333d4d..000000000 --- a/mods/atutor_opencaps/opencaps/projects/player_template.php +++ /dev/null @@ -1,106 +0,0 @@ - - - - -Capscribe Movies - - - - - - - - - - - - - - - - - - - - - -
    - -
    - - - - \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/register.php b/mods/atutor_opencaps/opencaps/register.php deleted file mode 100755 index aee8144c8..000000000 --- a/mods/atutor_opencaps/opencaps/register.php +++ /dev/null @@ -1,125 +0,0 @@ -db); - - if (!$result) { - $_SESSION['errors'][] = 'Database error - user not added.'; - } else { - //send email to registrant - - $_SESSION['feedback'][] = 'Registration successful. Please login.'; - header('Location: index.php'); - exit; - } - } -} - -require('include/basic_header.inc.php'); ?> - - - -

    Register

    -

    Create a new account with OpenCaps.

    - -
    - -
    -
    -
    -
    -


    - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - - - diff --git a/mods/atutor_opencaps/opencaps/scripts/install.sh b/mods/atutor_opencaps/opencaps/scripts/install.sh deleted file mode 100755 index d3c2e2597..000000000 --- a/mods/atutor_opencaps/opencaps/scripts/install.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh - -# apache, php5, mysql5 -echo "============================" -echo "==Installing Apache, PHP, and MySql==" -echo "============================" -sudo apt-get -y update -sudo apt-get -y install apache2 php5 curl libcurl3 libcurl3-dev php5-curl mysql-server php5-mysql #user enters mysql password for root -sudo /etc/init.d/apache2 restart - -# opencaps -echo "============================" -echo "==Installing OpenCaps==" -echo "============================" -echo "Creating database - please enter your mysql root password" -mysqladmin create opencaps -u root -p -cd /var/www/ -sudo wget http://opencaps.atrc.utoronto.ca/releases/opencaps.tar.gz -sudo tar -xvzf opencaps.tar.gz - -cd opencaps -sudo cp install/config_template.php include/config.inc.php -sudo chmod 777 conversion_service/imported -sudo chmod 777 projects -echo "Installing database tables - please enter your mysql root password" -sudo mysql opencaps -u root -p < install/oc_schema.sql -sudo /etc/init.d/mysql start - -# edit opencaps config - -# add mysql info -echo "**** Please enter your mysql root password for the OpenCaps configuration file" -currentstate=`stty -g` -stty -echo -read pass -stty $currentstate -sed -i "s/password/$pass/" include/config.inc.php - -# add matterhorn info -MY_IP=`ifconfig | grep "inet addr:" | grep -v 127.0.0.1 | awk '{print $2}' | cut -d':' -f2` -sed -i 's/?>/\$remote_systems[0][url]="http:\/\/'${MY_IP}':8080";\n?>/' include/config.inc.php -sed -i 's/?>/\$remote_systems[0][name]="Matterhorn";\n?>/' include/config.inc.php - -echo "**** OpenCaps is installed and available at $MY_IP/opencaps" diff --git a/mods/atutor_opencaps/opencaps/scripts/install_remote_only.sh b/mods/atutor_opencaps/opencaps/scripts/install_remote_only.sh deleted file mode 100755 index 72e02bae6..000000000 --- a/mods/atutor_opencaps/opencaps/scripts/install_remote_only.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -# apache, php5, mysql5 -echo "============================" -echo "==Installing Apache, PHP==" -echo "============================" -sudo apt-get -y update -sudo apt-get -y install apache2 php5 curl libcurl3 libcurl3-dev php5-curl -sudo /etc/init.d/apache2 restart - -# opencaps -echo "============================" -echo "==Installing OpenCaps==" -echo "============================" -cd /var/www/ -sudo wget http://opencaps.atrc.utoronto.ca/releases/opencaps.tar.gz -sudo tar -xvzf opencaps.tar.gz -#sudo gzip -dc opencaps.tar.gz | tar xvzf - - -cd opencaps -sudo cp install/config_template.php include/config.inc.php -sudo chmod 777 conversion_service/imported -sudo chmod 777 projects - -# disable local access in config -sudo sed -i "s/\'DISABLE_LOCAL\', \tfalse/\'DISABLE_LOCAL\',\ttrue/g" include/config.inc.php - -# add matterhorn info to config -MY_IP=`ifconfig | grep "inet addr:" | grep -v 127.0.0.1 | awk '{print $2}' | cut -d':' -f2` -sudo sed -i 's/?>/\$remote_systems[0][url]="http:\/\/'${MY_IP}':8080";\n?>/' include/config.inc.php -sudo sed -i 's/?>/\$remote_systems[0][name]="Matterhorn";\n?>/' include/config.inc.php -sudo sed -i 's/?>/\$remote_systems[0][username]="";\n?>/' include/config.inc.php -sudo sed -i 's/?>/\$remote_systems[0][password]="";\n?>/' include/config.inc.php - -echo "**** OpenCaps is installed and available at $MY_IP/opencaps" \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/settings.php b/mods/atutor_opencaps/opencaps/settings.php deleted file mode 100755 index 8ef685ab3..000000000 --- a/mods/atutor_opencaps/opencaps/settings.php +++ /dev/null @@ -1,79 +0,0 @@ -editName($_POST['name']); -} if (isset($_POST['submit-caps'])) { - $this_proj->importCaptions($_FILES['caption_file']); -} - - -require(INCLUDE_PATH.'header.inc.php'); - -?> - - - -
    - -

    Project Settings

    -

    Edit your project's settings here.

    - -
    - -

    Project Name

    -

    name; ?> - (Edit)

    - -
    - New project name: -
    - -

    Captions

    -

    Import caption file

    - -
    -

    Uploading a new caption file will delete all existing captions. Make sure to backup your project (Export Json file) before doing this.

    - Caption File: -
    - - - -
    -

    Coming soon.
    - Upload a new version of your media. The duration of the new media file must match that of the existing media.

    - -
    - - - - -
    -
    - diff --git a/mods/atutor_opencaps/opencaps/start.php b/mods/atutor_opencaps/opencaps/start.php deleted file mode 100755 index 9f9e2db42..000000000 --- a/mods/atutor_opencaps/opencaps/start.php +++ /dev/null @@ -1,155 +0,0 @@ -login($_POST['login'], $_POST['password']); -} - -//valid post -if (isset($_GET['submit']) && $_GET['submit'] && empty($_POST)) { - $_SESSION['errors'][] = "Can't create project. If you uploaded a file, it may be too large."; - -//file size -} else if (isset($_POST['submit_new']) && ($_FILES["media_file"]["error"] == UPLOAD_ERR_INI_SIZE || $_FILES["media_file"]["error"] == UPLOAD_ERR_FORM_SIZE)) { - $_SESSION['errors'][] = "Can't create project. If you uploaded a file, it may be too large."; - -} else if (isset($_POST['submit_new'])) { - $this_proj = new project(); - - //valid URL - if (isset($_POST['media_url']) && !empty($_POST['media_url']) && $_POST['media_url']!="http://") { - $this_ext = explode(".", $_POST['media_url']); - $this_ext = end($this_ext); - - if (!file_get_contents($_POST['media_url']) || !in_array($this_ext, $supported_ext) ) { - $_SESSION['errors'][] = "Invalid URL. Make sure the URL is correct and that the media file is a supported format."; - } else { - $this_proj->createNew($addslashes($_POST['projname']), $_POST['media_url'], $_FILES['caption_file']); - } - } - - //valid file upload - else if (!empty($_FILES['media_file'])) { - $this_ext = explode(".", $_FILES['media_file']['name']); - $this_ext = end($this_ext); - - if (!in_array($this_ext, $supported_ext) ) { - $_SESSION['errors'][] = "Incorrect upload format."; - } else { - $pid = $this_proj->createNew($addslashes($_POST['projname']), $_FILES['media_file'], $_FILES['caption_file']); - } - } - - if (empty($_SESSION['errors'])) - header("Location:editor.php"); -} - -if (intval(ini_get('upload_max_filesize')) < MAX_FILE_SIZE/1048576) - $max = intval(ini_get('upload_max_filesize')); -else - $max = MAX_FILE_SIZE/1048576; - -include(INCLUDE_PATH.'basic_header.inc.php'); - -unset($_SESSION['rid']); - -if ($_SESSION['mid'] == "99999") - unset($_SESSION['mid']); - -?> - - - -

    OpenCaps - a free, online caption editor

    -

    Start Captioning!

    - -
    -
    - -

    Login

    - -

    To start a new captioning project or to return to an ongoing project, please login below. If you are new here, quickly register with us!

    - -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    - -
    -

    New Project

    -

    Begin adding captions to a new video.

    - - asterisk Start New Project -
    - - -
    - - Project Name


    - - Video File
    - URL:
    - or
    - Upload:

    - Max upload size: Mb.
    - Supported formats: .


    - - Caption file (optional)
    -
    - Supported formats: QTtext, DFXP, SubRip, OpenCaps-JSON. - -
    -
    -
    -
    -
    -
    -

    Open Existing Project

    -

    Continue working on a project.

    - asterisk Open Project - -
    -
    -
    -
    -
    -
    - -
    -
    - - - diff --git a/mods/atutor_opencaps/opencaps/start_remote.php b/mods/atutor_opencaps/opencaps/start_remote.php deleted file mode 100755 index d08140c2f..000000000 --- a/mods/atutor_opencaps/opencaps/start_remote.php +++ /dev/null @@ -1,64 +0,0 @@ -start page."; - include(INCLUDE_PATH.'basic_header.inc.php'); - include(INCLUDE_PATH.'footer.inc.php'); - exit; -} - -if (!isset($_SESSION['mid'])) - $_SESSION['mid'] = '99999'; //guest for remote - - -require('include/basic_header.inc.php'); - -?> - - -

    OpenCaps - a free, online caption editor

    - -

    Start captioning! Please select a project to work on:

    - -
    -
    -
    -

    Open Project

    -

    Add captions to a remote project.

    - -
    -
    -
    - -
    - -
    - - - diff --git a/mods/atutor_opencaps/opencaps/styles.css b/mods/atutor_opencaps/opencaps/styles.css deleted file mode 100755 index e8b24afaa..000000000 --- a/mods/atutor_opencaps/opencaps/styles.css +++ /dev/null @@ -1,459 +0,0 @@ -/* capscribe styles */ -html,body{ - height:100%; - width:100%; -} - -body { - height:100%; - width:100%; - - font-family: Helevetica, Arial, sans-serif; - font-size: 75%; - background-color: #dce5f3; - padding:0px; - margin:0px; -} -img { - border:0px; -} - -h1 { - display:inline; - margin:0px; - margin-right:20px; - padding-left:10px; -} - -h3 { - color: #394e6f; -} - -h4 { - display:inline; - height:1em; -} - -#container { - margin:0px auto 0px auto; - padding:0px; - min-width:580px; - - min-height: 97%; - position: relative; - height: auto !important; - height:97%; - background-color: white; - width:780px; - border-left:2px solid #ccc; - border-right:2px solid #ccc; - border-bottom:2px solid #ccc; - -} - -#header { - background-color: #eaeffb; /* #eaeffb #e2f7f7 */ - padding-bottom:5px; -} - -#menubar { - background-color: #b5c3d9; - padding-top:3em; - padding-bottom:3px; - font-weight:bold; - font-size:110%; - /*background-image:url('images/menubar_left.png'); - background-repeat: no-repeat; */ - margin-bottom:5px; -} - -#menubar ul { - margin:0px; - display:inline; - text-align:center; -} -#menubar ul li { - display:inline; - list-style:none; -} - -#menubar a:link, #menubar a:visited { - color: black; - padding-left:10px; - padding-right:10px; - text-decoration:none; -} - -#menubar a:hover, #menubar a:focus { - padding:3px 10px 3px 10px; - width:5em; - background-color: #dce3f7; - color: black; - text-decoration:none; -} -#menubar .current a:link, #menubar .current a:visited { - padding:3px 10px 4px 10px; - width:5em; - background-color: white; - color: black; - text-decoration:none; -} - -#menubar input { - padding:0px; - margin:0px; - margin-top:2px; - margin-right:3px; -} - -/* sub menu bar */ - -#submenubar { - padding-top:5px; - padding-bottom:3px; - font-weight:bold; - /*background-image:url('images/menubar_left.png'); - background-repeat: no-repeat; */ -} - -#submenubar ul { - margin:0px; - margin-left:-30px; - display:inline; -} -#submenubar ul li { - display:inline; - list-style:none; -} - -#submenubar a:link, #submenubar a:visited { - color: black; - background-color:#dce3f7; - padding:3px 10px 4px 10px; -} - -#submenubar a:hover, #submenubar a:focus { - padding:3px 10px 4px 10px; - width:5em; - background-color: #ccc; - color: black; -} -#submenubar .current a:link, #submenubar .current a:visited { - padding:3px 10px 4px 10px; - width:5em; - background-color: #2f51b3; - color: white; -} - -#submenubar input { - padding:0px; - margin:0px; - margin-top:2px; - margin-right:3px; -} - -#info-tab { - overflow: auto; - border: 1px solid #ccc; - height:450px; -} - -#layout { - border: 1px solid #ccc; - border-top: 5px solid #2f51b3; - margin-top:-1px; -} - -h1 { - margin-top:3px; - margin-bottom:3px; - font-size:110%; -} - -h2 { - margin-top:3px; - margin-bottom:3px; - font-size:110%; -} - -dt { - font-weight:bold; -} - - -#content { - padding-left: 10px; - padding-right: 10px; -} - -/* left movie area */ -#movie-container { - margin: 5px 0px 0px 5px; - float:left; - text-align:center; - vertical-align: text-top; - width:70%; - padding-bottom:3em; -} - -#themovie { - padding:5px; - width:340px; -} - -#movie_status { - width:340px; - margin-left:auto; - margin-right:auto; - padding-top:10px; -} - -/* movie controls */ -#movie-controls { - clear:both; - padding-left:5px; - padding-right:5px; - margin:5px; - width:340px; - margin-left:auto; - margin-right:auto; - -} - -#m_timeline { - margin-left:auto; - margin-right:auto; - margin-bottom:5px; -} - -#last-saved { - font-size:smaller; -} - -/* clip controls */ -#clip-controls { - margin-top:5px; - background-color: #eaeaea; - border:1px solid #ccc; - padding:5px; - text-align:center; - width:57%; - margin-left:auto; - margin-right:auto; -} - -#clip-info { - float:left; -} - -#clip-buttons { - margin-top:1.5em; -} - -#clip-timeline { - margin-top:5px; - margin-left: auto; - margin-right: auto; - width:150px; -} - -#make-clip { - float:right; - margin-top:45px; - margin-right:20px; -} - -/* captions */ -#captions { - text-align:center; - width:51%; - margin-left:auto; - margin-right:auto; - margin-top:10px; -} - -#captions textarea { - width:100%; - border: 1px solid #ccc; -} - -/* right clip info area */ -#info-container { - margin-left:71%; - line-height:145%; -} -.clip { - background-color: #f4f6fc; - padding:5px; - border-bottom: 1px solid #ccc; -} - -.clip-title { - text-decoration: underline; - font-weight:bold; - padding-bottom:10px; -} - -.space { - background-color:#fffff8; - padding:5px; - border-bottom: 1px solid #ccc; -} - - - -/* footer */ -#footer { - font-size: x-small; - text-align:center; - - clear: both; - width:780px; - position: absolute; - bottom: 0 !important; - height:1.5em; -} - -#duration, #current-time, #source-file, #clip-time, #clip-duration { - display:inline; -} - -.button { - border:1px solid black; - padding-top:3px; - padding-bottom:3px; - margin:0px; - width:3em; -} - - - -/* skins sliders */ - -.ui-slider { - width: 100%; - height: 23px; - position: relative; - background-repeat: repeat-x; - background-position: center center; -} -.ui-slider-handle { position: absolute; z-index: 0; height: 23px; width: 12px; top: 0px; left: 0px; background-image: url(images/slider-handle.gif); } - -/*.ui-slider-handle-ghost { - position: absolute; - z-index: 1; - height: 23px; - width: 12px; - top: 0px; - left: 0px; - background-image: url(images/slider-handle.gif); - opacity: 0.1; -}*/ - - -/*.ui-slider-handle-active, .ui-slider-handle-ghost-active { border: 1px dotted black; } -.ui-slider-disabled .ui-slider-handle { opacity: 0.5; filter: alpha(opacity=50); }*/ -.ui-slider-range { position: absolute; background: #50A029; opacity: 0.3; filter: alpha(opacity=30); width: 100%; height: 100%; } - -/* Default slider backgrounds */ -.ui-slider, .ui-slider-1 { background-image: url(images/slider-bg-2.png); } -.ui-slider-2 { background-image: url(images/slider-bg-2.png); } -.ui-slider-clip { background-image: url(images/middlebar.png); } - -/*.ui-slider-ghost { background-image: none; }*/ - - -/* links */ -a:link, a:visited { - color: black; -} -a:hover, a:focus { - color:red; -} - - - - -li.choice { - height:19em; - padding:5px; - width: 12.25em; - background-color: #fffff8; - border: 1px solid #969696; - text-align:center; - float:left; - margin-right:15px; - margin-bottom:5px; - list-style:none; -} - -.choice-info { - height:17em; -} - - -/* msgs */ - -div.error { - width:80%; - margin-left:auto; - margin-right:auto; - background-color: #F4E0E0; - border: 1px solid #A64040; - padding:10px; - margin:10px; -} - -div.feedback { - width:80%; - margin-left:auto; - margin-right:auto; - background-color: #D4ECD1; - border: 1px solid #4CA640; - padding:10px; - margin:10px; -} - -div.notice { - width:80%; - margin-left:auto; - margin-right:auto; - background-color: #f3edf6; - border: 1px solid #9977a8; - padding:10px; - margin:10px; -} - -/* export */ -ul#export-list { - list-style: none; -} - -ul#export-list li { - padding-top:3px; - padding-bottom:5px; -} - -ul#export-list a { - font-weight:bold; -} - - -/* editor */ -#in-info { - float:left; - text-align:left; -} - -#out-info { - float:right; - text-align:right; -} - -/* settings */ - -#edit-name, #edit-caps, #edit-media, #edit-perms { - margin-bottom: 20px; - padding:5px; - background-color: #dce5f3; -} \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/styles_ff.css b/mods/atutor_opencaps/opencaps/styles_ff.css deleted file mode 100755 index 3c6575748..000000000 --- a/mods/atutor_opencaps/opencaps/styles_ff.css +++ /dev/null @@ -1,5 +0,0 @@ -/* Styles for Firefox on Windows */ - -#make-clip { - margin-right:5px; -} \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/styles_ie.css b/mods/atutor_opencaps/opencaps/styles_ie.css deleted file mode 100755 index 4b87901e1..000000000 --- a/mods/atutor_opencaps/opencaps/styles_ie.css +++ /dev/null @@ -1,34 +0,0 @@ -/* Styles for IE on Windows */ - -#start-tabs ul { - margin-left: 0px; -} - -#start-container form { - margin-left:-30px; -} - -.col-list { - margin-bottom: 10px; -} - -img { - height:auto; - width:auto; -} - -/* editor */ - -#make-clip { - margin-right:5px; -} - -#in-info { - width:6em; - margin-top:-1em; -} - -#out-info { - margin-top:-1em; - width:6em; -} \ No newline at end of file diff --git a/mods/atutor_opencaps/opencaps/styles_public.css b/mods/atutor_opencaps/opencaps/styles_public.css deleted file mode 100755 index 7a93afe7b..000000000 --- a/mods/atutor_opencaps/opencaps/styles_public.css +++ /dev/null @@ -1,109 +0,0 @@ -/* Styles for start public pages */ - -body { - width:50em; - margin-left:auto; - margin-right:auto; - line-height:150%; - margin-top:5px; -} - -#start-container { - background-color: white; - margin-top:-1px; - padding:10px; -} - -a:link, a:visited { - color: #143aa8; -} - -a:hover { - text-decoration:underline; -} - -#footer { - width:50em; - margin-left:auto; - margin-right:auto; -} - -h1 { - margin-left:0px; - padding:0px; -} -h2 { - padding:0px; - margin-left:0px; - margin-bottom:10px; - margin-top:0px; -} - -form { - padding: 10px; -} - -ul#start { - margin-left:-40px; - margin-bottom:20px; - list-style:none; -} - -ul#start li { - background-color: white; - clear:both; - margin-bottom:1em; - padding:5px; -} - -#start-tabs { - padding-top:5px; - padding-bottom:3px; - font-weight:bold; -} - -#start-tabs ul { - margin:0px; - margin-left:-30px; - display:inline; -} -#start-tabs ul li { - display:inline; - list-style:none; - margin-right:5px; -} - -#start-tabs a:link, #start-tabs a:visited { - color: black; - background-color:#efefef; - padding:3px 10px 4px 10px; -} - -#start-tabs a:hover { - padding:3px 10px 4px 10px; - width:5em; - background-color: #ccc; - color: black; -} -#start-tabs .current a:link, #start-tabs .current a:visited { - padding:3px 10px 4px 10px; - width:5em; - background-color: white; -} - -#start-tabs input { - padding:0px; - margin:0px; - margin-top:2px; - margin-right:3px; -} - -ul.proj-list { - list-style:none; - margin:0px; - padding:0px; -} - -ul.proj-list li { - padding-top:2px; - padding-bottom:2px; diff --git a/mods/atutor_opencaps/player.php b/mods/atutor_opencaps/player.php deleted file mode 100755 index 209ee2253..000000000 --- a/mods/atutor_opencaps/player.php +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - AT Media Player - - - -
    - - - - - -"; // end stript - -echo $playerEmbed; -?> - - -
    -
    -

    :

    -
    - -
    -
    - - - - - \ No newline at end of file diff --git a/mods/atutor_opencaps/service.php b/mods/atutor_opencaps/service.php deleted file mode 100755 index 31d67e550..000000000 --- a/mods/atutor_opencaps/service.php +++ /dev/null @@ -1,100 +0,0 @@ -AT_CONTENT_DIR: '.AT_CONTENT_DIR; -//echo '
    AT_BASE_HREF: '.AT_BASE_HREF; - -// check if is GET or POST requet - -// initialize vars -$method = ''; -$action = ''; -$projectId = ''; -$captionData = ''; - -if($ocAtSettings['atWebPath'] == '') -{ - $atWebPath_replace = str_replace('mods/AtOpenCaps/service.php','',$_SERVER['SCRIPT_NAME']); - $ocAtSettings['atWebPath'] = 'http://'.$_SERVER['HTTP_HOST'].''.$atWebPath_replace; -} - -if (isset($_GET['action']) && $_GET['action'] !='') -{ - $action = $_GET['action']; - - if (isset($_GET['id']) && $_GET['id'] !='') - { - $projectId = $_GET['id']; - } -} - -if (isset($_POST['action']) && $_POST['action'] !='') -{ - $action = $_POST['action']; - - if (isset($_POST['id']) && $_POST['id'] !='') - { - $projectId = $_POST['id']; - } -} - -// Get media data and return JSon - -if ($action=='getMedia' && $projectId !='') -{ - $myProjectManager = new ATOCProjectManager(); - - $activeProjectJson = $myProjectManager->_getProjecDataJson($projectId,$ocAtSettings['atWebPath']); - echo $activeProjectJson; - - // start OC Json class -} else if ($action=='getMedia') { - echo "Invalid request"; - -} - - -// save caption data - -if ($action=='putCaps' && $projectId != '' && isset($_POST['cc']) && $_POST['cc']!='') -{ - $captionData = $_POST['cc']; - - if(isset($_POST['width'])) - { - $theWidth = $_POST['width']; - } else { - $theWidth = ''; - } - if(isset($_POST['height'])) - { - $theHeight = $_POST['height']; - } else { - $theHeight = ''; - } - $myProjectManager = new ATOCProjectManager(); - - $saveMSG = $myProjectManager->_saveCaptionData($projectId,$captionData,$theWidth,$theHeight); - - //echo $saveMSG; - -} -?> \ No newline at end of file diff --git a/mods/atutor_opencaps/service_test.php b/mods/atutor_opencaps/service_test.php deleted file mode 100755 index 7a6b7bffb..000000000 --- a/mods/atutor_opencaps/service_test.php +++ /dev/null @@ -1,53 +0,0 @@ -AT_CONTENT_DIR: '.AT_CONTENT_DIR; -echo '
    AT_BASE_HREF: '.AT_BASE_HREF; - -?> - - - - -Untitled Document - - - - -

    Test Service

    -

    getMedia: $_GET

    -

    /mods/AtOpenCaps/service.php?id=1&action=getMedia

    -

     

    -

    putCaps: $_POST

    -
    -

    Id: - -

    -

    action: - -

    -

    - Width: - Height: -

    - -

    cc:
    - -

    -

    - -

    -
    -

     

    - - - diff --git a/mods/basiclti/ModuleCallbacks.class.php b/mods/basiclti/ModuleCallbacks.class.php deleted file mode 100644 index 3bc41ecd8..000000000 --- a/mods/basiclti/ModuleCallbacks.class.php +++ /dev/null @@ -1,65 +0,0 @@ - 0 ) { - $height = $basiclti_tool_row['preferheight']; - } - if ( $basiclti_tool_row['allowpreferheight'] == 2 && isset($basiclti_content_row['preferheight']) && $basiclti_content_row['preferheight'] > 0 ) { - $height = $basiclti_content_row['preferheight']; - } - - $myurl = AT_BASE_HREF.'mods/basiclti/launch/launch.php?cid='.$cid; - if ( $basiclti_tool_row['launchinpopup'] == 1 || - ( $basiclti_tool_row['launchinpopup'] == 2 && $basiclti_content_row['launchinpopup'] == 1 ) ) { - // return ''."\n"; - /***************** - * The ID in the next bit is temporary until we can add the box style to ATutor and - * change the ID value to content-tool. In the meantime this will fail validation if tools and - * tests or forums are also present for the content page - **********************/ - return '
      '._AT('proxy').'
    '."\n"; - } else { - return ''."\n"; - } - } - -} - -?> diff --git a/mods/basiclti/README.txt b/mods/basiclti/README.txt deleted file mode 100644 index 9f9e19d39..000000000 --- a/mods/basiclti/README.txt +++ /dev/null @@ -1,161 +0,0 @@ -########################################## -# External Tools Module Readme file: ##### -########################################## -This is an alpha version of an ATutor Basic LTI Integration module. - -It allows ATutor administrators and instructors to link external tools into ATutor, and to -associate those tools with content as learning activities. - -The current development source code is located at: -http://svn.atutor.ca/repos/atutor/trunk/mods/basiclti/ - -More about the BasicLTI Standard -http://www.imsglobal.org/lti/ - -Here are a couple videos with more information: -http://www.vimeo.com/18074396 -http://vimeo.com/14100773 - -###################### -# Intallation & Setup -###################### -1. Download the External Tools (BasicLTI TBD) Module from atutor.ca (or import it directly from atutor.ca via the Admin Module Manager if it's listed there) -2. Follow the instructions presented by the module installer to install the module. -3. Once installed, enable the module where it is listed in the Module Manager. This will create an External Tools Tab from where BasicLTI compatible external tools can be managed. - -Setup A New External Tool (Administrator) -1. Title: Enter a name for the tool being created in the title field -2. ToolID: Create an ID for the tool that will be unique across all tools on the system (e.g. demo_tool.ocadu.ca) any unique string will do -3. Description: Describe the tool, its function, and how it might be used. -4. Tool Launch URL: Copy the URL of the tool's BasicLTI launch location. Ensure there is no space at the end of the URL (see the Sample LTI Tool below for demo purposes) -5. Enter the Tool Key and secret -6. Set various options and Save - -Add a Tool to Course Content (Instructor) -1. Create a new content page and save it or edit an existing page. -2. Click on the External Tool icon in the content editor toolbar while editing that page. -3. Select from the available tools to add it as a Learning Activity. -4. Save the content page, and close the content editor. -5. The tool appears at the bottom of the page as a link that opens a popup window. - -Or, - -Setup a New Tool (Instructor) -1. Under the Manage Tab, click on Create External Tool in the External Tools section -2. Fill in the required fields, as described above for Administrators. -3. Set the optional settings below and Save -4. Follow the steps above to Add a Tool to Course Content, to use your new tool. - -################## -# Useful Resources -################## - -BasicLTI Certification -http://www.imsglobal.org/developers/alliance/LTI/blti-cert/lmscert.cfm - -Sample LTI Tool for Testing/Demo Purposes -http://www.imsglobal.org/developers/BLTI/tool.php -key: lmsng.school.edu -secret: secret - -Tools Currently with BasicLTI Provider Capability -QuestionMark -http://www.questionmark.com/ -Noteflight -http://www.noteflight.com/ -Wimba -http://www.wimba.com/ -Elluminate -http://www.elluminate.com/ - -A list BasicLTI conformant system can be found at: -http://www.imsglobal.org/cc/statuschart.html - -############################### -# Known issues in this release -############################### -- should the view button in the admin's tool listing table display the actual tool instead of the tool settings. Would be more useful I think, given clicking the edit button displays the same information. Or maybe display settings above, and open the tool below in a frame. - -- course backups need to be rethought. There is currently no backup support for external; tools. - Issues: - If/How to export Admin created tools in a course backup, so they will render in other systems without disclosing authentication/tool account info to instructors, who may not have license to access a tool outside it originally licenced environment? - How to import course level tools in backups, and reset course_id and cid to the new content ids created - How to reset the toolid to make it unique when importing BasicLTI tools in a backup into a course. - -############################# -# Tool options documentation -############################# -################### -#Required Settings# -################### -#ToolId (must be unique across system) -This is a unique identifier that you much choose. This identifier must be unique across the system. This identified is used to connect tool content items across exports and imports of the content area. - -#Tool Launch URL -This is the launch URL for the external tool. It is provided by the eternal tool provider and should be entered here. Generally an external tool provider will give you a URL, key, and secret so that you can access their tool. - -#Tool Key (oauth_consumer_key) -This is the launch key for the external tool. It is provided by the external tool provider and should be entered here. Generally an external tool provider will give you a URL, key, and secret so that you can access their tool. - -#Tool Secret -This is the launch key for the external tool. It is provided by the eternal tool provider and should be entered here. Generally an external tool provider will give you a URL, key, and secret so that you can access their tool. -################### -#Optional Settings# -################### - -#Frame Height -This allows you to control the height of the frame that will contain the external tool. - -#Allow Frame Height to be Changed -The frame height may be specified for a tool by the administrator, or the administrator may allow the instructor to change the frame height. - -#Launch Tool in Pop Up Window -Normally tools are launched in an iframe at the bottom of an ATutor content page. This option can be used so that the tool opens in a new browser window by clicking a link at the bottom of a content page, which replaces the default iframe. This option may be specified for a tool by the administrator, or the administrator may allow the instructor to specify this option. - -#Launch Tool in Debug Mode -This option should normally be off except when you are having problems with tool launching. When this option is turned on, The launch is -paused part-way through to allow you to examine the data to be sent to the external tool. You are then given an option to continue the launch -by pressing a button. This option may be specified for a tool by the administrator, or the administrator may allow the instructor to specify this option. - -#Send User Names to External Tool -This option determines whether you want to send user names to the external tool. You should only send user names to trusted tools and you should make sure that if you share user names with the external tools that you are following all appropriate regulations regarding student privacy. Sending user names is optional data in the Basic LTI specification although some tools may require user names to function properly. -This option may be specified for a tool by the administrator, or the administrator may allow the instructor to specify this option. - -#Send User Mail Addresses to External Tool -This option determines whether you want to send user mail addresses to the external tool.You should only send user mail addresses to trusted tools and you should make sure that -if you share user addresses with the external tools that you are following all appropriate regulations regarding student privacy. -Sending user mail addresses is optional data in the Basic LTI specification although some tools may require user names to function properly. -This option may be specified for a tool by the administrator, or the administrator may allow the instructor to specify this option. - -#Accept Grades From External Tool -Some tools can send grades back to ATutor through a Basic LTI extension REST web service. If the external tool has the capability of -using these services and you would like to allow the tool to send grades back to ATutor, you can enable this option. When you author -an external tool content item and enable this option, the tool will only be able to read and write grades in a single grade book item that -you associate with the content item. This option may be specified for a tool by the administrator, or the administrator may allow the instructor to specify this option. - -#Allow External Tool To Retrieve Roster -Some tools can retrieve the entire course roster through a Basic LTI extension REST web service. If the external tool has the capability of -using these services and you would like to provide the entire course roster to the tool then you can enable this option. If this option is enabled, it respects the privacy option setting as to whether or not to release user names and email addresses. If these are configured to be provided on launches and the tool can retrieve the entire roster, then user names and mail addresses are included in the roster when it is retrieved. This option may be specified for a tool by the administrator, or the administrator may allow the instructor to specify this option. - -#Allow External Tool to use the Setting Service -This option allows the external tool to store up to 8K of data in the content item. Typically the external tool uses this area for a resource -setting or perhaps a playlist as selected by the user. In particular it does not allow a separate 8K setting for each user for a content item. This option may be specified for a tool by the administrator, or the administrator may allow the instructor to specify this option. - -#Custom Parameters -Sometimes the external tool requires that you send additional custom parameters along with the launch. The typical use of this would be to specify an ISBN number for a book associated with the launch or to select a particular content item within a content repository. Different tools will use this capability differently. Typically these will be specified as a keyword and a value such as - -isbn=929293939 - -These values may be set by the administrator or the administrator may allow the instructor to set these values in content items. - -####################### -#Additional Administrator Options -####################### -#Organization Identifier (typically DNS) -This is typically the domain name of the organization hosting ATutor such as www.ocad.ca - this field is optional. - -#Organization URL -This is typically the URL of the starting page for the learning management system such as http://atutor.ocad.ca - this field is optional. - -#Organization Description -This is a short one-line textual description of the organization hosting ATutor such as "The Ontario College of Art & Design" - this field is optional \ No newline at end of file diff --git a/mods/basiclti/TODO.txt b/mods/basiclti/TODO.txt deleted file mode 100644 index 17a191f55..000000000 --- a/mods/basiclti/TODO.txt +++ /dev/null @@ -1,13 +0,0 @@ - -Need an ondelete callback from the content system. - -Add timeplacement based on the typical patterns of time -in ATutor. - -Longer term for CC 1.1 support: - -Add support for XML Descriptor import - -Add support for global per url keys. - - diff --git a/mods/basiclti/basiclti.jpg b/mods/basiclti/basiclti.jpg deleted file mode 100644 index c6cf71b3be9da5b70601ca2f24e175ddb011b565..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1827 zcmbW!X;hO}8VB$<%S*@xWJ7|%C?XW5ku5TaHZcl8P!5}eEQ2Xq3bg2vMLO3KF!SkKKFjP%Xxn1>R#w3 z0TXYw7aM>;005#NfNlcV2f(1v_0k8fFVGMK;cyUzKo}TeP#6pvg+^nI@FrLzoDmvr zVrqgT5J@Bw#(0C7DbWm1BoWsifxz^4;2;tNkwh#SOZ=as>i}?ufGt3SK`a3%4g$kL zbX@>d-zNz9HNfwIK=nNuAPkWxwEjS|2>^w_U{E-0y=(pHO#MCp$AS1Qjw}O$e+0tv zIMFGmxXN(r-o{Q+z>|3^=g7oUNR;UYGqU+MYnxAO?dUsP{_48ZZJ)ab+jGB{ci^GF z1sx6!35|-5;eHVt7oU`zaw0V?{p9I0x!>gdBmZnk>9-fl$}28izFu8(<7Vxx+jp7- z!e&v+{nj6(54*a1dix&zI5PV5+4Hd%<1)EI`FiTjFK?%3R15$7*GKiDW@&ld1p#2c zvGnV2u>Wx3^e!kI4ud1sT@Yxhe!_5YaEqe>p5>2-I8Ly1$}uGFEv{$G2G{~heq|0Vka_NPk*U|P9gr{1nry(P z^>cKQK%Du=l(gtB!gwUYp;ZVdZRp3%hp&B(PxR7@Frz)@B z)dBNdUVD`G(-pQzED&?B9p!Oac6*^LTo@7GT247i> zijyYWQE6En%azv}VxRcldh6!#;A&BvOKk!;;6(R7r4l>2+9f(S=MCKPM<|2?XUCd-sU{`-6PDua=pe?Sy1w%8PyJH8VkD>V?8bG~r!K2leI) zU)I4L`d%Ma(Ao=mEUkk^r0l8Oq^c}c#QKblH(L-6JPm&=?VTzsaW7`ery9}p=2|^zb^3_q_xA~*92P~@o>&QOq}>8DTF|9jd|)=k2H)4D6x` z7>%nBGScP7`EHA+lHavXwUv60CJ2}6yB7LJeC$@QKMx9cKRW;ef=dfZdoTJR;Z6D$*-((bId?u;CIjZq;;g&oerQ z{6aQ#^75g97IoPjOiK{{_JN90*Cn;ZyS`mYR&lWZ@j~}E_s-STOgAIAX^)EvB-UxD z#fPu9sHo?~{)%J9K8}|&b|x2Eb*6HkRE$@D=_>x&iEP2O6F2RdAqv0-Q1e0Yff7Hq z+*6yb2-5)@(!zY6`#gJ46Xc)+V!Agr{WLxI#uL9ZV_AZ)8~L8g-Z|uZQ({g<^Mae^ zA1`IRjG4nMn)`)?n0uAEjBgVU^hJ5Z7K)sQUZJ`ml}YNtd1s!jCP6uomB+wl!n{>b zWw@lwmVDw?x_7m(!XwbCrY<&$w(G(Hvg4eGUv2(5f1ecJn0xP*U;R@0I4GG)=g+KM zTFO<~ciZn+R6i&QlPO}Hrq@FJk#J=^KI?>Mf9LM#P2#nD9nk5#;+ttdt2~Cu6}M%K zE6>>!Rz_|5EXV3=($cDm(6yY^WjiNy-A&GnQ0M@Gb$No?YnYWNm0w8;tGGCv{#CZ) z(Szxmqm>`4)s7mx4!}x~apv^f+PA~I>k!zjF;{iK&+cQ^48h&Npwx)XRal(*vzWBJ zJuPFiR-$XLy9J*=uP04e^!9}=c5uvj+f~^2g88AY!*2K^yB?+1xGgQGOgNBJTaLo6 z8do}<&uF9sxwI;aWSk?TZ$@w{7B_q8Ttu5_*gAbL?sN{VziP#=C|*kq(0Gwp}=LHTdqgH*9Q9xOTG=yF;kD@qYuuZZI+c diff --git a/mods/basiclti/content_tool_action.js b/mods/basiclti/content_tool_action.js deleted file mode 100644 index bdf5ed499..000000000 --- a/mods/basiclti/content_tool_action.js +++ /dev/null @@ -1,29 +0,0 @@ -/* The javascript is used in module.php @ $this->_content_tools["js"] */ - -/*global jQuery*/ -/*global ATutor */ -/*global tinyMCE */ -/*global window */ - -ATutor = ATutor || {}; -ATutor.mods = ATutor.mods || {}; -ATutor.mods.basiclti = ATutor.mods.basiclti || {}; - -(function () { - var basicLTIOnClick = function () { - if ( ATutor.mods.editor.content_id == 0 ) { - alert("Please press save for your content item before configuring the remote tool"); - return; - } - window.open(ATutor.base_href + 'mods/basiclti/tool/content_edit.php?cid='+ATutor.mods.editor.content_id + "&framed=1&popup=1", - 'newWinLTI', 'menubar=0,scrollbars=1,resizable=1,width=640,height=490'); - return false; - } - - //set up click handlers and show/hide appropriate tools - var initialize = function () { - jQuery("#basiclti_tool").click(basicLTIOnClick); - }; - - jQuery(document).ready(initialize); -})(); diff --git a/mods/basiclti/images/basiclti-icon.png b/mods/basiclti/images/basiclti-icon.png deleted file mode 100644 index 7333047242cd6f6c7b17db35ce2cc04440183c45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5271 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 diff --git a/mods/basiclti/include/constants.inc.php b/mods/basiclti/include/constants.inc.php deleted file mode 100644 index dcdd0a7c4..000000000 --- a/mods/basiclti/include/constants.inc.php +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/mods/basiclti/index.php b/mods/basiclti/index.php deleted file mode 100644 index 7b9edccff..000000000 --- a/mods/basiclti/index.php +++ /dev/null @@ -1,12 +0,0 @@ - - -
    - Hello Student!! :) -
    - - diff --git a/mods/basiclti/index_admin.php b/mods/basiclti/index_admin.php deleted file mode 100644 index b7d7033c0..000000000 --- a/mods/basiclti/index_admin.php +++ /dev/null @@ -1,59 +0,0 @@ -addError("NO_ITEM_SELECTED"); - -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -$sql = "SELECT t.id AS id,t.title AS title,t.toolid AS toolid, - t.description AS description, COUNT(c.id) AS cnt - FROM ".TABLE_PREFIX."basiclti_tools AS t - LEFT OUTER JOIN ".TABLE_PREFIX."basiclti_content as c - ON t.toolid = c.toolid - WHERE t.course_id = 0 GROUP BY t.toolid ORDER BY t.title"; -$result = mysql_query($sql, $db) or die(mysql_error()); -?> -
    - - - - - - - - - - - - - - - - - - - - - - -
     
    - -
    -
    - diff --git a/mods/basiclti/index_instructor.php b/mods/basiclti/index_instructor.php deleted file mode 100644 index 4d95e29a3..000000000 --- a/mods/basiclti/index_instructor.php +++ /dev/null @@ -1,63 +0,0 @@ -addFeedback('NEED_COURSE_ID'); - exit; -} - -if (isset($_GET['view'], $_GET['id'])) { - header('Location: tool/instructor_view.php?id='.$_GET['id']); - exit; -} else if (isset($_GET['edit'], $_GET['id'])) { - header('Location: tool/instructor_edit.php?id='.$_GET['id']); - exit; -} else if (isset($_GET['delete'], $_GET['id'])) { - header('Location: tool/instructor_delete.php?id='.$_GET['id']); - exit; -} else if ($_GET['delete'] ||$_GET['edit'] || $_GET['view'] && !isset($_GET['id'])){ - $msg->addError("NO_ITEM_SELECTED"); -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -$sql = "SELECT t.id AS id,t.title AS title,t.toolid AS toolid, - t.description AS description, COUNT(c.id) AS cnt - FROM ".TABLE_PREFIX."basiclti_tools AS t - LEFT OUTER JOIN ".TABLE_PREFIX."basiclti_content as c - ON t.toolid = c.toolid - WHERE t.course_id = ".$_SESSION['course_id']." GROUP BY t.toolid ORDER BY t.title"; -$result = mysql_query($sql, $db) or die(mysql_error()); -?> -
    - - - - - - - - - - - - - - - - - - - - - - -
     
    - -
    -
    - diff --git a/mods/basiclti/launch/TrivialStore.php b/mods/basiclti/launch/TrivialStore.php deleted file mode 100644 index 506057782..000000000 --- a/mods/basiclti/launch/TrivialStore.php +++ /dev/null @@ -1,45 +0,0 @@ -consumers[$consumer_key] = $consumer_secret; - } - - function lookup_consumer($consumer_key) { - if ( strpos($consumer_key, "http://" ) === 0 ) { - $consumer = new OAuthConsumer($consumer_key,"secret", NULL); - return $consumer; - } - if ( $this->consumers[$consumer_key] ) { - $consumer = new OAuthConsumer($consumer_key,$this->consumers[$consumer_key], NULL); - return $consumer; - } - return NULL; - } - - function lookup_token($consumer, $token_type, $token) { - return new OAuthToken($consumer, ""); - } - - // Return NULL if the nonce has not been used - // Return $nonce if the nonce was previously used - function lookup_nonce($consumer, $token, $nonce, $timestamp) { - // Should add some clever logic to keep nonces from - // being reused - for no we are really trusting - // that the timestamp will save us - return NULL; - } - - function new_request_token($consumer) { - return NULL; - } - - function new_access_token($token, $consumer) { - return NULL; - } -} -?> diff --git a/mods/basiclti/launch/ims-blti/LICENSE.txt b/mods/basiclti/launch/ims-blti/LICENSE.txt deleted file mode 100644 index 89f059169..000000000 --- a/mods/basiclti/launch/ims-blti/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License - -Copyright (c) 2007 Andy Smith - -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/mods/basiclti/launch/ims-blti/OAuth.php b/mods/basiclti/launch/ims-blti/OAuth.php deleted file mode 100644 index 226d6d4c9..000000000 --- a/mods/basiclti/launch/ims-blti/OAuth.php +++ /dev/null @@ -1,808 +0,0 @@ -key = $key; - $this->secret = $secret; - $this->callback_url = $callback_url; - } - - function __toString() { - return "OAuthConsumer[key=$this->key,secret=$this->secret]"; - } -} - -class OAuthToken { - // access tokens and request tokens - public $key; - public $secret; - - /** - * key = the token - * secret = the token secret - */ - function __construct($key, $secret) { - $this->key = $key; - $this->secret = $secret; - } - - /** - * generates the basic string serialization of a token that a server - * would respond to request_token and access_token calls with - */ - function to_string() { - return "oauth_token=" . - OAuthUtil::urlencode_rfc3986($this->key) . - "&oauth_token_secret=" . - OAuthUtil::urlencode_rfc3986($this->secret); - } - - function __toString() { - return $this->to_string(); - } -} - -class OAuthSignatureMethod { - public function check_signature(&$request, $consumer, $token, $signature) { - $built = $this->build_signature($request, $consumer, $token); - return $built == $signature; - } -} - -class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod { - function get_name() { - return "HMAC-SHA1"; - } - - public function build_signature($request, $consumer, $token) { - global $OAuth_last_computed_signature; - $OAuth_last_computed_signature = false; - - $base_string = $request->get_signature_base_string(); - $request->base_string = $base_string; - - $key_parts = array( - $consumer->secret, - ($token) ? $token->secret : "" - ); - - $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); - $key = implode('&', $key_parts); - - $computed_signature = base64_encode(hash_hmac('sha1', $base_string, $key, true)); - $OAuth_last_computed_signature = $computed_signature; - return $computed_signature; - } - -} - -class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod { - public function get_name() { - return "PLAINTEXT"; - } - - public function build_signature($request, $consumer, $token) { - $sig = array( - OAuthUtil::urlencode_rfc3986($consumer->secret) - ); - - if ($token) { - array_push($sig, OAuthUtil::urlencode_rfc3986($token->secret)); - } else { - array_push($sig, ''); - } - - $raw = implode("&", $sig); - // for debug purposes - $request->base_string = $raw; - - return OAuthUtil::urlencode_rfc3986($raw); - } -} - -class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod { - public function get_name() { - return "RSA-SHA1"; - } - - protected function fetch_public_cert(&$request) { - // not implemented yet, ideas are: - // (1) do a lookup in a table of trusted certs keyed off of consumer - // (2) fetch via http using a url provided by the requester - // (3) some sort of specific discovery code based on request - // - // either way should return a string representation of the certificate - throw Exception("fetch_public_cert not implemented"); - } - - protected function fetch_private_cert(&$request) { - // not implemented yet, ideas are: - // (1) do a lookup in a table of trusted certs keyed off of consumer - // - // either way should return a string representation of the certificate - throw Exception("fetch_private_cert not implemented"); - } - - public function build_signature(&$request, $consumer, $token) { - $base_string = $request->get_signature_base_string(); - $request->base_string = $base_string; - - // Fetch the private key cert based on the request - $cert = $this->fetch_private_cert($request); - - // Pull the private key ID from the certificate - $privatekeyid = openssl_get_privatekey($cert); - - // Sign using the key - $ok = openssl_sign($base_string, $signature, $privatekeyid); - - // Release the key resource - openssl_free_key($privatekeyid); - - return base64_encode($signature); - } - - public function check_signature(&$request, $consumer, $token, $signature) { - $decoded_sig = base64_decode($signature); - - $base_string = $request->get_signature_base_string(); - - // Fetch the public key cert based on the request - $cert = $this->fetch_public_cert($request); - - // Pull the public key ID from the certificate - $publickeyid = openssl_get_publickey($cert); - - // Check the computed signature against the one passed in the query - $ok = openssl_verify($base_string, $decoded_sig, $publickeyid); - - // Release the key resource - openssl_free_key($publickeyid); - - return $ok == 1; - } -} - -class OAuthRequest { - private $parameters; - private $http_method; - private $http_url; - // for debug purposes - public $base_string; - public static $version = '1.0'; - public static $POST_INPUT = 'php://input'; - - function __construct($http_method, $http_url, $parameters=NULL) { - @$parameters or $parameters = array(); - $this->parameters = $parameters; - $this->http_method = $http_method; - $this->http_url = $http_url; - } - - - /** - * attempt to build up a request from what was passed to the server - */ - public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) { - $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") - ? 'http' - : 'https'; - $port = ""; - if ( $_SERVER['SERVER_PORT'] != "80" && $_SERVER['SERVER_PORT'] != "443" && - strpos(':', $_SERVER['HTTP_HOST']) < 0 ) { - $port = ':' . $_SERVER['SERVER_PORT'] ; - } - @$http_url or $http_url = $scheme . - '://' . $_SERVER['HTTP_HOST'] . - $port . - $_SERVER['REQUEST_URI']; - @$http_method or $http_method = $_SERVER['REQUEST_METHOD']; - - // We weren't handed any parameters, so let's find the ones relevant to - // this request. - // If you run XML-RPC or similar you should use this to provide your own - // parsed parameter-list - if (!$parameters) { - // Find request headers - $request_headers = OAuthUtil::get_headers(); - - // Parse the query-string to find GET parameters - $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']); - - $ourpost = $_POST; - // Deal with magic_quotes - // http://www.php.net/manual/en/security.magicquotes.disabling.php - if ( get_magic_quotes_gpc() ) { - $outpost = array(); - foreach ($_POST as $k => $v) { - $v = stripslashes($v); - $ourpost[$k] = $v; - } - } - // Add POST Parameters if they exist - $parameters = array_merge($parameters, $ourpost); - - // We have a Authorization-header with OAuth data. Parse the header - // and add those overriding any duplicates from GET or POST - if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") { - $header_parameters = OAuthUtil::split_header( - $request_headers['Authorization'] - ); - $parameters = array_merge($parameters, $header_parameters); - } - - } - - return new OAuthRequest($http_method, $http_url, $parameters); - } - - /** - * pretty much a helper function to set up the request - */ - public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) { - @$parameters or $parameters = array(); - $defaults = array("oauth_version" => OAuthRequest::$version, - "oauth_nonce" => OAuthRequest::generate_nonce(), - "oauth_timestamp" => OAuthRequest::generate_timestamp(), - "oauth_consumer_key" => $consumer->key); - if ($token) - $defaults['oauth_token'] = $token->key; - - $parameters = array_merge($defaults, $parameters); - - // Parse the query-string to find and add GET parameters - $parts = parse_url($http_url); - if ( $parts['query'] ) { - $qparms = OAuthUtil::parse_parameters($parts['query']); - $parameters = array_merge($qparms, $parameters); - } - - - return new OAuthRequest($http_method, $http_url, $parameters); - } - - public function set_parameter($name, $value, $allow_duplicates = true) { - if ($allow_duplicates && isset($this->parameters[$name])) { - // We have already added parameter(s) with this name, so add to the list - if (is_scalar($this->parameters[$name])) { - // This is the first duplicate, so transform scalar (string) - // into an array so we can add the duplicates - $this->parameters[$name] = array($this->parameters[$name]); - } - - $this->parameters[$name][] = $value; - } else { - $this->parameters[$name] = $value; - } - } - - public function get_parameter($name) { - return isset($this->parameters[$name]) ? $this->parameters[$name] : null; - } - - public function get_parameters() { - return $this->parameters; - } - - public function unset_parameter($name) { - unset($this->parameters[$name]); - } - - /** - * The request parameters, sorted and concatenated into a normalized string. - * @return string - */ - public function get_signable_parameters() { - // Grab all parameters - $params = $this->parameters; - - // Remove oauth_signature if present - // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.") - if (isset($params['oauth_signature'])) { - unset($params['oauth_signature']); - } - - return OAuthUtil::build_http_query($params); - } - - /** - * Returns the base string of this request - * - * The base string defined as the method, the url - * and the parameters (normalized), each urlencoded - * and the concated with &. - */ - public function get_signature_base_string() { - $parts = array( - $this->get_normalized_http_method(), - $this->get_normalized_http_url(), - $this->get_signable_parameters() - ); - - $parts = OAuthUtil::urlencode_rfc3986($parts); - - return implode('&', $parts); - } - - /** - * just uppercases the http method - */ - public function get_normalized_http_method() { - return strtoupper($this->http_method); - } - - /** - * parses the url and rebuilds it to be - * scheme://host/path - */ - public function get_normalized_http_url() { - $parts = parse_url($this->http_url); - - $port = @$parts['port']; - $scheme = $parts['scheme']; - $host = $parts['host']; - $path = @$parts['path']; - - $port or $port = ($scheme == 'https') ? '443' : '80'; - - if (($scheme == 'https' && $port != '443') - || ($scheme == 'http' && $port != '80')) { - $host = "$host:$port"; - } - return "$scheme://$host$path"; - } - - /** - * builds a url usable for a GET request - */ - public function to_url() { - $post_data = $this->to_postdata(); - $out = $this->get_normalized_http_url(); - if ($post_data) { - $out .= '?'.$post_data; - } - return $out; - } - - /** - * builds the data one would send in a POST request - */ - public function to_postdata() { - return OAuthUtil::build_http_query($this->parameters); - } - - /** - * builds the Authorization: header - */ - public function to_header() { - $out ='Authorization: OAuth realm=""'; - $total = array(); - foreach ($this->parameters as $k => $v) { - if (substr($k, 0, 5) != "oauth") continue; - if (is_array($v)) { - throw new OAuthException('Arrays not supported in headers'); - } - $out .= ',' . - OAuthUtil::urlencode_rfc3986($k) . - '="' . - OAuthUtil::urlencode_rfc3986($v) . - '"'; - } - return $out; - } - - public function __toString() { - return $this->to_url(); - } - - - public function sign_request($signature_method, $consumer, $token) { - $this->set_parameter( - "oauth_signature_method", - $signature_method->get_name(), - false - ); - $signature = $this->build_signature($signature_method, $consumer, $token); - $this->set_parameter("oauth_signature", $signature, false); - } - - public function build_signature($signature_method, $consumer, $token) { - $signature = $signature_method->build_signature($this, $consumer, $token); - return $signature; - } - - /** - * util function: current timestamp - */ - private static function generate_timestamp() { - return time(); - } - - /** - * util function: current nonce - */ - private static function generate_nonce() { - $mt = microtime(); - $rand = mt_rand(); - - return md5($mt . $rand); // md5s look nicer than numbers - } -} - -class OAuthServer { - protected $timestamp_threshold = 300; // in seconds, five minutes - protected $version = 1.0; // hi blaine - protected $signature_methods = array(); - - protected $data_store; - - function __construct($data_store) { - $this->data_store = $data_store; - } - - public function add_signature_method($signature_method) { - $this->signature_methods[$signature_method->get_name()] = - $signature_method; - } - - // high level functions - - /** - * process a request_token request - * returns the request token on success - */ - public function fetch_request_token(&$request) { - $this->get_version($request); - - $consumer = $this->get_consumer($request); - - // no token required for the initial token request - $token = NULL; - - $this->check_signature($request, $consumer, $token); - - $new_token = $this->data_store->new_request_token($consumer); - - return $new_token; - } - - /** - * process an access_token request - * returns the access token on success - */ - public function fetch_access_token(&$request) { - $this->get_version($request); - - $consumer = $this->get_consumer($request); - - // requires authorized request token - $token = $this->get_token($request, $consumer, "request"); - - - $this->check_signature($request, $consumer, $token); - - $new_token = $this->data_store->new_access_token($token, $consumer); - - return $new_token; - } - - /** - * verify an api call, checks all the parameters - */ - public function verify_request(&$request) { - global $OAuth_last_computed_signature; - $OAuth_last_computed_signature = false; - $this->get_version($request); - $consumer = $this->get_consumer($request); - $token = $this->get_token($request, $consumer, "access"); - $this->check_signature($request, $consumer, $token); - return array($consumer, $token); - } - - // Internals from here - /** - * version 1 - */ - private function get_version(&$request) { - $version = $request->get_parameter("oauth_version"); - if (!$version) { - $version = 1.0; - } - if ($version && $version != $this->version) { - throw new OAuthException("OAuth version '$version' not supported"); - } - return $version; - } - - /** - * figure out the signature with some defaults - */ - private function get_signature_method(&$request) { - $signature_method = - @$request->get_parameter("oauth_signature_method"); - if (!$signature_method) { - $signature_method = "PLAINTEXT"; - } - if (!in_array($signature_method, - array_keys($this->signature_methods))) { - throw new OAuthException( - "Signature method '$signature_method' not supported " . - "try one of the following: " . - implode(", ", array_keys($this->signature_methods)) - ); - } - return $this->signature_methods[$signature_method]; - } - - /** - * try to find the consumer for the provided request's consumer key - */ - private function get_consumer(&$request) { - $consumer_key = @$request->get_parameter("oauth_consumer_key"); - if (!$consumer_key) { - throw new OAuthException("Invalid consumer key"); - } - - $consumer = $this->data_store->lookup_consumer($consumer_key); - if (!$consumer) { - throw new OAuthException("Invalid consumer"); - } - - return $consumer; - } - - /** - * try to find the token for the provided request's token key - */ - private function get_token(&$request, $consumer, $token_type="access") { - $token_field = @$request->get_parameter('oauth_token'); - if ( !$token_field) return false; - $token = $this->data_store->lookup_token( - $consumer, $token_type, $token_field - ); - if (!$token) { - throw new OAuthException("Invalid $token_type token: $token_field"); - } - return $token; - } - - /** - * all-in-one function to check the signature on a request - * should guess the signature method appropriately - */ - private function check_signature(&$request, $consumer, $token) { - // this should probably be in a different method - global $OAuth_last_computed_signature; - $OAuth_last_computed_signature = false; - - $timestamp = @$request->get_parameter('oauth_timestamp'); - $nonce = @$request->get_parameter('oauth_nonce'); - - $this->check_timestamp($timestamp); - $this->check_nonce($consumer, $token, $nonce, $timestamp); - - $signature_method = $this->get_signature_method($request); - - $signature = $request->get_parameter('oauth_signature'); - $valid_sig = $signature_method->check_signature( - $request, - $consumer, - $token, - $signature - ); - - if (!$valid_sig) { - $ex_text = "Invalid signature"; - if ( $OAuth_last_computed_signature ) { - $ex_text = $ex_text . " ours= $OAuth_last_computed_signature yours=$signature"; - } - throw new OAuthException($ex_text); - } - } - - /** - * check that the timestamp is new enough - */ - private function check_timestamp($timestamp) { - // verify that timestamp is recentish - $now = time(); - if ($now - $timestamp > $this->timestamp_threshold) { - throw new OAuthException( - "Expired timestamp, yours $timestamp, ours $now" - ); - } - } - - /** - * check that the nonce is not repeated - */ - private function check_nonce($consumer, $token, $nonce, $timestamp) { - // verify that the nonce is uniqueish - $found = $this->data_store->lookup_nonce( - $consumer, - $token, - $nonce, - $timestamp - ); - if ($found) { - throw new OAuthException("Nonce already used: $nonce"); - } - } - -} - -class OAuthDataStore { - function lookup_consumer($consumer_key) { - // implement me - } - - function lookup_token($consumer, $token_type, $token) { - // implement me - } - - function lookup_nonce($consumer, $token, $nonce, $timestamp) { - // implement me - } - - function new_request_token($consumer) { - // return a new token attached to this consumer - } - - function new_access_token($token, $consumer) { - // return a new access token attached to this consumer - // for the user associated with this token if the request token - // is authorized - // should also invalidate the request token - } - -} - -class OAuthUtil { - public static function urlencode_rfc3986($input) { - if (is_array($input)) { - return array_map(array('OAuthUtil', 'urlencode_rfc3986'), $input); - } else if (is_scalar($input)) { - return str_replace( - '+', - ' ', - str_replace('%7E', '~', rawurlencode($input)) - ); - } else { - return ''; - } -} - - - // This decode function isn't taking into consideration the above - // modifications to the encoding process. However, this method doesn't - // seem to be used anywhere so leaving it as is. - public static function urldecode_rfc3986($string) { - return urldecode($string); - } - - // Utility function for turning the Authorization: header into - // parameters, has to do some unescaping - // Can filter out any non-oauth parameters if needed (default behaviour) - public static function split_header($header, $only_allow_oauth_parameters = true) { - $pattern = '/(([-_a-z]*)=("([^"]*)"|([^,]*)),?)/'; - $offset = 0; - $params = array(); - while (preg_match($pattern, $header, $matches, PREG_OFFSET_CAPTURE, $offset) > 0) { - $match = $matches[0]; - $header_name = $matches[2][0]; - $header_content = (isset($matches[5])) ? $matches[5][0] : $matches[4][0]; - if (preg_match('/^oauth_/', $header_name) || !$only_allow_oauth_parameters) { - $params[$header_name] = OAuthUtil::urldecode_rfc3986($header_content); - } - $offset = $match[1] + strlen($match[0]); - } - - if (isset($params['realm'])) { - unset($params['realm']); - } - - return $params; - } - - // helper to try to sort out headers for people who aren't running apache - public static function get_headers() { - if (function_exists('apache_request_headers')) { - // we need this to get the actual Authorization: header - // because apache tends to tell us it doesn't exist - return apache_request_headers(); - } - // otherwise we don't have apache and are just going to have to hope - // that $_SERVER actually contains what we need - $out = array(); - foreach ($_SERVER as $key => $value) { - if (substr($key, 0, 5) == "HTTP_") { - // this is chaos, basically it is just there to capitalize the first - // letter of every word that is not an initial HTTP and strip HTTP - // code from przemek - $key = str_replace( - " ", - "-", - ucwords(strtolower(str_replace("_", " ", substr($key, 5)))) - ); - $out[$key] = $value; - } - } - return $out; - } - - // This function takes a input like a=b&a=c&d=e and returns the parsed - // parameters like this - // array('a' => array('b','c'), 'd' => 'e') - public static function parse_parameters( $input ) { - if (!isset($input) || !$input) return array(); - - $pairs = explode('&', $input); - - $parsed_parameters = array(); - foreach ($pairs as $pair) { - $split = explode('=', $pair, 2); - $parameter = OAuthUtil::urldecode_rfc3986($split[0]); - $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : ''; - - if (isset($parsed_parameters[$parameter])) { - // We have already recieved parameter(s) with this name, so add to the list - // of parameters with this name - - if (is_scalar($parsed_parameters[$parameter])) { - // This is the first duplicate, so transform scalar (string) into an array - // so we can add the duplicates - $parsed_parameters[$parameter] = array($parsed_parameters[$parameter]); - } - - $parsed_parameters[$parameter][] = $value; - } else { - $parsed_parameters[$parameter] = $value; - } - } - return $parsed_parameters; - } - - public static function build_http_query($params) { - if (!$params) return ''; - - // Urlencode both keys and values - $keys = OAuthUtil::urlencode_rfc3986(array_keys($params)); - $values = OAuthUtil::urlencode_rfc3986(array_values($params)); - $params = array_combine($keys, $values); - - // Parameters are sorted by name, using lexicographical byte value ordering. - // Ref: Spec: 9.1.1 (1) - uksort($params, 'strcmp'); - - $pairs = array(); - foreach ($params as $parameter => $value) { - if (is_array($value)) { - // If two or more parameters share the same name, they are sorted by their value - // Ref: Spec: 9.1.1 (1) - natsort($value); - foreach ($value as $duplicate_value) { - $pairs[] = $parameter . '=' . $duplicate_value; - } - } else { - $pairs[] = $parameter . '=' . $value; - } - } - // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61) - // Each name-value pair is separated by an '&' character (ASCII code 38) - return implode('&', $pairs); - } -} - -?> diff --git a/mods/basiclti/launch/ims-blti/blti.php b/mods/basiclti/launch/ims-blti/blti.php deleted file mode 100644 index 024f04bfe..000000000 --- a/mods/basiclti/launch/ims-blti/blti.php +++ /dev/null @@ -1,325 +0,0 @@ -consumers[$consumer_key] = $consumer_secret; - } - - function lookup_consumer($consumer_key) { - if ( strpos($consumer_key, "http://" ) === 0 ) { - $consumer = new OAuthConsumer($consumer_key,"secret", NULL); - return $consumer; - } - if ( $this->consumers[$consumer_key] ) { - $consumer = new OAuthConsumer($consumer_key,$this->consumers[$consumer_key], NULL); - return $consumer; - } - return NULL; - } - - function lookup_token($consumer, $token_type, $token) { - return new OAuthToken($consumer, ""); - } - - // Return NULL if the nonce has not been used - // Return $nonce if the nonce was previously used - function lookup_nonce($consumer, $token, $nonce, $timestamp) { - // Should add some clever logic to keep nonces from - // being reused - for no we are really trusting - // that the timestamp will save us - return NULL; - } - - function new_request_token($consumer) { - return NULL; - } - - function new_access_token($token, $consumer) { - return NULL; - } -} - - -// Basic LTI Class that does the setup and provides utility -// functions -class BLTI { - - public $valid = false; - public $complete = false; - public $message = false; - public $basestring = false; - public $info = false; - public $row = false; - public $context_id = false; // Override context_id - - function __construct($parm=false, $usesession=true, $doredirect=true) { - - // If this request is not an LTI Launch, either - // give up or try to retrieve the context from session - if ( ! is_basic_lti_request() ) { - if ( $usesession === false ) return; - if ( strlen(session_id()) > 0 ) { - $row = $_SESSION['_basiclti_lti_row']; - if ( isset($row) ) $this->row = $row; - $context_id = $_SESSION['_basiclti_lti_context_id']; - if ( isset($context_id) ) $this->context_id = $context_id; - $info = $_SESSION['_basic_lti_context']; - if ( isset($info) ) { - $this->info = $info; - $this->valid = true; - return; - } - $this->message = "Could not find context in session"; - return; - } - $this->message = "Session not available"; - return; - } - - // Insure we have a valid launch - if ( empty($_REQUEST["oauth_consumer_key"]) ) { - $this->message = "Missing oauth_consumer_key in request"; - return; - } - $oauth_consumer_key = $_REQUEST["oauth_consumer_key"]; - - // Find the secret - either form the parameter as a string or - // look it up in a database from parameters we are given - $secret = false; - $row = false; - if ( is_string($parm) ) { - $secret = $parm; - } else if ( ! is_array($parm) ) { - $this->message = "Constructor requires a secret or database information."; - return; - } else { - global $addslashes; - $sql = 'SELECT * FROM '.$parm['table'].' WHERE '. - ($parm['key_column'] ? $parm['key_column'] : 'oauth_consumer_key'). - '='. - "'".$addslashes($oauth_consumer_key)."'"; - $result = mysql_query($sql); - $num_rows = mysql_num_rows($result); - if ( $num_rows != 1 ) { - $this->message = "Your consumer is not authorized oauth_consumer_key=".$oauth_consumer_key; - return; - } else { - while ($row = mysql_fetch_assoc($result)) { - $secret = $row[$parms['secret_column']?$parms['secret_column']:'secret']; - $context_id = $row[$parms['context_column']?$parms['context_column']:'context_id']; - if ( $context_id ) $this->context_id = $context_id; - $this->row = $row; - break; - } - if ( ! is_string($secret) ) { - $this->message = "Could not retrieve secret oauth_consumer_key=".$oauth_consumer_key; - return; - } - } - } - - // Verify the message signature - $store = new TrivialOAuthDataStore(); - $store->add_consumer($oauth_consumer_key, $secret); - - $server = new OAuthServer($store); - - $method = new OAuthSignatureMethod_HMAC_SHA1(); - $server->add_signature_method($method); - $request = OAuthRequest::from_request(); - - $this->basestring = $request->get_signature_base_string(); - - try { - $server->verify_request($request); - $this->valid = true; - } catch (Exception $e) { - $this->message = $e->getMessage(); - return; - } - - // Store the launch information in the session for later - $newinfo = array(); - foreach($_POST as $key => $value ) { - if ( $key == "basiclti_submit" ) continue; - if ( strpos($key, "oauth_") === false ) { - $newinfo[$key] = $value; - continue; - } - if ( $key == "oauth_consumer_key" ) { - $newinfo[$key] = $value; - continue; - } - } - - $this->info = $newinfo; - if ( $usesession == true and strlen(session_id()) > 0 ) { - $_SESSION['_basic_lti_context'] = $this->info; - unset($_SESSION['_basiclti_lti_row']); - unset($_SESSION['_basiclti_lti_context_id']); - if ( $this->row ) $_SESSION['_basiclti_lti_row'] = $this->row; - if ( $this->context_id ) $_SESSION['_basiclti_lti_context_id'] = $this->context_id; - } - - if ( $this->valid && $doredirect ) { - $this->redirect(); - $this->complete = true; - } - } - - function addSession($location) { - if ( ini_get('session.use_cookies') == 0 ) { - if ( strpos($location,'?') > 0 ) { - $location = $location . '&'; - } else { - $location = $location . '?'; - } - $location = $location . session_name() . '=' . session_id(); - } - return $location; - } - - function isInstructor() { - $roles = $this->info['roles']; - $roles = strtolower($roles); - if ( ! ( strpos($roles,"instructor") === false ) ) return true; - if ( ! ( strpos($roles,"administrator") === false ) ) return true; - return false; - } - - function getUserEmail() { - $email = $this->info['lis_person_contact_email_primary']; - if ( strlen($email) > 0 ) return $email; - # Sakai Hack - $email = $this->info['lis_person_contact_emailprimary']; - if ( strlen($email) > 0 ) return $email; - return false; - } - - function getUserShortName() { - $email = $this->getUserEmail(); - $givenname = $this->info['lis_person_name_given']; - $familyname = $this->info['lis_person_name_family']; - $fullname = $this->info['lis_person_name_full']; - if ( strlen($email) > 0 ) return $email; - if ( strlen($givenname) > 0 ) return $givenname; - if ( strlen($familyname) > 0 ) return $familyname; - return $this->getUserName(); - } - - function getUserName() { - $givenname = $this->info['lis_person_name_given']; - $familyname = $this->info['lis_person_name_family']; - $fullname = $this->info['lis_person_name_full']; - if ( strlen($fullname) > 0 ) return $fullname; - if ( strlen($familyname) > 0 and strlen($givenname) > 0 ) return $givenname + $familyname; - if ( strlen($givenname) > 0 ) return $givenname; - if ( strlen($familyname) > 0 ) return $familyname; - return $this->getUserEmail(); - } - - function getUserKey() { - $oauth = $this->info['oauth_consumer_key']; - $id = $this->info['user_id']; - if ( strlen($id) > 0 and strlen($oauth) > 0 ) return $oauth . ':' . $id; - return false; - } - - function getUserImage() { - $image = $this->info['user_image']; - if ( strlen($image) > 0 ) return $image; - $email = $this->getUserEmail(); - if ( $email === false ) return false; - $size = 40; - $grav_url = $_SERVER['HTTPS'] ? 'https://' : 'http://'; - $grav_url = $grav_url . "www.gravatar.com/avatar.php?gravatar_id=".md5( strtolower($email) )."&size=".$size; - return $grav_url; - } - - function getResourceKey() { - $oauth = $this->info['oauth_consumer_key']; - $id = $this->info['resource_link_id']; - if ( strlen($id) > 0 and strlen($oauth) > 0 ) return $oauth . ':' . $id; - return false; - } - - function getResourceTitle() { - $title = $this->info['resource_link_title']; - if ( strlen($title) > 0 ) return $title; - return false; - } - - function getConsumerKey() { - $oauth = $this->info['oauth_consumer_key']; - return $oauth; - } - - function getCourseKey() { - if ( $this->context_id ) return $this->context_id; - $oauth = $this->info['oauth_consumer_key']; - $id = $this->info['context_id']; - if ( strlen($id) > 0 and strlen($oauth) > 0 ) return $oauth . ':' . $id; - return false; - } - - function getCourseName() { - $label = $this->info['context_label']; - $title = $this->info['context_title']; - $id = $this->info['context_id']; - if ( strlen($label) > 0 ) return $label; - if ( strlen($title) > 0 ) return $title; - if ( strlen($id) > 0 ) return $id; - return false; - } - - // TODO: Add javasript version if headers are already sent - function redirect() { - $host = $_SERVER['HTTP_HOST']; - $uri = $_SERVER['PHP_SELF']; - $location = $_SERVER['HTTPS'] ? 'https://' : 'http://'; - $location = $location . $host . $uri; - $location = $this->addSession($location); - header("Location: $location"); - } - - function dump() { - if ( ! $this->valid or $this->info == false ) return "Context not valid\n"; - $ret = ""; - if ( $this->isInstructor() ) { - $ret .= "isInstructor() = true\n"; - } else { - $ret .= "isInstructor() = false\n"; - } - $ret .= "getUserKey() = ".$this->getUserKey()."\n"; - $ret .= "getUserEmail() = ".$this->getUserEmail()."\n"; - $ret .= "getUserShortName() = ".$this->getUserShortName()."\n"; - $ret .= "getUserName() = ".$this->getUserName()."\n"; - $ret .= "getUserImage() = ".$this->getUserImage()."\n"; - $ret .= "getResourceKey() = ".$this->getResourceKey()."\n"; - $ret .= "getResourceTitle() = ".$this->getResourceTitle()."\n"; - $ret .= "getCourseName() = ".$this->getCourseName()."\n"; - $ret .= "getCourseKey() = ".$this->getCourseKey()."\n"; - $ret .= "getConsumerKey() = ".$this->getConsumerKey()."\n"; - return $ret; - } - -} - -?> diff --git a/mods/basiclti/launch/ims-blti/blti_util.php b/mods/basiclti/launch/ims-blti/blti_util.php deleted file mode 100644 index eb67c9930..000000000 --- a/mods/basiclti/launch/ims-blti/blti_util.php +++ /dev/null @@ -1,225 +0,0 @@ - "120988f929-274612", - "resource_link_title" => "Weekly Blog", - "resource_link_description" => "Each student needs to reflect on the weekly reading. These should be one paragraph long.", - "user_id" => "292832126", - "roles" => "Instructor", // or Learner - "lis_person_name_full" => 'Jane Q. Public', - "lis_person_contact_email_primary" => "user@school.edu", - "lis_person_sourcedid" => "school.edu:user", - "context_id" => "456434513", - "context_title" => "Design of Personal Environments", - "context_label" => "SI182", - ); - - return $parms; - } - - function validateDescriptor($descriptor) - { - $xml = new SimpleXMLElement($xmldata); - if ( ! $xml ) { - echo("Error parsing Descriptor XML\n"); - return; - } - $launch_url = $xml->secure_launch_url[0]; - if ( ! $launch_url ) $launch_url = $xml->launch_url[0]; - if ( $launch_url ) $launch_url = (string) $launch_url; - return $launch_url; - } - - // Parse a descriptor - function launchInfo($xmldata) { - $xml = new SimpleXMLElement($xmldata); - if ( ! $xml ) { - echo("Error parsing Descriptor XML\n"); - return; - } - $launch_url = $xml->secure_launch_url[0]; - if ( ! $launch_url ) $launch_url = $xml->launch_url[0]; - if ( $launch_url ) $launch_url = (string) $launch_url; - $custom = array(); - if ( $xml->custom[0]->parameter ) - foreach ( $xml->custom[0]->parameter as $resource) { - $key = (string) $resource['key']; - $key = strtolower($key); - $nk = ""; - for($i=0; $i < strlen($key); $i++) { - $ch = substr($key,$i,1); - if ( $ch >= "a" && $ch <= "z" ) $nk .= $ch; - else if ( $ch >= "0" && $ch <= "9" ) $nk .= $ch; - else $nk .= "_"; - } - $value = (string) $resource; - $custom["custom_".$nk] = $value; - } - return array("launch_url" => $launch_url, "custom" => $custom ) ; - } - -function split_custom_parameters($custom) { - $retval = array(); - return merge_custom_parameters($retval, $custom); -} - -function merge_custom_parameters($retval, $custom) { - $lines = preg_split("/[\n;]/",$custom); - foreach ($lines as $line){ - $pos = strpos($line,"="); - if ( $pos === false || $pos < 1 ) continue; - $key = trim(substr($line, 0, $pos)); - $val = trim(substr($line, $pos+1)); - $key = 'custom_'.map_keyname($key); - if ( isset($retval[$key])) continue; - $retval[$key] = $val; - } - return $retval; -} - -function map_keyname($key) { - $newkey = ""; - $key = strtolower(trim($key)); - foreach (str_split($key) as $ch) { - if ( ($ch >= 'a' && $ch <= 'z') || ($ch >= '0' && $ch <= '9') ) { - $newkey .= $ch; - } else { - $newkey .= '_'; - } - } - return $newkey; -} - -function signParameters($oldparms, $endpoint, $method, $oauth_consumer_key, $oauth_consumer_secret, - $submit_text = false, $org_id = false, $org_desc = false) -{ - global $last_base_string; - $parms = $oldparms; - if ( ! isset($parms["lti_version"]) ) $parms["lti_version"] = "LTI-1p0"; - if ( ! isset($parms["lti_message_type"]) ) $parms["lti_message_type"] = "basic-lti-launch-request"; - if ( ! isset($parms["oauth_callback"]) ) $parms["oauth_callback"] = "about:blank"; - if ( $org_id ) $parms["tool_consumer_instance_guid"] = $org_id; - if ( $org_desc ) $parms["tool_consumer_instance_description"] = $org_desc; - if ( $submit_text ) $parms["ext_submit"] = $submit_text; - - $test_token = ''; - - $hmac_method = new OAuthSignatureMethod_HMAC_SHA1(); - $test_consumer = new OAuthConsumer($oauth_consumer_key, $oauth_consumer_secret, NULL); - - $acc_req = OAuthRequest::from_consumer_and_token($test_consumer, $test_token, $method, $endpoint, $parms); - $acc_req->sign_request($hmac_method, $test_consumer, $test_token); - - // Pass this back up "out of band" for debugging - $last_base_string = $acc_req->get_signature_base_string(); - - $newparms = $acc_req->get_parameters(); - - return $newparms; -} - -function postLaunchHTML($newparms, $endpoint, $debug=false, $iframeattr=false) { - global $last_base_string; - $r = "
    \n"; - if ( $iframeattr ) { - $r = "
    \n" ; - } else { - $r = "\n" ; - } - $submit_text = $newparms['ext_submit']; - foreach($newparms as $key => $value ) { - $key = htmlspecialchars($key); - $value = htmlspecialchars($value); - if ( $key == "ext_submit" ) { - $r .= "\n"; - } - if ( $debug ) { - $r .= "\n"; - $r .= ""; - $r .= get_string("toggle_debug_data","basiclti")."\n"; - $r .= "
    \n"; - $r .= "".get_string("basiclti_endpoint","basiclti")."
    \n"; - $r .= $endpoint . "
    \n 
    \n"; - $r .= "".get_string("basiclti_parameters","basiclti")."
    \n"; - foreach($newparms as $key => $value ) { - $key = htmlspecialchars($key); - $value = htmlspecialchars($value); - $r .= "$key = $value
    \n"; - } - $r .= " 
    \n"; - $r .= "

    ".get_string("basiclti_base_string","basiclti")."
    \n".$last_base_string."

    \n"; - $r .= "
    \n"; - } - $r .= "
    \n"; - if ( $iframeattr ) { - $r .= "\n"; - } - if ( ! $debug ) { - $ext_submit = "ext_submit"; - $ext_submit_text = $submit_text; - $r .= " \n"; - } - $r .= "
    \n"; - return $r; -} - -/* This is a bit of homage to Moodle's pattern of internationalisation */ -function get_string($key,$bundle) { - return $key; -} - -function do_post_request($url, $data, $optional_headers = null) -{ - $params = array('http' => array( - 'method' => 'POST', - 'content' => $data - )); - if ($optional_headers !== null) { - $params['http']['header'] = $optional_headers; - } - $ctx = stream_context_create($params); - $fp = @fopen($url, 'rb', false, $ctx); - if (!$fp) { - throw new Exception("Problem with $url, $php_errormsg"); - } - $response = @stream_get_contents($fp); - if ($response === false) { - throw new Exception("Problem reading data from $url, $php_errormsg"); - } - return $response; -} - diff --git a/mods/basiclti/launch/launch.php b/mods/basiclti/launch/launch.php deleted file mode 100644 index 9bc5790f8..000000000 --- a/mods/basiclti/launch/launch.php +++ /dev/null @@ -1,120 +0,0 @@ -\n");print_r($basiclti_content_row); echo("
    \n"); -// echo("basiclti_tool_row
    \n");print_r($basiclti_tool_row); echo("
    \n"); -// echo("atutor_content_row
    \n");print_r($atutor_content_row); echo("
    \n"); -// echo("atutor_course_row
    \n");print_r($atutor_course_row); echo("
    \n"); -// echo("atutor_member_row
    \n");print_r($atutor_member_row); echo("
    \n"); -// echo("atutor_course_membership_row
    \n");print_r($atutor_course_membership_row); echo("
    \n"); - - $lmsdata = array( - "resource_link_id" => $cid, - "resource_link_title" => $atutor_content_row['title'], - "resource_link_description" => $atutor_content_row['text'], - "user_id" => $atutor_member_row['member_id'], - "roles" => "Learner", - "launch_presentation_locale" => $_SESSION['lang'], - "context_id" => $atutor_course_row['course_id'], - "context_title" => $atutor_course_row['title'], - "context_label" => $atutor_course_row['title'], - ); - - $lmsdata['ext_lms'] = 'ATutor'; - - if ( $atutor_course_membership_row['role'] == 'Instructor' ) { - $lmsdata["roles"] = 'Instructor'; - } - - if ( $_SESSION['is_admin'] == 1 ) { - $lmsdata["roles"] = 'Instructor'; - } - - if ( $basiclti_tool_row['sendemailaddr'] == 1 || - ( $basiclti_tool_row['sendemailaddr'] == 2 && $basiclti_content_row['sendemailaddr'] == 1 ) ) { - $lmsdata["lis_person_contact_email_primary"] = $atutor_member_row['email']; - } - - if ( $basiclti_tool_row['sendname'] == 1 || - ( $basiclti_tool_row['sendname'] == 2 && $basiclti_content_row['sendname'] == 1 ) ) { - $lmsdata["lis_person_name_family"] = $atutor_member_row['last_name']; - $lmsdata["lis_person_name_given"] = $atutor_member_row['first_name']; - } - - $placementsecret = $basiclti_content_row['placementsecret']; - $sourcedid = false; - if ( isset($placementsecret) && strlen($placementsecret) > 0 ) { - $suffix = ':::' . $atutor_member_row['member_id'] . ':::' . $cid; - $plaintext = $placementsecret . $suffix; - $hashsig = hash('sha256', $plaintext, false); - $sourcedid = $hashsig . $suffix; - } - - if ( $sourcedid !== false && - ( $basiclti_tool_row['acceptgrades'] == 1 && $basiclti_content_row['gradebook_test_id'] != 0 ) ) { - $lmsdata["lis_result_sourcedid"] = $sourcedid; - $lmsdata["ext_ims_lis_basic_outcome_url"] = AT_BASE_HREF.'mods/basiclti/launch/service.php'; - } - - if ( $sourcedid !== false && - ( $basiclti_tool_row['allowroster'] == 1 || - ( $basiclti_tool_row['allowroster'] == 2 && $basiclti_content_row['allowroster'] == 1 ) ) ) { - $lmsdata["ext_ims_lis_memberships_id"] = $sourcedid; - $lmsdata["ext_ims_lis_memberships_url"] = AT_BASE_HREF.'mods/basiclti/launch/service.php'; - } - - if ( $sourcedid !== false && - ( $basiclti_tool_row['allowsetting'] == 1 || - ( $basiclti_tool_row['allowsetting'] == 2 && $basiclti_content_row['allowsetting'] == 1 ) ) ) { - $lmsdata["ext_ims_lti_tool_setting_id"] = $sourcedid; - $lmsdata["ext_ims_lti_tool_setting_url"] = AT_BASE_HREF.'mods/basiclti/launch/service.php'; - $setting = $basiclti_content_row['setting']; - if ( isset($setting) ) { - $lmsdata["ext_ims_lti_tool_setting"] = $setting; - } - } - -require_once("ims-blti/blti_util.php"); - - if ( strlen($basiclti_tool_row['customparameters']) > 0 ) { - $lmsdata = merge_custom_parameters($lmsdata,$basiclti_tool_row['customparameters']); - } - if ( $basiclti_tool_row['customparameters'] == 1 && strlen($basiclti_content_row['customparameters']) > 0 ) { - $lmsdata = merge_custom_parameters($lmsdata,$basiclti_content_row['customparameters']); - } - -// print_r($lmsdata);echo("
    \n"); - -$parms = $lmsdata; - -$endpoint = $basiclti_tool_row['toolurl']; -$key = $basiclti_tool_row['resourcekey']; -$secret = $basiclti_tool_row['password']; - - $parms = signParameters($parms, $endpoint, "POST", $key, $secret, "Press to Launch", $tool_consumer_instance_guid, $tool_consumer_instance_description); - - $debuglaunch = false; - if ( ( $basiclti_tool_row['debuglaunch'] == 1 || - ( $basiclti_tool_row['debuglaunch'] == 2 && $basiclti_content_row['debuglaunch'] == 1 ) ) ) { - $debuglaunch = true; - } - - $content = postLaunchHTML($parms, $endpoint, $debuglaunch); - - print($content); - - -?> diff --git a/mods/basiclti/launch/loadrows.php b/mods/basiclti/launch/loadrows.php deleted file mode 100644 index 2ddc05b7f..000000000 --- a/mods/basiclti/launch/loadrows.php +++ /dev/null @@ -1,65 +0,0 @@ -\n");print_r($basiclti_content_row); echo("
    \n"); - -$toolid = $basiclti_content_row['toolid']; -$sql = "SELECT * FROM ".TABLE_PREFIX."basiclti_tools - WHERE toolid='".$toolid."'"; -$contentresult = mysql_query($sql, $db); -$basiclti_tool_row = mysql_fetch_assoc($contentresult); -if ( ! $basiclti_tool_row ) { - loadError("Tool definition missing\n"); - exit; -} -// echo("basiclti_tool_row
    \n");print_r($basiclti_tool_row); echo("
    \n"); - -$sql = "SELECT * FROM ".TABLE_PREFIX."content - WHERE content_id=".$content_id; -$contentresult = mysql_query($sql, $db); -$atutor_content_row = mysql_fetch_assoc($contentresult); -if ( ! $atutor_content_row ) { - loadError("Not Configured\n"); - exit; -} -// echo("atutor_content_row
    \n");print_r($atutor_content_row); echo("
    \n"); - -$sql = "SELECT * FROM ".TABLE_PREFIX."courses - WHERE course_id='".$atutor_content_row['course_id']."'"; -$courseresult = mysql_query($sql, $db); -$atutor_course_row = mysql_fetch_assoc($courseresult); -if ( ! $atutor_course_row ) { - loadError("Course definition missing\n"); - exit; -} -// echo("atutor_course_row
    \n");print_r($atutor_course_row); echo("
    \n"); - -$sql = "SELECT * FROM ".TABLE_PREFIX."course_enrollment - WHERE member_id='".$member_id."'"; -$enrollresult = mysql_query($sql, $db); -$atutor_course_enrollment_row = mysql_fetch_assoc($enrollresult); -if ( ! $atutor_course_enrollment_row ) { - loadError("Course enrollment missing\n"); - exit; -} -// echo("atutor_course_enrollment_row
    \n");print_r($atutor_course_enrollment_row); echo("
    \n"); - -$sql = "SELECT * FROM ".TABLE_PREFIX."members - WHERE member_id='".$member_id."'"; -$memberresult = mysql_query($sql, $db); -$atutor_member_row = mysql_fetch_assoc($memberresult); -if ( ! $atutor_member_row ) { - loadError("Course definition missing\n"); - exit; -} -// echo("atutor_member_row
    \n");print_r($atutor_member_row); echo("
    \n"); - -?> diff --git a/mods/basiclti/launch/service.php b/mods/basiclti/launch/service.php deleted file mode 100644 index 1d59f14e5..000000000 --- a/mods/basiclti/launch/service.php +++ /dev/null @@ -1,336 +0,0 @@ -'."\n" . - "\n" . - " $lti_message_type\n" . - " \n" . - " $major\n" . - " $severity\n"; - if ( ! $codeminor === false ) $retval = $retval . " $minor\n"; - $retval = $retval . - " $message\n" . - " \n"; - if ( ! $xml === false ) $retval = $retval . $xml; - $retval = $retval . "\n"; - return $retval; - } - - function doError($message) { - print message_response('Fail', 'Error', false, $message); - exit(); - } - - $lti_version = $_REQUEST['lti_version']; - if ( $lti_version != "LTI-1p0" ) doError("Improperly formed message"); - - $lti_message_type = $_REQUEST['lti_message_type']; - if ( ! isset($lti_message_type) ) doError("Improperly formed message"); - - $message_type = false; - if( $lti_message_type == "basic-lis-replaceresult" || - $lti_message_type == "basic-lis-createresult" || - $lti_message_type == "basic-lis-updateresult" || - $lti_message_type == "basic-lis-deleteresult" || - $lti_message_type == "basic-lis-readresult" ) { - $sourcedid = $_REQUEST['sourcedid']; - $message_type = "basicoutcome"; - } else if ( $lti_message_type == "basic-lti-loadsetting" || - $lti_message_type == "basic-lti-savesetting" || - $lti_message_type == "basic-lti-deletesetting" ) { - $sourcedid = $_REQUEST['id']; - $message_type = "toolsetting"; - } else if ( $lti_message_type == "basic-lis-readmembershipsforcontext") { - $sourcedid = $_REQUEST['id']; - $message_type = "roster"; - } - - if ( $message_type == false ) { - doError("Illegal lti_message_type"); - } - - if ( !isset($sourcedid) ) { - doError("sourcedid missing"); - } - // Truncate to maximum length - $sourcedid = substr($sourcedid, 0, 2048); - - try { - $info = explode(':::',$sourcedid); - if ( ! is_array($info) ) doError("Bad sourcedid"); - $signature = $info[0]; - $userid = intval($info[1]); - $placement = $info[2]; - } - catch(Exception $e) { - doError("Bad sourcedid"); - } - - if ( isset($signature) && isset($userid) && isset($placement) ) { - // OK - } else { - doError("Bad sourcedid"); - } - -function loadError($msg) { - doError($msg); -} - -$content_id = $placement; -$member_id = $userid; -require("loadrows.php"); -$course_id = $atutor_content_row['course_id']; -// echo("basiclti_content_row
    \n");print_r($basiclti_content_row); echo("
    \n"); -// echo("basiclti_tool_row
    \n");print_r($basiclti_tool_row); echo("
    \n"); -// echo("atutor_content_row
    \n");print_r($atutor_content_row); echo("
    \n"); -// echo("atutor_course_row
    \n");print_r($atutor_course_row); echo("
    \n"); -// These two might not be important here -// echo("atutor_member_row
    \n");print_r($atutor_member_row); echo("
    \n"); -// echo("atutor_course_membership_row
    \n");print_r($atutor_course_membership_row); echo("
    \n"); - - if ( $message_type == "basicoutcome" ) { - if ( $basiclti_tool_row['acceptgrades'] == 1 && $basiclti_content_row['gradebook_test_id'] > 0 ) { - // The placement is configured to accept grades - } else { - doError("Not permitted"); - } - } else if ( $message_type == "roster" ) { - if ( $basiclti_tool_row['allowroster'] == 1 || - ( $basiclti_tool_row['allowroster'] == 2 && $basiclti_content_row['allowroster'] == 1 ) ) { - // OK - } else { - doError("Not permitted"); - } - } else if ( $message_type == "toolsetting" ) { - if ( $basiclti_tool_row['allowsetting'] == 1 || - ( $basiclti_tool_row['allowsetting'] == 2 && $basiclti_content_row['allowsetting'] == 1 ) ) { - // OK - } else { - doError("Not permitted"); - } - } - - // Retrieve the secret we use to sign lis_result_sourcedid - $placementsecret = $basiclti_content_row['placementsecret']; - $oldplacementsecret = $basiclti_content_row['oldplacementsecret']; - if ( ! isset($placementsecret) ) doError("Not permitted"); - - $suffix = ':::' . $userid . ':::' . $placement; - $plaintext = $placementsecret . $suffix; - $hashsig = hash('sha256', $plaintext, false); - if ( $hashsig != $signature && isset($oldplacementsecret) && strlen($oldplacementsecret) > 1 ) { - $plaintext = $oldplacementsecret . $suffix; - $hashsig = hash('sha256', $plaintext, false); - } - - if ( $hashsig != $signature ) { - doError("Invalid sourcedid"); - } - - // Check the OAuth Signature - $oauth_consumer_key = $basiclti_tool_row['resourcekey']; - $oauth_secret = $basiclti_tool_row['password']; - - if ( ! isset($oauth_secret) ) doError("Not permitted"); - if ( ! isset($oauth_consumer_key) ) doError("Not permitted"); - - // Verify the message signature - $store = new TrivialOAuthDataStore(); - $store->add_consumer($oauth_consumer_key, $oauth_secret); - - $server = new OAuthServer($store); - - $method = new OAuthSignatureMethod_HMAC_SHA1(); - $server->add_signature_method($method); - $request = OAuthRequest::from_request(); - - $basestring = $request->get_signature_base_string(); - - try { - $server->verify_request($request); - } catch (Exception $e) { - doError($e->getMessage()); - } - - // Beginning of actual grade processing - if ( $message_type == "basicoutcome" ) { - if ( ! isset( $basiclti_content_row['gradebook_test_id'] ) ) { - doError("Not permitted"); - } - - // TODO: Greg - Is this appropriate? It would be nice to allow this. - if ( $atutor_course_membership_row['role'] == 'Instructor' ) { - doError('Grades not supported for instructors'); - } - - $gradebook_test_id = $basiclti_content_row['gradebook_test_id']; - - // Check to see if this grade is in this course and member is in this course - // And that this grade item is of the right type - $sql = 'SELECT role,m.member_id AS member_id,first_name,last_name,email - FROM '.TABLE_PREFIX.'gradebook_tests AS g - JOIN '.TABLE_PREFIX.'course_enrollment AS e - JOIN '.TABLE_PREFIX.'members AS m - ON g.course_id = e.course_id AND e.member_id = m.member_id - WHERE e.course_id = '.$course_id.' AND m.member_id ='.$member_id.' - AND g.gradebook_test_id = '.$gradebook_test_id." - AND g.type = 'External' and g.grade_scale_id = 0"; - $gradebook_result = mysql_query($sql, $db); - $count = mysql_num_rows($gradebook_result); - if ( $count < 1 ) { - doError("Not gradable"); - } - - $read_sql = 'SELECT d.grade AS grade - FROM '.TABLE_PREFIX.'gradebook_detail AS d - JOIN '.TABLE_PREFIX.'gradebook_tests AS g - JOIN '.TABLE_PREFIX.'course_enrollment AS e - JOIN '.TABLE_PREFIX.'members AS m - ON d.gradebook_test_id = g.gradebook_test_id - AND g.course_id = e.course_id AND e.member_id = m.member_id - WHERE e.course_id = '.$course_id.' AND d.member_id ='.$member_id.' - AND g.gradebook_test_id = '.$gradebook_test_id." - AND g.type = 'External' and g.grade_scale_id = 0"; - - if ( $lti_message_type == "basic-lis-readresult" ) { - $grade_result = mysql_query($read_sql, $db); - $count = mysql_num_rows($gradebook_result); - if ( $count < 1 ) { - doError("Not gradable"); - } - unset($grade); - $grade_row = mysql_fetch_assoc($grade_result); - if ( $grade_row === false ) { - // Skip - } else if ( isset($grade_row['grade']) ) { - $grade = $grade_row['grade']; - } - - if ( ! isset($grade) ) { - doError("Unable to read grade"); - } - - $result = " \n" . - " \n" . - " " . - htmlspecialchars($grade*1.0) . - "\n" . - " \n" . - " \n"; - print message_response('Success', 'Status', false, "Grade read", $result); - exit(); - } - - if ( $lti_message_type == "basic-lis-deleteresult" ) { - $delete_sql = 'DELETE FROM '.TABLE_PREFIX.'gradebook_detail - WHERE member_id ='.$member_id.' - AND gradebook_test_id = '.$gradebook_test_id; - - $gradebook_result = mysql_query($delete_sql, $db); - if ( $gradebook_result === false ) { - doError("Could not delete grade"); - } - print message_response('Success', 'Status', 'fullsuccess', 'Grade deleted'); - - } else { // Replace - $gradeval = -1.0; - if ( isset($_REQUEST['result_resultscore_textstring']) && strlen($_REQUEST['result_resultscore_textstring']) > 0) { - $gradeval = floatval($_REQUEST['result_resultscore_textstring']); - } - if ( $gradeval < 0.0 || $gradeval > 1.0 ) { - doError('Invalid Grade'); - } - - // TODO: Greg - do we do Insert or Update? - $replace_sql = 'INSERT INTO '.TABLE_PREFIX.'gradebook_detail - (gradebook_test_id, member_id, grade) VALUES - ('.$gradebook_test_id.','.$member_id.','.$gradeval.') - ON DUPLICATE KEY UPDATE grade='.$gradeval; - - $gradebook_result = mysql_query($replace_sql, $db); - if ( $gradebook_result === false ) { - // TODO: Log message would be good here - doError("Could not store grade"); - } - print message_response('Success', 'Status', 'fullsuccess', 'Grade updated'); - } - - - } else if ( $lti_message_type == "basic-lti-loadsetting" ) { - $xml = " \n" . - " ".htmlspecialchars($basiclti_content_row['setting'])."\n" . - " \n"; - print message_response('Success', 'Status', 'fullsuccess', 'Setting retrieved', $xml); - } else if ( $lti_message_type == "basic-lti-savesetting" ) { - $setting = $_REQUEST['setting']; - if ( ! isset($setting) ) doError('Missing setting value'); - // $sql = "UPDATE {$CFG->prefix}basiclti SET - // setting='". mysql_escape_string($setting) . "' WHERE id=" . $basiclti->id; - $sql = "UPDATE ".TABLE_PREFIX."basiclti_content - SET setting='". mysql_escape_string($setting) . "' WHERE content_id=" . $placement; - $success = mysql_query($sql); - if ( $success ) { - print message_response('Success', 'Status', 'fullsuccess', 'Setting updated'); - } else { - doError("Error updating setting"); - } - } else if ( $lti_message_type == "basic-lti-deletesetting" ) { - $sql = "UPDATE ".TABLE_PREFIX."basiclti_content - SET setting='' WHERE content_id=" . $placement; - $success = mysql_query($sql); - if ( $success ) { - print message_response('Success', 'Status', 'fullsuccess', 'Setting deleted'); - } else { - doError("Error updating setting"); - } - } else if ( $message_type == "roster" ) { - $sql = 'SELECT role,m.member_id AS member_id,first_name,last_name,email - FROM '.TABLE_PREFIX.'course_enrollment AS e - JOIN '.TABLE_PREFIX.'members AS m ON e.member_id = m.member_id - WHERE course_id = '.$course_id; - $roster_result = mysql_query($sql, $db); - $xml = " \n"; - while ($row = mysql_fetch_assoc($roster_result)) { - $role = "Learner"; - if ( $row['role'] == 'Instructor' ) $role = 'Instructor'; - $userxml = " \n". - " ".htmlspecialchars($row['member_id'])."\n". - " $role\n"; - if ( $basiclti_tool_row['sendname'] == 1 || - ( $basiclti_tool_row['sendname'] == 2 && $basiclti_content_row['sendname'] == 1 ) ) { - if ( isset($row['first_name']) ) $userxml .= " ".htmlspecialchars($row['first_name'])."\n"; - if ( isset($row['last_name']) ) $userxml .= " ".htmlspecialchars($row['last_name'])."\n"; - } - if ( $basiclti_tool_row['sendemailaddr'] == 1 || - ( $basiclti_tool_row['sendemailaddr'] == 2 && $basiclti_content_row['sendemailaddr'] == 1 ) ) { - if ( isset($row['email']) ) $userxml .= " ".htmlspecialchars($row['email'])."\n"; - } - if ( isset($placementsecret) ) { - $suffix = ':::' . $row['member_id'] . ':::' . $placement; - $plaintext = $placementsecret . $suffix; - $hashsig = hash('sha256', $plaintext, false); - $sourcedid = $hashsig . $suffix; - } - if ( $basiclti_tool_row['acceptgrades'] == 1 && $basiclti_content_row['gradebook_test_id'] > 0 ) { - if ( isset($sourcedid) ) $userxml .= " ".htmlspecialchars($sourcedid)."\n"; - } - $userxml .= " \n"; - $xml .= $userxml; - } - $xml .= " \n"; - print message_response('Success', 'Status', 'fullsuccess', 'Roster retreived', $xml); - - } - -?> diff --git a/mods/basiclti/lib/at_form_util.php b/mods/basiclti/lib/at_form_util.php deleted file mode 100644 index f0d97f1b9..000000000 --- a/mods/basiclti/lib/at_form_util.php +++ /dev/null @@ -1,336 +0,0 @@ - -
    - *
    - -
    - -
    - *
    - -
    - '); - return; - } - $current = isset($row[$field]) ? $row[$field] : -1; - ?> -
    - *
    - $value ) { -$checked = ''; -if ( $key == $current ) $checked = ' checked="checked"'; -?> -
    - -
    - -
    -
    - -
    - '); - return; - } - $current = isset($row[$field]) ? $row[$field] : 0; - if ( $current < 0 || $current >= sizeof($choices) ) $current = 0; - ?> -
    \n"; - echo _AT($label.'_'.$value); ?> -
    -\n"); - if ( isset($info['required']) && strlen($datafield) < 1 ) { - $missing_fields[] = _AT($label); - } - if ( $info[1] == 'integer' || $info[1] == 'radio') { - if ( preg_match("/[0-9]+/", $datafield) == 1 || strlen($datafield) == 0 ) { - // OK - } else { - $numeric_fields[] = _AT($label); - } - } - if ( $info[1] == 'id' ) { - if ( preg_match("/^[0-9a-zA-Z._-]*$/", $datafield) == 1 || strlen($datafield) == 0 ) { - // OK - } else { - $id_fields[] = _AT($label); - } - } - if ( $info[1] == 'url' ) { - $pattern = "'^(http://|https://)[a-z0-9][a-z0-9]*'"; - if ( preg_match($pattern, $datafield) == 1 || strlen($datafield) == 0 ) { - // OK - } else { - $url_fields[] = _AT($label); - } - } - } - if (sizeof($missing_fields) > 0) { - $missing_fields = implode(', ', $missing_fields); - $msg->addError(array('EMPTY_FIELDS', $missing_fields)); - $retval = false; - } - if (sizeof($numeric_fields) > 0) { - $numeric_fields = implode(', ', $numeric_fields); - // TODO: Make sure this prints out the list of fields - $msg->addError(array('NUMERIC_FIELDS', $numeric_fields)); - $msg->addError($numeric_fields); - $retval = false; - } - if (sizeof($url_fields) > 0) { - $url_fields = implode(', ', $url_fields); - $msg->addError(array('URL_FIELDS', $url_fields)); - $retval = false; - } - if (sizeof($id_fields) > 0) { - $id_fields = implode(', ', $id_fields); - $msg->addError(array('ID_FIELDS', $id_fields)); - $retval = false; - } - return $retval; -} - -function at_get_field_value($fieldvalue, $type = false) { - global $addslashes; - - if ( $fieldvalue === false ) { - $fieldvalue = 'NULL'; - } else if ( is_int($fieldvalue) ) { - $fieldvalue = $fieldvalue.''; - } else if ( $type == 'radio' || $type == 'integer') { - if ( strlen($fieldvalue) < 1 ) $fieldvalue = '0'; - else $fieldvalue = intval($fieldvalue); - } else { - $fieldvalue = "'".$addslashes($fieldvalue)."'"; - } - return $fieldvalue; -} - -// $overrides = array('course_id' => 12, "title" => "yo", "toolid" => false); -// false in the array becomes NULL in the database -function at_form_insert($row, $form_definition, $overrides=false) { - $fieldlist = ""; - $valuelist = ""; - $handled = array(); - foreach ( $form_definition as $forminput ) { - $info = parseFormString($forminput); - $fieldname = $info[0]; - $type = $info[1]; - $fieldvalue = null; - if ( is_array($overrides) && isset($overrides[$fieldname]) ) $fieldvalue = $overrides[$fieldname]; - if ( ! isset($fieldvalue) ) $fieldvalue = $row[$fieldname]; - if ( ! isset($fieldvalue) ) continue; - $fieldvalue = trim($fieldvalue); - if ( strlen($fieldvalue) < 1 ) continue; - $fieldvalue = at_get_field_value($fieldvalue, $type); - $handled[] = $fieldname; - if ( $fieldlist != "" ) $fieldlist = $fieldlist.", "; - if ( $valuelist != "" ) $valuelist = $valuelist.", "; - $fieldlist = $fieldlist.$fieldname; - $valuelist = $valuelist.$fieldvalue; - } - if ( is_array($overrides) ) foreach($overrides as $fieldname => $fieldvalue) { - if ( in_array ( $fieldname , $handled) ) continue; - $fieldvalue = at_get_field_value($fieldvalue); - if ( $fieldlist != "" ) $fieldlist = $fieldlist.", "; - if ( $valuelist != "" ) $valuelist = $valuelist.", "; - $fieldlist = $fieldlist.$fieldname; - $valuelist = $valuelist.$fieldvalue; - } - $sql = "( $fieldlist ) VALUES ( $valuelist )"; - return $sql; -} - -function at_form_update($row, $form_definition, $overrides=false) { - $setlist = ""; - $handled = array(); - foreach ( $form_definition as $forminput ) { - $info = parseFormString($forminput); - $fieldname = $info[0]; - $type = $info[1]; - $fieldvalue = null; - if ( is_array($overrides) && isset($overrides[$fieldname]) ) $fieldvalue = $overrides[$fieldname]; - if ( ! isset($fieldvalue) ) $fieldvalue = $row[$info[0]]; - if ( ! isset($fieldvalue) ) $fieldvalue = ''; - $fieldvalue = trim($fieldvalue); - $fieldvalue = at_get_field_value($fieldvalue, $type); - if ( $setlist != "" ) $setlist = $setlist.", "; - $setlist = $setlist.$fieldname." = ".$fieldvalue; - } - if ( is_array($overrides) ) foreach($overrides as $fieldname => $fieldvalue) { - if ( in_array ( $fieldname , $handled) ) continue; - $fieldvalue = at_get_field_value($fieldvalue); - if ( $setlist != "" ) $setlist = $setlist.", "; - $setlist = $setlist.$fieldname." = ".$fieldvalue; - } - return $setlist; -} - -function foorm_i18n_util($fieldinfo) { - $strings = array(); - foreach ($fieldinfo as $line) { - $info = parseFormString($line); - $label = $info[0]; - if ( isset($info['label']) ) $label = $info['label']; - $strings[] = $label; - if ( $info[1] == 'radio' ) { - if ( isset($info['choices']) ) { - $choices = explode(',', $info['choices']); - foreach($choices as $choice) { - $strings[] = $label.'_'.$choice; - } - } - } - } - return $strings; -} - -if ( ! function_exists('isCli') ) { - function isCli() { - $sapi_type = php_sapi_name(); - if (substr($sapi_type, 0, 3) == 'cli' && empty($_SERVER['REMOTE_ADDR'])) { - return true; - } else { - return false; - } - } -} - -// If we are running from the command line - do a unit test -if ( isCli() ) { - print_r(parseFormString('title:text:required=true:size=25')); - print_r(parseFormString('description:textarea:required=true:rows=2:cols=25')); - print_r(parseFormString('sendemail:radio:requred=true:label=bl_sendemail:choices=on,off,part')); - - $row = array(); - $row['title'] = 'Fred'; - $row['description'] = 'Desc'; - $row['sendemail'] = 1; - function _AT($str) { return $str; } - - at_form_input($row,'title:text:required=true:size=25'); - at_form_input($row,'description:textarea:required=true:rows=2:cols=25'); - at_form_input($row,'sendemail:radio:requred=true:label=bl_sendemail:choices=on,off,part'); - - $test_frm = array( - 'title:text:size=80', - 'preferheight:integer:label=bl_preferheight:size=80', - 'sendname:radio:label=bl_sendname:choices=off,on,content', - 'acceptgrades:radio:label=bl_acceptgrades:choices=off,on', - 'customparameters:textarea:label=bl_customparameters:rows=5:cols=25', - ); - - $i18strings = foorm_i18n_util($test_frm); - print_r($i18strings); - -} - diff --git a/mods/basiclti/module.css b/mods/basiclti/module.css deleted file mode 100644 index 15f51ae41..000000000 --- a/mods/basiclti/module.css +++ /dev/null @@ -1,11 +0,0 @@ -div#helloworld { - border: 1px solid #ccc; - padding: 10px; - width: 50%; - margin-right: auto; - margin-left: auto; - background-color: #efefef; - color: #444; - margin-top: 30px; - margin-bottom: 30px; -} \ No newline at end of file diff --git a/mods/basiclti/module.php b/mods/basiclti/module.php deleted file mode 100644 index 16a4ef2b3..000000000 --- a/mods/basiclti/module.php +++ /dev/null @@ -1,90 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_BASICLTI', $this->getAdminPrivilege()); - -/******* - * set savant variable and constants - */ -global $savant; -require(AT_INCLUDE_PATH.'../mods/basiclti/include/constants.inc.php'); -$savant->addPath('template', AT_BL_INCLUDE.'html/'); - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_BASICLTI, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/basiclti/index_admin.php'); - $this->_pages['mods/basiclti/index_admin.php']['title_var'] = 'basiclti'; - $this->_pages['mods/basiclti/index_admin.php']['parent'] = AT_NAV_ADMIN; - $this->_pages['mods/basiclti/index_admin.php']['children'] = array('mods/basiclti/tool/admin_create.php'); - $this->_pages['mods/basiclti/tool/admin_create.php']['title_var'] = 'bl_create'; - $this->_pages['mods/basiclti/tool/admin_create.php']['parent'] = 'mods/basiclti/index_admin.php'; - $this->_pages['mods/basiclti/tool/admin_view.php']['title_var'] = 'bl_view'; - $this->_pages['mods/basiclti/tool/admin_view.php']['parent'] = 'mods/basiclti/index_admin.php'; - $this->_pages['mods/basiclti/tool/admin_edit.php']['title_var'] = 'bl_edit'; - $this->_pages['mods/basiclti/tool/admin_edit.php']['parent'] = 'mods/basiclti/index_admin.php'; - $this->_pages['mods/basiclti/tool/admin_delete.php']['title_var'] = 'bl_delete'; - $this->_pages['mods/basiclti/tool/admin_delete.php']['parent'] = 'mods/basiclti/index_admin.php'; -} - -/******* - * instructor Manage section: - */ -if ( authenticate(AT_PRIV_BASICLTI, TRUE) ) { - $this->_pages['mods/basiclti/tool/content_edit.php']['title_var'] = 'bl_content'; - $this->_pages['mods/basiclti/tool/content_edit.php']['parent'] = 'index.php'; - - - $this->_pages['mods/basiclti/index_instructor.php']['title_var'] = 'basiclti'; - $this->_pages['mods/basiclti/index_instructor.php']['parent'] = 'tools/index.php'; - $this->_pages['mods/basiclti/index_instructor.php']['children'] = array('mods/basiclti/tool/instructor_create.php'); - $this->_pages['mods/basiclti/tool/instructor_create.php']['title_var'] = 'bl_create'; - $this->_pages['mods/basiclti/tool/instructor_create.php']['parent'] = 'mods/basiclti/index_instructor.php'; - $this->_pages['mods/basiclti/tool/instructor_view.php']['title_var'] = 'bl_view'; - $this->_pages['mods/basiclti/tool/instructor_view.php']['parent'] = 'mods/basiclti/index_instructor.php'; - $this->_pages['mods/basiclti/tool/instructor_edit.php']['title_var'] = 'bl_edit'; - $this->_pages['mods/basiclti/tool/instructor_edit.php']['parent'] = 'mods/basiclti/index_instructor.php'; - $this->_pages['mods/basiclti/tool/instructor_delete.php']['title_var'] = 'bl_delete'; - $this->_pages['mods/basiclti/tool/instructor_delete.php']['parent'] = 'mods/basiclti/index_instructor.php'; -} - - -$this->_content_tools[] = array("id"=>"basiclti_tool", - "class"=>"fl-col clickable", - "src"=>AT_BASE_HREF."mods/basiclti/images/basiclti-icon.png", - "title"=>_AT('basiclti_tool'), - "alt"=>_AT('basiclti_tool'), - "text"=>_AT('basiclti_content_text'), - "js"=>AT_BASE_HREF."mods/basiclti/content_tool_action.js"); - - -/******* - * Register the entry of the callback class. Make sure the class name is properly namespaced, - * for instance, prefixed with the module name, to enforce its uniqueness. - * This class must be defined in "ModuleCallbacks.class.php". - * This class is an API that contains the static methods to act on core functions. - */ -$this->_callbacks['basiclti'] = 'BasicLTICallbacks'; - -function basiclti_get_group_url($group_id) { - return 'mods/basiclti/index.php'; -} - - -?> diff --git a/mods/basiclti/module.sql b/mods/basiclti/module.sql deleted file mode 100644 index 9b78ad4fc..000000000 --- a/mods/basiclti/module.sql +++ /dev/null @@ -1,130 +0,0 @@ -# sql file for basiclti module - -# More Language entries at the end - -CREATE TABLE `basiclti_tools` ( - `id` mediumint(10) NOT NULL AUTO_INCREMENT, - `toolid` varchar(32) NOT NULL, - `course_id` mediumint(10) NOT NULL DEFAULT '0', - `title` varchar(255) NOT NULL, - `description` varchar(1024), - `timecreated` TIMESTAMP, - `timemodified` TIMESTAMP, - `toolurl` varchar(1023) NOT NULL, - `resourcekey` varchar(1023) NOT NULL, - `password` varchar(1023) NOT NULL, - `preferheight` mediumint(4) NOT NULL DEFAULT '0', - `allowpreferheight` mediumint(1) NOT NULL DEFAULT '0', - `sendname` mediumint(1) NOT NULL DEFAULT '0', - `sendemailaddr` mediumint(1) NOT NULL DEFAULT '0', - `acceptgrades` mediumint(1) NOT NULL DEFAULT '0', - `allowroster` mediumint(1) NOT NULL DEFAULT '0', - `allowsetting` mediumint(1) NOT NULL DEFAULT '0', - `allowcustomparameters` mediumint(1) NOT NULL DEFAULT '0', - `customparameters` text, - `organizationid` varchar(64), - `organizationurl` varchar(255), - `organizationdescr` varchar(255), - `launchinpopup` mediumint(1) NOT NULL DEFAULT '0', - `debuglaunch` mediumint(1) NOT NULL DEFAULT '0', - PRIMARY KEY ( `id`, `toolid` ) -); - -CREATE TABLE `basiclti_content` ( - `id` mediumint(10) NOT NULL AUTO_INCREMENT, - `content_id` mediumint(10) NOT NULL DEFAULT '0', - `course_id` mediumint(10) NOT NULL DEFAULT '0', - `toolid` varchar(32) NOT NULL DEFAULT '', - `preferheight` mediumint(4) NOT NULL DEFAULT '0', - `sendname` mediumint(1) NOT NULL DEFAULT '0', - `sendemailaddr` mediumint(1) NOT NULL DEFAULT '0', - `gradebook_test_id` mediumint(10) NOT NULL DEFAULT '0', - `allowroster` mediumint(1) NOT NULL DEFAULT '0', - `allowsetting` mediumint(1) NOT NULL DEFAULT '0', - `customparameters` text, - `launchinpopup` mediumint(1) NOT NULL DEFAULT '0', - `debuglaunch` mediumint(1) NOT NULL DEFAULT '0', - `placementsecret` varchar(1023), - `timeplacementsecret` mediumint(10) NOT NULL DEFAULT '0', - `oldplacementsecret` varchar(1023), - `setting` text(8192), - `xmlimport` text(16384), - PRIMARY KEY ( `id`, `course_id`, `content_id` ) -); - -# Language Entries -INSERT INTO `language_text` VALUES ('en', '_module','basiclti','External Tools',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','basiclti_text','Support for integrating External Tools that support IMS Basic Learning Tools Interoperability..',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_create','Create External Tool',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_view','External Tool Settings',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_settings','Settings',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_delete','Deleting External Tool',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_edit','Edit External Tool',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_toolid_header','ToolID',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_count','Use Count',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_content_title','External Tool Settings',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','basiclti_tool','External Tool',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','basiclti_content_text','External Tool',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','basiclti_comment','You can choose and configure an External Tool associated with this Content Item.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_choose_tool','Select External Tool',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','blti_missing_tool','External Tool configuration has is missing toolid:',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_choose_gradbook_entry','Select Gradebook Entry',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_acceptgrades','Accept Grades From External Tool',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_acceptgrades_off','Do not allow',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_acceptgrades_on','Allow',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowcustomparameters','Allow Additional Custom Parameters in Content Item',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowcustomparameters_off','Do not allow',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowcustomparameters_on','Allow',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowpreferheight','Allow Frame Height to be Changed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowpreferheight_off','Do not allow',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowpreferheight_on','Allow',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowroster','Allow External Tool To Retrieve Roster',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowroster_content','Specify in each Content Item',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowroster_instructor','Delegate to Instructor',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowroster_off','Never',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowroster_on','Always',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowsetting','Allow External Tool to use the Setting Service',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowsetting_content','Specify in each Content Item',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowsetting_instructor','Delegate to Instructor',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowsetting_off','Never',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_allowsetting_on','Always',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_customparameters','Custom Parameters',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_debuglaunch','Launch Tool in Debug Mode',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_debuglaunch_content','Specify in each Content Item',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_debuglaunch_instructor','Delegate to Instructor',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_debuglaunch_off','Never',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_debuglaunch_on','Always',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_description','Description',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_launchinpopup','Launch Tool in Pop Up Window',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_launchinpopup_content','Specify in each Content Item',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_launchinpopup_instructor','Delegate to Instructor',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_launchinpopup_off','Never',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_launchinpopup_on','Always',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_organizationdescr','Organization Description',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_organizationid','Organization Identifier (typically DNS)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_organizationurl','Organization URL',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_password','Tool Secret',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_preferheight','Frame Height',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_resourcekey','Tool Key (oauth_consumer_key)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_sendemailaddr','Send User Mail Addresses to External Tool',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_sendemailaddr_content','Specify in each Content Item',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_sendemailaddr_instructor','Delegate to Instructor',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_sendemailaddr_off','Never',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_sendemailaddr_on','Always',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_sendname','Send User Names to External Tool',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_sendname_content','Specify in each Content Item',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_sendname_instructor','Delegate to Instructor',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_sendname_off','Never',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_sendname_on','Always',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_title','Title',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_toolid','ToolId (must be unique across system)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_toolurl','Tool Launch URL',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_create','Create External Tool',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_toolid_header','ToolId',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_count','Usage Count',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','bl_choose_tool','Choose Tool',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','proxy','Learning Activity',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','about_content_tools','Select from the available external tools, one that can be associated with this content page as a learning activity. Or, though Manage>IMS Basic LTI add your own external tools to make them available here.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_BASICLTI_SAVED','External tool added as a Learning Activity for this content page.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_BASICLTI_DELETED','External tool removed as a Learning Activity from this content page.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_CONFIRM_DELETE_TOOL_1','Are you sure you want to delete the tool %s.',NOW(),''); \ No newline at end of file diff --git a/mods/basiclti/module.xml b/mods/basiclti/module.xml deleted file mode 100644 index 2b0a63851..000000000 --- a/mods/basiclti/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - External Tools - This is a module to support externally hosted tools using the IMS Basic LTI specification to launch those tools. - - - Charles Severance - csev@umich.edu - - - http://atutor.ca - BSD - - 0.1 - 2010-12-22 - alpha - This module is an experimental implementation of the IMS Basic LTI that extends the ATutor content editor. Feedback, bug reports, etc. should be posted to the atutor.ca <a href="http://atutor.ca/forums/">developer or modules forums</a>. Be sure to review the README file included with the module (linked above) for more about setting up BasicLTI remote tools in ATutor. - - diff --git a/mods/basiclti/module_backup.php b/mods/basiclti/module_backup.php deleted file mode 100644 index eb337a058..000000000 --- a/mods/basiclti/module_backup.php +++ /dev/null @@ -1,69 +0,0 @@ - diff --git a/mods/basiclti/module_delete.php b/mods/basiclti/module_delete.php deleted file mode 100644 index a169a8214..000000000 --- a/mods/basiclti/module_delete.php +++ /dev/null @@ -1,21 +0,0 @@ - diff --git a/mods/basiclti/module_install.php b/mods/basiclti/module_install.php deleted file mode 100644 index b6a43d368..000000000 --- a/mods/basiclti/module_install.php +++ /dev/null @@ -1,65 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - -/****** - * 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 (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); -} - -?> diff --git a/mods/basiclti/module_uninstall.php b/mods/basiclti/module_uninstall.php deleted file mode 100644 index 6e6a507c1..000000000 --- a/mods/basiclti/module_uninstall.php +++ /dev/null @@ -1,45 +0,0 @@ -addError(array('MODULE_UNINSTALL', '
  • '.$directory.' can not be removed. Please manually remove it.
  • ')); -} - -/****** - * the following code checks if there are any errors (generated previously) - * then uses the SqlUtility to run reverted database queries of module.sql, - * ie. "create table" statement in module.sql is run as drop according table. - */ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> - diff --git a/mods/basiclti/tool/admin_create.php b/mods/basiclti/tool/admin_create.php deleted file mode 100644 index 7d793281a..000000000 --- a/mods/basiclti/tool/admin_create.php +++ /dev/null @@ -1,55 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_admin.php'); - exit; -} else if (isset($_POST['form_basiclti'])) { - if ( at_form_validate($blti_admin_form, $msg) ) { - global $addslashes; - $sql = "SELECT count(*) cnt FROM ".TABLE_PREFIX."basiclti_tools WHERE toolid = '". - $addslashes($_POST['toolid'])."';"; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - if ($row["cnt"] != 0) { - $msg->addFeedback('NEED_UNIQUE_TOOLID'); - } else { - $sql = at_form_insert($_POST, $blti_admin_form); - $sql = 'INSERT INTO '.TABLE_PREFIX."basiclti_tools ".$sql; - $result = mysql_query($sql, $db) or die(mysql_error()); - write_to_log(AT_ADMIN_LOG_INSERT, 'basiclti_create', mysql_affected_rows($db), $sql); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - - - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_admin.php'); - exit; - } - } -} - -include(AT_INCLUDE_PATH.'header.inc.php'); - -$msg->printAll(); - -?> -
    - -
    -
    - -
    - - -
    -
    -
    -
    - -addFeedback('UNABLE_TO_FIND_TOOL'); - header('Location: ../index_admin.php'); - exit; -} - -if (isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - header('Location: ../index_admin.php'); - exit; -} else if (isset($_POST['submit_yes'])) { - $sql = "DELETE FROM ".TABLE_PREFIX."basiclti_tools WHERE id = ".$tool.";"; - $result = mysql_query($sql, $db) or die(mysql_error()); - write_to_log(AT_ADMIN_LOG_DELETE, 'basiclti_delete', mysql_affected_rows($db), $sql); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: ../index_admin.php'); - exit; -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -if (!isset($_POST['step'])) { - $hidden_vars['step'] = 2; - $hidden_vars['id'] = $tool; - $msg->addConfirm(array('DELETE_TOOL_1', $row['title']), $hidden_vars); - $msg->printConfirm(); -} -/* - -else if ($_POST['step'] == 1) { - $hidden_vars['step'] = 2; - $hidden_vars['id'] = $tool; - $msg->addConfirm(array('DELETE_TOOL_2', $row['title']), $hidden_vars); - $msg->printConfirm(); -}*/ - -require(AT_INCLUDE_PATH.'footer.inc.php'); diff --git a/mods/basiclti/tool/admin_edit.php b/mods/basiclti/tool/admin_edit.php deleted file mode 100644 index 826595591..000000000 --- a/mods/basiclti/tool/admin_edit.php +++ /dev/null @@ -1,90 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_admin.php'); - exit; -} else if (isset($_POST['form_basiclti'], $tool)) { - - if ( at_form_validate($blti_admin_form, $msg) ) { - global $addslashes; - $sql = "SELECT count(*) cnt FROM ".TABLE_PREFIX."basiclti_tools WHERE toolid = '". - $addslashes($_POST['toolid'])."' AND id != $tool;"; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - if ($row["cnt"] != 0) { - $msg->addFeedback('NEED_UNIQUE_TOOLID'); - } else { - $sql = at_form_update($_POST, $blti_admin_form); - $sql = 'UPDATE '.TABLE_PREFIX."basiclti_tools SET ".$sql." WHERE id = $tool;"; - $result = mysql_query($sql, $db) or die(mysql_error()); - write_to_log(AT_ADMIN_LOG_INSERT, 'basiclti_create', mysql_affected_rows($db), $sql); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_admin.php'); - exit; - } - } -} - -$sql = "SELECT * FROM ".TABLE_PREFIX."basiclti_tools WHERE id = ".$tool.";"; -$result = mysql_query($sql, $db) or die(mysql_error()); -$toolrow = mysql_fetch_assoc($result); -if ( $toolrow['id'] != $tool ) { - $msg->addFeedback('COULD_NOT_LOAD_TOOL'); - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_admin.php'); - exit; -} - -include(AT_INCLUDE_PATH.'header.inc.php'); - -$msg->printAll(); - -?> -
    - - -
    -
    - -
    - - -
    -
    -
    -
    - -addFeedback('COULD_NOT_LOAD_TOOL'); - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_admin.php'); - exit; -} - -include(AT_INCLUDE_PATH.'header.inc.php'); - -$msg->printAll(); - -?> -
    - - -
    -
    - -
    - -
    -
    -
    -
    - -addFeedback('NEED_COURSE_ID'); - exit; -} - -// Add/Update The Tool -if ( isset($_POST['toolid']) && at_form_validate($blti_content_edit_form, $msg)) { - $toolid = $_POST['toolid']; // Escaping is done in the at_form_util code - $sql = "SELECT * FROM ".TABLE_PREFIX."basiclti_content - WHERE content_id=".$_POST[cid]." AND course_id=".$_SESSION[course_id]; - - - $result = mysql_query($sql, $db); - if ( $toolid == '--none--' ) { - $sql = "DELETE FROM ". TABLE_PREFIX . "basiclti_content - WHERE content_id=".$_POST[cid]." AND - course_id=".$_SESSION[course_id]; - $result = mysql_query($sql, $db); - if ($result===false) { - $msg->addError('MYSQL_FAILED'); - } else { - $msg->addFeedback('BASICLTI_DELETED'); - } - } else if ( mysql_num_rows($result) == 0 ) { - $sql = "INSERT INTO ". TABLE_PREFIX . "basiclti_content - SET toolid='".$toolid."', content_id=".$_POST[cid].", - course_id=".$_SESSION[course_id]; - - $result = mysql_query($sql, $db); - if ($result===false) { - $msg->addError('MYSQL_FAILED'); - } else { - $msg->addFeedback('BASICLTI_SAVED'); - } - - } else if ( $result !== false ) { - - $gradebook_test_id = 0; - $basiclti_content_row = mysql_fetch_assoc($result); - $placementsecret = $basiclti_content_row['placementsecret']; - $gradebook_check = intval($_POST['gradebook_test_id']); - if ( isset($_POST['gradebook_test_id']) && $gradebook_check > 0 ) { - $gradebook_test_id = $gradebook_check; - $sql = "SELECT g.gradebook_test_id AS id, g.title AS title - FROM ".TABLE_PREFIX."gradebook_tests AS g - WHERE g.course_id = ".$_SESSION[course_id]." - AND g.type = 'External' and g.grade_scale_id = 0 - AND gradebook_test_id = ".$gradebook_test_id; - $result = mysql_query($sql, $db); - if ( $result === false ) { - $gradebook_test_id = 0; - } else { - if ( strlen($placementsecret) < 1 ) { - $placementsecret = uniqid("bl",true); - } - } - } - // Override these fields (don't take from form) - $fields = array('toolid' => $toolid, 'gradebook_test_id' => $gradebook_test_id, - 'placementsecret' => $placementsecret); - $sql = at_form_update($_POST, $blti_content_edit_form, $fields); - $sql = "UPDATE ". TABLE_PREFIX . "basiclti_content - SET ".$sql." WHERE content_id=".$_POST[cid]." AND - course_id=".$_SESSION[course_id]; - $result = mysql_query($sql, $db); - if ($result===false) { - $msg->addError('MYSQL_FAILED'); - } else { - $msg->addFeedback('BASICLTI_SAVED'); - } - } -} - -// echo("
    $sql
    \n"); - -$cid = intval($_REQUEST['cid']); - -global $framed, $popup; - -if ((isset($_REQUEST['popup']) && $_REQUEST['popup']) && - (!isset($_REQUEST['framed']) || !$_REQUEST['framed'])) { - $popup = TRUE; - $framed = FALSE; -} elseif (isset($_REQUEST['framed']) && $_REQUEST['framed'] && isset($_REQUEST['popup']) && $_REQUEST['popup']) { - $popup = TRUE; - $framed = TRUE; - $tool_flag = TRUE; -} else { - $popup = FALSE; - $framed = FALSE; -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -/* get a list of all the tools, we have */ -$sql = "SELECT * FROM ".TABLE_PREFIX."basiclti_tools WHERE course_id = 0". - " OR course_id=".$_SESSION[course_id]." ORDER BY course_id,title"; - -$toolresult = mysql_query($sql, $db); -$num_tools = mysql_num_rows($toolresult); - -//If there are no Tools, don't display anything except a message -if ($num_tools == 0){ - $msg->addInfo('NO_PROXY_TOOLS'); - $msg->printInfos(); - return; -} - -?> -
    - -
    - -
    - -
    - -
    -printFeedbacks(); - -// Get the current content item -$sql = "SELECT * FROM ".TABLE_PREFIX."basiclti_content - WHERE content_id=$cid"; -$contentresult = mysql_query($sql, $db); -$basiclti_content_row = mysql_fetch_assoc($contentresult); -// if ( $basiclti_content_row ) echo("FOUND"); else echo("NOT"); -?> -
    -
    - -
    - 0) { ?> -
    -
    - -
    - -'."\n"); -} -?> -
    - - -
    -'.$basiclti_tool_row['title'].' '._AT('bl_settings').''; - echo '
      '; - foreach($basiclti_tool_row as $title=>$setting){ - if($title == "password" || $title == "resourcekey" && $basiclti_tool_row['course_id'] == 0){ - // Hide the tool password if its not an instructor created tool // - // Don't print out the key or password id its an admin added tool - continue; - } else { - - echo '
    • '.$title.' = '.$setting.'
    • '; - } - } - echo '
    '; -} -//echo("
    \n");print_r($basiclti_tool_row); echo("\n
    \n"); -?> - diff --git a/mods/basiclti/tool/forms.php b/mods/basiclti/tool/forms.php deleted file mode 100644 index 004e0f16e..000000000 --- a/mods/basiclti/tool/forms.php +++ /dev/null @@ -1,88 +0,0 @@ - diff --git a/mods/basiclti/tool/instructor_create.php b/mods/basiclti/tool/instructor_create.php deleted file mode 100644 index 6ad68648a..000000000 --- a/mods/basiclti/tool/instructor_create.php +++ /dev/null @@ -1,60 +0,0 @@ -addFeedback('NEED_COURSE_ID'); - exit; -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_instructor.php'); - exit; -} else if (isset($_POST['form_basiclti']) && isset($_POST['submit'])) { - - if ( at_form_validate($blti_instructor_form, $msg) ) { - global $addslashes; - $sql = "SELECT count(*) cnt FROM ".TABLE_PREFIX."basiclti_tools WHERE toolid = '". - $addslashes($_POST['toolid'])."' AND course_id = ". $_SESSION['course_id']; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - if ($row["cnt"] != 0) { - $msg->addFeedback('NEED_UNIQUE_TOOLID'); - } else { - $fields = array('course_id' => $_SESSION['course_id']); - $sql = at_form_insert($_POST, $blti_instructor_form, $fields); - $sql = 'INSERT INTO '.TABLE_PREFIX."basiclti_tools ".$sql; - $result = mysql_query($sql, $db) or die(mysql_error()); - write_to_log(AT_ADMIN_LOG_INSERT, 'basiclti_create', mysql_affected_rows($db), $sql); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_instructor.php'); - exit; - } - } -} - -include(AT_INCLUDE_PATH.'header.inc.php'); - -$msg->printAll(); - -?> -
    - -
    -
    - -
    - - -
    -
    -
    -
    - -addFeedback('NEED_COURSE_ID'); - exit; -} - -$tool = intval($_REQUEST['id']); - -$sql = "SELECT title FROM ".TABLE_PREFIX."basiclti_tools WHERE id = ".$tool. - " AND course_id = ". $_SESSION['course_id']; -$result = mysql_query($sql, $db) or die(mysql_error()); -$row = mysql_fetch_assoc($result); - -if ( strlen($row["title"]) < 1) { - $msg->addFeedback('UNABLE_TO_FIND_TOOL'); - header('Location: ../index_instructor.php'); - exit; -} - -if (isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - header('Location: ../index_instructor.php'); - exit; -} else if (isset($_POST['step']) && ($_POST['step'] == 2) && isset($_POST['submit_yes'])) { - $sql = "DELETE FROM ".TABLE_PREFIX."basiclti_tools WHERE id = ".$tool. - " AND course_id = ". $_SESSION['course_id']; - $result = mysql_query($sql, $db) or die(mysql_error()); - write_to_log(AT_ADMIN_LOG_DELETE, 'basiclti_delete', mysql_affected_rows($db), $sql); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: ../index_instructor.php'); - exit; -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -if (!isset($_POST['step'])) { - $hidden_vars['step'] = 1; - $hidden_vars['id'] = $tool; - $msg->addConfirm(array('DELETE_TOOL_1', $row['title']), $hidden_vars); - $msg->printConfirm(); -} else if ($_POST['step'] == 1) { - $hidden_vars['step'] = 2; - $hidden_vars['id'] = $tool; - $msg->addConfirm(array('DELETE_TOOL_2', $row['title']), $hidden_vars); - $msg->printConfirm(); -} - -require(AT_INCLUDE_PATH.'footer.inc.php'); diff --git a/mods/basiclti/tool/instructor_edit.php b/mods/basiclti/tool/instructor_edit.php deleted file mode 100644 index f193706e6..000000000 --- a/mods/basiclti/tool/instructor_edit.php +++ /dev/null @@ -1,76 +0,0 @@ -addFeedback('NEED_COURSE_ID'); - exit; -} - -require_once('forms.php'); - -// Filter all POST data // -$tool = intval($_REQUEST['id']); - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_instructor.php'); - exit; -} else if (isset($_POST['form_basiclti'], $tool)) { - - if ( at_form_validate($blti_instructor_form, $msg) ) { - global $addslashes; - $sql = "SELECT count(*) cnt FROM ".TABLE_PREFIX."basiclti_tools WHERE toolid = '". - $addslashes($_POST['toolid'])."' AND id != $tool". - " AND course_id = ". $_SESSION['course_id']; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - if ($row["cnt"] != 0) { - $msg->addFeedback('NEED_UNIQUE_TOOLID'); - } else { - $fields = array('course_id' => $_SESSION['course_id']); - $sql = at_form_update($_POST, $blti_instructor_form, $fields); - $sql = 'UPDATE '.TABLE_PREFIX."basiclti_tools SET ".$sql." WHERE id = $tool". - " AND course_id = ". $_SESSION['course_id']; - $result = mysql_query($sql, $db) or die(mysql_error()); - write_to_log(AT_ADMIN_LOG_INSERT, 'basiclti_create', mysql_affected_rows($db), $sql); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_instructor.php'); - exit; - } - } -} - -$sql = "SELECT * FROM ".TABLE_PREFIX."basiclti_tools WHERE id = ".$tool. - " AND course_id = ". $_SESSION['course_id']; -$result = mysql_query($sql, $db) or die(mysql_error()); -$toolrow = mysql_fetch_assoc($result); -if ( $toolrow['id'] != $tool ) { - $msg->addFeedback('COULD_NOT_LOAD_TOOL'); - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_instructor.php'); - exit; -} - -include(AT_INCLUDE_PATH.'header.inc.php'); - -$msg->printAll(); - -?> -
    - - -
    -
    - -
    - - -
    -
    -
    -
    - -addFeedback('NEED_COURSE_ID'); - exit; -} - -require_once('forms.php'); - -$tool = intval($_REQUEST['id']); - -if (isset($_POST['done'])) { - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_instructor.php'); - exit; -} - -$sql = "SELECT * FROM ".TABLE_PREFIX."basiclti_tools WHERE id = ".$tool. - " AND course_id = ". $_SESSION['course_id']; -$result = mysql_query($sql, $db) or die(mysql_error()); -$toolrow = mysql_fetch_assoc($result); -if ( $toolrow['id'] != $tool ) { - $msg->addFeedback('COULD_NOT_LOAD_TOOL'); - header('Location: '.AT_BASE_HREF.'mods/basiclti/index_instructor.php'); - exit; -} - -include(AT_INCLUDE_PATH.'header.inc.php'); - -$msg->printAll(); - -?> -
    - - -
    -
    - -
    - -
    -
    -
    -
    - -addError('WEBCALENDAR_URL_ADD_EMPTY'); - }else{ - $webcalendar_url = addslashes(stripslashes($_REQUEST['webcalendar_url'])); - $sql = "INSERT INTO ".TABLE_PREFIX."config VALUES('webcalendar', '".$webcalendar_url."')"; - if(!$result = mysql_query($sql)){ - $msg->addError('WEBCALENDAR_URL_ADD_FAILED'); - }else{ - $msg->addFeedback('WEBCALENDAR_URL_ADD_SAVED'); - } - } -} - -if($_REQUEST['edited_webcalendar_url'] == 1){ - if($_REQUEST['webcalendar_url'] == ''){ - $msg->addError('WEBCALENDAR_URL_ADD_EMPTY'); - // $_POST['edit_webcalendar_url'] = 1; - - }else{ - $webcalendar_url = addslashes(stripslashes($_REQUEST['webcalendar_url'])); - $sql = "UPDATE ".TABLE_PREFIX."config SET value='".$webcalendar_url."' WHERE name = 'webcalendar'"; - if(!$result = mysql_query($sql)){ - $msg->addError('WEBCALENDAR_URL_ADD_FAILED'); - }else{ - $msg->addFeedback('WEBCALENDAR_URL_ADD_SAVED'); - } - } -} - -if($_REQUEST['webcalendar_sync'] == 1){ - //populate the webcal_user table with ATutor members - $sql = "SELECT * from ".TABLE_PREFIX."members"; - $result = mysql_query($sql,$db); - if(!$result3 = mysql_query($sql)){ - $msg->addError('WEBCALENDAR_UPDATE_MEMBERS_FAILED'); - }else{ - $msg->addFeedback('WEBCALENDAR_UPDATE_MEMBERS_SAVED'); - } - while ($row = mysql_fetch_array($result)){ - $sql2 = "REPLACE INTO webcal_user VALUES ('$row[1]','".md5($row[2])."','$row[6]','$row[5]','N','$row[3]')"; - $result1 = mysql_query($sql2, $db); - } - - - $sql = "SELECT * from ".TABLE_PREFIX."admins"; - if(!$result3 = mysql_query($sql)){ - $msg->addError('WEBCALENDAR_UPDATE_ADMINS_FAILED'); - }else{ - $msg->addFeedback('WEBCALENDAR_UPDATE_ADMINS_SAVED'); - } - while ($row = mysql_fetch_array($result3)){ - $sql3 = "REPLACE INTO webcal_user VALUES ('$row[0]','".md5($row[1])."','$row[2]','','Y','$row[3]')"; - $result4 = mysql_query($sql3, $db); - } - - //populate the webcal_group table with ATutor courses - $sql5 = "SELECT * FROM ".TABLE_PREFIX."courses"; - $result5 = mysql_query($sql5,$db); - while ($row = mysql_fetch_array($result5)){ - $sql2 = "REPLACE INTO webcal_group VALUES ('$row[0]','".$row[1]."','$row[6]','$row[5]')"; - $result1 = mysql_query($sql2, $db); - } - if(!$result1 = mysql_query($sql)){ - $msg->addError('WEBCALENDAR_UPDATE_GROUPS_FAILED'); - }else{ - $msg->addFeedback('WEBCALENDAR_UPDATE_GROUPS_SAVED'); - } - - //populate webcal_group_users users enrolled courses (i.e. groups) - - $sql6 = "SELECT * FROM ".TABLE_PREFIX."course_enrollment WHERE approved='y'"; - $result6 = mysql_query($sql6,$db); - while ($row = mysql_fetch_array($result6)){ - - $sql8 = "SELECT login FROM ".TABLE_PREFIX."members WHERE member_id='$row[0]'"; - $result8 = mysql_query($sql8,$db); - while($row1 = mysql_fetch_array($result8)){ - $at_login_name = $row1[0]; - } - $sql2 = "REPLACE INTO webcal_group_user VALUES ('$row[1]','$at_login_name')"; - if(!$result7 = mysql_query($sql2)){ - $msg->addError('WEBCALENDAR_UPDATE_GROUPMEMS_FAILED'); - }else{ - $msg->addFeedback('WEBCALENDAR_UPDATE_GROUPMEMS_SAVED'); - } - } - - -} - -////////// -//Check to see if the url to webcalendar exists in the db -$sql = 'SELECT * from '.TABLE_PREFIX.'config WHERE name="webcalendar"'; -$result = mysql_query($sql, $db); - -while($row = mysql_fetch_array($result)){ - $webcalendar_url_db = $row[1]; -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -if($webcalendar_url_db == '' || $_POST['edit_webcalendar_url']){ - -?> -
    -
    -

    -

    -
    -
    - - - - - - - - - - - - - -
    -
    -
    -
    - - - -
    -
    -

    -

    -
    -
    - - -
    -
    -
    -
    -
    -
    -

    -

    -
    -
    - - -
    -
    -
    -
    - - -
    -
    - - - - - - - \ No newline at end of file diff --git a/mods/calendar/calendar.gif b/mods/calendar/calendar.gif deleted file mode 100644 index 2f8d5fb344f75be1ff41e77708b0f007aecef346..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2062 zcmc)J{ZkWn0>|-?CzB9rcnHXdRZuYzs^LkK18UJE# z^~AW;h}#zJUPW;gA3`H^v8Y=Wam5n0AidOcoE%cyIMz;j9(0`>&)heE#l7Y|JK4{7 zf5`02mX?)RZ5u5zi%gQqY=F~ggE1RI*ihOT1vw!Q?1T^}f;$n?iBe9Cb>b`pz%T@( z5Q0Lu7a~9$3?K-MpfG~LC<$W(jDaf!6D$l)Nf3_!D2Ct^LNExyB4D9-6u>YP!%>Vt zaSA196pWOB(jXCw!Z92~U^s~pAQ}TZ0}9|#1WtfRoS<+L#NafC(>xANSx}I`Fd~X1 zNDxhs3_*cdg7OmJ)EgwDD3SuvB*l<4h$X@94N*}vMT5K)BT%eBaUmK-X$+&I7@7gG zG~=bg&V^|{%)l^1QA`xeuq@*h87|21VHU$!!0Tnb9Ls@3mJhIC7eJC1LA(IRc{$z- zZbgZMAdV!tD4yd%0>_J-AadYHjPL}(d%Zj$2)rQjVt@x@Aj}6Mg3~E@y+V{Ih@ub( z3W1OS_FzP`*~F-T7yt#uU`PaGC=!6-0Ez~pf`K3?6bOOBflwq!QNgHCFa!z*!(s4J zLIC&?mcltXVVf-sLE$JVEJ>2hCP9#dAQFyC1R+tB#4wT|NWq{K3`wC7ctnySQX~># z*$Br)L@^QyMZolbl`R9J--1l@M&{L~E%vqCKA=gQy{^x9`pzN4bSTNXt#XN~rE25Aw|(f7wXW!ZPwR}jq|6&1kG&j^o%CX4df~2K`;Jk? zL2aC-s7>P^(U%;X_3k&!U;ezlz51puGyCM&kXEnOm<(I#IX_S{R&>=|_}%sRy#bGrEK2~Ium=B$HDOWZ#2d1UXeWoJ}srK;F(K})tftlLUc$>VI%uYPhc zz9h-!^VG$tDDt0E?#1;&DeA^1Ii^aN7n?qNk#i_{d47&utt#3Oqs|($K$s%EzQJLh zr1WnSjQLPmZIz{7w^RGC-j55r)(jp{uXMyZzO$lrGg|d!o;eeL>zi({Tf2YM$G!E` zuUD-??`0~Cdw!ZSVyxUxuTXAOoG9?E@+7Q6jxWv3deEcGsM|HPa9{TGXPXlXJlbBj za!Q3dOZ4SJGrsX0bLuL0?I_(*mpxBcp&Zz+I5GRxoi$8 z)2zrJQql!&o*sSmt-8L<)?H(0%JA#a{<(wJVU@Xm-t{B84Hs>LrVPuYgYL`Cx8HaC zF<}>Lzd5$apIfJVaPj)p${`iH#J$1ecFeB2koWyqhd+nE{8HUH5PWbyCG!iDi*%9a z*E_0x_5PfTb6VYVyBWu#iDr}IE}4@+*Z0a}s?u9J)T90B)vr8G<7R)8X4bif^8T!e z`};c!j$GL~nCbG3UP!IZelEM|Iz=|~e#H1!n9L&{ajBo$Nlz};h z%ig4Z`_=U&X?4th$Fk0^J2sV-tKbf1_U?G2(KWJQ^Uc87wNT2wa8pC-*2I18x2>&< zSMrUcm%en==;-zibM50DvmpJxZ(p1%`n=QrRrwr4uc`AV*3vUJqU+gm-t)Wp$kStg zHD>I$jW5alblt{jH#?Ck4)xMoq9=|GXo-Dmr6ML%2Fs2-Gs_tLvcguwOSA;X%brQ+oXIXH43e88g$!cKGMX4R3zleQ1tp+Tc`IY$uQgYwrl#1+e9jcH#hJD4>XCQ-EqLdpUVYyfIbqu2 zEmCdUKlpXesKUig@Yi}wkGa^+fm=!U3J;o#t}M*0k}Zv|e0*nh<$|J-)2ORcWz2li zZQfh2UH0&p;ZH4ceNoFt4U<)$3gg#To8@uK^wYDSPMh#(k8@9+;daSWg)Q4nW#CJv z8drbdTmDh`(c`ar5}G~rjRuddb`~!1M4pnl)QA1ePzUaZ7CXlhWzQYi2g>y}xAj4a1}}6%7fx zTUpgzO()u4zi)}3A7A52Z0;csJM`nrs%t8kxUzI>_hE7OwSWKZx1_~(nXK@C!pR*S diff --git a/mods/calendar/index.php b/mods/calendar/index.php deleted file mode 100644 index dcf520d94..000000000 --- a/mods/calendar/index.php +++ /dev/null @@ -1,41 +0,0 @@ - -

    - -addInfo('WEBCALENDAR_URL_ADD_REQUIRED'); -}else{ -?> - - \ No newline at end of file diff --git a/mods/calendar/index_admin.php b/mods/calendar/index_admin.php deleted file mode 100644 index dadfe2036..000000000 --- a/mods/calendar/index_admin.php +++ /dev/null @@ -1,41 +0,0 @@ -addInfo('WEBCALENDAR_URL_ADD_REQUIRED'); - require (AT_INCLUDE_PATH.'header.inc.php'); - require (AT_INCLUDE_PATH.'footer.inc.php'); - -}else{ - - require (AT_INCLUDE_PATH.'header.inc.php'); - $sql="SELECT * FROM ".TABLE_PREFIX."admins WHERE login='$_SESSION[login]'"; - $result = mysql_query($sql, $db); - - while($row = mysql_fetch_array($result)){ - $pw = $row[1]; - } - - ?> - - \ No newline at end of file diff --git a/mods/calendar/module.css b/mods/calendar/module.css deleted file mode 100644 index 89938c4bc..000000000 --- a/mods/calendar/module.css +++ /dev/null @@ -1,152 +0,0 @@ -/* -This stylesheet is not being included because WebCalendar is in an iframe. The CSS can be included as -a custom stylesheet by an admin, under System Settings, then choosing Edit then Custom script/stylesheet. -Be sure to include the opening and closing STYLE elements (commented out below) around the custom stylesheet. -*/ - - -/* - -*/ \ No newline at end of file diff --git a/mods/calendar/module.php b/mods/calendar/module.php deleted file mode 100644 index 35ef6a3c8..000000000 --- a/mods/calendar/module.php +++ /dev/null @@ -1,72 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_CALENDAR', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -$this->_stacks['calendar'] = array('title_var'=>'calendar', 'file'=>dirname(__FILE__).'/side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('hello_world', array('title_var' => 'hello_world', 'file' => './side_menu.inc.php'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ - -$_student_tool = 'mods/calendar/index.php'; - -// ** possible alternative: ** -// $this->addTool('./index.php'); - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_CALENDAR, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/calendar/index_admin.php'); - $this->_pages['mods/calendar/index_admin.php']['parent'] = AT_NAV_ADMIN; - $this->_pages['mods/calendar/index_admin.php']['title_var'] = 'webcalendar'; - $this->_pages['mods/calendar/admin_cal.php']['title_var'] = 'admin_cal'; - $this->_pages['mods/calendar/index_admin.php']['children'] = array('mods/calendar/admin_cal.php'); - $this->_pages['mods/calendar/admin_cal.php']['parent'] = 'mods/calendar/index_admin.php'; - -} - -/******* - * instructor Manage section: - */ -$this->_pages['mods/calendar/index.php']['title_var'] = 'calendar'; -$this->_pages['mods/calendar/index.php']['parent'] = 'tools/index.php'; - -// Instructor and student calendars are the same, so grant access to sync dabatases only if the user is the course instructor. - -if($_SESSION['is_admin']){ - $this->_pages['mods/calendar/sync_cal.php']['title_var'] = 'webcalendar_sync_dbs'; - $this->_pages['mods/calendar/index.php']['children'] = array('mods/calendar/sync_cal.php'); - $this->_pages['mods/calendar/sync_cal.php']['parent'] = 'mods/calendar/index.php'; -} -// ** possible alternative: ** -// $this->pages['./index_instructor.php']['title_var'] = 'hello_world'; -// $this->pages['./index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages['mods/calendar/index.php']['title_var'] = 'calendar'; -$this->_pages['mods/calendar/index.php']['img'] = 'mods/calendar/calendar.gif'; - -// } - -?> \ No newline at end of file diff --git a/mods/calendar/module.sql b/mods/calendar/module.sql deleted file mode 100644 index ac05b0f7f..000000000 --- a/mods/calendar/module.sql +++ /dev/null @@ -1,30 +0,0 @@ -# sql file for WebCalendar module - - -INSERT INTO `language_text` VALUES ('en', '_module','webcalendar','Calendar',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','calendar','Calendar',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','current_calendar','Current Calendar',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','admin_cal','Administer Calendar',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','today_is','Today is',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','webcalendar_sync','Synchronize the ATutor and WebCalendar databases to enable the calendar for new courses, and to grant newly enrolled students access to course group calendars. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','webcalendar_location','The location/URL of WebCalendar being used with this installation of ATutor.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','webcalendar_sync_button','Synchronize Databases',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','webcalendar_edit','Edit WebCalendar Location',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','webcalendar_save','Save WebCalendar Location.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','calendar_own_window','Open the calendar in its own window.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','webcalendar_add_url','Type in the URL to WebCalendar. This should be the the URL to the root directory, with no filename added (e.g. http://www.mysite.com/WebCalendar/ ).',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','webcalendar_sync_dbs','Synchronize WebCalendar and ATutor Databases',NOW(),''); - - -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_INFOS_WEBCALENDAR_URL_ADD_REQUIRED','The location/URL of your WebCalendar installation is required. Choose Administer Calendar then enter the URL into the WebCalendar Location field. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_WEBCALENDAR_UPDATE_ADMINS_SAVED','Administrators were updated successfully. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_WEBCALENDAR_UPDATE_GROUPS_SAVED','Course groups were updated successfully. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_WEBCALENDAR_UPDATE_GROUPS_FAILED','Course groups were not updated.. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_WEBCALENDAR_UPDATE_GROUPMEMS_SAVED','Course group members were updated successfully. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_WEBCALENDAR_UPDATE_GROUPMEMS_FAILED','Course group members were not updated. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_WEBCALENDAR_URL_ADD_SAVED','WebCalendar location was successfully saved.. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_WEBCALENDAR_URL_ADD_FAILED','WebCalendar location was not saved.. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_WEBCALENDAR_URL_ADD_EMPTY','WebCalendar location can not be empty. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_WEBCALENDAR_UPDATE_MEMBERS_SAVED','WebCalendar users were updated successfully. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_WEBCALENDAR_UPDATE_MEMBERS_FAILED','WebCalendar users were not updated. ',NOW(),''); - diff --git a/mods/calendar/module.xml b/mods/calendar/module.xml deleted file mode 100644 index 5015fdeb9..000000000 --- a/mods/calendar/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - WebCalendar - This module links the WebCalendar into the student, instructor, and administrator sections of ATutor. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - GPL - - 0.1 - 2005-12-23 - stable - WebCalendar must installed and functioning in group mode before installing this module. See the README_ATUTOR_MODULE file in the calendar module directory for additional installation, and other useful information. Be sure to run *Synchronize Databases* after the installation is complete to import ATutor user and course information into the WebCalendar database. Instructors should also be told to run their version of Synchronize Databases when they create a new courses, or when new students enroll in their courses. - - \ No newline at end of file diff --git a/mods/calendar/module_install.php b/mods/calendar/module_install.php deleted file mode 100644 index 0e5f32f4d..000000000 --- a/mods/calendar/module_install.php +++ /dev/null @@ -1,62 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -// } else if (!is_writable($directory) && @chmod($directory, 0666)) { -// $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -// } -// - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/calendar/side_menu.inc.php b/mods/calendar/side_menu.inc.php deleted file mode 100644 index 5b6c7c034..000000000 --- a/mods/calendar/side_menu.inc.php +++ /dev/null @@ -1,48 +0,0 @@ -'._AT('today_is').': '.$today.''; -echo ' ('._AT('new_window').')'; -echo '
      '; -while($row = mysql_fetch_array($result9)){ - $today = date(Ymd); - // Get ten approved entries associated with a user, from today onward. - $sql10 = "SELECT A.*, B.* FROM webcal_entry AS A, webcal_entry_user AS B WHERE A.cal_id='".$row[0]."' AND A.cal_date >= '$today' AND A.cal_id = B.cal_id AND (B.cal_status = 'A' || A.cal_access = 'P') AND B.cal_login = '".$this_login."' LIMIT 10"; - $result10 = mysql_query($sql10, $db); - while($row2 = mysql_fetch_assoc($result10)){ - #$this_date = split("*./4", $row2['cal_date']); - $this_date = split(".*/4", $row2['cal_date']); - $this_date = chunk_split($row2['cal_date'], 4, '-'); - $this_date = trim(chunk_split($this_date, 7, '-'), '-'); - echo '
    • '.$row2['cal_name'].'
      ('.$this_date.')
    • '; - } -} -echo '
    '; - -$savant->assign('dropdown_contents', ob_get_contents()); -ob_end_clean(); - -$savant->assign('title', _AT('current_calendar')); -$savant->display('include/box.tmpl.php'); - -?> diff --git a/mods/calendar/sync_cal.php b/mods/calendar/sync_cal.php deleted file mode 100644 index b66de6ee1..000000000 --- a/mods/calendar/sync_cal.php +++ /dev/null @@ -1,76 +0,0 @@ -addError('WEBCALENDAR_UPDATE_MEMBERS_FAILED'); - }else{ - $msg->addFeedback('WEBCALENDAR_UPDATE_MEMBERS_SAVED'); - } - while ($row = mysql_fetch_array($result)){ - $sql2 = "REPLACE INTO webcal_user VALUES ('$row[1]','".md5($row[2])."','$row[6]','$row[5]','N','$row[3]')"; - $result1 = mysql_query($sql2, $db); - } - - //populate the webcal_group table with ATutor courses - $sql5 = "SELECT * FROM ".TABLE_PREFIX."courses"; - $result5 = mysql_query($sql5,$db); - while ($row = mysql_fetch_array($result5)){ - $sql2 = "REPLACE INTO webcal_group VALUES ('$row[0]','".$row[1]."','$row[6]','$row[5]')"; - $result1 = mysql_query($sql2, $db); - } - if(!$result1 = mysql_query($sql)){ - $msg->addError('WEBCALENDAR_UPDATE_GROUPS_FAILED'); - }else{ - $msg->addFeedback('WEBCALENDAR_UPDATE_GROUPS_SAVED'); - } - - //populate webcal_group_users users enrolled courses (i.e. groups) - - $sql6 = "SELECT * FROM ".TABLE_PREFIX."course_enrollment WHERE approved='y'"; - $result6 = mysql_query($sql6,$db); - while ($row = mysql_fetch_array($result6)){ - - $sql8 = "SELECT login FROM ".TABLE_PREFIX."members WHERE member_id='$row[0]'"; - $result8 = mysql_query($sql8,$db); - while($row1 = mysql_fetch_array($result8)){ - $at_login_name = $row1[0]; - } - $sql2 = "REPLACE INTO webcal_group_user VALUES ('$row[1]','$at_login_name')"; - if(!$result7 = mysql_query($sql2)){ - $msg->addError('WEBCALENDAR_UPDATE_GROUPMEMS_FAILED'); - }else{ - $msg->addFeedback('WEBCALENDAR_UPDATE_GROUPMEMS_SAVED'); - } - } - - -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> -
    -
    -

    -

    -
    -
    - - -
    -
    -
    -
    - - \ No newline at end of file diff --git a/mods/ccnet/ccnet.php b/mods/ccnet/ccnet.php deleted file mode 100644 index 5b30c3e77..000000000 --- a/mods/ccnet/ccnet.php +++ /dev/null @@ -1,67 +0,0 @@ -addError('CCNETURL_ADD_EMPTY'); - } - - if (!$msg->containsErrors()) { - $_POST['uri'] = $addslashes($_POST['uri']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ccnet', '$_POST[uri]')"; - mysql_query($sql, $db); - $msg->addFeedback('CCNETURL_ADD_SAVED'); - - header('Location: '.$_SERVER['PHP_SELF']); - exit; - } -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> - - -
    -
    -

    -
    -
    -
    - -
    -
    -
    - -
    -
    -

    -
    -
    - - -
    -
    -
    -

    - - -
    - -
    - -
    -
    -
    - - \ No newline at end of file diff --git a/mods/ccnet/ccnet_logo.jpg b/mods/ccnet/ccnet_logo.jpg deleted file mode 100644 index 68619b6b14b3d1237c9e259d44438aba36256ec2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1355 zcmb7{J&JE%O z0SJNs+Ymti99RXWijDvf91Lgx0D>V6=tqG+z#Q5$C)yOk>)9UaNmF0L*PuJ#U&4qqjZVHJpSF|DAwf1cSw)0Pk$! zK_F9HSUh1urlpk)lbr{ zF8zrt({X`J6H3iyM)y_8Y=^wkFIC? z;_({ucHZ~K+Vb#w7q(yLkjiv)qGYFkX;xKf%3R;n?uBJJn$xdfTmTjuW^|dT4htkWmS4mXV#EGKJED|)-tU=;jP@bL^QXR zlQ4Mp!O3E-72jyd2Q4i==Giz?yMMc>eSHyMQc?Kb5W`K0YW6RG{5xnd%)lg{tZdIt zK_0kY<4A-pmSH9es{Hm)V{}HEfVV6Wy{OBIQ_(i*){IxOYTVEW!K?Fr#9A6ROud7) zs`@CEnp>A%$UmiUI_R`vD5UF@vU*~9DC8ns9p}C^4@Nn$DYHB4?SD$WyXVS1i`oRI z+DL_4X0%IK=H%=S4W(&9B;NftfW7;I&(SIMi`Ac)`Kk>~cggC@SyK527qC^=P@Iih?{W8_0sXhb(+8Wcil>RA9sHcFy1hx^~$ZOMCnxF<<&W}v+p#=Eo1z>P9OQ;pFBG5{UmB@ zQ?V|iF?$7%D~tG}80~T9uDW#d@Ue}YJkI&>p^|jb-mp44H`2%k%k}c|y&ck3qEw3A zM_Yx32dZ2G&VcpU%c(Ya-TkiSNik`{@0Z#eD#813MwQ#2hnDAyMHy|8JE`=G3^&OH zE0}I9Td)8r8ne54AY{}I(nwEuQ11rsr@?aONPhLtS8Zq5)RE0oHugz3o|<~U9@+e9 zns2Mfa@%KX8|%8DlX-r6nw%0RdaUTlS0}5>vrZ25e4e}BlkZz@mA}mNZQB*#g|RMr z&mwm8^ojtHXN7Tqu}^7^`^IvuWck%SpQgAS#XB02h=NpU%d8;-z4gyTKG|A zEvjMJ2g&V*6C5QGQMgLTc@8W`yJ#Qx0}ZKL4jvceL?zvcNa)n6xp_n+Q{Z z`}SBC8ndNV!_^Jb7;KGqQeV2DU*Y-C(}R=;`>cWb@*l!Mr^F$@PyDJ}-%ASX&6o}q O-WqL0Vj_9^Xa4|4vK&qT diff --git a/mods/ccnet/index.php b/mods/ccnet/index.php deleted file mode 100644 index 4deb21dca..000000000 --- a/mods/ccnet/index.php +++ /dev/null @@ -1,28 +0,0 @@ - - - - printInfos('CCNET_URL_ADD_REQUIRED'); ?> - -
    -
    -

    -
    - -
    -
    - -
    -
    -
    - - - \ No newline at end of file diff --git a/mods/ccnet/module.php b/mods/ccnet/module.php deleted file mode 100644 index 4fea49894..000000000 --- a/mods/ccnet/module.php +++ /dev/null @@ -1,38 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_CCNET', $this->getAdminPrivilege()); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_student_tool = 'mods/ccnet/index.php'; - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_CCNET, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/ccnet/ccnet.php'); - $this->_pages['mods/ccnet/ccnet.php']['parent'] = AT_NAV_ADMIN; - $this->_pages['mods/ccnet/ccnet.php']['title_var'] = 'ccnet'; -} - -/******* - * instructor Manage section: - */ -$this->_pages['mods/ccnet/index.php']['title_var'] = 'ccnet'; -$this->_pages['mods/ccnet/index.php']['parent'] = 'tools/index.php'; - - -/******* - * student page. - */ -$this->_pages['mods/ccnet/index.php']['title_var'] = 'ccnet'; -$this->_pages['mods/ccnet/index.php']['img'] = 'mods/ccnet/ccnet_logo.jpg'; - -?> \ No newline at end of file diff --git a/mods/ccnet/module.sql b/mods/ccnet/module.sql deleted file mode 100644 index 44f2c4ce8..000000000 --- a/mods/ccnet/module.sql +++ /dev/null @@ -1,13 +0,0 @@ --- # sql file for CCNet module - - -INSERT INTO `language_text` VALUES ('en', '_module','ccnet','CCNet',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ccnet_add_url','Type in the location/URL of your CCnet installation.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ccnet_text','Use CCNet to access course time tables, bulletin boards, course handouts, grades, class lists, surveys and evaluations, and other course administrative tools. (Opens in a new window)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ccnet_open','Open CCnet',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ccnet_location','The following is the location of CCnet:',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ccnet_missing_url','You must supply the URL to your CCnet installation in the field below.', NOW(), ''); - -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_INFOS_CCNET_URL_ADD_REQUIRED','The location/URL is required before CCNet can be made available in ATutor',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_CCNETURL_ADD_SAVED','Location of CCNet was successfully saved.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_CCNETURL_ADD_EMPTY','You must enter a URL to the location of CCNET',NOW(),''); diff --git a/mods/ccnet/module.xml b/mods/ccnet/module.xml deleted file mode 100644 index 911e9f1f8..000000000 --- a/mods/ccnet/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - CCNet - This module links CCNet into ATutor. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - GPL - - 0.2 - 2010-10-25 - stable - This is a simple module that creates student, instructor, and administrator links to open a CCnet url in a new window. - - \ No newline at end of file diff --git a/mods/ccnet/module_install.php b/mods/ccnet/module_install.php deleted file mode 100644 index 0e5f32f4d..000000000 --- a/mods/ccnet/module_install.php +++ /dev/null @@ -1,62 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -// } else if (!is_writable($directory) && @chmod($directory, 0666)) { -// $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -// } -// - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/ccnet/module_uninstall.php b/mods/ccnet/module_uninstall.php deleted file mode 100644 index 52d8f8129..000000000 --- a/mods/ccnet/module_uninstall.php +++ /dev/null @@ -1,31 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/certificate/README b/mods/certificate/README deleted file mode 100644 index 7c51ef2a9..000000000 --- a/mods/certificate/README +++ /dev/null @@ -1,14 +0,0 @@ -Certificate module is used to define tests' certificates by instructor. Students can view or print the certificates via "Certificate" link. This module includes one default certificate PDF template at module content folder as part of the module, that an ATutor system administrator can replace it via FTP. - -Please note that if test property "Release Results" is defined as "Do not release results", students would not be able to see this test's certificates listed in student "Certificate" page. - -How to use your own default certificate: -In your certificate pdf file, the text fields are created in the pdf file to display customized texts. Once the pdf file is ready, the names and default values of the text fields need to be defined in a text file called "default_certificate.pdf.fields", so that the certificate module knows the relationship between the text fields in pdf and their default values. Please refer to "default_certificate.pdf" and "default_certificate.pdf.fields" for example. - -In example "default_certificate.pdf.fields", you will see, if a text fields with name "full_name" is defined in pdf and it's supposed to have default value [FNAME] [LNAME], in "default_certificate.pdf.fields", please have a section like: - ---- -FieldName: full_name -FieldValue: [FNAME] [LNAME] - -Please keep "FieldName: ", "FieldValue: " unchanged. diff --git a/mods/certificate/certificate.gif b/mods/certificate/certificate.gif deleted file mode 100644 index 868f2741e01a51a829bdbbe370783c96ef41d681..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2163 zcmWlYTUZkZ0!Amv5CRzjfq;M$1*BVrsDQz1s6!GVT*RP=fT-L=bR#0hOErrDQUpvD zAu6RQ1vVhMDT_MZM>fI`F$M)3UGz(-;;dCRt4K#zcc-QGe>hL)>3rWGpAffnS#A^% z1^gEPKo;m|7OARCsMRi(s5Dh}Vw{BYOxbIphCWiwhPp?Bx(dPEl!PSaLe*#RKz>VTyDkIi|v* zAbf;$^oYEIL}qs|bGu1zBhOqU|4&nEGR@}8c0&^uAr>o?8j(~YDaOf1P=k$fWeE!O zX5tZH#L31EyV*wmJP5DJGV0p!v@IsfkJR~_4$vJ`HQRT5i%HQ_w}kkWVAHBDya7NhDEPEpkEgD4y( z!g)~EHnSup+tf9L*~s-<%=B+GhCBTIMG~n-S8vA)1=|`>!%Z@~%rrUW)ai7@7XtMH zF?mlc$}$%2L=8=LNxDkkjN;>T&@9-{>mbHRQ-{g25d&8z~2O?F2evqcjK6i1l zy%<7!9gSBB3kQ_PNsJx0%TZB8#g0oFsP%gpp^T5qKVA>!&LoP6Sd z{6Y=xkiLm9U&m9jOmLQ|NN3ho6QFmfbBavfY$opsUcRR-g!9~0LbO=od?GN|X=A_h zr9BiMqYZ3GSB1+{^hO)~!4^utrs(%{=^?CO2lfwlC_4|;bP`y<6HYO!PGayZk=gFV zdK~Iz91euh9;bi_rKOux$I$FNW5Euy`V=b3Qp;s>!*_oOp~hw+Egge+kiq8UxI?-w zLJ%gl*qr)$LUjyFOE;z!Vx|$A7^5XA1;HOd;L}8(@aYq-oN3?<2Uc`HwYX$2$bLGd z3O=pl^#>Rg=i4j=o4vm{^r7T=@7FVDALI}8wk1?-pS78DcK0)zE@H!Vv~aS%->_bq1RhZO0 zd%lhy>i$=ua-}oqO^TO*7#Yjw{C5@?}GQM!+?(dNT4rj>QaW` zR)%=(0SM}@=a)L9 z%J*@!{5UdhA%^01K5mVjQ(=u)3jK?whj>fZ?bG!Oh0CZq-y_0{72h|q!~L3ShFlSL z*x;A(%vINjbZ!+qz9V)al@0}*$?ES-+OX5mx2OZv-a~b^2Nm80OYaoP+(Ps7FXX;^ z@ilVEI7hUHIq!jtm81&FU*pyu`Pr4tw5t^$-F1WEF~mOy8#=6lk$9lm!d}8m2&v)2 z`<-uZ!(8;3aAlB`eI;gfqe^i&Ay*MwR(6^x`24^`YVxw1>YooQM&E9-gC`s^7v2Zr z!6Hsfz}je_bNL%#VNLY?o4ehpgb3c@g6A%;<1p`-D0=cX-TE$O)tw)@ zxIp=x74r>)Qtmv9ERM7C+B8V4_x#8Jy@thnz26moP`!F>##Eo%7nXnXyQX=+DgVC7 z3$4z$r1CbvPe#wX@CQqSUkS$rE}-IFP~2@K0?G66oTF9xEMD#mVd^&nJ;OZa`dQvy z3-Lv@$S-1_coD3s)Q3mU-;?bB>VM=2B8q9~ldXpH6hH0kVbnuq5Bp)iP*-8-($e_Pjr)Bu489(b0u_;V(rB6p1-5#}OSPP9kl#sTZMBg36764pZI z%gPKjzaqY)0!kf~3W{@1rPOTY?(77B6h1TT>T}PTB@fdmzA#D^1kMbSsx7U``)ZGJ zNpO(#`oIwT(31y#Za40<0WX$lKc>vt>Z1rm+D|N74Q*Sp5s|yq>jQ@>cJf*N@+FCU eQADU~IKvp%%#hSS3Jv)1Od9B?=+Xkfir)duKF$sR diff --git a/mods/certificate/certificate_create.php b/mods/certificate/certificate_create.php deleted file mode 100644 index 3a1ec998d..000000000 --- a/mods/certificate/certificate_create.php +++ /dev/null @@ -1,245 +0,0 @@ -0) - { - $sql = "SELECT passscore, passpercent from ".TABLE_PREFIX."tests where test_id=".$_POST["test_id"]; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row=mysql_fetch_assoc($result); - - if ($row["passpercent"]==0 && $row["passscore"]==0) - { - $missing_fields[] = _AT("pass_score"). "
    ". _AT("define_pass_score", $_base_href."tools/tests/edit_test.php?tid=".$_POST["test_id"]); - } - } - } - else if ((!isset($_POST["pass_score"]) || ($_POST["passpercent"] == 0 && $_POST["passscore"] == 0))) - { - $missing_fields[] = _AT("pass_score"); - } - - if ($missing_fields) { - $missing_fields = implode(', ', $missing_fields); - $msg->addError(array('EMPTY_FIELDS', $missing_fields)); - } - - if (!$msg->containsErrors()) - { - if (isset($_POST["passscore"])) - $passscore = $_POST["passscore"]; - else - $passscore = 0; - - if (isset($_POST["passpercent"])) - $passpercent = $_POST["passpercent"]; - else - $passpercent = 0; - - $sql = "INSERT INTO ".TABLE_PREFIX."certificate - (test_id, - passscore, - passpercent, - organization, - enable_download) - VALUES (". $_POST["test_id"] .", - ". $passscore .", - ". $passpercent .", - '". $_POST["organization"]."', - ". $_POST["enable_download"] .")"; - - $result = mysql_query($sql, $db) or die(mysql_error()); - $certificate_id = mysql_insert_id($db); - write_to_log(AT_ADMIN_LOG_INSERT, 'certificate', mysql_affected_rows($db), $sql); - - for ($i = 0; $i < count($fields_array); $i++) - { - $sql = "INSERT INTO ".TABLE_PREFIX."certificate_text - (certificate_id, - field_name, - field_value) - VALUES (". $certificate_id .", - '". $fields_array[$i]["FieldName"] ."', - '". $_POST["fields_value"][$i] ."')"; - - $result = mysql_query($sql, $db) or die(mysql_error()); - write_to_log(AT_ADMIN_LOG_INSERT, 'certificate_text', mysql_affected_rows($db), $sql); - } - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - - header('Location: index_instructor.php'); - exit; - } -} -else if (isset($_POST['cancel'])) -{ - $msg->addFeedback('CANCELLED'); - header('Location: index_instructor.php'); - exit; -} - -require(AT_INCLUDE_PATH.'header.inc.php'); -$msg->printAll(); - -?> - -
    - -
    -
    -
    *

    - -
    - -
    - -
    *

    - 0){echo 'checked="true"';} ?> - onfocus="disable_texts('points');" /> - - /> -
    - - 0){echo 'checked="true"';} ?> - onfocus="disable_texts('percentage');" /> - - /> - - -
    - -
    - - -
    - -
    -
    - " /> -
    - -
    -
    - - /> -
    - - /> -
    -
    - -
    -
    - - - - - - - - - - - - - - - - -
    - · -
    - -
    - - -
    - -
    -
    - - - - diff --git a/mods/certificate/certificate_delete.php b/mods/certificate/certificate_delete.php deleted file mode 100644 index c5154f34e..000000000 --- a/mods/certificate/certificate_delete.php +++ /dev/null @@ -1,66 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: index_instructor.php'); - exit; -} else if (isset($_POST['submit_yes'])) { - /* delete has been confirmed, delete this category */ - $certificate_id = intval($_POST['certificate_id']); - - $sql = "DELETE FROM ".TABLE_PREFIX."certificate WHERE certificate_id=$certificate_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - write_to_log(AT_ADMIN_LOG_DELETE, 'certificate', mysql_affected_rows($db), $sql); - - $sql = "DELETE FROM ".TABLE_PREFIX."certificate_text WHERE certificate_id=$certificate_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - write_to_log(AT_ADMIN_LOG_DELETE, 'certificate_text', mysql_affected_rows($db), $sql); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: index_instructor.php'); - exit; -} - -//require('../../include/header.inc.php'); -require(AT_INCLUDE_PATH.'header.inc.php'); - -$_GET['certificate_id'] = intval($_GET['certificate_id']); - -$sql = "SELECT certificate_id, title FROM ".TABLE_PREFIX."certificate c, ".TABLE_PREFIX."tests t WHERE c.certificate_id=$_GET[certificate_id] and c.test_id=t.test_id"; -$result = mysql_query($sql,$db) or die(mysql_error()); - -if (mysql_num_rows($result) == 0) { - $msg->printErrors('ITEM_NOT_FOUND'); -} else { - $row = mysql_fetch_assoc($result); - - $hidden_vars['title']= $row['title']; - $hidden_vars['certificate_id'] = $row['certificate_id']; - - $confirm = array('DELETE_CERTIFICATE', $row['title']); - $msg->addConfirm($confirm, $hidden_vars); - - $msg->printConfirm(); -} - -require(AT_INCLUDE_PATH.'footer.inc.php'); - -?> \ No newline at end of file diff --git a/mods/certificate/certificate_edit.php b/mods/certificate/certificate_edit.php deleted file mode 100644 index 3ef9858a0..000000000 --- a/mods/certificate/certificate_edit.php +++ /dev/null @@ -1,321 +0,0 @@ -0) - { - $sql = "SELECT passscore, passpercent from ".TABLE_PREFIX."tests where test_id=".$_POST["test_id"]; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row=mysql_fetch_assoc($result); - - if ($row["passpercent"]==0 && $row["passscore"]==0) - { - $missing_fields[] = _AT("pass_score"). "
    ". _AT("define_pass_score", $_base_href."tools/tests/edit_test.php?tid=".$_POST["test_id"]); - } - } - } - else if ((!isset($_POST["pass_score"]) || ($_POST["passpercent"] == 0 && $_POST["passscore"] == 0))) - { - $missing_fields[] = _AT("pass_score"); - } - - if ($missing_fields) { - $missing_fields = implode(', ', $missing_fields); - $msg->addError(array('EMPTY_FIELDS', $missing_fields)); - } - - if (!$msg->containsErrors()) - { - if (isset($_POST["passscore"])) - $passscore = $_POST["passscore"]; - else - $passscore = 0; - - if (isset($_POST["passpercent"])) - $passpercent = $_POST["passpercent"]; - else - $passpercent = 0; - - $sql = "UPDATE ".TABLE_PREFIX."certificate - SET test_id=". $_POST["test_id"] .", - passscore=". $passscore .", - passpercent=". $passpercent .", - organization='". $_POST["organization"]."', - enable_download=". $_POST["enable_download"] ." - WHERE certificate_id = ". $certificate_id; - - $result = mysql_query($sql, $db) or die(mysql_error()); - write_to_log(AT_ADMIN_LOG_UPDATE, 'certificate', mysql_affected_rows($db), $sql); - - for ($i = 0; $i < count($_POST["text_id_init"]); $i++) - { - $sql = "UPDATE ".TABLE_PREFIX."certificate_text - SET field_value='". $_POST["fields_value"][$i] ."' - WHERE certificate_text_id = " . $_POST["text_id_init"][$i]; - - $result = mysql_query($sql, $db) or die(mysql_error()); - write_to_log(AT_ADMIN_LOG_UPDATE, 'certificate_text', mysql_affected_rows($db), $sql); - } - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - - header('Location: index_instructor.php'); - exit; - } -} -else if (isset($_POST['cancel'])) -{ - $msg->addFeedback('CANCELLED'); - header('Location: index_instructor.php'); - exit; -} - -require(AT_INCLUDE_PATH.'header.inc.php'); -$msg->printAll(); - -// existing auto enrollment -if ($certificate_id > 0) -{ - $sql = "SELECT * FROM ".TABLE_PREFIX."certificate - WHERE certificate_id = " . $certificate_id; - - $result = mysql_query($sql, $db) or die(mysql_error()); - $row_certificate = mysql_fetch_assoc($result); -} -?> - -
    - - - -
    -
    -
    *

    - -
    - -
    - 0) - { - $value_passscore = $_POST['passscore']; - $checked_passscore = 'checked="true"'; - } - else - $disabled_passscore = 'disabled="true"'; - } - else - { - if ($row_certificate["passscore"]<>0) - { - $value_passscore = $row_certificate["passscore"]; - $checked_passscore = 'checked="true"'; - } - else - $disabled_passscore = 'disabled="true"'; - } - - // set radio button / text properties and value for pass percentage - if (isset($_POST['passpercent'])) - { - if ($_POST['passpercent'] <> 0) - { - $value_passpercent = $_POST['passpercent']; - $checked_passpercent = 'checked="true"'; - } - else - $disabled_passpercent = 'disabled="true"'; - } - else - { - if ($row_certificate["passpercent"]<>0) - { - $value_passpercent = $row_certificate["passpercent"]; - $checked_passpercent = 'checked="true"'; - } - else - $disabled_passpercent = 'disabled="true"'; - } - -?> -
    *

    - - onfocus="disable_texts('points');" /> - - /> -
    - - - onfocus="disable_texts('percentage');" /> - - /> - - -
    - -
    - - -
    - -
    -
    - -
    - -
    -
    - - /> -
    - - /> - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    - · -
    - -
    - - -
    - -
    -
    - - - - diff --git a/mods/certificate/common.inc.php b/mods/certificate/common.inc.php deleted file mode 100644 index d452cc9e7..000000000 --- a/mods/certificate/common.inc.php +++ /dev/null @@ -1,157 +0,0 @@ -"[TNAME]", "value"=>$row["title"]); - $tokens[] = array("name"=>"[USCORE]", "value"=>$row["final_score"]); - $tokens[] = array("name"=>"[OSCORE]", "value"=>$row["out_of"]); - $tokens[] = array("name"=>"[PSCORE]", "value"=>($row["final_score"]/$row["out_of"]*100).'%'); - $tokens[] = array("name"=>"[SYSDATE]", "value"=>$row["date_taken"]); - - $sql = "SELECT * FROM ".TABLE_PREFIX."courses c where c.course_id=".$_SESSION["course_id"] ; - $result = mysql_query($sql, $db); - $row = mysql_fetch_assoc($result); - - $tokens[] = array("name"=>"[CNAME]", "value"=>$row["title"]); - - $sql = "SELECT * FROM ".TABLE_PREFIX."members m where m.member_id=".$_SESSION["member_id"] ; - $result = mysql_query($sql, $db); - $row = mysql_fetch_assoc($result); - - $tokens[] = array("name"=>"[USERID]", "value"=>$row["member_id"]); - $tokens[] = array("name"=>"[USERMAIL]", "value"=>$row["email"]); - $tokens[] = array("name"=>"[FNAME]", "value"=>$row["first_name"]); - $tokens[] = array("name"=>"[LNAME]", "value"=>$row["last_name"]); - - return $tokens; -} - -// replace tokens in the pass-in string -// param: $str - string with tokens in -// $tokens - array of matching between token name and value -function replace_tokens($str, $tokens) -{ - foreach ($tokens as $token) - $str = str_replace($token["name"], $token["value"], $str); - - return $str; -} - -if ($include_javascript) -{ -?> - - - - diff --git a/mods/certificate/default_certificate.pdf b/mods/certificate/default_certificate.pdf deleted file mode 100644 index 0776f9e7ba2bcf9887601b241308bfaa793f6fb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 526128 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%0DMi@4n7DeR-}N@o(W{Jaib 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%0AI%1_GIkj_(skCPRnN0+VD_ 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%0A6j6F&AyO*>15RC{$EBL;%(pKOEV$|im$H4 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 DGphXP diff --git a/mods/certificate/default_certificate.pdf.fields b/mods/certificate/default_certificate.pdf.fields deleted file mode 100644 index ebe650889..000000000 --- a/mods/certificate/default_certificate.pdf.fields +++ /dev/null @@ -1,18 +0,0 @@ ---- -FieldName: course_name -FieldValue: [CNAME] ---- -FieldName: full_name -FieldValue: [FNAME] [LNAME] ---- -FieldName: email -FieldValue: [USERMAIL] ---- -FieldName: test_name -FieldValue: [TNAME] ---- -FieldName: score -FieldValue: with a score of [USCORE] out of [OSCORE]. ---- -FieldName: issued_date -FieldValue: [SYSDATE] diff --git a/mods/certificate/default_certificate_for_fraser_health.pdf b/mods/certificate/default_certificate_for_fraser_health.pdf deleted file mode 100644 index 6d026671b13a104cdd8076c64902a8868e7365cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 525683 zcmc$^bzD^4_6IB?ASt4Nbb~ZA!wd{5ozmUi-JMEzcS(bkNT*0icS)DDlr+ABK5_5k z^Zf4pVMYKG1f6PSb!ZG7g%w1~LTasNM#{y- zENN5VJHXD}-5y6aZoa0s+iYu)h>wf3dQ$L6}8J)nV;W z2q_2z*5u(qH?%T<4TVnnZwESxi=Cm-kD0(=bQG4~4giGo#~G>B?`;4!5a5?KcD7&I zfGj|^zxIQP3R}qC@#lCz2oU&78#@5{*ESFf@RvD2KmhA6{aAr4zqCRArr+Pp!OHUM zy{teW_^;!!vI2jZmlg8sdRf_lzpMky0{UgWU;yNoIlw^ZFS-J=va$bF7BB?-i=H7M z)?eGezv_>Th3ywzu>rxqw6U|W{9*^}5Vl`*00sRbGk}HV&UpU~a{vp>NdMXf0I~d4 zS0Dfs^w;&mAZP#UydapJ|5ZLPI~&Z({(W9BI~4p^8v;XFez7$$6bSySEU-5Azpeue zg|Ph6`AZO~ul0J8joITQ$h{8eTs@Neb-vav$|b*ya!2JJ{)(S{T})qrk{Z9>!awP8K?o0*fUq!#jg_4b4AU_`8*FjxLJ)p1AIv5M+1WwDLOgerhhp!bYv=Hj z;aJd7sHlXbh0#&|l>pIEpfH!YbN(0oJ#CbTa!BKyI*2&&I!nfDOFBAnOAVwOS?ibs6(NAot%o}( zWsmfbInblg>(OwN)KsiYm@qkpcbB>y0^|L6BECKde`G~EVPW|= zeQjLVhuLoT%9oGBH`TYBEX6d$X8eq6s!bE&61^1TVPFxcg1HQi6H!nDF%$sQf$v9? z#9G%$@zsTc?igc6E^0$p2N0QYwXK30#n{%yV~ie!`01UdPij_Y+wFI{ z@$2+^aESLDv6$)6QD8ykw>AG3UVZ@jQ=Kn$?ac3hg=zNg6c)G~>>Lewc$lRf9V}qc z%$^ixX)wTF8an72=sM_qg_-xAFn8w+{MHr*q%c2&HT<{{@KYEyT|qrkzz?Zm z%M!AJS%|5XF>C}_92d0K|Gk0q&cx(+ejLAtVb(iQe#$0bXKll8?V`@Y1RE9hVS@r; z-w*)oTa%g3%F5aSw)!7Kz*J#pXa)0{pVKSo>e(~P|E7|kf7z3=Fblv|0qbS24*B6+ zq>vx0CWZW15a}IVkjjzXMS#1XAHtKe{ct@}wjY3K!d%k?#4gOI!8B;@j z!`~1Vv#@Z4S%R*EwH+z+$Jj89@Yy;1-p2x z1c2JG^PlR4ox^VX9bFkaYkhe`2lYE_nH3CO95k7QTpUE??=%IQO$0U@`wwyNVE$>4 zcZSO>scY}>5@r`hriKR31v!8$EbOpUfDORP3T0(yWMQRYVWFY@7n}W!j@0ky8V1l^ zRKEN92@v=vqTrv1f`4?;{KKT~E`OSooT0vhI+T?O2w-C)1wg?}us8;T9KgiJ4u(+| zgb9{@X)?<@>N(swjr2K?P)?gswt9A>=#Vi5ld+TFB2ctS;5 z&kUv?X8wP*DF_Q26BuR~AlQP~G+~xuXL;9|6!0gh14xZg?$G$HE9hrmQaeKwBb2{k z!XL=}3miZIhzSHE3jlmWOET99R044ww`rp7|uWxPlzk=c}MfyonzeDk( z<)5JdvHXvq072N9SYZkRf|%IBK*;|M#?Q_$HU8H7pW(Rkpnrpdm5B}J9Y7e{vcqZ{ zFgu6|2!w$OVE=F7FtmhaIREMy0N~Gn^8bcwfPe7S9hv-r$6d=m;{k;Jukipgfgo)E z!8!f_?`P+KhU1RO{tXV$4>&*|HYOGrv4PovKjC15IX3_{>F;dt&tzrfXkqaSS-~p1 zA2I&FfrOO>3i%I&1^y8x{tcD8mj5470fCsHU?||f@shi(fFGUz8I?b?k{=-i3<5K; z!-_ywSj2$sH^6cTRwghk`apn8U>H*W4JxMg_Kt=I+OP!gf5u#Yq*s4<%5Omw7Gr)l zoBvOO2!NFxM(HqyX9BW8V2u8MMUj8+`_G8{C8)EpGu>61tgtx63QOCdOi)-1g_TQ8 zAa?fu1`d5#vSe@gS2y{Y-~!qIdtdoak^Qcc{!2Ld50U+UMPCpwj6r~;AP5umPDTG0 zCO^CW(fJ=i`H>+0yU*Vx3oOinhW7ffLP*!j;jWahCuRQ;RGIm8?G5i5m}U9Zl=$T7 zf8%vOId8<@omU}?OmgDa!x&&1_!h(E)@kIeMH65@w{ z{3!&#z)Nve<)1?Q`}{xh$v^6t|1|$^0acw@-q1!Dmie1nTQSSIxMAx<$JnT#)dye{XGr*n_pP+_eY-mqY{8A?jHmPKp-%|75^)_ ze~JnL!9<1rNN-^c{}Yk_jF!J`Qb1t)55I0t{F$tZ2FJ-;O3$%iZoKpE^!&`j0G-?X zm>@%ir8CPqtU|E|FCagGfTN(65RkavZOu7H%UG&kE$7C3IL|#~FV!&RG;m?^xqaVC zjj_yJls63LT`IyVRM>Goy#@pl%5bc^S##}^sdz92G*`u>a)}kHs4Ag`vO>9&O zT-3#U~fS&U^ zr%6j8{=LDq7MXS|`3FQeU(5AOX`@qkWkw;kTESXyxR2dWe1%#fIOv{CyBl?;;8!U> zWTQVh;bO#AFHXM^iN2%?VNW-SzYz-AZJ?B9&iCuKG_;`CSBI$8zbduMvX56;le8#F zOuG(vhg}}d)>AgfWx_XP^Nn|?F|=tp@*e!XMH~&Tzo~wH)YE@qC)n=Kj{@wD$L^TY z&eY~^yWnm!6;_$w70Lo8x^}P)71q0w)WO7F9Rz|gz#r@>sV4DKOyCdV5;nE_mplHX z(YsAy*m!@?sIsXQpOwAoAJ>1#@Go5YXWsLhf3dQ&{0ILEi+yQ6_X0D(ezH7C-(7WJ zu;1%pSayQ^7c!Zkh}U|OZYFZ_q9`|~md45@J<$dwkZ{2}|Yqg{`e?W$%E2{1$WGJzw2M%_yow zLq}Z<>W^Q1h0xpoY7~z>SVQ|V?M+$M9WH29CmR@n~b?si{VFQxoCHOv+~x>`SQ3Z2e~$@ z0Bgw=Ss1&WjgCa(r1*o6&Bg-y{?0ez<@3^jjhqE4}t?7}E?F~(6OJ|mrBsD4y7tj1`8DCe#Ku~E5 z3sT0uxQnOL4JTA5eoQx9?eIIl4KX%1&KNTu^)%~onM5MEHa}a=gqgIXuF$=|GwI*A zX8u0l{fry`Wx)F_aInJS2J8PcaQvA*{vJ4B+t>eh;AoN`u!`kF+r4l{A(?|8oZY#J zEf#;Nh8aklmH80?Sy5IEAdVLEHd%zCal39)=0jnYIjfkXrVk+&(Y^33G7|JnMjFu}6OQ7?o?^J2tT|wR_;hu|~gErfhb>aO{kk>mr%t{K3Fi zQ|D?ByrC@J%dOYekkDnKx0&RFOz;CF_kxKx%w3plzd2Pl%rfyZ8#$LW4jegE&NFOQ zt760|+qAeo>&LH+5gUKTzJ)`RED%sF3q_=ompS?*s4MX_wW@fTZ>cnXL!due{k4F} zQW|YnfSgfrcr2YzXj-uxwvy?-b@2O#@gJb%Iw(Da$k^Ea@%7_q0cq+E2b6>oM?0f3 zF7#m!yhxUD;FS1}meB27Y_cGyYf#n@sIBZcg^nY^=F1mSXw|61&z!Q~Gx?}dhvtbm zH5!nCmLJ&3)%iUoCKV7c6vC3D+;)HY8vf6fRBd6M8D0x?hFmt{}U?^%A{x8lf`Ol|kN5=18d&QJd= zG=8&rFckWqY+ixeS{;D)d9i$ne4Usa^QxD-`F0cAPAUUOOm=N0>7 zH_autOCHY*ua|5k^WSKizgOoJ$;65iK^NA$y+EFMS6c#1^QBg@D-_5htCz&l>NeVt zMr-N0&4F#*vx>z9%ZzVxr+L)W=y~|TXgJ6wdMkxE_z#OQ(o>&D1g(^A7+jP~ji@3} zso{MdwtpTOU`RPm&dPCS>l1`XSca#CuEr-PI?j>2@^tI?0iua~I(EuVFo*TC&v^rq z>_DY;qhNmtf|CY+wos)727H4hICb_es~8@j{uw(KavpuXe*X!$|n*jPuI=WQQFY@VWGbq9{Z%U>_HPq z-!#NchwCzfltTOt5n&8op^lRC5)sJh`5$x|-OhsPXKh+A`9K24(a zME>jptDQ}^fdYi{=DE}Pt|jC2?plwy*h2uWJjezW4(;#Yd%Fvf8PU_GQJhvs+m?}c z!m7`ap<1NS2b=7J{v=$t!f6{Jk#alO!lwF!!CzwFm|RKSg881;M=(s*Ew91%-$x6+ zjGj&pl2qAy5oh6CsYPv3sUnZ-l0DJ4wRVt6E$IE=**%$Hj^@9y%^#0lex^mg^D+28 zB^q%GjWJIEnEj{Nmv9EAxg(-m_0P%glal7wpjpHpVC>SjWM)J=O}%1|b{9@DK67jR z?0IzC(p2|F`9La@dCJ;)C$sP3^wLc|li9k~@vwFxoyQ~iwtIeE+&A@{A=~C`C@?!P zsaIQ9G~1|AS0tP-msYa!yr0`951ok#L_Xr5DUg`6{QMgc4$63MnKV3--l@croM-fl z4>-;5Yxp!WXV`en=v8I=MT18{RN7`QR2rKJ1WV(C)q`H|@hJKu1b&DU)h%CjMPbZN zBF8TeKuHesMhICAvq;+g`K% zs2O@fMb8CPoKM$`q@nU1w~mv~hnD*AIWbQb3GAgTYhU@(eX# zWMDBq?g@Dv>ziGpdznE4+HEB{rG({Af+HH9ri`?+Ep^S3;}ozU?Y~LL=ej?$y%ZfE zGJ-2(=zuj*A%@LypeN2sBwZM3BE^sXX;v7ArzZXAdHCoX$_Jx(DEM9|M5_ywWO$c` zv4UVRN%$)4vCM@b$EjB)Nu~8qhU$xQ5YznGn?}yVYCq4y9fF@bYGojP}l^;B&O8AGv~Ygjej#|*i()FNVV+|PXK7m zL&|GNHnG!EEA-eaAK}<-gcW_o$23ipJ$Q$b^Fh1&uJnp~?oKhrS5#y+hQ&&L20&UL z{uu_*9CG@QT*VK%_z&3R-Ub=dJ+6=o$sndp1TN`b0z5NrB^z%%E{PVrX9H;iV(bbN zIyk@EL!}l!beyycG~P@-!AqghOumy;zSaC zeavAi5vNZ;lR;J?%g{ha_sUx5joJlmH>+3K#EXa}Fa3=^p_f!}DlA}D5yV<{ zh=Yrm%bI+}KS*4ri%z;VReRM5EquV*VZ0F*Ez#Y7&*~nobKR2=bbbhUA+|rU;YFI# zVfliWEVi)JHecmx`_&DRk>K*HX@?STvJEL4k{0B%>y(3LZ%9aN zti7i%*^uFYCZ8{SR90_f|G3V;vh|adT!QcZ&tnh)i^z*C&H^d!IZtj2*$wE=2#&m4 z7nVGu9xBI;WFNP&h?RT4P^p;$+4xV`JSJaTnSp1hW5Up1hI`cG)P0OE;;e4}%rh2F zw}+hDlWfu!k6Kfkta{nVWa=G*tC%3&wqRSg^ZHqKaYJIlzUV#w6Mn;T^U2uH5v$KA7apK|G zqDeedUfZ{CmAJRejp6M*6PFyKR3PpH*O#@Ni=u9nDKs)q2zsAHx|akFeWF@lurwxq#ZR{Ckf(-o zzw&8A1BHxO?BU_ZJO*o<+Amd~n4~GeM6O{W?nGRLH)L%a^9YuNl z%&6_v+a;7Mux%hQOLQ>?RjL!W%^uvaCW1J5x23n^-1m+RQSwN*t{NU0w+~=QDsZK~sbWc%*yu?vGt)nx;r*VQ0@(i(Vam-}jlID1JX7v}@9M?*LFT#y*->Jc9QOPlIX5cYw|h1l3y=Xf>6g4mf}|3b1+n)N=UnIX?WX0 zdfaj&xuda`IptiMgRvH4$1|c!X(1zpwU>=)Ed!>wjFNQ01Tm;lxo_}x7Z;C|XGfcM#SYEAKf-@v%ubh12%V0i6v)&=!qesc{DJei ze*X!PYJI5D9?h3{m#KPOJ+KkjNUj03J1`G%ox9(6&pKX3Hf`DxVMzj>z zE^La(~Ca@X&ohkjYCk%T(kd^gsjOn+RCt%OG@7@gl*FEChL{}SZMVv0_ zv#o;ws`~+o3Bw0`-I(OBe9*cuKLC9mb_@oU!eNPuias!irFt<95RA%t{tSnVysDTq z)Q`NUrH`Ca_woJv0iLdrTthp#a{USe{Uq{WMG$y?Vv&3E+uqoX*V*U&V^NA6xj0El zPj$!r*fH}VW>~E2bIHic=hU%i5)B+ zM86}5MhONiVs@1m47QtRFN8SA(=OW&{=%)%?g!Xia4W z-dxH84y&DBawaRN4xVEgykeq!@#$N$+OU3*CWDiT9@p#H+2>B8yEY-BLByC6jCy*3 zg0ckaoFBU}!g8zx^0F7cO&F9YJ?ky8DAA=CbPV3pcei_V^yYYE0_6#VVes2j<0=E@NH36~7Es^T)qb(f7@{Ou1IWu1=oJd5k9*Tl?Ak>^jey69ag ztXJM%6Mb)Uci|=3SoH|;UbblYsC>aTbC84MH;h9xj9{HbbE$U^k&IaES%mDf&^#4i zMHPSabF5UuHK*N=k<+369vZW;?Ec4fKH9eEY_e|xQ zdIWZzoO>w9GP}h5<&~Aolje~}fS?Xcw9bcNe257YPf9AKGEU7c+Lb&4Nh*-8Y@dnP z5*B<#t+GW{J|yt!*5rDHO5FKLBwk^tq^dZ_jc*zvqg!0CU4nQ`q)UTj`;cwPohxb(N*@k;uuDNi@lBia5UVE62mjb*ifh=Y*x3IEfa$Dt3J zUe^NfS1Zuy522HK6fGavfJf>ck@M4m0v`OcnYK8pbwTuX5$bjRNG^UJdGvYWg>w9L z_c;|6vCD6B@k@A$Tk+2q#Z>I&=u!!L+BE_N>dB;6o@RU+bEPh@!*3nhYKp==meXo4 zaRHYvJ2v^YZZKXmdJi?al8~(EUxPB&8CrUj&l`4Y*&`3W!h3y`p0@m6)@9wov9h`+u!lppiq)3EwOcLG4JndK> zAwypgCi~JXu`uQ;;2Xa_!B~12vHU=4H4Q(Yucs4zZJC(3{jDfoang~ZVO%C%0bS9j zPpvvsCHSA@n2XhlYuv;p6i*dAPpjO7nu}8k^NZ`Z^KulbWyIebzjs=0l3MHKdR@?a z-9iuII!K1zhVgDPyX>{5?WA6FE^b_1N0Gei+jtW3P%sBiEsIL+do07VNCQcJlzcr7 zBRz;*bU?ie$=3Nj)I$KycXd~}hUfCd*hjX-DReIoib=6cw+k_`>F~xy?Vj@s6&roO zN`960-FVcSB^Hg&$~Y!}OAe}#PdWQy&V-F9`<+9w)dMn;j=7+ zmnKc9y*>3)Qrx`CmDuNg`f|BDXKaQlrC2yRg4!(1L>{bEU7x}S z)Q1aSqUC6!B9l97p9Q#&t zB}y=aa%{Eh@H#@xGxMRP0HrB$WH)igYmo`RPo)OAE_xR=ly7p!bJY|F)Xx<24rd=& zMnII+bKZ^(ni4lRwumg2WEzJjhuWhPGarP_RAFJ@wFtYvDH!QaGG<`G!RreP?^0R~ zvwaCXX(%-dr1d94%<@e40|W`3C>DRO3ssZlTI~G!q7M7U%;QnZBz`l z63P|3=!_Msiq*hxbxM4(tvc0vl|sPtDV7885>!gwqEF(Or@rr-wI-?=R8hYF0iGN_ z1>pq!3kl{E7IxhFc)O0HlO{K&dBX<$h7X#L%ks-`%1+Blm?9e&$Ec+b)*893Qs0Q- zLDJDI-#W>-lRG$}rjJPqImo?|qGJZJzKI(d`C^%ix7Ee3UsTyOZIK4CGaMl1(;_1Z zEUjpv8{(be?KlDVrC`65|MCDiUFJBRpTm~lIC)t0l+A&I(~W&J(GgO<%D?&#JI zq0SiKJ6t-3ki%#xnz`cRbWi@x>S1L1oF_z>i6t`*)m$BU^~Lpm8sV>`a!cw<@^W>0@R}df?8ZZ+)D_ zA?B#7?g#INboe?kRN6zPE2xCSHT8F!yD81WQi9MWb~SgO7<&Xo}z-U{z)y3Q7R!O;&Fs& z#MIu0^;SB=ce7oKT|-?{T{Oq0;qG0D{A@Bepj+cF4^<%?(Wf=@BeaTioMJqLF8VPvAr0di}ZrYvaS?iVsg7 z`dEG?%-}1Au~HB=)}GHnHZOxOoXvg24*+(ILmMn9KEltwBuflwI7)l3_&(4vi~88x zXt6p!BKDy{^KEB&>V<=i;s1UKgW{DHh3-?AHj|MJl{(Z_!Ms)7`;u7A`+<%u2-F=4 zNr-35WUp3GG=g8D;DMW7^V(ovW-(v3bBc<W9kpDIj1iR zO#F(%wj})dRjMtjRi|Yg5xgzZe%vY5L+4fE&-50}KF2mZh^stk?Kdv>j&-!qI$8Py zosvjU+rV`Z2$h((0Z5fBIPC~74?7N7gmoy1+jC4FHIhCg8h#w9_Y^1geanM{k0xQh zY*C24Ht-U7}+ zqvaDC^&qhmNrm(=Q@f&vAMLrq^dVZNJ{>G!Imchr!EabmzlLAbhgvyeSLD@GwieC)m* zxv@hBz5=4ToGP8jdeMDFO59?>GS)<{_vwSusHTq@^QqQ^Buw#K$L!R|uEf=Zc-ADm z)}%{leI|!vzb{_NeiGR~Xg+&Wa1xdwPuHB4coL$uGvugwgV3DK>L%em%qdPIU*{Y0 zib(QNyw?HNj_224$M5@36^lx>WEIbyYYR2L4=@+geYX$$w3o^C#_g-=RH2#o8bN9i zp|Jg%*CV6npG*urEUO{2&n&~8V6^NH<0k_LNJ9|Y7b6EYw`bhpT6TG7nf7n&iavjW z*joW_3J%`@lGwfqFMLdOMYUeHY)XfB4U}=jMLM)vpxCEKIxd^nye6X>@lJ z;z>VG%=;pTIJ>WPg8a5Hk?j>YC$t>ph!jL76dmQ~6(3EgI{M*ibHp@p1j+x?}`(-Jj0c-`BmfF znk!c(?pOA28?T#!a6>5$-44XAr?oxQed=lzcRONT(972yR}>}*-k?9yFJ(^^6wfht zNRQbrbc93r#7Vq+%VlK$IayF(;k4$XDGEwwMFpnfm_k>-j6#~=7;d2Y&p+$Mh zctspVcQHswadFXh%&=KuN^wFVt77Xgvry%uQ;HiE2QwOR#wbAkm+D-AU^U11x!CBm zXHj5IUsq0le$I*cWrGyXX+ux|eNcd=BdQpWRnC@O&L&;Xikqkud9(3S#l}J7%&D6kts6vbh{brF*qG6Pdi8bj#MIllYRjn>fo`evMu)x0 zW|1MS=BtyN{KeYE_Olx#v}@hrNdG{zo2^aV{SJ{ZLh!79|FrF@cQT9Z=o+nj!OKj5 z{p2pxo_ljZyTWEO_ropSD>t$-K#e9t>!v1tUy~$Zd zbNdzlH&yFp7EH z45D+Hd+It!7&t(p0E(phcqKN4P2W|XqYSiZtE`~gxA|xth0{31X!e~ge9=J^0B48A zgv8d&zlP|_JlGp>=g&~xZaPUpaBaiG7eHE`;J46sdqE<)g7-D~yik{gupouIUuZ+l z-v0}YLTAbWDH}Tq$(2Cbh01p;wd{}+6()R%4|&itJ_UER7A; zZ6}<7dQithyZFXOuQ*L2pD4=L_ql<3!eW#mj=P{q( zzbzv(Utu=7|MWiF7dq)iRkwvMWmeU1v~&ULNiRvu`$LtxECi}CM`VLwk9(1kKGVJk ze?fzMt`266Nti8cu6V`XWBnXnC^hdUzZXuPtfx2UYjwmFH;@xQB?~ zJg*PI2J1H@T_xP?#oJ-tn`w>CY^hUBWRwQ3p9iSm-UV}!M=8frrD|sRii+|(Q?zS} zQtBxBJ<9UaqYtQmVVFkC7%`@#_BscijddFRt$ddnX9UW)+1tIa74vE$ysa>qK7DKN z&3&xc+mS8qv$U(`!5z-Ui z4xN)P^d1OGZsEeO2<74B3DhfJ5SO|~UaHcixIs_5$6HHXC-uiM++7}&e2243)t&BD z{W$LYSe4fR!vNLwIgsDE5=oX=?<$JB$3yqoyEJ{0s#c0wEj{JOipV45G!*0^gKWo) zL5|Xg@1Ad-Z(c9vh{mn(4B(=F#Xr+g^w;D4BzEX4cV8R!PSr6crkiZ3(ps?**maIbUDB}r^s>P><91_b*m>dYiynDz9^GD z34Ea1ci|R3manNvgse`&n!oAyC@tt5R4`X;XneG<-$=diSm?JFQth}pzqfMw#3Si@ zvi4)CkFPvrpVNKR8=<)T=&6^=PAYlGk+UDTQdJkAM{8x+AXgkm4`&Ftl{^S^zEZdt zuf)&Td@}KNA&)1YdcvCnmz^M;K5cK1cyo0SH_f_!Wt6i+w+TZOrTNDbW*n3#9ZlUGg)fEBwe2A|A(2tsi@o3d zM5_?$j~}U)R}o)0g6ASi&s9H%q!K!JTwzx!Um$iaAy_2U9ii@);kahnNal*DM!Lw| z__c;woR_ZTpM5-5xl#3!WKd?}P^$9!>_gNugH$SFl1fqB)H_LGQJw=_=W3dB0!SaO zUa>TNGCQxvwP}=Yf5d>*$448m&fu@<&@R9gd_-}MjDS-O=X|aHRnOQ&Wp7PP?Vv~h zE64eqE93i^hPTFBS?@FUYcjIv&i(n!Ifc3SGly3lUhRo<2km;|TMfEfBvX7C;viST zW;<_e@+W!b-7@Ti2VC{eS~>{ECu*e@a1G=r?431lM&HRmc;t@hjlC$C;f{Mtz>`h2 z!m3y>dme@TIJIK&tZ1IY;-#_Gc5TbcT5==aRR@_5cn<>_IB*eC@moh^w3XH0+1xTt z9B&LJd)g}+X07C_g8KT5zT|mXURD>$dr-xOhEiioF(fUWu5GSw7&N}qkebMTI9LcQ z6IY4PF=Qz zv*@GK`Vu7@H*m5G9@^|?t>-xY zG&m`(gP^U6(P+e(hv^o-bLk2HNPDG5Cd-FT0@h&st}LV5YHp5%okUB90Kjl!qR@)) z1Nnp3Sn8at{awzTIn;BnX~FeR>Pt>;FHb6RKeCw_B`lPl5fH4hr(kvD#?M{Th>QDC zOuEt`n+qE&oTa|x;Z86~2C_zn#m{*`p@lDrhl+{`k6gw=h(7fV-GkQa`?kntpwFye znQ20cRjHM8nP2lI&2pgA2X9Zyhg)2l^{6Pr1GoSIT1L!L2L8#|Ap{v5Vu?2|MUq9P z!X(be!gg?ZNTkIKo|`3aVu{Jj_7)cTdc#BD;ojx&rv!msfjaRCEIqsw*Wty=c2c?U zd1Of5`dB@wY?zU0U1WabA`KKZ_f6uQdt<8c=6%bPr)fk%$y`j(0&5$TMoQyN^g)xe zIt&S7YQ#VplZHz64m4jbK>2-m1KXBEJDnxU7(fMkxrLw#Q_$fvb{sI9_7%a zFz+`;%&v-h>T{DPhUbu$#SGv5RdlDcIIL|1Pgrn@T==sn<=b>~$ALEl6xUR@F_pB0 zt-7#xgT{$7@n#78%Pv)km=Fp!$kO+$NKmTgiRMQhKZ>qt1iATvh(p-A1B`rdiAI9_ zAn_8#l;VQ158neVjvhGA9JNG~j!31JOg|vdPBbtW(_k|Ro1}70*{J7R&7w6`8_w?) zxlEEVb|^iaRt72wrOgz*^N$MU48GQCtwlo@U~kS39-H#RXb?}a!zX)$2Ru}c6FwR( zX}_F7=zqhaSucc4251(jmzI6kRK}pJWaZ07pZF@&P+B%!lFE6q^oD7JZURLGj`=hJ z;5X}^v5iox5m(Fi#@>PW9o5_N0B+(1D&H(N=0{O6vHnT}gEd7{ZAw&M4Q=GScu2uC zNN?%ca4qLvbu!~3aV5eh7Z{Tc+uZ0&4<)AZ=EDxug;}+xe$MQg1g>(7jXf9FeZuXT zez)T0iPxw&3PbdE2|Ibk@{A|@9OHG_TQ%VDfq_$VYAN|onZzn`&Mq4(`R5xu*3q8c z2qQO^!uxv{=!qIUiRq6BFHMYIUq>`?dt7`v+}Yt?`veC|#%ACrW|GX_L4C;63L*h@RYD|cqc#{4nv2*pXqe&@DBqz3rYZl6cA zBqNXCC+y$9wLiIf%U>Qg zWMtbg@l9O~8SqWbi^BFuk;7lOgX`LQKWAA2| zlndm^!C#nS>KI7+y(YIWFsd>1@46YVcht{BMapCA+X;!P#K6)vAb%&cf)o%&eA|CI^lce$NCAEJfoT~X1%MfEz8!MF!>h~JB zd7f6-I$6XBAS$5z0Pq&F0*JT|#L*%*AQYjn%-{!$f3h2ml>|lVM&B4d(Wc)LlYprckwkm{JyRh922Q(}_=7wey=wg`7}(vWI0`Kax* z>3S)09(4~zgA+a3jA|l`=Fe1(Yub*OpR+qxikVXE%_w_Y2A(ETZL1ap>|ElCry7J} z@O&C%z5a%OwI!u78j40Uked+~%h`i!fZ2`M{XVXF)aWB5-g6j|Mxi0Foo@kw1n!yf z>Ko@vol&ixIG$x`j45Bn9g{;OG{0SW_9bJb9_CdY*j2i(hV{!^&@s7w+Z{`K&QS;w zojb})cidzYOPtEm2EkZ2Gyo`e)&cUkIM7{hduNB9( z9+Pu=Q^T3ZQ=E}{W^wsyBQVL@JIr=c2hG_|wdSZ3Ba0NK$G#cRxcUqYHj`fe45O&xj_b2HxL=s|Ws;JGF zeXQ)5d(urT*Esq#75wRTEW1!gohUg}I{%CmvSO7> zlHj68F*#kU*Q6eSpD@9aL;TTps%lp(V^Jexe!^l=mkUN-l_@ zR<09HhC?*%!{OUUGRD~1DNY{B4ir^ciM=V0_oY#| z5N$Huui+TBTF1D_YbJa&1Bx~df8pE+3Yf9}TAI~NU+E_QLGcjtS zXIk!)^b!v(+oFLNNPG`qp&f2LZC^1xD?N9`Ew_hMKV`9b?c+2WxyP&9ioaU^{JqhU z#an~RrdpBhA^?6fR(r-P-D1uA;>wvmgBwrF)E}S4U5a0#covy!NNabOd@0zVy{Sqc zudLNWTS_Ot(XVn$QT0cZGrvXFuG(*R4%b}Z(`i5*yTzO5BBC@qPnSvfhu(2C}5 zYYceCm?qE{zc`-MhnKh+%h~LI-?CEFhJKi;>VamdFT=rrlW)^l?B>?JOR6y%ye{Om zVsMyj61#{u@AF12_yVl8m*l7OU+YgAiR)Ui*GkMhdHJ3C1EP%5PNZZ9S*6H3+`=HD zNhDn!39T8oJeAiX#atEM)!008&E5!o{ufIv)P1Q#`cmXAL?8Eb;k!_r;C5nlc-)@q zBb+IExxcquSV(>)hgMk=Bvsw+Yk9oi{OozsO`-WC(+-fx%EgnD$Aa6iC;BY1GRBEX z;U4AD=Vu;axLA{pait~islLrGl6Y(TT?yQv?5!qALVfI5*U>(aYj^FbUxm_Jc&YU- zthydj4ft{-4t-pIXUo5zQgU|j{lU=S&e}uQy;kl7xLLYh(tX-4GK4US)MuGoK6Fc1 zp1qxfNAj21SG3>TfC~$6{l#eVIp6K>#7V>B4gzm16WBVxN;cA%Icm(L8@3KxzG-O1 ztNe!Rh3YZO|E+UYd-^4@(IuLz-xjYtasKE2OOmSj*tqhKE!rs^*H}kb#|6pWuln`e zxD6reGBHBH8LwE{FX)NN-rgD|2K`k&Zr`%GMC)141L};n4vewzJj~CpG9@`K z8Ap`5CVj2*&z_xeC!T-1khUh&w&PWQQW@GT5k|`?PRLkU`f-TPYh12*QGu|})|aUz zmxmUsReYD>kUsCE^^;>9Pv^LK*{H-KL2%22NxM@FpPQNLAjjr_?}F{Z%dL|lV?6VH z%<*~ZGyLrNOqoS#H)aWJ5e^{Q=sdU1-(C1Q1Rz?(ur$AkO?-v5M1P1-wJ!tL>b>;hr}W2ly( zmIL!q67LHa>zZ5tD#;dE9{urq8_)x+<3(eh4xaq&!O=LXcbi%B;vQuy0%gfZ{yRe6 zYf;QGl2w@uM`vmaQG{2Fv9)DQ_Iq*%rJiXI^xATPB#|-A{RN=Rh-qulp75?7bmYH3 zE;76CeFk6Cw_yqDki$chkf+n-xK;Y$pOh9|*OIm>oidxk7j>zmL!vjD-i+b2Y!Hr` za%M;PTMdeE?2!-by&Zde-9=P9CW{utFtPQtbgNpRKz>hoyeDSg=fbqZv4MhEQoVdE z{j>0ye!5i0ZnZrSbXp>sSvH24b^_wCB#&`Tlv3~M?H~IwY(#Rb*lv0EVyH@>G_qQu% zDSI+1pBNLVujoLf3=A#HcL65#rDhH0`KV{zxs9{2Gv4=tISIc7)Ky^d?>?sdNEFQL zN8t^Rbl$8yL9%L#g)=#M(p2WQcyOjQ@%i?{n8Yz}<0+f;;?wjw??4)R)VNcE+V7nw zsS45SJCfSjr|W0Q8{&+Mx|eigsgl~qV7uy)=r@|-gnMRdUtZ%x{&8WVOd-;U51pOp z87UKvaQeMpkd{TKd%C{sr<3r>%a;*11(K~ol?;!Py$DX;uE%USt6d+&5KAvwy>0ET zYSp>)tXX&PYVADkz`21t{vNVL0=QAnS5CeS`BK98y}ZU^-sJ6Kq25+-@H1paME>A= zi*g>p($a#GBteq7=PE-~olFaM!zT(VZ2e@FSOP8Z+koP)y_E}`2gMqL_B9<=270UzCo!Cu57w92aawI2nV%H)yPC$%rB z9-pR>R`u~Jt&X1Sl%v!LbABW_sy%KsFppuZZU&Yv>hZ3h0d^vq9QRy7lj|1BJAj=U z9tyYx4I`!_)i2{|*#6c9oL}jwj8n`evM5&@*3w3j)_djoMOO0YP~rMA-AlSe#NC-v zU*aGxQCeEP?=3l;8StPCxRCHNFIHpG)Bm<_C#jGwKVCVk_2Ckq2)di*Y8^l1-IkO< ze5N?aU&FnoNWm7h2`}Y0qIGNbCZ5tEYwmq?J+qP}nb~3S(iPID7&F`Fh{`cOuZm(Tk zy;iN>RlTcs*Y3T(pXb4LNR#S>ON&G70AucB z^vPI`2bNJENHd!VP1o`Vk@@dtxvFlLL#>Jq z0J>ck&tMgc=nh$R-=HdciT(70z@b%ZnIu~n&Ma)V-E4BU!y>`T9cSO~Gr9L8*B3Wk zw)u{*xLNiq`#^eZw>sGN%JUHHBaHiPi_&N2-1maKs#9-B zoTx{->xY%Pza6>DpS4Ur#OkkR7iWztThXAaT$^L6Bg-K=2)(IovZ>~DGP^XTe2bs0 zHV(pS*k{Qb1Ai*>o9+_U5wkcE$Z{{-wMQ~K1}G>#PI%Ggcu%oi*BYAk&ty{x9P(z=aN&&V~Ib}X)9*yjl_k9lU zR);X{0^`QCww9}A_Lp-Ve*Oo?mOR!=B#MFz!sS66$& zDW@e*B+=4amc+kN9j&&tuBzR&?Jy z=%yQX61zDT8DaTLW7&{v)|#r2Q?rGn2o*b`X+WW_f`v3ENRd5~Gvi2r(iG{0anFk; z9EYe_QlkA$6C#aKH&wEnQkiOKKpJLKYl<(9h()sz)EmgKnu&F>ih*zgDx9Xko1mJQ zb*V+nooQ+O(JDbmiDV=+8fgQ>u@NGKHAc9ho-WUf$z-X4o+?6jNxFI^qu>DDSO^#{ zo=z|~SE$nj@=E-C?gfUQ3G z*Ft6>D#{z>Tw-*K3w5_leY9%t2g*2-6@l~W>d`hR$`RJe8NL(V-{%Xr#eos$g0Yx=mN-xNJ3&yj0V{ZDtoFLk#x8-eLCVp;ZZGO&_ zak=AhPi{}}@{dQeONTu@K|Mn|iwBEF48l~EGRm3~Oo1ZHsZ|PZL9J77$(7Ct4_;Jon1sqR{gbugjkC&C0V1t)pN< zF-F#va2&&Uhb?j&|(L=nJc(MGPLc&KhtWSoTo}s4JM*2F++!nFi_bM+0oF zWCEye9`+ntE*YP)yd8uPaG*E~}goz;;nY!RILvM@YHwt;?T*O?a| z!VUO+^^*9~(Z6)vOB0>!q-S9OjD)(WYQya#s@m)6BQFjh=nFYU+D5bwcn(tCwYy1n z(Aq{CpKIOaz2)D-4m}NEn|=fWb+b6N*p^CeFUxGQQZ2H}+HSV~XS;gx{eX1q@@ktS zZ75EiPSl1*@T;J0dC|ZIun9Na5(MGGXTIohq8?w@( ztFm?B9b5s}ZS)7Neqq|)Gn}zLy)G?Q8DIFVSe}ZO!heA%o7b7?)?}?s;IA%uYT92I z`_$w;v;nivLu?q}7>U@X!?hu?FN$qg;20a*X2-PsU|%5LFv$WjU$W_(5#-D=ZL)38X+GVzO6}sK5?YeoruG@7w zGY9Hr5qH_Z*HHF2oi&N^xTv>b?PY9#mDAIP@VLOgVg6>Mf0gCaM)0`gyJ7!k>}MDr zE)gD086Ig79*Y?sp%EU#86M>x9tS27{!=2FR3g$uA{JF5LPY|Opg4fxJs$l$9v>?n zDI*?Bb1$xXJoIurAbUJyYdolXJnWs)ALzSm6;+Hdk`QWuGSY}L78y!NGFjL%xDa+w z0sUA3A58%%MFC4y0c}MAk4*ukMFGb}0pme|0B#;JW*$>^9(86Omu?=pW**yi9{p+_ z|GTCuXC6y;9&LLbk8d8OXCB9A9^+%40F)6ih!InS5p{?WmxK|yh!NYE5&e)6AB7Pq zi4jYg5p9VPkA)GXi4n(%5d*+T08@_`RgWoMk2+P4OH+?rRgZ05zv>ls(EyCo@FS}M zT)P2ovjLQ+0j8?~(yIaC%>n4Uc00@gOxyu>%mIYL0lLfq!rTG=)Bza7;YXSSxVi(} zngb|@15BF(q?-f6(;X1P9aP*MnEV~=+#LwR9dz9tg#8`-%^fho-H*IGaQ!>D-8)c$ zJD9#ZNIy$3$pt3dAr=r4W@Hi;=ptt9A{Gc^W^`i~_(SI08B=d^17UI_BXUC}a%0C* z1F2FYt5?Pt*%F42^wjh8T&(njjPwl6v$^W&(aY(9?CFuM>7nlFv3J^jAaoNVbTh&z z#_$2!Nh8`>WLQJVR3ppKM%W>Z)MJfYG>wE5jSN+dlogE}HjShfjVu?9vo?w$Dw2$>XP|o-u&U6vZ zXFl~-FZBCGGju>uE2v3d#PXHiFQd_yG{UJa_qiO3Lk{>LH;jCZK96qN*;S>N24!H=t@e zpsL@Y>iS3lVVy0?p9M{)Ok=;lU;YyM2 zND=o)k$+JY1g0(*rmhx5Q;ZK(RT)vyAww-pq%K*6R>cabsGh9orY3WbXrhKnkPi#o!C z3d4gM!Go&6!x|9WG9lb5BHRii+!|EOGG)vvX3Pp_%o>>NGO6q;s_Y7@?33%O%*>+A z%!1C$k~iJFFx{dN-GUO`l4H%hRL!DQ&4N}9;PDH>cA4CE72S5F)enBXLN^!c(Vc$1 z?1MW$h`V@*yReA6^pLwCiMwQpyQqn~4A7Y$)mc2%Sys)mgIHS=7~8_U4%% z=2<-ESy<*-dg@t_=2^1lS=8oP_Vk(`_gXynT3Gj5dh=S4_gb?1TGTg-i<^_}w6Eii zF(B%kpksnDBI>fBm}LUdGOBB;v+KVe)@F&YIRZN`dXBp(9t<3P(E}RMA}m^r_%-SN5$VAb z>46pLq37wqaJCY};32NX2?4PgXZ``SG8*HC=r)|c_6tyS&qi&g2Xv-~ylMM|X$OsH z2b5@s9IN}Kst2vA2ehh(JZ<_NIPod=er5+JIY7&eSaRZ-@5y9`G&#V}j(BhqVC)I& z1V=gipdT@9$5r2x(g~?@fcp;KwB!G;vRb!2xvh{c2ZZYppLPO-Jt5xUusbOH5#xVX z!iJRH!RC%Qxqs($M7x92?x6KXtljbK_hi45CwK5WBVO(V1bZUh!Etv#_(#m2arO74 zy+i8m;Ce^gp790t#NUJS?qGaJ?4R-c_T=9~`tA@uNBp*evl=m^p%Mo%rLoMhrZfk3 zE{A5;)3Tgk>?Ug3+1mD7w_-P)Ag{-B+F9K8Yqw&$oDi-jdfGXj_ItPD-T*-O<3a9> zZ+D1~=44eGGho)7{-ByuLcGagcfarlNIX#E%<$s&4d4y=!W=Pi*2nj82NHNwi`Iv~ zt4JGg$IM!P@oIAgeAkL5afK*z#Vm0JVQ;3JL`Gi8u!!WaYzPHuW;UlE(*AZnTQsKV zTA$g-9_q**d(r6+(HS1m87$EmJ=PgW(HU9M8EVlPd)Vqfbmx`di{Oo*0Q{4kap#`f z%ixVN2jJ#T0o?f+_WmjN1R(28PPuc{?WJ@_sspg~rY_w1?Dt~2BRBx)JCmF4JU4qe z-BE4;{GF+{?*!Cdkasu&0EvHc?3pufFUdPn9)QI^b^6TvPrYjd0|2dea_yOWcQ4C3 z${v8%JN5L;FR&N(9!>y2@tvG|=IYx^dymuy;P_76JoEYO#l1%e05Co$cb|E__VV7N z`~U=>Q(q=18!DcX5rUM&OjIfD$&wu^687gLS(5r2I<4_^rZgK`tqHcKJR5qh@pz^b z8=9^Ox~3c(x{vXErVJa}j|o1e0vr19@u0_qTpF(vM2q^=B~q1SL~P805K=X;i6Y00 zTspDwB*&CoT7Ql(v1mn#^+G2ZE#t+o=t)e9acPQ*CB>#Nv1ks9HMLB-nunkn3cJQ0O)|zG#tJO6VmuRFj znKhTaTG6CUTZ(Nn9IBSSqGh#O6RUHjG;5bzHY$}P)Z#UAQd(tJkd{DFh$Lt9$tnax zIYUoOj2;RSpkw|7by3GBXe~OWUxd|}#AiatUkk%cyq6Jn&w zyTkR{W2DPkSwa8*X3##zsU+ETFn@pGo;s_NasVUKvfd zBGRUkSb$BjGGe@)TdJrMO7U+cW!@j+pKZvB;gd%5<4&r{R)rS09&$flNF!ZDb5XwE zZWJIY5JJPmux6$)5u4r@=3&an@*A{e``0x$7F~%3rg24V;OOQD=ye`_RTnMc=I&j( z^@Y~&DR8SWKr&YO0=?w695!`rR*tPNK*26|&{|IIX|5nu!EpHq3 zIYW%~RVRObBef!q;uWFgt(&(&3#-cNDk(@s1+9dOOGb*aS-f90y@eeU-TeK)i&eKx zS3&1g5)M`n0KsXI!02Hg8m)X8Qda>D?7@TQ7~y!x(_QN6mX+2%;W2E{P_augOkro< zShjR5Gn9QsY?PpQVI?LRxreY}lo5k(x`b(56oK2(c-`hfa4PKSmfwjaEjIlA462}T z$PbHhX?{96mlh9eo1GXFEdWbcvL}OH(TsZ)mE0uc2OIbgO>inaoSLShz_AC3iF3tY zPQ3;k`oE+V>M>BakYAsKzvu$|7%1DxXxCw2?5_5EsvzYr2bwsTKlrmAkfd{K3Y91!TzUo6~g zz8+~0d&$M@dnnzLR=FptrkmiAzqGt@E>k?+c-}>QmhXOTL|qeXeopV+K$6Sry#fe* zwy!=EyXuB7@NH9P0tCKBh*a^nc}C#LW$k}UUaq~szeu9+?2N>6{Mzbczb;Oo&X)m_ zB(z%*#8QAa@uyWlQpg1fAVI(tF3J@|3!wfEl2l5lBq&f9$QR}Y^G8e~r;t(8sHl}! zD`*aYg2VrJgMDld{_V&;?A}Tuw_0hB_y*TIutGlZZ+3o z2OP;O0-=t%3i)iHz z-q~$#wxA94>C~NSe}15FmpsiFV+-j+uTE}l1>y9>`r)#5>tXnzEF%}9X6K^mmX(v^ z?stz51}r2bLQbb1z(GGeQuh0UN6EkBF1sU{dK+zJ{lTzWEDBhpP(POb;C6LI*pBNt z5AJyY<=0XJ#q4@fXwrwBY%Mrk*JLJ?iO2Sj{dlLmSPhTY&Iitconqz9UgS=Q28#U< zUXWo9Tq98h`S!MBj_g5+hP!)dD?98wMe@#`}iu= zQ_pfLKHGS(-85U$_fR`NIo~R3Jzx50`f6n^vM8H~F0JblhbV^%cXbXsJGx8&8`R+D z@=69i7A(&O*He`s1TPL?&c_`GazLY$Enr1UCu3d8$fikXN@ZkU5)vw9L|9CemagGD z*ve;EOT_)7xJS7cTDX*NpJGU>VoLRTEEL5|g?M7PmlB{3VGQRL@`9bqwUUIqW8Q3j z+L*5sH*OvV`)WF`1B69bi{U7GyP--IFTH?ZFqr$GbJ>}~uR^Lqu*`YTx_U*ZeV@Hr z_4-y5T;&|MKs;rsw{!I%lx(-6fir^`5uV;V64Nt{=#=#u(m&v*YINcr20$-|NAERO z!&X69sQ1wF5F(uvv<&Px!&(CUz)?{ZB2hGHE)A&S`ZEU1n+88qjr^oNXuTD;A_1ZD zB-zl|USKy9-Nu_|_@MCKXll0_)kt{{fxD6_=o$z+U3a5e-A`%;e5|a8a82%RHN&0; zr;Ul?f>Fbs7QZBZVb+E{^w*k`c>$F~+Ph#*(FC!zbys%dL%*W3(v&OhseaR|epR)& z`}%2i5~LltE9_nC^-Ub+i-~KzlP~aqPKtCPDeB`G4z-70pdrl?(`Jm#d?R=&0~Yee zStob*iL=EuL^-4C!HT*bL@zyp(P$iQLr_WVFT&8k_ z>b_Nhh=}Qg_3v(SWVX`(oC8hHFUi?F90!79DZTwRw<;~qod{`pj{*WaGfNhaIW-h`%pPNE}KjuVu zMDFyMaX~Qc(-BngXT*E$$clq$*QMvTi_d4q#fo|DoSSZ)t8Sj(f#<{8))CHJ4Fs-V z5DeQqoI=n72XCjL3rCl-y(;G=>rG_oJih7VQ6)j zIX?`N`ApcDVKfE7sJr{0rhu#Fh`iA@LA<|Pjsvm#bkY}?JB^dEsyn_a8$K!?Q`9_a z9&bXXPeR9T`EKR!v*5cg7tj3OcsKliyV7|yYbj@`^bqc-ODHL&A|ne+(-o(wup?8A zgdC(C#O@Mju{HnoD;)aT8IOuKl3iH9S;AT5F6oe-m%I2(6_Ynh1rJzhN-oTo_%L7g zGowOBjj$I3G>G73D86OC&JEFt?xz<1l2&Xlq1;kJwWES=LnU+i*B7#&|KBa(EmA3{ z&!d#mDl(aaYGl7S*EBF!QFTco=nr@F47`sRj^`+?vk=xagp2Jx#o-DL&YI$|+mp^N z*FaB`q^)w^P0p9DBz@&o*V8Gz-IbTy&4wkN3CE8C44KP!rpQI92otJ=cnLjHVx*K& z)dVFdz~oP97=p8~gHi&@7n7474j%Dh@BXsg*~`nz z>F$l3?G}asy%aQzaZmdmm(L^X+E@dd0RCbBf%@rWmESyx1$%K`sQ(nbgO^@{wA9G=+a^i|i z_#-!Csvte4sj&cYZ7m`uvjOGGDM5MP9i6t?+}dX4Ma^(n!d7#Y{X2F-`od9`tx~AQ z&z}>EZ8ao>3(C$czr9E{%j_sT$zv6Q@tW8Ja~v^^4E~Vb=;MfK&SRQor`0pzWU;1f zp{C4~@qjp&--B2D-d*p=!5mFBQwV8Ex6IUZ7+Z3jX4_dyO{_Ypcob{cur!KPk;<-8 zQZ~gwnUz{pf~}$={f1bya`mrd>BQL`#8jLC0Sk3ik%V=f;+9HGCi!9NL-qOMHIyVJ z&389elWKpKy@6c%tR+}qYp|*8=Ps3XesI@Rs!uhR_vtyAj7s$ie)4cl{} z)hP102V}Fs!Rh2PoMTD-LOfZHC^7S%)U*Ue^4qI&?dO%&cZle1u`cwQ_N|D43yk~V z290*7yO#1pYmKxPGfC;^ht%evjREy~`X)oeZ4Gv%zs84FleC-d^vu@muPqKAHh&rV z!1N0`V?J&F+86oZe8i4lUa07E_mH`G?8cxzB@7eNi{pwh6Z0Kj(aq_g zJVi)4D43o*Z=O?Ymi}I>Xm#$qafX|#0OrMkw80)wb~FekHOcuSUA8Irowb)+eE>dS z9#%9v8(ngF1P#@Sg;>u_ib(_P~E8&DJ+A8^o4aw)H;%#%!mhb!<&K^L5q z^}uO`-_geRUuaCT@dq;J7MNl{T`(jLwmzR{o|eTX}F;`h<+K3@_D-+lc{m;WRG z;$TKf*ziOR)0~k4f)%0}VUz&5Pw$VV8v6`+1N6CK{uL-J=qT`#zlUIt2AXb4krWGN z$LJ~vEGx|=O5SI553*s%p%js7AYba=%;j2&fFLuXj(Fsd!!4Iek_OJmbgW!B5HnIQ7vziN1LIi3+&@ai4uaz zLsXPgU&B*ysb0_ny#ChjE~WCMc+)McDTdy6}hVC(p-k?jpSP=!+5Fgv5l90i6Y52YT@3!~q(RGYGGH3wSV` zKh%@29;k!y%_(e}M~WI-Y}hV%;fy1Hb~j=nf?Zu4#I&}HWL5PzyvK<7dMQj`ONTos zOgG1?M`R$*soT0xsC*YsS!NsY4(^*qcB#K`&nzGydUjnPc%3*G-|bY$@r@~EoA2A;sFpoVm0 zJFlu8cAB)l=>5Zm*{-8F>u#d?V&|>m!G4V}4FL*yny(&C?WF{nylpTSNuUPpWZ|`!FlV-7_XB4X^RU#0g4_>j9=|txPd&& z(^LTyQ)}D!*w%&k`ucwH+fC25YVUCd=(WhU=rwy>LxYbfM;d-rD92N~nCCQ{ytk8M z0wBsXzVqNsb@owK?WL50d-s|>ja(h`RQ6Qg;^|C%u1|r!sWnx3$aZK(MD_*g0(b_t z_58Q~rjK`+m!-{3@mo}EW7b{zOzeI7+fdI$#RS?X*VlBb+Ouw4GKIRZ$h(tQ90dZL z=JCBo%FWY*M&d3w-#U|Cl0oE5BK#s z-R#5qs*!wL-BPBBQ}3*f^}V0Vs+Uk%+uE9?!+K|3)6RiA_jP<7a$JxU@paX$xaO96 z1VG#;<%2DSU!_Bk8pB(jNN*_uk~_w&Snd#SUh=EYuW7_NlL0O@PG+NN`%$Ki4<_9q zPr#*m#s!`tDN1~DM{p6Y#0;K*>tsQs$*#j|)iKUldtzju0uol2Ql{l;MNtRv? z&8%k9z;OPW-y|hXj6&s*Ums&Ujr$JB7$ui!1;A#-Yp{MBD$b`LdOCIM9fL0Bqd&cS zh>{eAq(+-o3erj1Y8UXqy|klA-#RP@|B~fa-*hGOrs^L5o^30e_EiPPJ1K|b9)L+& za#4N(l?ZY|6^}}wkWN5Nrf6P6*%Rdet|A3QNn3t7oUf~-r87ympLq@3Rf|Y!28w)m6ihuF{iQ^C1v?22C)35j!adHE%7`k?Y#$GRHv~ZkCsGvb8~rJI z3BsNxxFX^}Iv+F={X2Suk)?mu%)cH>@H1pTQHc@;8=g!7yAYLe6ix<+tub?%N^B@c;LBe2;&d2u#1tl>eX%mHsvH+wW@XY;3_G z_bp&FwE5SNx~ZkP#Xr*1Z=S1-q4~Eqmib%G^N(oBnUIc!`CHTby`z809O>Ac40H)A`p-F+*ER8xP8VIhd%vrLn&x{=I(=CUypm|9Z{F#P#3G zrTVHxwv9> zEZHz|{B&r|Y|AEZDDf2fX`U$Gr}In!#R-?0mbes#lg6Nn@y?6IfOoLF2NWX^^0R}) z|AnjkZztP-kx!Y~zlG8N$5Hx!xJveKQR??m{?^L=OR6jp@xO4Dvi`gGiHRxc2?KGU8cFgmB{h=$K@9bG zNbG0-7qGIfs?TfoYP0O^IqGFeonLHCt^cYo}F<*oRXqcGCi>%kUDtHp7h zxKIkFq|Q$#ljhJ!MXLSTv0F}RYaHpMMGRot-6W8p?`|Zf^o^{blZ^;GLEP6+`jb9< z3U7}owoEKJT1Sw$7b)Prq9e6jk~(b7@{{|0?9FTBhTb=c$dW|tv{GUB&biQ2R(a`A zhn0aUbe!x-fq`^}jr*`+;#21Dq$`#^yi*C;rF5s$&v(F2I4{#;1OleF#fG|Y^e|*m zFBWDL=0dzX=1&!x!awInZ*?h@iE4=_lg@CZ&fKw&CO$o zUBdUbe^sDcT5Rv@kC0F^QW5iHa*&h4I?A(ZdX$rrbe08_u_GJi$hBJ)wZ+>scL+dRB4oKf_TtgPNYP(td%j z{llwNu!R2RL&EZ@(7BesT9sQB5vxRFS0f+CzB!QiCgvTey|c=nZgl%&0GRa#Zf?cj zsr+U)pK(58-2lFy0e(j)-l22%bKa8I58Ro=VB5FiykVcuFh-1+5fTH8CPt*A#28fx zVJ^=K*AFZ<0~pWHn+-5t4u}H(U=~rKf8k@?(bVpfUk}3786B5VSB`ZIFSnmw%0{Hod#a}q{PK0~=Mc=b* z+Jb+v{QXJ58;5aAtRo@Fym*VOH;NfOL|r}bw(cKyN5!9(pnsr!IgF3HSG4#UoHRbh z^&U9Y9*Oe}tfW-@#&{%FQU_Z%DYGe5{Bf(y!7e^fS@feYoRQ?Raa4xiKf#@}bw@S_ zSo6l1|AL>}f9Z}-yLHr?xVhKT8@qTB*%{BfL;pm5T_H~y+~wTQED9wwLvpDX0?EMWKy2F48LBsHX5WWp`Fg(f#3CO7^U0rJ3Q zdK4!;3|u34L?hDF9f#%?erE{sS>nVd>DPK>T?6Q@F#-HOW9$K^T-AQNKk<90(bgcJ zJ1Uiks)DMD%W<7mWoKnBG^OrDWkcg~614=IvU~-4WeT*ie3kj~jj9(~4R<9*iZmHi z39gq~R?5u9&)jKc_sZ#;3+5pJe#YU`v(KkL$NN-A@8Ca+|0iAEdE4xHP(O*G@#cTz zEIj0y47i&ZA~)V)ml{Ht5kdY_)z*M$Z}ekl@ZOI`zB0vJYKWO%ZsjLSp&k@;JFt433hr>Dsge;LsY`_qUj4(XRF=r#C%=^M^v&rC-`T4z z`4e5wQLY0N8l^Hma!$;mXu z&~#*bd5|GUrB`R^!N;XKFA8}PwZbWq0C@I1V$yHoB&(UF6b++PNtrWKb0l1_&U?G) zgJRdo&YM{~wV?eD`)xT>)t7&>=yqYQVSEy~l|DAbVw_qX3@V0Jl*TlVX)?|753W*m zbZiu3^v7YM$${xsVv2_TJ&g`uU2S=yKNaxPjFlN3OTTkwfSFTM36@!C7Lr-<#)J$9 zMS9f?+X*)$E*owOo}74oQAbf8$!J4=!s&9(q~^@|P4#j0sm&3rBfFEUOK0|vn1|67 z93I+6=c-86?Mlm)7HkdKYQ(A*G{X`tO|@3GnM~7}CN+(V>X>g}WmU`2Z)?0}IgLIr zF)%T3SEy*XXc!q-T&>{3PSO1lPY0T|YxZs1Eu?D+x8|;-HX+>Il*Q?-t@Emsbo@M-(}4~DWN#B`E4$r3U(M8-q9ofyb;oZ?+w#=&2{eI?G%vClsX*yK zsUzzMy^;pjL?uh8hj?=c4|tD9PiVd{KFEqow@=YRr!wiQL8?XuPM&oc4%|dSe`dWA*q4%LAp~BXea1v=x;Kk6dM2Sz8fpw$M2ht7uFk@*t*As6fO( ziTHGLBX@l!2&O2)z^!Yj-LcrH{qg-zEm${K4kQoa*DFM<_jy3G&UMB?F!Bj?&sPaw~XgcwJ(jOfec*+A2*EWy97Tkr*Qno-3y^F z&PMCUlygSoZlp}x@IW+1VDd_PL;kHmNk-68A;jvC6a&cKMi;++Tz6P`18!P>s(Os- zTc|)H)LdccVyQy7pdjJGhj|#!A=)$0umT2Lf019fvHgmi5N-RAoZu9}syKV%hA9Hs zAxpo+Skqvi45gXR9gdH@{A$BpwIvM3n$FOza zs`Wp;1yMJGsvTTuhgdVBtQ}(1iNh)G4L&5_iq;OUIi1HSGX(plSz<wBegsX{3@Z6%U$HtfZ2OTLH_JK){s* z<7og#9mQ6Gn^Fd?lAtpYL!H1QTTt;^4x{*-HOOp{_P%U`HSA=OH+E zo#l8Yr?{i*opIyLxVh)+okMsg5;z!p4_1DrD!XUt4&Zp<>f2-Woj8AoW*;!SAJM8u zYaQU138X^=elz499yD3eYEisW)n1WvQOZ%p_y$)h;O%4Wlw#tOTzew%##>>4G&K-S z|CGlK{Ty86Is@HwK;`cbsy(}Is^nXR+-ww%gq&ZpiJ>T&BloeRyvZ(qE! zLs5J22PPk#W*!YFW)&4)!LL$CscT17yMLIK#rP%SQHf=dxfD^kWf8q&Qq)znm5*sQ zYO1QrD`W*L3T&!$ik6kWrFl_CHy4nv1!v20$y$_7atjqj3-Zmscb_#E*LBaIMALE$ zr^O2YR=sBS(*JQmfm26?>$)IM^ydA!bSyfj`g7zV`c({6GSFpNIfeS2op6d%`d`dS zAm@99f0&iWvq@|0`kx@K;4o;d3`)%!cgXN$(kZUAhewx6tvWBzXu8|f9qP48Em|&d z*lgA-wSb8-7lA7EzJXJ?zT5Z41@)LL@9kzy06Lv^i``PI?i)NFkIVI9i?&;xy{Grv z_7h)$`VGI2-}4>Cjqiuw=kXeF9~>^L`}n*e|B(2*`BC|T@#rVN-8%saxm+f%Y2^)T z-#Lrf?0p`e`E~aT3_86QE+Qssx5;_qF^yViwN{Ur?HM;(>o>ph_8VaN(`FmJ!$*91 zR=2C@X?Xa0yG?-pvwuJ&EDo2?^?g{9)8%z~!|BHViKxjqOhFOxFj@} zBoPJG5ot(var}P9MA>ZoERho0Q4vkdO07C(?KfkfH@BtSE`ef^N4%Ku+lyuy6+Kv>YT3 z-B{Ff=Fk_5Cg2g#w?CRw?{b3OCa8aOW<(KT$b@z)ApAB~JflkC0?wVlKIzv9A5}EV zoVH^4lLhxMfWkYY0bo-B5y&lJING7s*@_6=*!&A2{tH;&kppF#Mgh3^0_) z?0}{Q7ZSSB4>SgKK=2}#g*2ZENsqXh6+})*A^#qYH-B_UeNAsZK^Do(rh%a0uM{>9 z5$4rVHPpe@lhYHj+d#Zu3cmIyNJDzvT3)8CtU=Q~3Sh(`->ZmfYx68S(JW~hIQ?p? zheSM!S|{gZvxI7#UtmfW)m-SA!jKtUa_c9g!;T|hL?f8kMYDpcFD-l~Eh2_Lf~N$K z!FdeZE@MQ;Gf1~+BW4=XymhGtbNQWx!ONjs)NtRmHf|dI?!OI%vRmr!A75^#PW)Gh z$UIC0r?@|e< zu@ubnoj1sv?Lrj6YJSJsA<-4h{}eqa!X`caxJF(yQM%J~yZPGrI_!D!%S%SUvkfNb zwN*pGNDuyy*2L4EStb6?z`HobJl)#=tZLWwCVZ3z_iXzlY@l>V%TA8!Yz2K7*mo?o6!<%Wcijyd&)MKL!1y`ik}&xq(iMheXf_yDae{%Ck?xN$f@YC<{ zrLMs2jnCNuJLNZ*#SzNZAl{ZRJ#~DrITU(1#sXecTj*zII{7Eq9aXF+U+~$Z{iAm0T=7qY!YqFaRH5Vz7_VI+v1RMP zJlg<)6T(1V(+)w3bnu=<*eTowP}L8=^H67Kbk!IMPhI^Go4+1LVufJ%5DY~_w_WU+ zkZ~OlG+aRqOj_{r@?x|Z&~>#%Vk+-*gnzE2Eh0W5t|De4TK@8{?ue&&uGd z^9_34Cd#klKks*oPrc|0^n`StkvkO<=R*6PrLYsx;0eh-)H?4lga5uRRySNwH=LP> z&&SdolU;sN+meMxQ^tCxgS-*)j0_8AQ3=Ye$K%%y=hWk)oPfA&g!{dT;KvWT+aAK% zkiAn9w_wOgsK_$gW|XIO_98j$i^9>4$2X``jTgrGfOaHje(X&$3ot56Lu~2nUqW+M zYnuRGi^bT<`csuWmEzMFg zhgD|eqga?-hdfI-M(Qu%e|cQEVT0FRFBI!LX%uCd*$c+2b3d#5rzVr7%TaA)`W|a( z5~rtS%oEbgGt7*+OGz?? zY$Q@&wHdqqZRO1O9GVv!R2J;LUQ zQlj;8=IT+RQ6yOzkPL7!*YYE#)3hOZKi+2~CWSS2`l6$1p8k}g4+Lap{7qc5h0B9b z-`uflm{cU2+ER7xvP8|Q4ZaifO8S^ZDz+?poT3`m;ygZ?+7{Y2PTSICJw=PCZ3HcX zl`yGEcEbKZ2mj2%T?k;4h@C(cWs58O4|1XJDfI}ZSP>6eO%*?9_8<100>sCDty}^q zaZpZAhGdP+{5{rQ64d2&c-#uiL`)^P@wLiVI2rerLb8e#D{W^NO!Xw36^jY8r-m(^ zn~9$s$FC`8i}`<6D|M_W4{%U$WEaS?;!fRDvJ;XM57POJ1sfWiHwoi2*>NrK3Nzxl zw*9TrU@cRza4TR85HlC6{gd*cGbUryt+_vul@ z#mdF!B&*{JmyIHiH-}(^fS+Y19h6=$Rg9t>h%YN55l}44=sC$o(xv{c< z%ddte=t}hvT9OyaFf`#P zMmG8SbLcPUB!q(-ai#!M4U8*~zA!odlPp6vwshHOf0oqEXk*wWV>h&N4|9^~ELl zV4}`sxeh;@OSjx;uk7KD_Z8I}{mj6W=E7l2v=dWrcqAD$DtIk)ds6nC>34BVH7zBpI z1ulerpAFSta4C(uAvUIj)r0>xKaj(7(^-RcVs^v%YUstg)2Hi*v&c{SHuBx$lS}^S zxr1lq4pfv~01XOs3U!6<*eyGUpwooq#Qr|sM@vG8dm%(uw9{#n-F}b`hkvTNmkL9G z#F1v9QKtns&S)RFpQWmxJ^_GRKvs+vgIyeyQukD9zm>iUp-Wfe^{RhOdBfpl#F`t{ zmKuJ`NLDG%eU>zk#Qv_@SqVvN7W`5%PIi|%UODb_CvdOf(thc5|EKlG7&vPtt84g# z6{$0JOE}M9RBiHdx5v>G6Q(@-gz_QyT;<2#csKJ2zjRCh_$jYtQ)rIh$e=( zh)z^?gfC|C-c1XId@}Zd6zDpBGLsa}bO#lEgw3*|HB}(+`lRVfSL- zL@NE`PxNV$sTDCai6cyIRl3+4-3F=kw%G4HV7qoJojaUsKGCGfKiHfdRVZZ_!S_Ud zz4oTIHrKIrFv=!fC}D0Y%(F=a{1wnpD3nQ{9=5U^VLxdV3w)5EGB%}2%H*Y*jceUCMJ(Wk}E4(zJYGpPNg}t;*L{w44xAyTe8BA#K$}BM|H? zjj7_KxQAL^hz*4hTW0s_@)WP6AnATWscW_BiowSOj|2gnZX`K^e-s}J`5crVF>U&? zCU;0E+A`Csc+)Te_yfqUbG5VyYo5(4{hp~#det~fA^L3Z)Kd3n2gL%XMpUVx_&CH( zM5+T1C8gXojaR`7K~U)~xz4gwb9MCaRiH+uXtz{#LWBe4R31t!%xQ7VHb|#eU*!%iNsuSldbHJ#C!V$0QG+4lb778Sj|J^rK-(+e{9W&f z3@-4Ztt8;5*i#^MX~7OszH#iJ!eOO~euWVRP#D&Uv7@ z*P^vX41Wd{786N`UVj0T?xWZbdP09SRNsmkF6^u9C?h-%jO-Q+nIzuE;ju4IJ-)pz z$i9;0^A9HFQrcxPDon78{@&?Bv~i>DJBC|$3*XfCE&A2<%W)sfM6RUe@reE0=O#6h z9)VX?2+fN(blB@p0=|uh`9YmMKJVQkVl@D9*;=qNAQa>Eg@aIj%bEM#HaMWKCwr7U zWv}xo@ad1SVirQa=|1}kyuSLb$Tf>6*RPc)!ENEKY~ZJ6Ux+`9ltnGSktR@4#b+n2 z)mfzOY6%tZ3ow8rI}gE06fe-;M3h)mKw*j}xF8Nxt4#Xi8)g})wc{U&SuOi{PNW1V z`j)gc0M5ZCeh;{mVE0rKOT@*bRv@ldEiWGg4$Nr`gi4|w0) z5uDN-DpUDs7)BhVCM=;4SsyU{i(-{8)+jc7K(uIBLB1vKiF?ZLMd%H`E;C`n>=^o6 zT`zX|8|VFu*|L~XjJ%B;jM11KJtK{-oOrHDD8lVyGm|%t75RB1HOlhd%!xlvJ9aDW zf*3!Lb+C7+dMhd<{kLGzgKtw@fp9X0ptbbU;WnmijQ?ItBQ)_RYu-Nh9$GJzvIif_ zJXNAE75Gv&Rp{N!{9&GVvib7)drjKiDHqY)7;vhHJsR)f!KhXK4(A;T8a0#3vXXD3 zh7mBVprI(Nk|KiC$Rg+HKZU;N#U=Rcjj87lZ+WB(Bnu-Eg2mzcplNAd#b^_w9l;Im zvGyB}E@Ot3zQORSI_T0uf|+;#i&dp@l{pfK$D5J)mLrbadJGwN5!3N3+rN=}h@;*kfpkz3FO&^??%u zE{E%f+%qZ9E}zR92jOos(E)XrKs!Gi6gg=0fU;g&zY_GgB!a7#cYYW76&e38ee zf8H`(4nOq?g!HYO%`yzOyXrLfi_!@pQsc+L4yl~e4Np_~%*dHxkzpx7;8-M0f8Hn{ z_ZED~$EViaH8`i%>AQAo@{>V6${L8l&|;9+Ub|sV0^ftNs3CkOOmGJ=w`J;#(zC9b zL&T}jwTT^%!J9>!MAr^|N6ag_u{bb!vc5U0k<_->u+wBr=}pyYvST@iG2q>!VbX~@ z&u|2dg+xnx{LSUmR4i}RpfP^w&Wy`YL4_169@^Xk5Mr%1yQ!={8Y}ls19WhE>O@<+Iw( zByk>P2L{6>=)QdfUzJAN?(*zidGcjn?bdlWPVxDYIC{y^g~rF#ha$sL@=2Wv&a&(f z6BfCTP=HcUN2V7VZ_Llq`6o>?S=<5rLCTdXz|>L}Dl@@XYLpWWQ7v1%71v~qkwQ-i z!z%cxCUVYuwGt2=sp)a)vDNmpId<1RHFTvuN1%gxXl0f=DM&R*wkxs$FD?i(GOP+K z3g`EmKbxNLBt-h$2ckzTE+~ei7%eOCZpVXMNx!#sb0q5X_PFL@VzLk(CaU(- z=OvTfqq?M_x!+P(6Iv6>Uy05A;;eTY8@}>sR&xIPg~lT#?}3^2*5%2@@3nXB8QX znkEk8N+7EkOcRJ_$4i_Cz(?{rr;il>fDRkf&`RCBeoFKT|J|$Iqia#{f@T8+i&VcT zk?qeuaQU{TIcbjx9~T4~>2bE0&yrLS0-CHJ^}V*JTtCWeTxU4&h)u@zEJ5mGghhZj z^(lW|86>KD9>VMQC5|v};Ye&Q|G9f@vcEc8>+HymdonVUzrAl-io<^@2-?EL!{g%N zkvYGR{fxo;;R)7l8axjMb1`<2P@#m*7I=}kskH$;2klw$#7)1{TR*A6s{RQVHQpVi6y}7mX~==3XmhQCBL4);*i*xwRLX5h+eO3 z0?l@1zy<6vAM-oJ^_%_9>HYx?CDLZ>N^eHx^Dz!u6xT$i^~BnX$h~#Ge0^G3%-#hq zzE;op61}hE#P%Xu?{OJsXLPPEJ{X114Gq+SO{m*o_ExRMk~5TnS+xi_ZhL5D(k}A| zZ&3fF>- ze&JLo{g3$)gAZA-H|W2>3yI2_+k_%&i8-fiiMzK-I%;9k&L0QBXjH#1O{nUM3?*CX z9m$TRNx26@$Ls|g7BsAj{1ZrqVNb7B6UYj!LV8kqOAxsq(iBXD0)oaH@=gwTBk*_D3NAP2@xSpA8iR6LEleHMHm` zNYX2$7QD!tae$#QnQrW*S;F$4QFwak-KI!^YL`SRZ;xPFn|lC${;VE@S1zR#G=9CJ2&`L}G# zb=y8aMznL@)T-+f@;*R*e)l`c1VnQnN%WA*dECf>J4X7*g z7P{-juG|g!Zt-sYU-3MG!_WgF+E!lfAiF=IuQOJEk;8N4WC$2pTNskW9+_{j48?>W z74&jfyH+NYs?2{*3@%Hmh}JX5FPX#AsI(R9dsB z{IEzlnv?56ZR?Up6AW1ZmJ+_}K%hi0AqPiVa5C{F2!+FqfS|!MVf5IO!?$5{DGcH0 z8!|Hv3&b)#URg>cyb&Mn)8)E0jJ$lIjjH+S^|LLS&HnjQf}b_PMR&cvx#kTi3p52b zW(k7hub{CLUP8Fp{33k|HH~ROhl{2ji9K;!?3t1NcF|okK}Sd>$goHq%cuVRWPCie zsV6TQR2fpzt{wX5h#3uz9SBj(t_zMMnmrIQy#>opWTa=sG!QG$X?aKjBc~2Mg5Q@q z1FDCS?${j{daK$4sy`6hgF(19I&m$Q0L;|hZ^q8-Ra=f7`UUcNU16}gY0FEIZ zM9&6fA&TtCK(o?SEq=kz|XEfx6t8DIw0jtv?t)GNfv&a1aw)=m5}MXLX0cky!V0 zQa)LQ_?&*OIc#>0_>MMY0scM&f&H1b0zMD6L9Yc!3&Peaj3=mp*Uw9QL$PTe z420f049zmjTOXLxKSzZOKGIupQkdVh6V1T}JP=Qr*B>DJzTg$zPi@DQ^QssShF7T9 zUf*!!^p|0m&F`|ml^ma28*OiRKyd<4K`vB~U{FD11&|dAkQDPJwvdbl0%h=ET%fiz zGMI)|IWn|@64*2ZLIw3|VW2b=7YagW!Wp-@lxmR;^M)2E5FzyqWTH^jAK7hfJ2iws z1{WL`p3Gf<%O~EaP3J34?ftX#$~k)}{0=qEJtawJ-%*WDf0VdySNt;ie#)?Gb6lNa zBlVYS-nmd5>U6TLSekw>+h|Y5mzeLy^w}Yo)}qKqgIu!Mql*mByyT**|9o8Xt_zH^ zBciio{DX(LPwio)Nq}Z}&3f`(E!|s+r&i8J$E54RPi@(u7>f0YdFT2L5bKmFQeswT z!@pDsT9G_|a5c8e2jw;4ogrV)U(>G$`c9&E*1L?Ne6dq|7@w>>Q|P#wuM{5DhGKeZ zF3CtU-UO=UYuU%Q#+_-+*6N(_o2$0S>zW~~hjC`2@65-t?$+h8?;Je9KJ|vI)3AF!*13t7-%Xn~v)*L=`L*b6REaiAHrs z_I?T8h}!XQ6oB4jFh}c&+bapQH~k9R%tnl11A47}!t#TZ_)OILIq?0mzTqZ4kxt(1 zTf@pLcAC9kD!5zKXAFc`!emoUz;Aq5an=D6nTowFJ_V&M=&tTESJs&;>I;~Sx))j1 zhB(z_6HJ+QqWmR;mcx5|59Ti{&{#&lh+XjItpVL|^*4`GnoLC`__rt9644pV2(F8tiv?3-M5UUJtwz*yT1Q zJdXOGz%KfjD!-^YaeZg69B7MPpSa@pV{D>o)_ldS$}{bVuZ|s$P@Bk@Rx4`YTUjUb zF9(Nh09|!`6}zp>+Fn-Uo@4ubV4W(DlJ7>_;uk&uG*7TAIByi@ZG6XZ|eS* zI8UNCWljhcRGZwFbMjx}(>Phq%E(JL~H(w%-iFnX} zY@6|{7ceV12U#!YoH859Pu?Ot#TL;q{mN{@&*IrcUazH#qPy_R9`yR}@hWE7#yesd zGu2(&f!wi_Ufug{48P!$batJop@q4SYn`kVxI>EhRHG`_fBTJI;L zjJmvW>j6`yoZ1ZD%G73P$s;?4`NoK&*SO*N92D3jQ&HUp?X29?P3M}j!d-0H+d!@> z+|Nv3wBkFe%Zn!qggpAWo7b>P+F!3+dQ$uya+t{B6YwECVxCq z9Nl3}2dx0fih(zSj7kS}sO;7)nKJ$Es%8oCz!Xa*be?FUFP%J|F{*4#0XT*> zNHy+aNH|7@BSc~?7wf#3-U4qQ1$gqLRw{A5SNk{ua5{qVJZ`LEC;!wQnO=)!oD;`A zSyw+FMVA_j@4V2FY|X!Q0cFpzxnwYU^lw<74`vQ3KEZA|i(lUkPrtR`ZTLGId9=_W zWa8VJrl>+v>rCED5Do`VHFWR{WunR(Kmf(+>_eSGuEjfKeGxP{>r+V(T+$Bk3meLeZ1&GM_+jtncCF8y-mV_X=rgEr(1{H zOl%x{*Y^h;5v+*&eAP?}bF&L*la?6BJVEb8+D542AF&_8{QWVR2r}XMyAE)JizU>O zXd0h_C-6ciX}&@u^(+4{UuJ8lRb7&HC5JEa?W4IC{cf+l^N8(r@8RiHx{Eo&EiKsN zBRx6BRp!fYdNl1xsj|Sv=*{+=J+L;yG@LS+Nnc=)`Ahsz95Ma`dl*WHcZw;3GkxOo zY=kFNobCqqH9OJP%U7qeAc}PVjO(zVbH_epEUCw%k+^RQtLLSO{EvO8+Uyp@pch17 zvwb$g#~>8R)E!8+*e#%8o_8pPDR0kWu$JpE>3JrZYqN6hrXbf?>Kh;tjiy85mVTGg zEbO|2SIlmCrg}&#e}I0MSYNX;GXy_5=>s6J*G`PhAK?#@6=0;VlMN;%`aiQ>3_*Te z!X!|7IcKxFwaF$ljQa+4mMd@1`8PEzV6UwfdzZgNy$(}fmmqtY1wxLRzXqJudA~v% z>aQ!V-fgI#kF8zL-1xlaAA<1XPwVMmMS-l2HL>f7-|aLL({<@S$Nb7f7$OzqlPP;$ zY&;rZ#%#9-%Jp1QbeA70ReGB0@rHAO+}cZeL-Qi0>6bOpA$akD-RF*zOnTeW{YWW7 za6u384bKv_bD?%h{X%_dXy;5&=Gi);V|Qan;+yEkJHj{N%d>J_Gs>pCSaDvqBjsDV zA$*cK(;KO?5MjdmIz-%P4IWG6Y=w4b>f1ynvHt@YQWt%iZE#l26a6K{Er7c*o7 zUje4bk&XAj#%sQKRs4cwwH-TQL@?uBZzYK`AqHx&j$cs;QXLgX&Hd*2@HSAU{~TD7 z3QYBaW~)^Gq7w86g+d~ch#~l2UOaaV{>TWvmX8pj#7U75Wh1Mh;cq}eyX)4q0{WsI zzH0wWuJ0lggc)!fm#4n3)_VdcmN95BLHilj- zVKg^_Un~O)eCzaRJ7RHFpTRTw_m)9!L7Rl#=YdVlh}vwY+;?vzAUW}-hDjQU+i+3X z{=ROWc9L!_tp|H@h2Y1q8o_ag#4MZi#Gz8N5%eQ$LsaiVbOYov->P{Lz=+E1vn#o# zuDo1Nf8B@^b)8Poe`@S65g>^AY+%!o5l#JKx1$O5npo5RrM}-%bz=W6ywBbqS*Wt_ zadkOsFQWJSDv$m}b?aKybq_GP9fi&H>1ZOjjd;4)q^9W#duZ8|jWusC++3qkUeY`J zP}s+`uW9PJJ)2M7j2%7}wNF0KET4Mv`rhYYQ(mK!?8CM8tSVmDH}m}U%w$QQyzP@~ z0vP;hGKkZ81=NvpeB0^T99J4p@u6d&VKGM|#pRq?4 zlXUC~iEqpo1@oEaE9*e@@eVz9WGY)C>tdUKt;e@fdC8`@@+IoiOWe0}F8QUE9>o6C zH0wqz>(R@L`pVf0TyOXm=up*Po>FUcZJ-K=iI;Ve)|#SRr20zu*YMfv*M0q>Nl`oU zxrpAvF^b08P*Zr*j_scPhBoR6eAQ()QSTF@&ERmZNty98_4P=HGY`llVNcf0E?GQ| zBWiuUh|?AtfXn0P+!EW-2JfxaWl0Aj1A=A*t5|IQZjBd(MSaVzDU zQ_a~!hew$*FD$Wv-L;oT(?X+y5_MW>rAz6_5HTD1R3vVrno{Ct8(%ub z3Kc0&_zAQ?M3#|sZCl3%e>z>8UURIH^PPH;yU#Z`~b$QQrAJHXnFh% zr?ZXB@~rBtX_IYAVfB{^7qT;3zwAg*(FK82Ex@oXivM84A3=!!D1KXR`XVZMVQ>tnd86{nuO(}2B|4SgTsHe_spaYy zbCRWn$zVg>s0Z&rW=?zbvYyA4Lpumh^iR+J^9n^`AG8Q}ip|$e!h7&$LA;&1@GuF! zUaA%T-aBEvt-evHEEjmZy~E|cEubp+b};)Weh@Re8(6(EvklYp)?`WFwL1q?e85#< zH-ULjK)LRcviw(?vhZf6P?wd_>jaMLvZ~G6BtJ2EK#>Y}-9~veQ#MR0zVV|`+KcqE z57CT8T*lZs9vgdhxMt^%)HKt0GbAj|jUrBd&Z$x*vmuG*FPipKWciTPsAM-Iok(=Z zu8=X|tX{gaTo*FLsj1Ux*~(KQCA(LB(}9KI2b{vtl9viGVk;60bf&5-^tP#Wc`jz} zUxnymn-;C)LmMb*%%d2Zt!*^fP03F>Q0VcKI2C)dCkPmpYb`amliEvC`I!LswNCPO z49ZbDvoF@FS(s0<^)Kd2GeFvWUGsuW?%AQtKuG*ob;;1df+>JzZf)mEPL=H4qWE1D zzTc}|Z?{6{t!-62SnbX2yl$%OsQEIbGvMJ^+H@_?i?w$E5FU<+>0wOgsJ@7I zob(T)BHpy`Z9lixJMs5=y}L?vJuBTSSg&uZ*`VYRUVL|A zH=6;V0c?X#J#G@H&G@Q6-E1u+k9kHu824-S)$KzGc4+Oj9hr|KJ@L)hvvjROBKtr% zv>sB2DqU6R?i%lTGE9t1yoq^Ng6AqiSjHu3D79H;6}HgXrv0V4eLKyidyr0898Tqu z%nwt8ZpiMoGxqfKMvdn7Za@}2U5@IjRTwH_cxi!hn=4>pQX?HXVL-{VIM{`0aF++ zVEJ72uAu2?ima*@s)(!|#K5j03sOtQIU54x8EJCb;A9jxi)Hclv(#%<9ai#}om1rP z==w3!AR6W~suT@{Mr>3JSusOt9wgCG*tKIA0UK0l-o8?}6ILo6(tL)0UJ6eml=c1z z=DOAXl{#dCgPGsLUcw`Ju4rIxC=)?kX$>!XdAIH&6)+AJTQ^+|-@I!QW_QXnxFF7Y zQn%6}Wmu>zi|XGBfq3Fu#I=we+CcWe{yRfPmQpI2?P(TyDyha>C|_17MJArSzqR!v zDN<8#uXe5FPIDO zM3?z#j20H%9A>C0^78ZIttwZ4d;GYtB40DoLZO+Vau@k|u+I5cw>B`(@o`J@#ZUV_ zHahy^c^mGY-R-Xot{kcvni$w2XCknytzbFDJpQ)r^Rc{apBL`wnC~R){rrF`*-??5 z3#0MgrKl~7`~3o;_FHM(rn=XEN?~bl9b?yC-y672;SbMA3_L!~7|h5|6J(-X!8W)D za&{jmw}{_9>FBI{xY%ljMl5a?6de5JQq5v%l#_KDVMe=7<3h^uu!9rz3%$>NJUseau6lCLywF`mTq1aC9qvX6Uvj%pc7X~&~B3e9AAGH^Zs70h_ zGj$tIqmh0xFpdEntzH7q#pK*psvE6cEw0+Ow(I)3TRQq(ZWs3;G?n%?Hg>x$t^jG< z4uJjJ=3}ppM$*ckhK3Q7+32&uH_LTiWHH|Hhk)vCL=mNHmkfAEAq2(-rHE%#u7Z|_ z3N`YyDKS6pv(L<0#jdo~ka z#*Ivu$6L07zn4}SLmHaVpFS;7L9p|35P4jUrQi13v$;M1+N@PWS5i<{%Oh=ZIZ4o$ zoqjW}_x{Gen^<4$XCOkmZNvwh#Oy0hz2S~h*_L-R_(giIYb?xAT8td4=-5!S|lIh*Eb z7p)FK8zIt03AdV|X&tCeK^rsD#tFB+q3I-bs3WcIPwJ1;Vv@F_)bWfNRno?Sm^;A% ze|7KSj|cgpfq$ywyr0_H=1e|lCZab9#BD`)MWwzxRhX4(Sx9os(VqnJ z0xLVt>8Kr3RaI{|RqJagY$$JBsA*N360`+r8V!Qy1-WStZF;b_qt!{$YRRa7WRth; z_^#hRcX2XU8&IuEcWuJ^zh_x`jFoLlWrZ2i4Vi7x{MT^Ot?z6)X{!SphtbxMw5`T$ zS}N*Q8&?;XwY1I8Z2x@ENj9!DE~~AXt=U2dEz_-iPcBwn)P1;h!>y=xj*&pTm$(R%i<_M%j{`Ke_q&8 zyYx7?xytQnkAI%;3B$LB{${mx-u6+Q{h0jWPe>v}$kIzd(@V%hL_kDD$dpGwl}E^B zL_lUl$hJ#Bw@b)}L_ml{$QVaJ8Ar&eL_n%U$T~|vJ4?vx6$6AB3zZrRrWp&j5(~l^ z3)2z{@jV0fqWA+$5%PNhh^Qj$fFdxdB6Oi5xTzxifg%v9B2=Oxn5rV&f+7g3B20rK zgsURL!_1FPix4pjSbi2kWfo!QdI9Nre||0EAOHVd7PPZ!JnU-3^lD7)YSguAT<&V* zwrXt8YV@~id`sn$qtz64ya2Gxa-qjoU;5HUkzF#{DbC(M|+j2Xy`8QJz2==K=-kQoS(85!dlN@UHL z$jqUOOsI;?u!>B%ii#1K8Hkw~nd=y+>lnG68OWU(+3y(W?-==EstI6f7{aS5!fQCB zt4XA5SjMVp#%g$|tBI&Oi<_k-6(&+G?@e>L5I8(LL)B-fHpRoPR(#{e*Ca{KgT2ok7K& zP{f^KhnzBGkKE<9MdWr(;_WEn?Kx&`OJ?m_X6g}lN?YVAl%Wm%4Ztm!A?s@ZV3-j$7^X(|}?KyXDOLy*CckXC+?s@ub zi~H=F`|POu>;XQvUl(Zco7{Pxk}cd8tJs)AmsygaI+U8>xFSQe`MTB_pP(wwl;g3;2v($b>S z(%iJt!qw9J*3#lvD*}C172>s$!CU43&a%9eH2}|x*)GUkEC}K*NMMqD`EC};1 zNOvrVdoRd;unK^%O8mi1h5bLsEK9Hx^E4BSI1>vz6HCCf^F*|ZNVE$~v`f$x^Hdd! zSQQIg6-)mOW?{2kf*;~*!vVUO(Yu)Q5f_GVl?Zkf5qFgtaup(Xl`3`>Gk29cauq~( zl}vUORd=C{_8=j1T6}Ua*>=Wb4cvF?!4*wl=T+(9YmtOQe>m zZ;_?XU8Y+^rq@KKM@6R3WxQKvyw@fpoHHfdg9Cwz>Zcee78Rl>EZ1Q^H25xqA)y~w zb!@;Nl+v1?;nn|Eq8#|>x&t*rRW%}6HNssrqT!Z9WS1jom&3vx80mTnn_-jppmjpO z<5Mbo8k*sk_Q2Oe(jA!XdMcXXn)cw=L)#qKFMB$g5uWz`+d6J{*yuedp3vfJmaLvS zclfD2u=bGTYbL#(GIzMDJ-F|Gx@)%0o;G)ct342}kmzehzMkS|*z7$Ruh9Qk!QJ!> zzqJSP9+G{{?9)^A4A-@XVAJPz-YxeYs{8y8UFB;`|7ge$zm1R6Plz+v#o?dN5wyqQ z7ylgnkM{KUCrKdCA>*(YTJ^sNnQB7p8piZ$%Jdpe?P^l(8rHRHT6tscMso-^6LL2* zbT?CWH*Ni$;ebyehRY!2`vFtZyo4wi|*!D-b?eTycyUjjN5B#em5U&`78$-Tc@fQsI zBV?~Q`5Q~VKJyox>?0VjSo#~&&R+EwEd3*FuXy_#+s;0~3*Ocd#Cr_>jj>O!{0k=k z5&CdEdP!9XRrPXw(k-C`ryTSPv(1k+w(tq)z{&_hDm;&VPT$e zUylHBkBA`;fAW{?`Is~%X%s&N5#Ts-!I5O(5?a@S%K7-$Sph65VoMs?f)bYa!&xCM zDQZjF?`W0`vWxEmhM1^XNiJ#h6RM4Zw)>d5!s7e5%~|nRsazDvnt%e4S4m$?0ua-f z48lJLGMv&u!z)ZGK_d>BgoR8>qXjx*BNm+EgToq__0HjTGQqODErm`E_3XQySZTvctwY+xlfO_$o|HJe}y zM&!t9qir@_x_EA~T+14I78`OfJPoZ~wkR?oVDJ~UL8gK#=NAQWZz(n@B7ztR94jVF zf>~yLxpGNUsRx4?TrrL;EW)6Bycjsc-~=Rbrdvjn%`b+@J0|9zIQS*kd4H0oOyVHi z-1cAA@MIpz;xUKQkrs(s4gY$`B@LrYO^o~~UcEFoqO$#??3}99B2&ks5eGCbb>$vv ztx+_%M^)UiP7C*`8jiX&ShcS{%qtVgw~TPBWqC_XG3t3G{QU#vD5MMJRvG0m?sZi3Q%#uDT%U9Qiaf!S{`)yN zd0&sAI6f7s00}h+wGz77JVopmasI6E+DKHUiA5l$|9zBcOC%Eatw6}=c;1}Tz<_64KA?#mvL`%Q zy4)|Eqo088KK=G62=HPA7fh9jRvWa3jq9yW&x@WaJQmnrb!IDNX$J@JNF7WkY zXZIFt{gk^6yd9UMUmVRTEsf<3dt z^))N?D=~V!%=ZKE&eg+nOL-3&RTmU`u{9?{y^zzgjh(snX(N>jE-k<>VKEgOQ~37< z%ci_QXLt6Ns%&1q4aK5Cz104p3M^&@=&uCt zlsnJNxQ-pWbe2qvHV3C$T)TIcB-u>|rv>>AO*g>~WgknO`8GZg-Qj#q>7?~L+fclA zB}7M)dXwAOp&!inK8kl;Mt^D}q}&}hwLZO-UVIr=&GL_Z{C@FFE^B>StK{p5a-V9M z7<|GajiGGtP94`n!DM0^2 zVFZewpg`i39R0+40j-5JK^!KE6(tG}P=fMCdLg-&G)Wq!iPa>m6EX`NhsL9D`0vfa z;ol8ZpM~R}=5me6tTZmcNIVdM!p!t{G>7z0608=J$z%+t@F8p}v&m#Er+5b^hm*tp z_Ha+^A7Th`_$VA4FpmETWg(hJtaXR)6#$0x1eE?}Q2##wqYU_pkXnonL>9GT0nv;XT zRqU>xWY@$voc7&7*o_3x8BN5-z*Mvvh=sjRVe6pGwYDx@b!@36oDFnR|D`P5?s1y9t#Gv6uTp^7HU^!t$RVme6_ELzVC!M?&hi z(l@?i;x|i~AO}_&VAdJ0Ogfu0FeO{B9z!wTqotJUTqQ_&cweYhD-7-t1#Cyr2`5u^ z@0?4OYNT`8@Ye=9fQ!jJv8N2yxo#WvbVBGLLte@~`#Lpq)ZZAqW-5RwLOQ4A$LMb% zK78u-sf0oSn=nTMX>U0QkidHY{EkC~SJjx6MRPEA{EnU@6<1BL>gwvrK40>z|9lr7_%K(* zgwGTm(Sd_{N?=CNJ`e%pT<6y9;aukqS6;Ed*(3IpCvq6zQ;{tOJ8#}r2`2MC)M*I$ zh2ORy1KweI;jWa4c?5QKmG&35n9JH4);2(os$Qw7x*R^ zh>?Ky7w)NA?Yio>Kd_V|v2`G_4VKyVBqX4&_l0fXg$>SmC;U4~!oJrwKwEGx0@B=x zqvr0I8yv@-+6nQ{D6&_VzBfz6%XkQe2i(n3w4u)D0gs7J7@L8pta@_48) zg#+yV;vqi6ot3M1mppU^O5ya488LE#I0HVT0P|FmziF^ES@(NfM4t44u#;JeUmj6U$$qA5ih=vw3;sQewK$7@ItUxKi z{$W`hApesl@lDtKt8L35?#Rr{U9%y5n=BtMr5kJ?i=SOJUr&c!Q~q_r+vh*24(Ls` z%+}HP*BjE;T1(OoN^S8+*B)D(bd5$UcGVol@HdEFLP~Ty^i&QubQfH*6#Gas+n{cp znk~`~D)rd<8cSMLJ9HyjlNbGQ&;0VCN+pmk+l-7xDh`vZk#yn>_!J$+y0AdMtbQ`v zac1uek)l(WQrNW6X17%Tq`7*;h2We!LO9l`->_}4)8{}>C)W%&p^a;hs1$UHjI)l_ z3BTXGp~o3nCAC)nE+!m>nc|`1#nLyB9U|R+3vc`7*|fD@RaVuQ@N{5EfMtjqBEH-` zWC4ogOS1(z*mBMm>b%k&Jp)O>P>XyMDUcJa9w@PkMClG{rMz zwe5k{mli^PI#$I zc*)$pS?`0HtrNas;dj1uvjWJ3pVoL*@QSShJ3mbaFYGu%hXq1MO4ottTN3)6F#W19 z{h_`4Oy^D@uSZ3J9F)(;&iPW-bFHx@ zRdwf?8(X*R7vr zOKb%S=${gXMM6a~+SBWci%I&W8KXw<7fc9+BtYN&JDJa2^q_5zdFXU+l%?9?+voiMP@}kvkNS74-b>;)xTVH z2xWU|K{n`pBTD2lkmx}g^oU7NwnD+vr1y~Cy}ubq%6|?9sPbEPUb!3*-?lCr%Idl`_m=9iLdIyz0ia&WwY+Rxwvcj|An@D43ee$ z+Xdad+qP}n-fi2qd$(=dwr$(CZF{%P>F4>s=bU#Y&dm8Vu_`KSWn^Y$uB?j4s<`ua zT|+#|PSOnRX@(E9Acxpc!0squcNejHO4?cFH2F5gvOMk8!i9LTUk>QwdFt9_>U(?5 z5I91V@sK0H%AS|27P~Z`BQoh-RPVXFZS8|TOc&TvE%q1ackEej3D^uUb)JI-66EcT zATRxDN&$~*qV#eB*A_s^QxA%siF?UZeNtef0W@`D{_2g~8T{Std3Tgh6KilUCB@Ru z>1Db>V9I#t1{sC&H1SQI8A}99u^(#yPHqEuL_@zr(cJsMbUh4J!~NB=d)EWfBD4k* z^+*Rd7fH{&Ge#xKQg5tbu%N)2N!cQ&BRGy^nk#dC>>+U7INlFp*hiXy61_<(6QtrG z)^@@(in9$mw{HtIH0}|9f!=}Jg5JT~BG;JYt4ZE1FM?y3*07tbeh@0*1(rj^=`GbC}`z=FV=Ra zm1D^EE<2grdbg>!DAJ)~Wf5&LS<-Z{z&(=L7HfFe?jV@q{yLZ+4r`_jMrtrUY#US% zL{yXN>Lw#;+{=rH|3YuqJ?$Vv3GZHj4b z0YXJR*JZr4EShqrYsAih#XUQ0W3k}`s{?AYUwzNw!E;<9O2t`iG8Sd$dne_#Wdr1Nh1Flq;tBG!nJn4C28fMJgexR2rLm-Yfd;$2faY=Q>X4r+9O`@{A22SzfS1l4o}#+cCKM%9 z=y|5dbmGam*zx(Q1?tpCQ!Q3G6!8zY!yAvk(Wi|IoQ&~tPqqwii5uH|JeN{?ka-6J zo`NnC$0NyO`AZ^sc}DMvpDu7VfH!{^A*o}gyi2`aP5%ye`%J~aJ~Z!$g~V!aJ11rI znRS)p_pB@x50B}HhqAQv1#N=rKoTyvx1Gw2w&XLv$F=f6`!0ZbArW0Tk2G69AK`}w^*iUu?#hkj)cgw-kYF#;3%n%C~l`*Ccv6?={wv*#@JjQFI#wO zek)8DA%)}`)rPGS?KpUE7%g4^0&{9PyXyXY`T%-VwgV(Y_^^K-ZS*o0ojS|&Z0GW# zCSqQ=^%C2P+tc!8Pnzlja{4Ll%VZ~Dnu~;Xn~juEPHunaQlDci`lbFwlA-$wevR>! zeFGQhgT23yed)4CvL5d^6g)ja>O?X%1q&M2$m1rzjLI58uXE|`ID_2arFUd zg>m%lkV+I!cd6DCOYa(#F-h@op>IyOZ|zrA>Vkd zA(8pP`7QKjYoX%(@}cFq#n_zz_aVAAwbb|$=q3};W82CJniaptuqrmh=*$S;(>&0+ z?e=RE zEP1ZlZ`Mk=m~(`m5;865C}&pW)NHS)#JH$LQFEzk#lH^S62pa5*&b$sPaZt?6N+_m zquN4o-2c{>T5By-8)~R(BH_-^KypQWx$tRZrQ1P7!$)Mb7Er;jh-Dk3<*pI5{;d<@wmN3I~vKxd=gB7oDYu~gXoGeutc~%J%P-|rzyO?${jBQL1;v?g`%1v1S^_L9YV#CF885daPbX9i9F4sZVh`$;EEHg@PW8WD?z zuW~FPB@ICU`;qfd9%g0{rCp{J8RAjxQNo7D*0SPhk;==)3P{=O zVwGv zFTK_}@_JEzF|cd!rZI-x?MU~oyuvmsOubQK#ZeV8Xt-?W*w)o;kkim^Osmrw&Zf`B zO9P);*|lrkB4XsJ+NCkzf2QrPG3(~UZsptgq%7YuK+JVOL?yx zuj%2{h1L>ZH>9U70%EPFAG^`xnB*x?+xX~(fvQf^Ds8I4gL758c@Wk%V=%9|v1P_Y zzt3e?^OV*@^LY@}rv5o?%)m;5r}rb?GRi687HAS6&8)Ns@D*o?r}B0~Jmx8_;7<20 zxs%-V&|Ezss!O89ULJxxd_M05MVw&V*X6Fl9G-l`FIp!MmM_|y;X27S z5Kx3rUYM{2yyviim?|d^)yFMIjf(P{tHzC)-X%qMmND^Jb5LXS#xnS5jO?Dr z(k2Wuq98zeJOSnW?zcFoxvdC{4syRA8b5#zzF59L8VoSVjBK1LkAlNmc{yaX%xK&$ z_Sqpe7$vAd!;+a&EpyWPXnu2XcvMtq5IT@VCIn>Aj*|g_NDw+6U%{#L_#uU{g4ydS zMhFW#&;ZSJFTHK#_gXkcz%pV|(}0%z1WKb8g1ev3-6?-4pSt|gxdsRh<+Csp)iWMG zEt;D!mC0**vT{Y(0PB^YBUz(W6816b<$0d^WIF^?+(L4L3=NB6$#+qcUAgg0qq-F+ zT7x`QlJ$X10auWQ`JzOD%D5Cn)uv$OyLv}?Y@~x>nIB6T6#$DCdL(<=L|4U1UGBv~ z-0b?U17BW8;e_prFwH=~>>P^h$ik`rPr-1ffVPq|$SP@3(42*>;tI4$FOA?v1<6>W z+cAy^(L0wv)F{@pEqo1#tb4F=n*-FHdk*T3u34t>3L7fcE0jqR5Fz36goFD9ZV^2! zU|ey=v6MzQwNXu0yg9YXTwD&@W0JO*wGbL29GMu4zR>A_txjX}&Lhp#d&+rQ9f;Yk z*I=&xJ^(mZcJqcV+yvGLF_way+q&aTw_~9FpU87vh-m;p8i)c2kD%#ZcBxipnzvPl z&D}UVGS0qEK46hnV0cAWFVQiHQ3_ND^fX+tR;#GzUPs-SsQnx44A3Lw@^Llaq#4ce z-s!6f4omTB-J6`T!CgX_hrtV_jsBEV@Ozb^@R{F4y#TW54DA0qZ-)KH6#9?Jqxi2x z#K80)|L0$dNM1lgg8 z{}+se&-Tw~E6@q(I~f174Bh{3d{s4>G#T00wVBv8*%%qMnHe-$85p!#*)>^MShd;c z|C!+b%)$R>%EZK^&BpT20{H)|!p8B>nm?Enhc-I{K0DLD%dxX)GO=^~kH!C)rOm+c zpN(q&v$KkB4nHSe+}gwjpY5L!QJ@o2{l|o&|6jDze>+}={~WL8zXz_M4P$KmGa?o+ z>_4dSe|?Ppi!EaMKhsY0TNVNI$Y3|`+`_aQ5eALkjrjc*WUh5^$4>yP9M1ib1nW>c z-VERKeZL_2>}BlZ6LKqOnyyT7J2&K6neVGt#^;&0D~Y}HENj%!?Up89X}?nhEmJ4{ zB%2rKEpLt9WrE>ZTc`i+XOp$)oJ|I?QHlHem}JvEZZZ*YY%&Q4Q)o)-DsL-{12vwq z+}R9t+gtM2;^_F@ZLKY{Cv;{AKBiM}kx*1P!JK4GMK|oIKg$0k2@8a%>T62$mwAee zcgu3fwRS6f9Jz{cnQCW9wA?w$h>kfp0i&={CO?CtFCutF;j^;LEFfhbkrIEADq$`Y zvcQZSurmB~>>jlEFJbueNjX!0PNv1Q+-Yd1?B%VB1n|$HEgQ2gffci_)0j^63ylNa zfa|gKD4m6azSKF}lqT;>RbM~=vg-od|IOF==bZmP&jSMk>;E?&#mdgi@c+g~fr=P%2n#{8FG`?bsaubX8{|-o<#EA$kQ6!{-x?C-le9p}){s2;{ z`Q;TI&ladCO2{mkr5f1}k5RG?#+fmaVW_&(E8<~zOzV>o?A$+*f)p_p*-7-|W}6R( zh|qqMa6SXI^OwP!-o-W{>4{L>zv+p)n3#yMtRdtSGW$(3@zJ}MM5*(b};h=?HEhd;g#b39m6sT#)q+1qRf-57)UMydkCmeEv zz#9e968|25^3s?y4AmxaQ*x&iURx)16S^}CmzG3Nm%>3x5N$1usNzxhhmyJ$GdIii zVp%I!7P+I?uvmqZ*ERrK&E5>~r-)Ic#wSso977k(2s$Z&W)Yp6~d1`$t|x zY4@2tvwh+|G5Znxs!#p4T~R+7&;{cHm5lV5hxG}Q4{$1nHLM0hR*8xD22x%yJL+;` z#5|D6Y#~c-nP_(rt9LoA531*pm6V;}+RNWp^Uf>w%A3OFftKKt$YnP(u`?6PSMNVo1O zSN>AUZC71Va9RZFZ%ztV`CQUtdAJ7W;_%OKprSqC;Lg!K8OofYYV+kglhBrXAq~vP#d6Pw%N_t|jrBDu+;i*ny-f{7Q44ymg~i(?@}wl< z8*%>Ekh(7X#O2F{=i9@k-Dj-c2ffPGI+G~-QJ3JmbF#|)B$Ry=Vk-D4bzt7Fi7PoM zLZo32#H`2VH`7b(P-hOUyu*HSN4iJcI)jpK96bXSZZI`RkDYOR$5S61HYZvCF{HA6 zb_Kq|W^RSo=o~0?kFY!=u4_lWv||cr*7JbABBxyuW%Ib)_b?s?@COaigNbko=uznm z{`I5uP)!buCx^H@{Xx`1S8hPJ2N64iejKUmeJ`t6j&~t;t0C6QUbfW`LH5Y&pXBNi zd8ROgw=l)HEflWs_zxi!TVCd`{6|@JNs$1BN}WX^*hGI4{v~#v)KGBUuZr-oT|26Bw@(;govAMQC(_Zv`uw%ip4^C{w19v&z~ zDVIVjB2X%@C{HOT8p&ae<*A{RtbbpdB8GqGh=2DBl-Cdn^~P)0>B2D#rL8@OHQR+=dbcFVLMZcEQmchjU#SL)l&bl94S$et^_&MN~Mb}-OUkOBcrS=4Gy9NpKsQotf0A! zs!$vQ0hUm$yEmP$`U){;`B7+w;eyaLEgQCdQ>FY#YMxnj^j1!kc9E=rxm08JswuG; zQ1Kg1DfnumFg%@}YJs-?(7N795-(21&d8mIU13|%5(B>CPbAUQ#pAkR>z$dLd>Y7b z7@3M38RIXk2`@~u?)Dl$>E&Xx`^MLG#y?%o3iszTXB`h)ZxqX^ZIo>LV|UZ3L{xje z2u6-P9zE-SMXDFk3*ds|#zA~PZcv8qDc-x<4`fDaZsS*qe zR+gVC0#jy8!;vgp>1W5t4n=L_S_i%b$p_vc3kc_C=cj+sPt{JzZO>(nD)*qBw@-cu zsZ(edRy*E3M-C*+vnUHzdo`mom00D4@<0C&Qc+c66-g+DMH*=;$w_~v>QL1tDp{6A zEE}4Z*7g53!D^6II^;3r+2#Ee1Pd7sAq|G5;}_qGKUL^z4AOMTxLUqKcd6{i>L~CC zc<p*~PU6zc1xk#wt%&aI_ z(}C|a+O`FO)9woPO6H2lI>vN&OD!+qtl)r$2%>pbQ*)=lXZYuy7N=J>WgS6A%WhT` ztm>$T!-$;AiLN`+BZQ;9BYgvzLI~zy1&XltajpRF5N;2iq3nU|0HwApjNcCnV~`!L z!Pro;&s5Wt-Cpgvu9dDiqj6Ltl0ykHJ#vW(%-yc{X`}m@`TqHx{hj?sL3Btc-3J}b zr80Z>K>>sBS)X^&<@@XXFWc{zOlop7g)^m)e)BWfp_c z;o(22SY&vpRk?y^$R{1Sx;#c3qT?>TI)h!>M0s& z>L?mxnrT!rN%0Y}5$2H!XM{W5r25;I+lJew+q&CnPmP1>+oD+*rJl%d3{HXMsAyxA zl=F7OpF~?Yjsnz(RFn=d{Ad_+%J&;X*^;-C2KR&DA-?ag4j7|&s6otJ= zY5-LFu-Lz-xPt*!f6eSt{DVjNvlGm*z5u@U8Jxn6=mB8+6~qFJ>;VrB{CPo;84%ZB zaz-bwyz>`g2Qn3QaM|N^?bkyG7TiUX-;+}Vx}w)QW&I`M4;G2|C)$sTUPXx$c6dN& z?m|ZmDnTDn%CF284)-^Db#IbbX{`JJmTN@CESA?S+BQGuj~&I)E5!FO0-!~6F|08e z)<(~^zHieCtJ5n9J^0uP$hJ@Vqea{qJu9M0WWj2g$huh39acf75g365$S;QIlGF zK~RS=phMLVz*P4+Q3n;xL1f*65AVry2antaR@y+Qfle53P{)wnB4-aXxuPNwU{mP{ zJN8Kkd}X-8P75+>A>--!5w`-Q+%gpJBI%DPdIp!h{LiXi1;v`S%G=CE!STv<7&vjQ4I5n~a_vkDp_6XrpeROTpd32?9Rc&~~8 zRmCI!;8BS&n>!xYqOzwHJOxVbGIXaTUGq5??Qc--(&i7r+w)u!WQwhR;ej|(aEad6 zh!4zV)IutgjSg68I5 z#?6d9|1`3$qyLF=7V#(un43E_`f;N|f9h5_vbm%4MCsTUJ?A(S*q3dNvpQHaewN%O zFoXiR@!0G}b%wFsqi&D$cS@JG2L!m0T_Zjt^n0);K0}%guxoXWdh_-oc*YWOg#Toa zqmR*}kBG2G{*y$;o`LZEuP`!4+{~?8H~#;`qr@{ORbMD|4=y|dZ0=}&@TeEsorCue zU%Wda?@5Y}z??fKnWGa|9Ge>`@3EQ}mXcenRfrBV+GT$pc*u}j(#v4@&|q_TkOpP0 zB^@UP93{~oH%f6!8E#44$?wE9gU~I$)zZe5ykg5;%^yY|fpvK9l!RJ4+)xisrZ?mz zG~^yUdz?sFc1iLPmGa>TiXTWl(tddCt19uqRj#WHSO7)adyWqkxzLh{=!pxz!f>=r;1NW586@l@((68r_mTaSC`*{#Hm9T>MRP$&n+}` z<(`U5+g6cpFP|hdb?^wxBcFIl;hs(7o=x_aO26 zY;KGPM4~d7|15V3Pt<65ZM92pIRE8xyj*OPT(RErc(`2ZklnHA{=D*d$!svg@ zBn82Ng;j`lCt|mCs|BOCk=z<%FNR~hHqx45pXb?I>xKiVg=pTxCs^QT52T2#gA5sa zj|s@1h5iU6nb2cJpOx&s4V0<3eD%iQOeK($CNC)5FZ$z>C(Vw`?{QxpYg)`n)ny`p zYa2W~%kSC*u#t*83l{Ij=}F3KK@L4YVFKrn*ER@^{25rrevfkqD!OOL7s`fr#wSIk z6o)$@Y&h0Re1dC6Tp$&f{Ph!Ln?pzknqqeQMYgBQP2U*g8cD3$_72b*^~BE4lGIVj z6fk9Gu8jQ#DeV;q-Bd@yamH(+$%Gp|if(vRy36PJ}coZ z3r?(8DB;7#(xo5F6RU3T*KR+ALm0SU68KyGu=GovAw_BYTS^O_R+ zzMu;LDN&)O0p=CVM!>Tu9>6wNuDb(&ucyg8Uv*q>I$U);Z#vBIoOF0%+zo=1JxpYsqu5p~mp@Np8F$&; z+E|-6gD{(c|smvumYP6 z7=-FdJp%6N{fe~mh}!zCLSm#?GZ{+G`Aw=DqV>$k7j5tFGyP5RLvdx6oaH0RA7IUv zOI`|bkn<`+!b8!lwjsA2h>oJ!ut$$(gx_yaB;M^!;rVc!O*Dv0IFq@Mc*J)tndlsG(%QO;8*DtxTv2A;|$^bzfTk1elfJdk@t1 zn?4&oQ8;;janzZ@6LI^8hB~}JbEV@O`Xm9OQqarBl3nW$=dn>WtJF`~@p}^sdIXGwA**G~(`rnlpqt zuUrJ){KY~)=)@~Yt=CkUz5cq`H@CxAXVlxj zb+%VxjW1BxpDqw>i|z~HVYAOCMyeim^;LK|zY@5c))31tTz8)^lUze3@T$KWJ z#-M93=~Hb>YL|BpU2vw3^ful-CnvsFZ4F^KPJvF7ADLN^A+q3N-=C9!Ljw(iE)kE)q=(kWUrG45j_Ozp`@HR9GYh=U zB(KP`@9deG4OZPmlQCTVDiCZh<~lPjQJcDI9q^+sbmXl(@<|7#M&vniJX6ihnmqw7 zI|1MwU@hTpy=^gj+qQAX;k=ZRw1;+7)GCHuC#BQwTbMIiizYl0a73m(=Z3wYqH ztdkIv)$Y0f>P_z@vQ$)AoW^%vBtu`~KlLqL1xliShHZ)PX@p=$ZM)Z znAD}9()ODEh>)uU?CqOZ=i*v9B_S(rCV?`-B&Jo=L^o_wnjmqrDIuIB#={m({^}w% zI=*0008&H_PS>0ic8ZgWS~-bGM$Vva70|Vg*ZE`e@|PC5v4mkM_pGsGPGxLqmX$_l z)6`1V)y!@3+ImhiJw-%n4m-)g=#9Z9D((Fc@7|h?;pJ4X@It0c6+N$0Io%3VB*o;a zDq@r3af}ml2>m4)E!a>5UC|~4!SaG-a=1l^h;+lBf~5_yt-SBC>6~CJtjW@(T&Jo9 z<1d4iw4eU`K1_GEzke^m1vg3{a{)pA`{bI=Pw`_WR^H&qA*}6bII~wG5|SZ1+2dUO zg9652aF@3%p^Mtd;>)Y}a&2xabyAjjJb%H|bx4?WA;-!xEtRSxqe^m7wvT*h-87oj zIAs$HdJ|VlVqI?=PDq}1lb=7;n2O;%dE*zj2j!u7R>b1xWrMY0?lc?Eo--0i#nJ3Q z>q=(p#;s-PD0DJ*+q>5b_CW6E2v?gqG#D_BpI;9_Z6txsI53Zo+eh^@3y!vNA*G%~ zrEwGDyEWr4MJU!hB^f{5q(aD^5e0vbvMPoLe`924R?2AxjoE*Nv^vS@Xx6MO(}bB3 z5V0Cg&T7@z;_#^Bc2_ip3YC@K1ac-)!5?U)#4C*#zwUg{g`KhjB7Y9kp zT3zYkIK6s)pNK+Slz)tSZ+%&bNjLQK)$>>ic?7y!3;xzG>{|~e3Esmb2&jOOd6}Js z!j*+V$U$W;Lm+E_{|;PIrOhc_f$lZpUjzJN8^yGUK0U?BFL)8Zrlx=;n#B-NTj>{> zG?P)wNV!NCWrMvX`UtJ#MD93Zhq$<5t-;vF4XRpK1Azr8Id7eAzt{&{*6ty;9~CTg zViR&_Kj>3)V&+AtA0>z)*K=q)lqj|`tLJZmj=0>TaQ3;*1DG?>EMJB0=pyVJJuceZ zXV8e-4d9-k!3C4WI0UiE{uo0?vI^Zi<9UjUOolgQb##WWZA}E&k=Q+$iPi}eX}0$hNigg(5Lu)iHQ2H2PZXr%BU7{Rf1$=-43Dl_*rfs@KoVC|xQ zxApPi`whsVk&-ASisyDpyNrIKkmXyUm${G5M9ag&#-gu%H8r{$6%T$`QW7vu+;S)v zy%DueEzEUo`L%4p)(bvD#^{WGV}^Ynh8_cFys*bE%1gyvo(T7Ij6kYMGripApKMN8LFCpxeFMZKqYfq`%J67B~}qm~^W8 zq_tFEwmaae8j~9}*6OJV+=7adjF%2dh&RY@6%2ciqhR003kQVTyZ0 z%xgm!jfn+yQCF3{AAqQ@8y0l}6KBS(BFKxE_T{`GiKk*^)bo70ysv7i?HYM^=OkuJ zR&jn=vw)l|*x4uc!agy`F!O7GN{)z-If2N3`s!8)E-{yZq^MT9x+dhiT!ITe%kRJm zpKHPH^=`oMx4Zvx5gK~6t?Ddws`#~egnCXPyJz?BK`le`=0Zm478Nf(?0q1D;*750 zboUt8?|Um70P7@>E%XxnraH@;Xqn%r*6QQ?K)!#uB`LAED$)I#X?pnm=B>Da3M<5#w#6{+s^*Iyoa}G?=7Oo!{-CYYG{0jErhoCr`U{udM)@2&WqiG1Dfh3 zC;Mk_4n+%SpL&XY!Du-5X}d}u@&T!S_z0ACAE{fF7`f69L%HnOqF5>xNxB7;^@c*v zSmhhue@giz7G6zCLRHk!u71w1A_6Dks7yk39d#-oA+x<@N?1VsVyQeIGJh8&KnBEpJ>dXws2V0mQkS(9(qOz6Fl ze#Q+%pKo^Mr?9#~81R5Bimio!7NO-w4!gNQan9*+PNvk!?i(>!N?1P#_Y4M9Q_`zm z*ZuJCC*LG3-MCOmWTw&P-V(f#G&o!xGBPrawz)jVf!RUG)d8$sYA(GM=yu2Ot9Uss ztZEOTmZrV*^+^q#G<8YAv?k(Mb)N0Xb4O#V+DYmq%1yv4mS}zC)3x_GeMiJPlvyH; zzFa>3%*x&&pwKxRv`5D*b@Z>KfV~|K^ec;a*ns?j8>pwOXgYadlkOefD0&&k2dhw7 z;`-l#Wo`3?mR2^ICn9*0f!Kx#cnsRH1u$8&h1T`)J7TQ29g`haopE}rBcb5C`^3)X zgcnViQRQRArG$;Yy2wrew_;Pv0&q96^EC5SnZanHQspky>MWmB-dip!aVkQ$6G+~x zv>v~btG2OU9cdF16HmvC62m1MEsOi3785QR!2U+effL8qbSyNkKwqS^RMPV7*j=SL zq}=MC+*V0oa5!k1$vG(SNsaUwaE@ zf2bb15yc^xfLiJH_1z!R0lZ`pyoAf77JQ9$MNx|Tp=wQ2n|h>0QDcFNq`px|OGW5c zm$bPC`v^aHsw&BM@Eo#9}f{?rwGqIWa|E865;E%mCC5@7p zD$jXI)5Eu@qDezAt5z#-OreIXL{ZIHQByf|;c5x>I_AA#HBabat4&y=flYPMd=~%w zG6mwJ$7{r;zA*u7wa=mKQ2r^BOdBdUO46{TOnDB9#FAoT2iF?LwM(Dk5det2i;dkh z%pFd2Lc`|X1uK#h)<5frXls-L%$(Q%7Or$WQJe@Fl| z=yZAV!HYnZ`hp=4Cvk>nj}Dg}Y28pKzahh&wo&1R-ZoFg#%IZFbzZ-eXH480 zyvRB>YBwGTGmxi8ee`yaw~cEcuhqBX_zY|y*=X1fYi{2hvrK{7IZxG*Pcg(ieNsWy zsAM=8mqEn^O4QtQ>L#hz1I9`n{_era(`q z7=K&EFZ^8dJ%c`kTw9dN4u#1_y8!GdZ4gzus(?>;0b~wrhq<_oBmK1GInofSVn>!6 zYvyN@(fZ`5kjLgRD>Eg$iD+Z_+Df+rf&5hT(~pZj|7MAc-REFfmEaqJy^^{=HP5-k zri@p4C1@X<%*>0%>Z7BFC7|?zWQ$-m@*fX8AuE66@;4O74T$cxx$x>fUx$L`T{#Ro zBnesjy>B}8Bh=WX2A;Trr3)kz{WXTKp)4G>aFOR|k@Jq7XUZP(t{>Jq<aDNwj0jk7+t*o}FaW99Jyf7fun5m5~AR3%w_-2uJAP07#F zt1dH653{U2R#FlMO2OU^gjRZwXKPP6C9pT=6GF=8cEghp?VXX0Qy<&uRghIup z_Oj#^&9cm1?v3bP-pi~4<~*Y9m~vgC3YN0q1!c2xFJys)MZ8YRTakHLt}bRQu2>_n z9!#7Gc8HKv6E#y-yl;@8!ObOwIB1o2kSSeAba`-}f~#UGxRgU?1&dj?L04zCLFiMW zu%X&)PUC{lQIyJL5C~)!9zUF{zg>I~Ix8u6w|3+vIctGdUB!)?XgHTro0g82jyA8H zj-Fvh;5)EI1D-Z1Kg`!8LWIP^(o-&s>}v1w&D!yS&EmKKiE^Dwsy=AC6cP{y1Rn*_ z?maz$C$30uh<@mTG4V%hWTegXBJ=cUVNmeeEdvw>36x7_9mayCF=^GD{HCW!WpUjY zf>3UG+9%H|s%64cI2Js`C~l)1&#O6HOD5=@W=`}$@xbs2|9pTyAoGWL(Gl~2MC_!W zD^ix*t;Tb2lxa^}srSWS>D=nq*(+73nIN6l-J86IzxAS2ZTe<((0?>F-|v#AddTTE zSJv(-J|~`N6-gMdsSb3~SXwH`7VigCOh4ntwRJt)e5{FDGw2V6G?(%>?`NhySrwk2 z&fXu;%TMXm?pcX7Qj?uM{8GSHd2K{-w~m-xS&dp<@j=wsWcVZ%#vs{~DkBxg;;}zo zk3C+ixf82~RHdB;-Ij>}7SwiibDdte8Z-Gya6(4T4EHHsmDFq_I9Fg=X174N0{`yg z-Zt8fIiz(EgY)nC-mr;Dl3a9dbar$#qU91g>Qs?t^M*t(g-Csojc$05*QAtma~AkT z<0fnt`b!d?z8Z8I|MI2gvZY_|?L+y6s^7?uZUYn%_1h{Hgmhz2K&3xJ4c5j00&p!| z%>7jSSqT1Qf@ou7U4FgY69$o=o@aHHWtq!5>M`C_^eA^#+1?rW69LX2xfIF_-Ah9J zy>{;*Ip!*tgqbDzBl$d-jv4R=0x@8WQjs)z<@TJJjlP z7?1bkbnDs>#ezT8OUfidVD>C?KUb0(X<=WWE?1|DO=Tcy6S8Sw6i)wIFkR~ zq>tuX+iQ`poOkxCEC$uvKqiBKp|L+rk8~4r+xjWZiX<{DsgI*p$0}&bAfkO$ZK?{9 zEv#U&q)${&E1uss*>z1)Sgsl+918y}(>olq1=V#i z)6sq2Ln+AH_V>c|PRHjL{BR|TQ#9dV13-V}z?{@Lc&`knX6&Qm9oAVD$Obo-n+w1N zv6~e#JC&`H+3rf~bqz?&Vpwg(Fq>!%!}0ri|9#X^cheiBVb}H1jk_UQ0~I|WnE)dS zu#Wt~dO+Lm6Fv@er`H_>#&|uIfi1NYPWBLrq)xy zP1R7Edi;ZpEO#0&*)ImGd>6Fw@da0>V?zQ~Ka9!*!%8H{V$)bkZ%B#&{3NneetJm6 zPIv_vSt8>m>1gVNIF}s!uPzuaufv-v1OZxR&?lo%hyh!DMFHk!mtX@%WmQQEN-UBB z>d<7Qw4xqwp2ydwnPOak$7vdTzmey*`*$|%v`&~5sHh59pJ!;bqO4AEsoy|=#Kl+A zJc$ut)i$7_aMY`wm}Q}O{H%IjQcYT0hwbZx37 zc@;zyqbm^UYGT3h2{#x@ND0x*!I4cTr|6m1o@k?jA)BX@x<9d`R5mrEl5#_HPWfc{ zVe*CWeC?~Go*q6!m4&8@c`cbGR@YF_K$WgQ<0;wLW?<}SJcQ~j=qM;m+eGHX<<0lz zb{5c@5Ar?XyaXU@m%aDt+_TlSrD^^A<^0@w&+a!MWQDmm8{TMDQ5px1nGnq)LlAIc~$|dD&*|*)8Y93zy>Ou7jHQx=`I=af3lM@Boha@kiS(>d>s+77k$p;`|Df zHUw#wfT3Fh7VC{JR0ir1jXzBqj+j&&-v6TIqm z9ok_gv(T*F9K!6Pjpx2MesSHi*mmVUlGFWSeA0}E=lxuiJTOt8G8nO3ox0YPk+`)g zJ8Jo^iC5X<(RPHRf1Z@RfHvdl3TkhJH3E@SSB8SW!!wpvc^jZ20ALsaN-ZN92)U<( zIwV=7LayJYW(5UKxc3lB4z^j2s+zfv5hfq>Kt4E#VaN#(aEI;<3h)c0vIGsXB==FN zevjALi5(;i5kL$Xo!;8DI{%mU?)!n9X3;n>twtC|7_GzTA=V^p!vr=<*%;XVsOpHG z&j7p!9_=t^Nlw9U7GxzgcGP-gys5U`Ic#aBhipSaCbvQoIJlE?|9iBODPc^OW4ei6 z$8CzqLvzDD{1Aums514z6oV4cyHUHC!XWYFh}-yp%Z32MLeiiiD}%m6#(-^Zx_)wy zu0LBF9_in5YhA_z`zsSarK^0dt9TwR4k^F%HkOM#nn}J#+1nxjhq?`_Wshk&cH~WZ zv6QI(N`%Z8J&=2i#}Yb7M9=3oQi9E=yd}vCPsyi_#8c3b$Jb`r#*@n{#~%=i!p*|2 z3wxOHCApu%A8}w7bX`W)2fCtNh>To_)LAP9l_)5&au!=zG5Fty{t8nnC8)CJ(dd${ zbjLS53ScMPMbq$BG|cNMWGAmJzdXOXDsG|E?ZztvdHx3UYD@5%9CYb+(;7rWF zZKV(bJI#b3{e{Ma#wTDgENn6xN4WMqH|y(pZk_3F6&!t8+xeh_PXT~#;x9j#M*Ptp z?@obO9{kWDx_T=Z*ixN^3zz3ET|H6*?K*B=ob@-OvwY56^*iY6X(L6lwQ82wRbfSM3?>e;FSEoPz`p7}X1eMVOV(8l(O*0qaL(gb)$plc~0s%S4 zKpT(A!KWD^otarYb4*|iF*MS`n8f$^Q(tbdwW%3JEnTZWso{peR34xMC2&;9ux|pUF4$?#oz_hG}k;R2Km#D))ca@FMs-R>fOFM=lkz<^wE-M!5-Sy#4>MJ zK_Y6We3Qjgy`pF|S;14E;_rJVj6v$ub!Mx@PmR{`piYZCLF~ruUW_j5Ic>(7>Hewj;9DEI+VSx^1mw z^W5s*5eIyw)d@rydHz@A(d6V?9PnJ^(K(>qP{ZNC*B0q%M%x(Zte$`DFF}S)E!QP& z$4GH=FB+Ki;jwMYN`}GqH=6Au0^qX=IJ-1c-N-EuCww`zVQaJ9FU8@0F7k6YZDYQG zNq4{M6gZjEb_zF?rK0h2d<+n3nxL@iw|RWoEx?0}Cir~lH)|eXyNwJ@>q_3%Rk@B5 zYqi?fKN_{yV!{LY`G3ZyJ}T%IeH^Zb4&P&ikL#%!gYr^`f<}W6__4MJXHr9n7yRNg z^ilfhJnJ#%k0qhBc9N4jy6KkMv>*x=RV|WNQACPr<|}J02QiN@3YJwZc@0-09>+Bb zwpITxw%##1lc4MSok=E{iET}6TUVS+Y&%zM+qTU~GO=yvif!Ar@#cQc{k-d(wN8Ji zuBxu84_(z=y>{>Y|JhVF_z3%llNeW^W~1dOtD55kIqh&ca4Q33c`WvpTA14_9)!`tD>_}h&9Or=l;2oe4$@ZNxl+5yc z_>cu*$&_G5UC5I-lwLHR#X{bP0|m)>Df#zL9(GM<-7+}4HA7Y6+zqkl}Q>=$|yRQD}U#)?iYe>WzWpFg1v}e z&A+0!5YJ{vO-mSK=vY)Rb6Ra=u^HEN5MUCJ>RS?ysIQ&=jBz) zDyX6e0~rGqjj;Odz++3Z06*~tK`EgH(BP22m2wwv{w|rLTw~mVIynaK5oct${$OAc zv4kWhn4^#AP2^&uC;|P=rK*KOAvKYIGwX#kQ`jRsr>J7<^eLv{^g;UecBw=IP(i}P_>cd{qY zBS_$uPzW^o4oZ8U|D4f2uaU-3ZtC{40jMoHaj z&;4#0u7Tg1yN#suH+7(xgiKx#znCaafs|1G&unp!Uia_myky~h1nOcU3V}R<(s?3O zNqONis-foF@n@}-;?|C3n@4ABwM6rL$LLrJycU<~=i|0K& z1}R+Nn}Z|3dr-LIoXi;NFNrwJe_mABgQ-Gv6}QXtINarq@3UGExIb+#TM#=bJe;4y z7~_pPB`uy~c7f@91>?YGZt0|cJ@p+5RPpH|7&FhuNhNS4-tM9Jf4VR}oMs8YAf0v@ zT?XLr7@(g{yPG1MLOmSuismecy{hR}%U&`E*9vhmr$`^p%$gLc)+zVg zFW*0BMRCu9ANQTXz0beJ73z+;ro2n|kUv^~7(VP;vgjJ+m6T4avCb$9@qp_{C`S#H z##LfB^r84%XSGhuYtZF0Q)Z9JB>0avTjjXZcSb_>qLX2|dXs4M5}gsY1==~to+oQ4XfjJD z>EQ^@*cz6Hr*%E+|EgA+#VwE7bzQmbt5Kkqvhl0EHAq4#1w{x(yNahCljtR@>82N zFbtTXmR)Jb*$;=OaMlNW$NARxsE0CKPx);Lb(J|G;n#IV4r((Ja`#^txj$ZE3{&R* z?XS5B_Lv7E04Naf&Ek4Cn$(}Dr{Ww0dbHhPoCw;^y;*WDsw>E|muk#+XI%5=xf;%YQl4hU9&4X2$kfy|MUFGVQTq?&xm-L(R!PaVewoLuh z1JcaC9DR^#d)(ZEAUxPX$@es;rsXAYb&jiRAKCLZ-k(Cnvv>XM|9*ExYu!Do_q)Qg z8B3xPai`#b8vvsX&#`?;AdH6`aSp z&Z`H)5+DW{i|yj*zUkjT9WvUW8bp{GG4_PDOwm+}Q5V1eY!-C(|EcwT^CA&o7X+~T zzVVd=Z8-|$U~a`gVd&b{w2{CwrbEtgF_mFYRz*t;z5&3obd+YHgQ{oU&1U02RRv%kf zo>e4)l}?z1*AI4F=65V%P_Orf&+}TaGg3M(f=tFZ3O=*}*^;0Ar-{YpaihPG!0T{< zB*HkpJJ7TzrfoHcs46*foHd1ZfPpr_cFFg3_{MaOSvp{1EjQLyo4$(z9kV1hY#{Nvxc5MU$w&Vo zpu&P8mxtiT<-ZasD3Ryxs>)}+QT7zMc!WX#-o9C~Q=W6a8;S5ox?UK#eCD8stO zvK(c` zBi^CD1^bR6uf8r~P#lptWr_&J7jH?Cl~zbSP$3vB(AEICC)Fm{QX2R^3sH--p1iK&FK681RQw1%BiWIs7;j+##k z6Iy-e=Y~d4t(V>S**8%x6CpLm7Is)|KmQpkDH5_}Sh_Q+spa<5$VfF+v2tn<(h$Iw z!7+2V@f#?13k|ae!iW+L6haLIy0LBdJ0w{~)PhfyP2} ztogA({(+!5U%&fEMjpHQ%WsKHt`BH|D$KSd<<)<)j6^(w>Lc%$G|#+W-7=P?c3OUI z7ymfmtGqy~Z!B=lAh5NH>Mfdie~!B%{;q!DTQHKy7-fNKyv#QEC_-+uXFG9I+!dFW zyGLN9ELqyPi)zG5G-@6?$O#N23Pze~UZZ59?JXj9D^)=3DJ3>5tO$Xv;SJesE-ax+ zj0UFXA{xZ`Xh75L>459L!qd*fiuchQX-{NDh1+w66r@ zwO2m1Y+7__8$GLO>H9@(p-3n>vbMqxNCP7!6D^J0zuGopIjMRGK7n<*Sj=w}E@#gAXhAcKM3o@S^2`rVQoV+D(HOSDqccoqr z#8snXBP0FWlcy9x@g9f&sCh^3{a$1D404$%AZpn1=EoH)adoayrIqP~T~0LHZFJ%@ zQ}i~Uv&gk2$uIbq5M$^Q%GSAdVP^Zj;l3FfU?S5x#VK5a&lXA!J_&lnOR ztPB3T4nO#ld6{WHujFZvM{kC_*NktsE5s8%=C{xm*YY%^z_h+wQT@x~AXI&X#v$6H zvq6eR0X+?L0kIHakW>pTn=@{Z-?FSt+nB+qZtMDy=98NtIB{pZqfIqyJE{KF;4OwP5szb zJ9)SCP^~w|J(7>MH2iy71}x9V*}x&G4YkTx6P?+AocEC-$s{VnbKCvq(iV z-WbBoCk?gp?l06Ah{_b;QR(T?NN*~oU-K2O%YTG;+Ox5qv4s@M9DZ}7qNI@|n4GF+ z`tb(~JGvmDAa}SIGmeq7k6tS#km)ULWV@EM<92?Y_p?)6(G z=GW`1>d0rngN|Py4jqeo4i^>UD%G!I7&XN>T$of-`t}(anMIma;SFDjwWNeHPS5^# zY%+Rea?>9Ifrwi{hIFe~D*u3%E1}oAKMTJT^+Nnp{GH|C3SnOhiXiNM&mKy)r!p9Z z@(H#U5>}tdquyt((>b6304Z*w`^Xt7iYi58h<)rt1Xl#p;SgxinT*o-CH37f5?I8y?)B<`p+IDD%p_uk`@M8!lQhvWva1 zfEBj`QLo-s_2su}k9P~fC1NRqhu&6&>HS^7Z9wntJ5NoE$Bu*SLmH-^`NspU+25P- z&$Gm0G##s2T+Ae*EKT_tYbm>$ZyIoph)faMux=VWMISnda&ky6EwKy`!#& z5l=jYOs2p_SRXqj>n-RnI`rdk;4Qbw3n0&A z>=fbb*+VZ7xsjWH{e6NB5e=L{3{IZYlrk2Yr$8&eVI}4dzpl*@-ajTim-3<*-{TeY z^pM7GPMABDl}W4Lx_M(4(;NS|8X^kwE=>jiLp9hh+20&zUH2WZEh6(4^>mqQKG?Q? zFT4q_^qFe}z7P5Z*Tb6$ar>?>oo+Jn)>uz%1bb+QcHmd@>3M&@BDpBQb&Z=0cpt2r zc-|0^x4{IiG8$unzmY%y=5K8=n^c|Aik0zw(3e|p7DGaYWH?BxlRm@4E z!ntWnE8=k#ACXCO-5Dv?h=F6yFCJ5*l{}YOu3MU5^XRi_7o+b2la|#E#5>cTr9WWx zsA=kWR3n2)%L1i!!_cQRp}CZuQgi?D@rXZkbQ(|?`Qi0R{rTy4le-a^x@_oE*tE>H zx7-KVK0)Q=caQYx`i?j}e9yCcKK+N~UllN%2yk9<4<^t2etDF4ptija{_=!+I>Zf#o z-v5}IvxCbGym9c{!yIIc-^CqFTYB=V-+a@SAU;doy<(+uesgaQXyMr9!`l?Y9q^)W zv;ro3&6zgDlmK2+8Id-9zB|5B>}|}YD5flR$NBdXD~uX%HHm8)=NYfb6f_o-W2! zDJJfSW$LGYoO2934F}jcDf~p@qB{3KOh&Gu(<&Q+$jAy|Y}e_?L?O({kLgpuum_kU zHPSCYEU>)Q%PpW}IsT#l2fE62SLK}FMdQDU0IKc&IzYQoXP_53IPJJ&c`JjiDS>7T z`S*^o`Z!NER0m~;CpVg#PbRT2n%k#9`6@+=4WwT7nG?kxXEQhx!98#{pg*6fJ%-9p zH195(Mk24VVRfzQ^KsZ}<7V_pMQMWaxcrfGII*P>Z1Lj(Lp2aN%3l3vED!i1<&y4u z;>moA5(KyR*cuG4Wl_x#23X@GA_F1x^2Ujt3u?THNXd{K?MusE$PsvfJl>DCeOz~) zRZ+g_aML_4KQIljsQHf{y6?g8#n<&(9y#!)hou|3ZwZ0{GjK z!yB~5s`66m_mv8>1JBoqVj3Y`qTF8S^~i}CKdH-4`Pbg*U+3|O_mx4DJkHMQ5Bp$} z`av@3Nd<-k{Ob4(g47VuMgn@dp&FT4S?hSq%gYmE7tU}JrSoLc>9N?-0S#;o@?|p; z(CLWzjWx;^zNu=Sxjrlle4Z=|{L+&8Z&?nL@0~WC>X_&Zj9hKcO1dCtp+enaNl37oF%ca2bNLG4l)Lon)ioE4D?L*$Q! zolAojy}E^~p*JSJk7*A(ja$TbR$Iecm!?+58DwCaV+061GN<5G;4#$jv)VKG-x~=B zT_7I7@wVw+09W6R*y{OyWHWosS!>^UY&mSbgRLAsxA`Ky{iZ!c2g-hn`QBCSpmU|3 z5al61oyn&&#TTpv{$pYX-UQ}wZ|tXBipzI`Ap(f?ZB*P%lw+H^o=&0-X?hWpm3MX6wR)X5(Y;W zUx2gf77J^j=yt%jm-C~^>X&-w-X{#hH50xkXn?})=S|G(t9M)S$odo=B{O+rFJs)pJi- z*H-LqV$(x=dS_g_6iwFbIc;J;N;li=q8_FXyM54qw>d=HD(W8nJgx)#p$mcSJA^ey zXdx%o8UC_Ie5alV6H0pN45llFdm`{^5lQHw+m2NX@s1w}_xBxo`q|+xGp5h{Zvt5M z*#r&MiJqlLN1LRZRsDyYPpoNf6Tic;kK0W!!1ovFEycf|z7G)fG5YVi)t3VG^y$wq z9@7Ni-o78Y(*$770f10v^c6Ne$f?kGT?1QQg*!a=_0{1nzRG%$apaIp_B`Hb=dMqj zop4QyN#u%8&Ayc`CC%JTWKhL4cxRf9(E6kHWz*z-r=2B?ht3^QJG0MsRwKB@X{}NF zcbfbB#+!FCCz=V;bTiE%=BQKE%B&V|ku&(j7 z`rus8;)BFqk=Njab1q$$nWV{12YlaJf+=bdz^6>67 znE2Y++W+uQk^cCaU14%CqxG}XgTg5GyonG$2R1qRQ zI{59kz2dig%vZr2yDSNL;P@EAmh%@JMxPv#@`K-r;{_3%!G zkF!V3%E>VRb$@!VCMCYggHCEmz{*s^H0%ZAXAD zhL`)J#e`=~N4zN;#CE7=HSAp8g#6x+Aw|ffHf^PKQI-mk>$3v+FGy{iAPY;f=xz?I zao&g7ij<=e>vX0^Sb7s;$77E0?Z=tHhsB?+C5Ks?Pz`t_+U{1BITe^qLi2#Nb9xk~ z-k9WWo7Rs515nk-lTCN&xKX0KDAxafa_tlKO@2@Rtvr{p^xtn*Ir4KN=tY%7%0R&M z%M|)saOfx9$X7&WDSWvK*B>V|A0;l~N0m3V<7yLWh;_N^;2EUSh%wdHcyDAg#nvwu z`wLZfY+kL``kDD{jD5qxB1IeRkQvrFT^G6Im7(b&zQoG>n1v1ydqNlZ{b~}toXC5I z#Ltr2Yxn}8x#ec1{~33l#afBW|DLgcx}?cY?wBf_F<;==tiG~Dgmil7oew9gSvqWqiVAdgb z=@L7F>>NG&o@?T3oykjeCpGz^J|=cdHu;3R{2DtoZlAo(Iazlgim*;}+C_0kl-ot- z*fu4WT6r_1yU$tnH3sl$cX>e26k6m z9SJmq_~7E(syF~#94eWOqmkfdU>44wNT(TK%VRyH%~gKVl{%N8O`7Je2L3vCKEv{b zySd#mM#tRWTfBI;u}Ku)wL8Qxl>PyyY2X{A8HiPQuIx6hi5Iox{YIau+39l`H<{CgWkKHMhStV&^A-vX z84DRCM(@RUT4lx{V2E(*uvc$qX1N1Kwj>l^iWubKnW7o6^t1WNQR#i-q+E6aKUTiZ z2bWpAfv^h8|2!(@-!->y3*&s__EzV9>e7g-n35yr;ww4GT&UJqcq8q4K!4fHdguP) z->$m+*k)C-co@rB#(=fD*RW7DF6D8{M#e2Dqx{m_jyGSGBQm`3721RqZ2Nxg z(|A!)oImEqwy*&PA8}1k5VY0LHZuAYFUpWb0f>wK-$@ z8^@4)JszbPd@8dSK;iZ0LCnlAb1`bOf}>5BXVE;;i{VsITnEd*}G}}B~<;|DYd1he}MarYK zW-9Nglk5Kb1X7^1YQ9;KYZ z)h6WWvxG899&Q;oWj^p~FO?h`CQO{CKA|b@W>a8=udIvv&@bmf*YyFIcAQD5V9E|J z8&}V|eyY$U*3wa=(Uy49?2^E^!ohgGM6qzs4~y!%7-3mR=U}G7Hu(sc@QT#Zxs);6 zV|!t*G8caDi@FK|IJV%leALKa=vZ=U?%G*Pnv$AY15ZYp)tr`00wQHM=}bCxHHdt2 z2Id({dIp9yK}n6B`z9NPf)-J|k(SSBtJ9{V6_LBWbx(Mj5g^aji=6oS%H#-HigIdb zQVG+BOrhX4wdVNbY3RK^3h$J^i_w`aQcUDN4j2F0oc0aI=z7MO3RHjh zRmN(MmcVS1!5#o8SciX2oc4bugLl`RkbanIQr4prjVqgaR-BvYP%ZZ!K~#h*wfr$2s{?rm z`|JPa$Y=!2vxSDR3Ryz!L>PH5|3V4>^Ej2peoL;z@o(=4SQ_UYCvviUD%%}vzw$dg zYD%ldT3qkc8&6V{w8VWb0gCg$eNE>fc!8rOKUkDx>Sy(cJA;{R8Z%vyqzeD;TX3@$ zc{97W$gEfyO^U%J{Q+gB(?BR^)%FvShNey#jm&^|TDn3n+A%72M^w#K&$w$%q8a`j zR_e{22SHtR{cr-apWJ=4kX-6ppk^sWL7D`qn}U+0*&-g9o#tsN#B`N_YSNNMVL=4) zDfPr0doAF$ha_h?=zbMTW-omtFBqGsFL{)%~~vgbl%>YtRS8?-UG&UNF0xNp9HR5AIHYO(UZ-Cg)$9FsUA(b zfhIp$ce_dPq7bcXz<)v~#B=M8FSUu{#zE|JrIKT$36%MW}3w&J-eQJzpkP zMuV0s=)qZ;?T@AzU6gd5mch{vu4*>fSDg{&X`*wj3R9~J84$DhXq8&8cY4DtF$iQo zBRKfL%bPzuV6GqV+@!+x#PgcCPd|_MNq^u#Z%3AE(1|5eV+QQdvJA5Kw^XCR02v@D zrb<9kW$4xYInN7DZ(&tVf@6&^-_L8Y7m!wVvhr#u&s0^_?x=2UB;=##t0L^lHx<)} z5&3y=(0n>2m79;h;ij|JG!urNAeNxJJ2yw9*&g{&&nnc?8i~Vt29#mQg{?|Mfv-y& zuV}7HG`11Gn6QS5DA{E_t{BYTRsosT*QWc2hg94-dK!g{MPUNFTIhJ4=_@0{az#Q2 zViK@66QMX+QjV|b*79=01U%%WKHw?1GFgR;>XOFPq{k$v^;E2m@#3N?x7{Q?FxC`T zZCxeRnEp_&hH*aVenBtuEHF#GDop35nT-#g4z{SKMmu{JGJk!_E6s>=wi3!1oYiJ` zv6zxJZda?{)sCe}Db7G4b0G|x2XTY;4qn`pj?tGTp4b8#Wel&1!>p`ja$HB5s2I$i z%IlLZ8=bbA=B*+F0#n3A)5^x9M;h_%e9UxLuSw8yu&2id4a8!!k~t&KZEqu;fGV2v zHC+f65*N0n+|(;zcKFogQ;<>jNwsn^>B<^x>d8rCR5Wz7bQcR1b^v09`ooyqk2pkj3-Z&66+v zRK}c(J9p%rnyvy(v zTb2cy;QAvetnWM6xuaFSLx%*n@6R7VVu+P5yKYS}X&gH3bmlzgsr|*+@{rG|1KXZf zhX~E+uYiZwCTYtCWx57s78H6HLu>Jiw>7txy63jc3fkLnOsfQ9D6JS)PD2tM($!bd z>|;#-F_T$g4H2K)^mDuVmyw-KJ5=gKi{a}V?B}~`P*|?|O*T{-?bRJX>BRS`uTpv{*=v=V= zL~4n!lJJn%VMdT_`)ZdWO;cZw8I^{C7jjsaXeWi`IP*5Lmw{0T3rsH9=NU$G{D$}E z=X8(bFFc8m>21d!c;aHy(~husl7rI{T-h>zQI1Kt(qwWKk6E~~CjK&;q1hi>a)qem zqhv`QPCp+>Va#B+hSC*E9x1d&(iJs0LTHPtPP01FYKtw-a<%$d|I0WsZVj?7ST*If z`n!4z@0ix{hD-|=9e}~B{BRiFFhsrBGIaPOu%PUJi6>*2$ zAyqY1c8A>|V>6X;hkkpA=bo~W|9A}k5(_X;@fOUPF}dUP640Gdy<_zf+MIE@<9+An zn~}X^ei!VTvAN@Z7s%j03b!5-a=GINxaVQG=Oeu25xfAuK^h=J0)GV?U3^+Ba!G3P>;|2!U{elPSbKr_?{lN{&w}Xua*{Ox? z+JVXRi*sNVZ7F32&)Pvw^iyR9)!D(T?0$jQ4!1qEd|_%JF}4k~{3Y$M=ms^k{HX2F zDhF7b(HE})S|K>L#MZsz%@9pHY~_QHYth`c@xDZeuK<8ANw;4FyC|OF zlUJOb-6>Ddy1V~TxV_@_?v8na;@ib|3*Wrr{^%wX022(wjicrYo5+heqG}D}nby8T ze9kL6B6W`dx_g!i1=zNT?!=sA5ow!jy@kScxK>o?$n|zTr>M zNna-4eCX0V?9zNl^BtTyL900d?KvSY7JeZXK_H8OB8!kiJ-=kVphdlaX8o5KF29(g zpoyb^s^fnane3gQ&7FYmosbV~H$QBz9&C>sY@cmp_n*k#Cd{a>8#JItGoa5yw)Io0 z|KA_xD`M~e#mc`$Vm(1HGs4s{{&ZkOxUKotwZr}v9i$crdII;^p{MClpy}IGi$?oj zh`i4g{enI(n;!8;ADQI<`j;lK|u<7*2enU#|GbMy8UVTdue*}Xa;s@dg5t7GcNXaCg!eTZmXtltKs&jCikdef32qfFIe7=A;gv<#EwJEmPG7YGy1^gEgQ&@yvvb| z@&rz9kLj|AIbxQHe|?Ab7R1aMQO6nLz!`Jf;@fq@{xK1x)em|L@VTL<+g6~9 zc>1)j+>)r=F|XWS`Q+BaTNDe`0|vsd*)ccSQa9OgyV#Pu*s(v_(m&eqAzb}NxMqmC zqKLWXki8<2y=IxbqM5wrp}!)czhRyrRUbAjq(QaPz@?GTOv^V1u3bC z5dBb;0x5q5I!Y8MiyA4@^|J0O3!o8ODvIlt)s_~QmX@@d7Z-NQ)6T2l%`5ZHtAevC z5wohGuqrdNs=_oVQ8%dIG$?a7sQz?PB6m{3a8hP>Qbo8|qQ6%mxL4-8U;G9)_Zw~j z5pJFVZt+*t9EDfe^oz`Z*>)i;mjt zj*3l=nl6s2kB+(scXBazYO;4qlXqJ5cM4T^8a8(-mv=e@chhmW%M7%uJ@UBo)41!5 zxU)65t9H1H*SMQG9DZNUohaO430!Fj+(C*jibXdjGUqHGYhUse$5}mCS;J{rAoZ;A z<*Yu=_aFz(rdy7xTh1<+=D#p4)e&DB@-5Ah&Hp4@>PMT)N1r8ATp(2MR4ezYw3n5& z=I6E6S+!<2o0BctqEB11Puu)(TH|oq!oC1B8ErwDtx1|~QLC+4t8D??tqI(15pAs* zZEYbQttlRDF|VyTuO7ZX-D7`xgoe1MhIj;uxhHnroBAAH@(uubCw6&z_+0bIpT$1+ zhO>7{vJZ|wmYLroOx%-AzT_U=vkyJ|eC};N)?qq^BHlwj?{sx`3Um&-I@YM$XUf`F zEZP@7pLDBk-EFQ!KM$oh&S*DItTrz2HjcG7&UrUZy*4hv0Y^fBGh)CA5O9G4I93Fl zGXqW?0GBYGN0Oaq)SV|5ofkNr$C{nz+?}T$otHnokHoys$h}WYye}}kk5#?T*}YF) zye|R833bNuq5gsp z%9Z0lg%S~}k>g4H^|{+RlJfMim-&p2?pMtG_>v6VA)%K+X>${wOln4E zKOnrmnt$zlWykRFbH9%av#I$8_|~>oAhV5?+2f$r%h~RmV*9;ni?!X)W{Xy+lNZiIhRD2U}sQ+K<-o_ZG|=KRiUDTo3$%oDevz zqb-b!Eds*TuP%SxKAWwkEAA)Wx9=aneEj+PbhoOm*q^xHz(1fq{eAj;wz?(|M(8GU zl9kn~Um$(P7TV8G?ByJ9dt}Cbrl>P&IXmqaLTD~3b5>eko1C?la-tGRm!Zq3vUYv( z;A~~ftdwtXQp}(x7hyYo&+oV;)R8%)420t37i8~iwCkT%?#EhOi&8s~2HV8irAn?e zxwp>kR5Vg0Vd@rApYvAI_&;jQ8UH)Cpaqy3<@X<%k1NIB%gMY_hzfLxCT4!E#W@ZW`Nf6WzmXLt6ER(^!CW zPUAQpnPb5ThrD>rg6GYUCSa({BD9b!|qBPMQ?x%CB&$GV$z~HWGG#J0BH7B2O z)vRk@N78D@M>xDqdrQ!>?vC`e@iP(7>*@9H_aE|K@}KhU9=I;|Fr^g4S#Gl9DZ4I@ zGT9AeoA1VcWrK_HHF~rJ0KRjhsfBaKtqf&Lv;GF+a8^J6P)doyReOwu{>LG)>)fWS zQ(>c}B}9qGJHoE9P=VDXJ)m$=T$Hgv!MU*oIk>L8F3VDC2U>4Lw_H81FCXWiZ5U&( zM!)Ae1j=tzUR`Zf2#YSFf;|#yI;`1%av?sc8V@CuKq$A@6gkqCh|*Z-l;*L zKa60QBFd!ReoZhRl+5b#C`DjTG2`S-n0Ew`9X`%F#e|sL80qZxX=5W)lG5B$4kcmI z72pjH-hl-EoeTWKm@$ZmnTGLLvxH0S%F?W!O_e^Q3{XcI;mz{Wj6xwQ$X?ebqqO%naef6YA~a z%ZIlWg3s*=Z<8@x!m~M#6m3!xbaAX8Igpg8Qwk%!TRI3NW4D@s2#9gTG_ZEj@SJn$ z%W8Z{h1R(hW!dG9*h*mYl-n`f)W=mv!v`HV8<%(zK6R{Y*NGsH4Yr%vtzW}o0c*7I zpO)=1wtLOiq}X>Bc6K3&lbj8-x4rroEOZ)W=cOI~+OCwAr=w&fVN1*G2Ni5xD{QKo zGiWqwaCa8Na&^)KYGLs<0~o&Oi=Jgso#>_?c#vX@usPdF2Ry2edD~dt$th$vu%tn^ z>F3U{T`1woBhj75(HqWUo6w84_#G$#kLvrLa;nE@r&@h{U!q)F+QiZH@UA(j;@sKQ zoqxR5NSZ{THTNFdE?cSgZAlY0N6NgPC=!zUR5qT4j*r%g=Nz)!m+{tNJSCMj0=UZf z*FPN=h4IT7fq^ol8P1+dRpg&y-dcFh?c8UsB6zB+kT%$pO%$0ZH^1)dzURiu2~&{O z|4vjx9sh+SX2^N)9h9M%$SIPhh#HgUiVDh?;vJdHcg5d7lsAka@<3fK8UlzsP}a)w zUWN6M!{=~#?))bc?aKkS^DC72_gChn^G81tq8LA}z^2Jf=nyecOehc0O(i0-p`kSZzfHCaM0_GB zbFKV(6SwPQ1AlXg&A?IaiTM6;DzKac{x+DS579Lo%oJKi=KN+lNDkcym+c$v4*!5= z9A1K86#bNO?3}5xPBjR>4)#G@CI8#Mf`_b*5xPB(K-f;DU`N-GV$1s(`%fv&o76XpLT-bZIhLo0Bgl+# zrLoYYmIg6pH)~-_?@3@THR;WzCyJ%EnU{UV$z>fG$SCZ@Xj3W)DcNs&>^-e2|Fcq2 z*-w#3Z1)zVVisL(tT2BbR;+$G2otpWvR0OFR4_b@i=zzqxwVmoLy@AVq2R@}aFX8q zimUoM{bw>M>`mR?`-%5ZpnnAg5(zTq0-%k!@}*21O5^R>Tc(Sfbo8LRvg?h7fk&?bf$%UW-)qM;|DC8~_~RAigYmuT}i zk4YJ>*ALx}N7VR~~clC@qbn z4uz`s+0xm3kC}Kfvi>%F`|a&*?BY|MpMnGxsn$!%lHhaD`TlLlPHB5Xr@dye*5w@Y z)i*Ip4mnWpYA&Yo;=tf>>`p>J5Qju%2$>@CJgQ^sOf8zdr)Y2Ddq1Dv=g-u8P$n+P zFGR4g?wg)x0py7uEzY#2_088(=UVIz?mab=cW4&jOoMiA9udF9<5t_dOMZ-mewhhw4ALry=##H^+<=^o zR0f3p;SOeL`Qa6eI{jksYGI>P4^dA`8VS-ltmI^ zoC&e=b*&n-MK2=`g6!0mUaHFV5qp4I3l)wBV#L0u>p}IH{D5mFf=b7TD17J~NE7dM zAZ1Wge-ZAI3*s6(Om` zpQA!4)ap%?OtpV;5(tLLVAx0gZy8FFPJe_{iZLb=+ME$s{oi6sAZ5z`yN$3yeBBJG z)N>$Z4g&})`J_@MiD4h5(6cvDHuVNd5uiUpF2yJdN-IyTDMkMOR{u|*uePDWRLvT! zG|ZS&O!YLhVxzNErVtvW72)U(mkA^PxrxWSyT|4&6)A5(}C{3vcRr<$Tv zIi)wEOa2mF&AVU2=&Xh2&%$+w4iD=~04uabi2gYP-BxgUYhY!JZfd8yw}XYl>CFD| zok_y&>>~RM8MCkR6eM*<1=6(r6E@zX+@ zTH!7gSR^bmRv%?*Ep@_^6Gg?;T<_eyJV#N_vLnLmsq58r8~A|?V9|l~m=Pega{CY; z4)i73YHq!hgxcw`5HfRGw#-=&)cF2E??D61YE`Gb(eB~8TrzoG^j<`?-(AFn9nrJD zpRCk_U13eDQT)IOt}K}@#SJ;R?gO6ngzoB67My^qYy472S099r3H`k{k$U=>msl4( z_>0rS^hT9gjLbtjzPZ_S(~@X5@GYnjrfEt{+uB5YBh{(CuH0sA!`( zmw^O8EP0w4crT6%HEg3G$K;5H_vX}#LC^{f#;iKs z!o#*fD*}f0{`ogLnfzrpZn=&o<``!ke-5to+m*-T_(w0U+dqf%mSTm+tGP}ZtNnHO z;MQUeyn?II2kycxc=DB(A}t*l`~S@gv~>L3=hR>iz0rboCBBGuc)w_#E?K7{BOk?V z4bnNkcl~Ddm$p9OVG6?0moAt32)oq}UoggYVQFQ?zMiK7&{_3$6@H4;5u7&=U*K`~ z7Vd@pXtRFm-Syq}tLybU;wHjZFYM=FOxgLt8i*B5&&?BB&~@^TtE63f0mp^{t_@{$ z6RHV#MZAhg#Fy$A$ARtGc51*Q+M&C*(Dq+mmbd+Ht$ZaRK|S30?sqg;>lT|kVH3NO z?GC7&!6EtjYbX4NJ(@nj2trWW0v4Z;#VXqb{1)|uD|q!GDuJ!g+P~xZb<&K=v*XJL zu2Z~=v+`oMU9bEb~^kf?GBOll;imItYwn9Tv}Cu8xiH2lb!7zWxJn_LH}%2ZhW zMaI&HXkX^k#?hKh;BMZn%jX^`~yl3?{%a5RQ%|KCZDRdeCy+FitzB{Jo3%fQ|tqnNPJA~N1=ROhkt8s z0K~S1oZz_TTTd*nVvVQ^&a)cd1{8)#xU{m+xYr3)bX|zM-e|g-N=XqZwih%ye4;8e z`a_n=isnLd&?sjVHF;&KM*e9g`dR>}drDz$2?J<5l{1!Clb4aqOQkX5pzrH31Uv9G z)xI8~?}`D3*gU)Sa6%9JC8}3*)HH|)@?Pe1aoG2H10&e(55Envoq`nmA$Z3|5-M%O zIi^s)_L)@tncc7qkJ_v73{xH?ds%dRPlT|!!OLT6R9=~CceG1AC6~ci2VF#V7oa?a z_4=g9RCC!~EZW5Yk#7=`igN%jr{DsTD3{w+0F+BrVV^Q3El@}yc7TIL~hR$L%thDZR#z@8!mBDXkv^&w9yRFEt zt5sJ&Xn^HfYv|zCeFBdwYQ*|?z$kEMTNwC}0nAt9H9=z8h-IZ@&9R8u1tOb>XNx#p zF@H@{)3`2?5AL|L`cA^K;$?XdBxUJXMNJE9kf;9$ z;V;U&XX#u;4>q9JH2n^>DddV^&GXHc{i)1Uj`bZcs=ltGe$6N^rbaS)+IAQQm>A;M z+8^&$q`#U=&}64Q*lHnXKi~Y&D|vo-EBQaPy>oDG&9>;Btk||~KXJ0+tk||~W5p}B zZD+-{y<*$8jhpw~`|P{Vsa^L}eO2EdPtBfV^c+2VJl$Qh`8$gpHjI6?63HqSSrFDi ze=Z!Bjt#Ve$|@aBCw>(ESZ&D2Hkwppf!Fn%h1mTg_UjhGSdC!Rk;;d1q3bLn}LUG?JNv-9@umZm99z?<(YACk4N$Zy^c z^}~|Hd`KGmg?ZU}KgGSJ+`_w+t`q6%8l zySi@I>rH1&zvh*X zW@o$!Ki@M=qpEmpqV^wuWuduep>vYdKKO|KCTxr(4x7+TKWjC&ph%blSYC2PVWe5( zpekexlId`>QJoQ)BU9T}rvXX}XNb|v<3$CDt;nd61aLqV{D|dCA(Z5mBk)k!#0yn! zLbaNGIc7j0JgCq8X5yb&P79PkL)AYYKi@u04lc8o@AIT`X!8J&O}`#Sp$fq$)JaZ} z1xy0h_FpU=l!*ta2ByHTB1&QFJCmmcoAY$0L514xz+AA*F!%(*{T@Dkm@!Rla0a7; zoLAI+1!Xb>!~NL4`=Ntao59k7sy>~(Mja;XO_|HF2KsoTXN@4(7L@Mt0B9%8I0*FkJ%zh3y z`}h)Yg}}?_DNn>hga#NA*v8-Xc@sP-;dnAVDZgWxi##fp%{pM z9Z`BWrN5a6+d~N}Vku7~uAvDQ zmAi#AC4?xhmr{n)p3 z2UQm^fKT#bg09jc0@}XmotCbOcN|6nL8}(j*SYi-LP5<=~<3T8i~`g5j%#cyPhA0$Y8;zqVrpAU0*QD=dz z7$7^+N_slaqFIsvO4F5az4PV3o6T~Qp$VG#2chZbQci#3SYuI^Bl;fPVyvWif4qVH zA>Ll7JGN^r?0Vj!X`$1rje6Nd_wJ3Fk~}c;^G2yLV`s5I`cse{RW{HI&Ev~=(}LDK znV_t8ecu=G26_AX;+SOIYL{>u0{s{pOmXo2P+UHb8DGAzWT@@z8kqy%9Z!mg0g(`D zLK5^_#v#NY%_`orR!e?>qf2T30j_8Ai|mBQH_lMd!+I{GOveRHyusY}4B|gxp`#h! z+Cs;un9mLp@}sG=okx4gjs2?j0)}vxcLD3mTYzt&Fz{gp8GXm(k<^{ZJCxC)60V^SX0)BGmN$c8dc&d5{)e3umgV5^-ez7 z<XgYcFNT$oFndzG71_fTF z8sy>~!7m7HKP#16qgBoe5jn9B)d^>(HkgWYe40$WE-y{7viyO*$hG-Y?NiIb9&&tu zB_cn^Wi@{pcFUy=JIXX_5`Ja-85!x`>ac9dv&){wD{$+no{f}%VricA>euy{)a6#? zsy-=g&wRU(4*96@!Lqw1AP^v(>hDtji3$z)7Zv&+karG_zscl(Gu{P-q$Si<|G{|w zZ+Q2=S|7QCC zGv1x;-)#Kvcz2G!{QPft_y6JA|026HvHuNtXX5Y`HK+G@;4|R@VAcR3lz`7Lim-?UoiQ{lU7Ox-?QKfRK>f-^Qou~NXx&FOFV`o_` zxbNl7sIBR#pEg0Q1*r|0Hn7rt>vR2;PN(%4qUFaY?j(;DuNHS_RxMI2_klJL4B{!D z`j)d+=nqa7K{V$)pW^@{E-yn_UG)}2Z+C(rf)nvcT0QeoYztmK&(gugGKzz?8n5Xk z4|WDm?%T!dmWY1hA)@*@A)#5dc_V5s5(cQV_*&8?*^^kCk9ot;8cR(d)xn0LMqbD~ zLTxHofl0!zS+79>qN8tIoMBTV(^yo95O@N}34T$88NE%44sr*SNm0VEy{X?!2TiAX zkb;?^jBy>29sl~h0U;Ao#><(Aa3~P25jNrEXb7?f%Rprk18MUw<@AG#fQ||*#q}nE zD$$gne?#@#66gu=g#bhNhL6ev=_YqY_?MvD1+CFjNBQuO(5Yt$xmvUzJeBuGbu+SN z+R@xKRdaU1+~W;#mywyfp>w0^tDPx(o5cE0?F{F?{!LjqX+kCjL1_jVTL)`>D+VC} zLMD1f23a{m6MZX3V+KWOeMieLrHwIzq5j`00dd8D>TK=)8BlV!GiDHRbNZp^^i>iV z6a@&K9Gt((0-Ujpk*$FR94F(y(vx#AclnA#$jS6q`C^dLcXX1rH8M9bH#VXa=3-`K zQOsoJpMs^BDMhdEbGxXO}Ulw_I7=&zXob=6Yj2%>r9URSVZ3sCT6l|Ss zjGP?I?fy%|#LOV%V65+C`>#k}5&>~(V<&xKeJ6cFPUgQ~LO@(jSoEJS_LrQAkdx&< zDwqj5|Iu>%&nH+2Isak<$7;doi43(7*k%97DV5UJe3C_m#tj_4#Tb)C+)Hp-w z;O^0_$YoNQmq&QZPZOpi9oM2s%O5qT*DhpC7iS^D@;$~pbWn~x zAv<$%A{5@)Ow#pW*@-oM;~Rp|@Z~z!#;3XVr!_35ZSM2l?NHq>7psH7cT(|}?&IC_ zJ9tz?%4du@6_Vh^M<`?tj_9@f3Vhm!C#OzYJBEyvknyT@6G<9UV8n)~WJ0J8;6Q}4 zS0~%tdM^mc5I!!X+jH}FikB;qtw+?Nvi_hZsr14paUS7NTPoYJaE&~jHme%WA?T=l*&v0U$HDDM8KvD|vS)o1(gs+R+ z#Ufl^?~`Bc)Wz2qnNwR^r@-`v{TUbMFP+^?^%6t=YxbbWkj zS6x5dU;l)Y_OWX(;;27A-mLrhyxf0o@_lcA-Ar%uR=a$e2wB>`c^Gny{yJeenBDac z*MsY3=ll7^&FgDZ*OGzh7e;h~#d@NC6}@g(j4!G@isbih$-G9Uw$&}{G7n3d>F@zo zt$QUa+c;KQM()T1hv!7hJ}lO!8PO`+a3kD;wW0B9PHE!2#^Lg^Wnhj9lel>)Z6vAU z@9M#q5X)o2K6;JeYMSzSY|&}K0Qq_w&t{>qC6Pan`DV)!6Eh2#BBzbF!RBXzWk0Fm z2>SpUW){Zud3&ROW^W3$L}*mh89)j;>*If_eiuX|^&spM)o4^8G;UeY*m?rNViPUc z$7V7lp(BAsg*QvTk(w3^imZn&+9E!b05Jkb*Lvnx_$5O<`WQ3fzK!!`O3S^Jd}M{Y zmpslbr>DD{5}d1zc9EHFMv%PRF#nC%M8k}6Y6)aNR@@=m2=W;C5J-A!A`!y~G)ycm zq@tbSea}-o=~n9*Qfi6fo(Sf7MF+=BTUJpgl-h{q!6Bxx_@HUk(9)x}qG{D3$6ry`@6DaFFlVSc zv4_NX+2Ci{3M;y_&gi~YeZL;ou02$LiY)j@aj9uwY13CdPJEab5S)sS>9GEGlGHHq zHs6vqZ12l`bddoJUeK<_IS>Upd{`a(h_<5rDebbZ&+>X+vvC-s=JQI zx9X~PdT2b3t>v`TJP<7X5M1J*pXjb|m@dA*Mz*tJ=-0ficvUN)-6l<_vIT#wD^2dZ z)8E{=Q0$8f0sbJEW$Eg=+If~Gd`(|^H81(a*h{gmTX!ue?Flt;(F!RvfgV6-5OZK7 zn-5~_MYdT*b&a&Vczyyw_+4h|!}yTb*azzMA&R9c&UKY0~7~mt`G9a@C{MlfA`Bk+Lvul&eB<#JHkiDb@OYL%Y4HX>VUGbJPe!Gj-YD z(ibUJFo{(DkXTOGXj$69t0$&w@s_;`3y@!i6+eCg1|s;Zx(uQCR7B{v>~)5-(U9vN zxGKHvJ4kg#MNrVw&)U|-{~SH=+W06&R*+7u_@jDiM+jUpofPFv$2qbM)_&g$B>Ikv zbx3O@j$ZvOD1hBMMe^IiS5v@O~;3inPGB@I`uJk>5p53dtr2>$MC}qYrh*r z-=5on%SwjxbvCBn!dvO0D=4b)sHkT$mJo^)IC5VOTi4p zDkQ!$Nh3o@`OFgxQS0qeJ+tYLM$gg<^i7DKTPt{F*in`O#fAv_{NIXJjI zYjd)!^Gp>thlgCEUDHKO!*-rWy7`)0^<=z7m_Ed_Sw%i_ljlrCU03`YV#-m}f&!D{ zI9!_J&-*WK9V@V_s8u+u(||_gjIH^L>zZSGxSZpi#3y#GoJU7&#V77h+oC=1pE%lxJ%S=4Q{s~az{HH!WSP(<)^EM9 z3Qnu( z`sGZF3K>$(NROOmElwBkKNA^~DFzqiUBr#DOjVvZ53Uz%L5;aPIy@1~@*C5iTV?_|G^IVur zI5f#`iH&{saYnGh4_CfsdYLc$PA$iHGO|qDP{e-UYD5~Ne$_i^)ok}seu61HfFVZFq z8I7X_otTVWEXA#Bi5q>wS#M-GVjr(~U+{S59>7=iiLdEk)eQ_aPY~=-!(TEJq zNNNcS-;@4NZ`hFnleVO4HoM}Q^NW3yvS|b@Dpm`yzy(xQMInn zi^`d*Ge{$Y+-EP~p`u>o^NnT4i)sEX{;n1c?Z{f|z_=KB*#d!^APj?kZ#4%M(N0XK zay>;DYSW6uQ{p(^ETP@liTZaNyl=?V-eCe~hw-&aA#pKJkMPB}9T&sPsz)yHhiO$K zCi^9DDu`*e7mV{965p4$~9JnHF6d)(4DoJ+sr^6!LhB147 z&|9{Zvx#BWkbB;5O^=doG$yL_QDX})s)GgGO^BOKugL@o{)G~;m4V)P+qd~u6bau~ z;;Y#e_k~v>I%dQkTU}O9dF|yX|~+;k#(M`pHo28aly)^42jwG`2F&gXO-dOJ1*XX z0cTu~He*?J5OJ2H0CPQNST+!YIzc zq8k(&aspH&b}XT&HEXagV8(bW8wI4B+$Lj76tP|&)2R>fzOsC*bWC`x|Go5WP6U_> z7Gw@SN}k3_|m8&8%Nqf9Ok6jRCh=yV$_PW)`d^%Iw5 z5vl}=%SzNnMl+%fYfEr{i|G%(R4sCTYUlv^ zTljWe%ehr)0~Sb_>AK&pRn*YdI{_Z2C9}u4xrpei^W3@Qkj~#RsLO%#z2|^pi%<|` z*LK+m%F93JE^Ll?9pB;K?>-18XHve_yg9Z^n7L@&8~PHgZq7S?9j)VPfOkarlm!a+ zI^OadJP$^c&t3m`4&b- zvq6h&^UFBdpzyjPNF=?x$r{coJT$)3pk-}AV~)O!QH%mpl5IwMFq|8fMn#ddLOvS5 z9o?K6=eZoPn|OQ0lzgvNv9jKF;0{XqDbd|Le~l-3>o~a?hs8eLW4OU}*|rRJ$+?df z=)KGSDphAoK4K%25^9!EUADHe278HaWchw)h2J3!ZzxD5oSV$Snu? zie<=<>B!$Zkvu(pnnZ5n#xVqc{IVM}cAPAUB zKp>a1IsIfFqNi}huTqZ70M0#6PZzGh}s2?2aLDl%YlsO6?P07^^&&Y zW8KXT=!`8tjL1xmmj}rV)ngtX2fg^N+x1Z^jOk*YgY0oRw?7ySv*>-~871k2rLJxMevZG4>7Kqz=&P=$P?5cr z+#}-m8b=4Kkx}!w3K^~OR|Q_fk@6{y1^y|c#v93OaztMiH@tmzFF~4FC zf3-zDGa@)RdSWc|zN`w!@vw!QGh@`hKxE<-* zu{U_TEIQ(W=EQ2D_B*(27sxpYm!Rs=g_rM+*Vek*NE1`aT}{{8rVu7}&vz@w8EwsWXLoKZBeA>f<7(~lOyu!AR>grwKNEZg)@F01p_ir|{^7aZ?|tW)QBCX7?_`nV+LJVa_2syaP2?`a^3S&=&@Y zn)ADhbwt~9m?s@rG9AFLrR(cJx;P?MtL;r#KYv>{pYFYP=R5;bsfXgf<6~J;7WQG}XCcDUV6l5{7PB|*DeT{t-cJiDb zle44YYm&i#3<|5gZx;-Mja538U`I@>;VU5q(PNb%k!OG^POnTaXJfBIOh$DyOFP0* zs`f$qW2i+%PU(o#e6OCv_&(9TO0#&zYK0`@SXx8yE|~at1u-Ahi0e8=eDZ?y+@A>A zcx6zHwzfQ`KXDQpXIB34xK8~K7CH%7xYT8(0xmIVL|q*oUUY^hyA|&w6S-)K*~s+# zJ5wJaXbx@N{#WHOM|-JdH{;B7(vJzm?s@EMVkJaOch^l<#BUZ1=)z3QfdaCT-fUSs z2tPg+pWRyG!VV&a!oELEs0intqotb!o!oS+EZl`xlDh~s#ouzzy+GAibJ*y&wz;is zuE+|?=D57>cH9l4Ei^m;Cod4JjPwGd)>75_BbDU#|Z zydt>x{Z6M`2=htfbY@^qc~Cefg=lTrXl-iT#@(Ak$_#+bTz@{DgoVr{ZqB~^IeE<4 zrQTk*;IZgsuRCukz^o6IC*=Mufi)zq%`lPg!#NH=^wY=YO@`O&y|Sir2z^bj)aRpZ zc5a6CxriPxL^o@2<_*88E|+KZ5u|<0WXQvQK6yuI>>yKMYW5ePO?0;r)0Xa2H(Npw9Hb!NQ?p(}p)$O+dN$QF7}*(K#;D>@ zBZD-UQ4es{3=fcFP-~8Nm+JzouGFKpSEas?Pd_ebiVX~PT1FS#*lhFjt>91&XOqiL z#{GTnQzPF93TlLl3m z*5zSB=U2ShP(-Igq8c_J>+|*V(1|TS2Arp$4G14f9g@cVO;YXa3%TGN*Gv*M5xa5zXD#T7{ zILmEN6A#A}LHNbn#!Mzo0XnLXRpp0JWLF|fsUbQQ(Z_*I!e7vUJhWXZY`UWG8!Fj+ z8-bTvk6A%YN(I~JAV>usSiROtO&*{fQ~HNMzA~ROMD*;HE5|;83-4W&Q*m(sHO(q5 z#5pNhY?hMR4SRsH=*o9zMxGv!3u$qYKy$l3mj)z$F4-8h_*)<5v<{hVyhLBZo~0+d zo7D(~QG58VyR~kDCXE{i41ZvG@B5W3{q(!*Sgy!QJ-ktx>n0zoati6@0mp%Vn2{U8 zcu3mWGeF2EUUg4He^lyg8AmdIkQmXTxlx{?*IrO06@;)1t`RUbf=G3-oMm2W0S4wY zOp0P8srxWCH?--pUmsg4?bj-pmc#Be46g%)+K_M-_I^V|rrx#XAF!x|b09}qk;kA0 zFB2EW75%JY@kZFB?@m|YEu_1MFKsS2AGnlhykwsbNtD=f(RmDcteV(J`a&)WW1x9h z1+j)t4=c2|c05oJ4}A7^q{8x$CENzE!%vF7)38DGCQjJyTM;?#<|B_d=MVY5Jsw3gdGI{Iu`qq?Lg>ZqCJagY7b_1~(qMaoSR4p@0bI>$DI2=hI?N2}2` z9cd8nK`vVHB1!95bjK&ue4)K@ODojL7cwe{gr?;$8cEoU1`>=6a(rr)-e^LsQf+&_kSW`qX*FSYZ~R_&Lf#Fd zl|*@wlw_U1SW+H0W>J7LPiHVbFU^O1Ss0o4F2TF>v#IM{6zXh&Ci5CtUa@?QXTe=) zBef`Mk|uTLZd;8ekvYkuo1|sDklc6zgDM>FG{~*89z-G_pj=@A8!Hqvm77oIqS!Ad znZAfVID5UqBVSt@HtjgyU&L^>lY!i#5d5cvvTeevgH4K?)80Y^onWcTn&edV8V1Aw z0l2fWbjlg}qbZa}zEj;z0p$RH`H_UdqY^`s10jGUiGV&>qu_<6rR;X~JoTpKJLii{PI5&2H znSgWag&CwNTfIgxMsZRu_8jGN<)E-FqpG`^ktj2z&92Z{-*;ipE~_NF#iv?H{*jZo z#^#E%yR%=AdQw|4`IF4~3WaODXj927Z$aEyx(TYK-^LJNqfr?4(`zL8!XaRQL+j_P z?ZK~4`;|4>&vB2$Mv6aYTbl+A7nFH!)dm5xOw4w-6~Tz3&R|9LZ?u*?_9O4xpsJ(otb8By$~M)sxt(3FIjOw_ z;Yz5k&|?sFg%i9nOhsDNp#|B}=$o8y=|L;UQ5;ewp$?q5#yUBw41%g8*i(HDVBRfU zh%i>Uhd8<6pzOEVyJI~orMvNc{Lw8kei(td1ZD-S--s2NlHcUxqQM~nV^+?mTe(&; z4?`xi2+@UB<+5~^?ZXp@=RtD*wficn!XZF8)CCr_1*0g<+os#n(vL}Ya9#C_nN{qcnB}i!--fx7Xr?pvc7bnE-i`8^QYqdctj4+bU-atBlf{bCCC%JI{ z8%!~_lukDZQoL~W7v=c9QFj(DIRa>nQzZxOU|uq&fyToAgzK70 zGve3Y;UP6Yr5QR3NE0!`XX(C~8Te`$JHOO6E8g+Ts(AZks3EB;vh)u@)p6VS?M}16 z6LR9Bj9Z48Ap8g^KKmVns%Hvw0b53&uK}w?n-7sC-d-{x7i4n@FSJ>qs7)r4UFyD&0tNPyAr*cY2eEo+w#p>!VwFJSp$3KB1 zOf)JHLcaC6@Ul~Ivctbs`G!B3Rw;K3t+AT!}~zT4Lm9Z6z-&#TY6_$ zCbA#6!AA`o52Od8&La$ID9ad?Ly1YhXjw+Q{*nmf@ntQd6OWHEg)-GtW2}}NA+-0CQkTs8FSbzR<^LC+)B4b*m=awCv>Pzb{ z@=etuAu1oUuFz~|3h+#|A*2kC9kfw-XoR_2r)paMSz}~-7mHE`7JX^sUgx&Rq0vdy z)KnAd%PY*wG3lj8m|+8XTfNk|OlFHFwJJ?NPjW&3KGh+sBeT6}ut>g6}@f!BBMV6{VA)pp%W*BGGy zXZi}hWx}AmsKdVAH@AqLTNA&=TW6fI8#Or&W*|A_8Kf8cJW`0tqb6dA*oVbT5Jw)r zHh~rGLlx09^tDahMHRfeLtFoL?@SPxwb8yc{>o4WhmQ4*-*%C?G{x)wx|u4ZOGYhd zUAWgoTgKX+bFbAlYQ%$okXh3|w2*e*9iTEA^2B}e7i&RXym{(6kEGj+jy$LO8F!-Z zMRv(F0&t+B87Mmq1h$ynj5i;&uu@y>+=ySiYaeH#F^9*G;tS2d>JY5PFdC#p;U)#j z7N{0Y+%|?ZVig`w?dJ1LFg38+eUa5XDlJi^1mHx=^O|djt?VrMGIgpF4l#gmhINu;Dthu>eWiv`f=lgupn{tCr~F zgV6;bK}KqOzi9y4tK*5VN<3S5K=`wS71}+fOVbhoHE*c)>WS6H<7YfpXW@ko4A%@v72G{fE~$mh zGNPHt+(Z-^t7zYXM(}AMBaxT&8(Hm2rm8KXMt&9E9NH=T0qUV%EJcfh1!h&YS+?ku zJ6jqO9rd2DztD&$iPAM+P8h5vbU>5xp^Bp@V=iq`lwX_JC(%-2#HF3gCo`n(3THpD-9H{rmwA!sv`=OsxqKVx2Qh;#(e63^Ky>4>G- zYyyqQsoM6sc|lk>j7|wDPtWt_wdVthggx#7)ydKX$2t>F*GePE%gN8+o6;QhYd7O= z+8|bP3^_u@50o{r6q-OFkA5)+MA#*M#+E*s;%pO8Dox#dNoZpwYDx zmu#;)39I9&W#cI3tnv%ZluQH@zoo+;21S&OihQ>v|1cJwv0OmrrW%~qQh6u47AwRl zn`1ddU3bJAbx?dIDr&+WjSkj`yCf>22L*8pcxNi=duA^a0p4EzoWt2VjD&LyJ;or_ z4n9Dbrr97pe+ToSenO-}4L8bad&fyb$}atKd1b;P>D(%X<5d((y%QhDPaG|y0N3eDx8@xJZge6sGvtoOfV_+^!@7Np^3{1c-evP zSg5S6?6*uN7usV8nr@nUi4Iwzkz3MA-5pNs&fC?uDr2~n%Hk>rN-h-8GY(71(7>t08 z`NyA`5ldG44Wn#A4go&O*|Kb{r9YNkic~ioek|#)QWRqUR-GU>kWV-l(r`h0S3Fsp z0YZJ|>ABPNEu&`ee{;HZ6X@E+cy3#i(TKoCNZ4%djsg~w%}xF8{+mjz#znxv?Up=u zh&z1X;siFWSLSN|WD;=$0KiAvj9Lz^n4nQCg64dftcHY*no47n7NllEscp z_Hc*-3`=7()T}e=;{En2zasXo;BJdc_10sBqHB-yt@jL$W+xA8V(#e#IAFNH-=RZw zrB@RYuvATv{79nQ(@bPNn3Sfj@LXCY&i&KFfg3b`AFqFzwfdsbf|1`jfdDOt+{}fw z%EOECZRbXu!&Z2LlkPET$=FpJLo%QZu^Bx+U28W|@8bQqu_Uxcx>`5o?HkoSVj#YI zZYN3YnO=zni!k&&0gX)&FPe+=-nq3Aou`i0@HtjfbiRAQY@Gj~mp7a3bJ@+-RfCyQ ze}#63*O?NT76XF0DUC4Gtl&n>cRBdfh0t%5BmKZ`yy~+BFIvm9}qg6p<-n#c7Ld~UB`2(TA7^!=X)B5Yc1bSe@f zi4UN!n-q*SEj)<&{*U+*U{WwrF(dyY{%d^i8T|-xzUJ)OYjk8`s3pf3Y5xf&GvU zwN`=cq48(;mL%v3Ly5KC*jdz?vtGPn2Lo`kh7-;bK{>h;p18k2K zz^xS0g*6qB)I1B{VA{&q%pKic#@Ib(9`Gz1(`nr<&%GNo?hl!xM8w!QkNPV zwmBc&t_b>(&wQFAb?LCb5o}10gQDo~(9`EV`$XxX%LFq9%SEwc4eE@3d}>hXVOmL1 zGwrbAk=nUKJm5+6F^bot?xCJ!-Wg{9*aST^Ve#{m!a|@}TeW)6?IQIui%knKnRLbg z4Vd@2k|LzN{#Aod&HhH{fD$An#o;4`ApaxcYgvbkMpJ14&ss>al2eF2>Y?Qikejv+ zai-{aU~atU;>VV7>*O|rC*zV^kllNpDl)paw4a{LodL$Pyt*d@J`9P?GRx9wwrA^- zv|Yb^*^xn)dA-+Q`HUj%UDl+`-Uj-lVhFtye>TLPEEI{`$t#KI=|QAfY{e=Bj2q(GC6zqDa_1b zxwxv#Y@_!|RtnPL_vT*XtfTa0+udEp=AQY>Yml45qx=-h16Ehh=Onvp@9BV=ykGhz z6r>A!u}5G>BJ3TMc*YFZjs5#~7Qs8Z!Buxk{1cTPL*WpsN;ydL#O?0Jgir>}KW*v7 z0C7Cf82DI4MewOIJI{gWQOH^+LaGIF`cFmz)rpkFL{ZeGKe~u}pHq3ZN8|)2*8sgK zxphAZS)h~Rn5-fv*S(*elw4#=?>;NHH80~rYL&ytEkv`;Qlc!5*m@+RP)Y3m+&i>r zWr-;}n+B+BzGIA!DYR4X5|EvSHxnxG!4?M^^(n+Kzsn$(qQ?P<)8cT46kaO>&JxO^ z0juJ@*-i>GxaxIBYJ|6A`UiJuoUs-GiQm_}JFKxMy65-xwhIDM6S;oK&VgfB%Eys9tpwWg+Ox=QXjD@6+Dueq<(r$0*GWxJ5(mcW+S>h z!$n@hoxccKR+1iYOKsT#RY@+oHAjgC=ciaNnv*f&Vau-MVzX1H(sgZ}ckElUuV)AY zARXYZUJKrLXF@Oy@GoF%Co_o0Zc=9*+ji~pJ#LxMgKbKT07btkDKH@xG|2HeaKPb1 zPAc>-6AQfYwrO!MA(n>854nHD5M*gV8!u!K--Iz{21*#wlOqohNQDJAW=8z`21For z4ahiX#g!Z~VZ@p8GKd^YE;c4uC>0je*a2*m+bF@R8K$n(qd27OJMo3`Dp55&pIp4+ za%6+SZ?L?mGlV>{W%$}TAF`iN(}In;El-F{qt8NaV_luqEvl`h0O-d0B3%h&};MT4=-3o7U3~MVw9uGab=gcisiW)P}+0 zie!d6sbICp=z0DjN>SR4u=ay+GXPY?neZ*nNFvJ-ZJ9~8w@F92v4COY>G$f)(%e*& z6ASQ+SMkXxkBHNQUiLiGm{X(e+cKCfhXitfd2NgcW@UaU7cuVLBz;QNVR#~4J_G0D z3`Xr4810Fe{CW+7g(rWF3is2+`sEWL^13HTq^((V)G-&C(9i(O9W`Q9KKvXQg_Xrn z%VTRU&P}j!#Pk8O74F<^Ut|x^H}q|QC8rOZ<(xt=!GsSK{!T!Seh!=x+%q%c*gG#a z2ZX>--x~ax)iJh5*f)mZGJ2s!{@S#lBKj3;j437^b_&kAx+c5O55w}hjb5G)I;F6+ z{rd9!akb1FXCD4e~C<5}lPjX?Nb33~m{a9X{tetT)h zug(Cxb(7fDQGE1rdVtO((+d6sE47@9wGyk3UL;JCVe`6x|qf)HP>l!OK%CLp%%=7f2wY0$XeeHJ8}yPojC`*uxo-V#72@cKf% z!uwU%>u+K|G=QyuOXwYpbrGzJi$gLcZ#+uMgj?~&(T*sXf@FU~`8gt8JibyN*9MC+ zCU*C=g6Y#{Ax}K*6T)~)3t-NToWNVu^2>Xo;vu{NidpLS`^_6z-5*PT=sc3`$Cv8Q z^T{HRb_tZTqy+~Q-{~9s%i9XG6&*h_lwaD7VN>}tn5pEwlH5Y)54P0aG^rCi!H_JguWIjpKNzA{`vTr|paSpT z>MyJ&bYbi}-+%HrbG`O~_;S&9tvoz!XmFC~*S)DC9K4LT+64L( zuPWPn8c!B8*+QH8yAAM*jqF%7Kx5D=x)wIn1=v7lAK&o-{ z!EHP9we=SH`MS?iehTB$q^_v``4)jfpg&HwM$oc{_y><*1S#{96?TmbQ#P=c$2r`P4f2GRgJZhJ@qr) z@{lIctfX3W(O=f3SST=BujspEKw?Gaz-N)+esLx>Wc4&ZfCthCE-p*mp5PdwTcWOl zNBb~($jRc1^zKY^%H0Cp=`fK<2^)5<617o`ix^-3(s}ExO5cef?{4~qXU$5xkh0wd z`RL6rI++}pF|}>dGo3e~{}KLSPrQ360+TeKO0)MTpJ|SlcxRXB;Bx-* zr{bN7YSEfxRbpQ8Z=%{FY0gpP$Pcu3;P0X>v!wyb1N^fy5T-XkiQXRy30X~Q`&G-1 z;F`Pl;<>g@s;_o+pc<4S;ReC>{l6&O#=Wh?@MwYrfsS2p#V_T>qO;bIk&P9-ASWY} zzPmsVvl^zKL9jJ8*RmE*f5p9ZgRvN$`U6j_h0j5Natkyj zSBobuU8cN&|<{^Ogyzh(Vw=~ZA`47h5H9vzVl}Q{0t_w$yOZ3B8QQ?dsmGq&*US)n15?cbc zW)w#UtJt-LEK0G?V|lb1-6=0ciyZQ!cM^lgWkO=l)Ummjoegc=U(jA$@PGJQtS%%m6%|{Lq!dxsmUB%x zI8qDLXC91nfzz!Yo7c2))uV*<4DNg`WMU_?yGNP;Zs>pqpEI_iVo9d;&W-rCRxxZY zPiD7V^5@rNlko?2Qb0xhlTJ=?yVZHGS}-8$oiJJQoYuBs@bAl{S#dc>xSM&9h@r_Sgvm(07}F zfyFH^{&9fbRLG3U{3$$Y`Pon%5u&w2l-6FRvr zT?ODDhIDdU`+z`FCNfEPgKsW}ixRBzSR#XN?_$U;aYlv(aOi1Z6(=HC(r^^{OUT zAYdH@DJ9wzLX8ZcYc+L37aJazZp{E@-fK1YCi3Xrm=FsYD4=o&1EjqU>%zKw0yRf z2PxG7naM@7A4XL_c(X9Qs}2(LQCXlYC+pL&HVZf{?El&R>ock@mQeo4u%fH;5uwfr zf>2$19pJF6DLO(>>}Mu+K(!o4T2@eJ&lD*=*f|)3F}t!!y>F4CDoRo>$?YCVAOSm|#OP=|bq<^o~CM|(`b-*XnD^eeRi{M=)4X>ys4QaCD00ncro!v)OsQ(vUHC^apH5|gRdJ&}{41Y5Iq+XN}c8j17i-ss9}mKY+6J!TRa9 zgdg#d<6`iXVKoANzMSo$-!23t?->p%uSnn(AO|3Y;mMI2ew7g`G__{tH4hy;=) zN`ytYk2H*UB%!eS%dfh!vZK1v!g^mC7rxZ{v*WFAUpG7T=kaiwXFI#-qbo17&b;qc zhO(mol9(O@yUCbAE6+-mww5uxdr;sHp*6E!q}3BG^Um{= zHXZ_`B7|}4cC-Z)bt$cR$qLD~39{fuyhH(3&D8^RC8(MvZFxi-(0{)~D-g&u9&ASvz;~XfKik&A%(^Ni%W>r^*Vp<3_7Z=q4Pk?WUy9 zykb+w{cC1vtA6rbUg=FsR5`oGEZdLpQFeMTqzX?^s(G()wIQQo^b*H|^G4L~uBM|= z;PYPNTi)}5d4?8wf^Bj(;8r#NGB#O!?s?yLv&-ayHm45>Jv zUzi^2B<;@e2N8i18!u+~26=63{w+-^+G4C3lJHMrNGUWZEhkDlMFBAA9jz}#0aJ6d z7+Hs;h%c%hMshV?h|drlz5Ye8(hA!~@ujzL9^oc-E?e(~J(<$G_+I|icQFEv=;_d- zz)KPP4pw0973o5!-s|&fwBBoq`^K5A*9NG0&JNsi_JU)~TB1)o3QQ8KOHi4WMgN(Y zLa%3bH!mon=NzVj z0J)umF%;Buw;K95XlRInS+R{&4{UMsQ>q`y{#dYt89kST+0>huZm$$Sc4C*JWvVD#`V4HpaRZQ8bHPCCx&d=^B@d3(sY_4Y*|m=~{r^MM_uDAaU&7fCHV zC@%aDWg$TO!D?7y$M$B0DP0Ym5npWJYEp;dJ{L;p#<#;`CqUoG>9k_|6%d@ikRHoP zrM8v;Scqv8ySvYglz*K{_$pr8N?cXgeWEp@MU>`1E&>*vyc%%fjwdO75OtO3Lk7Jt z5%ns=V9|{wMIj=bOEF8zHa9(w&T zp(MUHodqQitn(%G{Pb0f_Nich8*wM$@>qi#r4yD9vGazqfNAN4#vcL&AeWn)3j|6) z_-hEVnP?R0GDZpekSJ1&!vTas_!(@)tgi5R%lvRVkF=MsAUjRK3b^9eV*%dYg){<1d4?1GJ{Uh2?%C;P&|PwF3c&u6~4dA;6#3 z`crbCYLkC?Sd@oE^P)KmMEaQ9ZoalHvLG@~IR)-v;1(mQKOT#2Y#{V}u?_}oPQw3A zhYokWe%RO>PJOT3hSOVOW2o2w{TKN5bs2_l2){0rJsuBxmyd_^uupaT(0iyY?H}Ya z9H$idEI58X8qAkD=1?zU{1lt}DM1Tcq-(r@)c{mR?2kfL0}1IlN=sObNgR@T8sWJ4 znYeF=EH|2M@h}|5b&8J$6lt&b29%{lum~L6SCmI$h*Lk}&0G7-i?V#VUvw(c1>)(w z4toKc!|K$kvaU>(zsGd3>eETg6#MpbfvmEKGS6b|XGf`{c~jwGG@BEKa0>G?fYtn! zfo8Rk23`> z7d&rKtt#R6fO-b=vH841Pfm$SIPx)+(e^-L<5_4c{ovrM(PExu2KE6h!ZS{;C@dtR zN31M_HWcH1>}$EOCIGjw<~R9k_fVgujA&kryfg=*`{r}!UbN#c0RE3J447*|^jluV7=K^89JOy(`byasqDO5{@)d9D7&~isR{F~N?K4M3Szqo( zL|Jzv0j&Aa*O!%#>2V+6!%Lmmdq;p-o5X@l5g|;M3^t04%}KkvD)QN z==J-!OyLG}j`rNj#Lp0B=0cd`afnSv=6WMs_7WnOV;S^#S`lT<$Ko# zEht{GY`RMl)r&0F86UGOx7F%F_2h*TtA9I@6W7S|)FE=yjGx*iO1_LR2-mKxbfs!= z>pjZ`Ll3r2GH+JCrByjFg!Ob^X})2)F6vt4H&W)U53e@9#r9uFP_*)F@GdX1-!j0-*@ZZReR*)3h#}DGaH#Cl4 zHkY*iw5{`hLdSbYzTr}3oh>obCWnSg_uL)w?vH+=OifQApXEEBl(N zclx98w1kTlnA5lpDGjqgif4CcBw%Z^AbHR$+_s2#s@Wuhd@a|l+kNr^Xl_yPu{+2x zVlR0ZE^KP(QYA9niUOY_uV?#8r`E&RbtPp8 zSIAN7k3~+}2IYzpm-%vYI+IS%Y^#(b;`!QX3rbhAK4nJ9N;p)rTVm(l!>J&#g2Zlu z*9Yg@1O>FiiVoe$QC;->Tt{s;{CfcqJfHbYz<})q2?rb#Bj+3JN=(EG3<&psH)PH# z8;=4-_cIM=gt7PR7-)m5^B~KTeSV~KK=@0^%l@5|bdklZ*Jf@Q7l-6I|9v{7wenj% zV|N?*``?k2aYk|#rrm3Be^c{v>^!ul!X@=&!S}v4r!XUjRU>)2t$c8`2<^n)-v)EMDgVT7Xw4I_L6l~#K;q9n~leVgqJ>a8kFscj-VD9_Pl=Zj| z)mH5IUIRTdd*#9HLJ{}g@0vN^m%AhEL?{$+42~62lzM(Av8UE0+8#!($-Szg$ zdE4V!ya`sedrzIS^eCNB2XED}sSR;$cpp)wZe-&d!C7IKm@gb05Yq_C6o>MV)hsm+ zF6L0_$&l2x@Q_d4mj1UJZDs#FgtZVX9A5YU!|o*DHQL_JkY_d%50uPoZG0YWx(LlY zmG50+Fon#9OE>)a&RI#hvsLdM+9iOWsY}ptwIsZGAwpOjgyFrz zQ5U&oL@u}nSr#|2_ta&37k|mCZppmtR7iFJXU=tQvvICx_=2ORrX32{={;&I!BAQJ zI`e)u$w@(SORoa_=U-Z>9z``UAlN=z3MJ$Bo)F|C8_iKD=C4FA^;8KKu(UfiUkS9t z5-Uo7P!ii0*3CKaPsy_{je zzVlxiEoCtv2JihF<}q5xw4?+ZP;4H^gsda>OACmO6HtDBUCbLh@pm?4_~`I>c)B)r z+)puorGtUgP@xXfYW(Y1)%8iUvflj8?4cu;Lmj4Xil%~Q zB7~`k(GMgbpV~CU-x;Sq32fqVYr&L6k}qal}dmnjFBXd>5nK&fx}fR0?{s{PF1hM$OruuoeFnXcFU6@+>PKf% zZcKgLesOAnVVa%4eI0@zw~DIqle|M zeOKiQ*p>#J+k!%F#SsmK!Ke`RSZpW2O}SG@zTq2G5$Ste>dR*?IMk{cIBg*TOH5)s zpNCT(y}KVv4#*7|4zHQ6r0UWH8jt`jz;+|dT3Bt=YhCzK+|r@|4GOPjre3tR0MfXJ zW;W7ozs0b?kVTD~gHC_U5^O;465S(W~mr#2ba&0j(F ztYl_fkc^KsPMv!jX16 zb4b~QWbpgGjR_uCKpbY3tB0vm1Jb%!)G~0{-~FN!z1GxD4$Il#1t@1aEj};3zNafb z1(3>;T!-Yc9Xx#8!tjbyhHggAmFtp+ZHYq1G!1l-^~~rkAUlg{=929s8)zo|WjShE zBz<(bB;yXLw)C+5JxJ!%+v*H$qGgPHy6wZH>yH2l)jwt9rTv)3Oxe5`vaq7C+6LhU z0bc~RCxCrdlIx&U*X_CMnhPFqQb(ZP2e(Chciq-w4S z-XF4Vi(DC@2eoIG61lQ?LW1I3p$qy8K?+U&HQ`IuE6Nf#J$&KI{Tp$LkE1Qf?@GwN z>afL^frhl3Svf{d-D$$wM7gyhDY9iTPI=E^%hhc+zkN%t`Tp&~5(A8!rzed{M1tc6$kG(2;z5R_~vz zGmTJf04z1S>T`qcd7;}Ft}UJLs06>Gpch9S>-i;m7;0nTfMd` z-@@kaq0L$zF+|l4&>E6{?KX%9y_8bJEm>T@OMhn@ym%z__(;)hszdeQHC@%qZP(=< z>0_-`yZkC!IMn2c#G7o)j~k*+!Lacf2V0VBP&?Gruk_mx>sA!_ofgUJSnZQk16QuF zN0t;E?3Tv)J|Wc)zg}(IK-cqk#YdSE4!)uh-neBzR?Dkz48)QsVYZ8vb|At0>qdD& zrg}R5wA(UjFw!Bk$)3<7G|s8Ij{xyUr`#6UY5Jf%YUXT@%9;vF##LiVgB5~H$LVp+ zaux?@r%Tsq3;Jkv@NI|}j?u2GI+FWJ{;R+A7X~@TP)9>>jxCSM8euc4%xF#xC5H3V zsIj07t6Dtq0TE$$jj)3FPS zZO#ci?Mz>vBQMBZ+`~b@EoaW(i2tUC8ST*W$Pb$XMvX$z78bOxcR``(IiS6V9oNVe`==thC%nXD zV}{l)u6U2b^bk13JZarE z9m+VCP!xsN(>0SYlsjPHf%tO2KvZL+HG#hFN*tiLVP#;}c$lYac__=>akNR1Z;$J! zT6(NaJZjZ;W0Kcxrwa0%)#|ZH$DFi5r4&2U0{&$%w1YY5jfF%ZUJ$k?<2B)YyBBbE z)*<~lk<8mjkHw$bh!hbapki|Pb)`<@LGnh6FTX(D;LDkKv&1p`2$|98L_X{LD|`1z z?rT)-r!CwxDN*m=>-184u#p%Nkc6$W??*lp8Z<>lkyRhH8G2YD7m@bU&Cnt*oAtL+ za?00g@i9Ck5)!Q~+X`9mq6RH@v*)`SjKjhr!mEQZyy|X3>srj;Z6>20E2Wq0b9iTd zyTSa)54P?zYk3y{;MhY6!>EmuYs1Yf6gFo*XnyHUPR=+&i! z6<#>8$BF}>l$Fx%XL3e5nk_Gm`;e+o4q1KkdV0j?2m-gvXI8Znn799CVkUy`Ur6Pl z%l;+=6VkO<$umrgje$xiLAkZmKJuAZh?W3L{Bx{^j<@}=)AyvhI{>;NOKW;Jvz3?d zUW8v)I3ZO7T6>~CZUxAUM$CpP{gtc;0Vj}d4m;6=pkB^x$3!~L61M)tK|0m7@xu6uC$yj4zvxu_XWq)lut88T01Z5*{ccp&0Vds-SgQ8 z?+X`}d{3PNy<7^*8)7;DNcot?K;qPBlst}3@Ak(60!TRCl2g}6Cbq(8DH-xwd#0jC zvtO6+RX@2!m?D#-#HP2+25HWHYkUhAGL%*>ME}Y>o$^JScGhmGvoQJTx@?TOt5OHy z>fL{r2P9VQ4>p%jBl*Y!Xp5*oTJ#KT!rh$e;GWYL1xfQhRW+3koBiZPP-Pr|vIyKw z1Xt3L%c7gQAdFYZ=RZA)OX+0CnusYW3KtZ8hl#T>?>bx_h?ROE8L@h-rV{}X#6m^k z!{;HsiC}Z&v|kPw zvRvGuPmVfsrjOywc0+S?!6CqcwX2*v0eGZZ87%@!6b;JGLZ9Gs*0dA&3!B~6@gmU4 z9ZRS<)P{gXE5z#Pg5ws6FbWKI!6gS#Ug6cfq@oCXt{78k{fPtD`vsA-07#NQA}vMB zCS%nDvZd+coiJ7Qas7D`%8REkAy~hKf_dNFzM+s1X>l3V>e+lPk2Pq-7WFz*`av%# z5D!1}%Sxj?UWq35Ku~aM6kS4I zt!yp49k^IfV03Dehl8$eu>7QeAAvWXa}oESizG~JC(TLHGd4w9glZNVwZi}^BN>y96n_v4{r0|-%|yi zJPK99X6mG;3&BS8*zofMPZot7LlJk`J%Jui=Yj*xqu@x>M|JmSRel=SA!;9Y*KYDG zG<6U9!~L2DW&0XF?&J_w=Z5dI;+D!^M=k@FjenE6FoUmI3O=8CN8qcMp8qVnQWE+B zr~nEgD*5Iwfsy#&q$VKr$2eH?5^{P~pm{c~H!<^LK-^%`LB)w7RrJ-55~-7eVAV(z zs1Tn4=vp1gaz}el6lNKE7&}F+j(5bGWII;p=T0l58=%0dy5S9|u&U1S1nspz#!CXC zdfS=Z|WMPFzNLc<8G-_-QVQxgYp~Kc=|D$L$S^yQ2BlH)yZ>=?Z z{}VNEn=(c`#7UCW==fOqF5Ylzn;sk%(nXG~){J?EjP=%HBv_iVU~fk9MYIZy4z?jh zj?KHOG5hXEo%Y&#zLll>NHGy5)tNZy1{I|Mczrf;tIb{pmn`&Ie+R_9 zH`Ffuiop2jYEe&hnth(T{m#P4%5ADLl_AyA)~5=xf?=ScvJ49y!CJ_V1^Cq0lY$S@ zOtd4~gBIsYk4C|n;oITduU0PoSF4+89r2?6rZqNS+XgBMikhM$poRh}YND73plH4S zCWkDN*)EEHC%NbKdc1kxa!$ww02`I{k635op=ZzFA2?5l?jf<#so9|JKd~oTnE-ix zc~~zrD}YDA<5hY*ce}DEt8iBAM_rp)QkK1d%tXyd&|D%1z;x|4^>}M&zY8~ zSMu2MG4wn-+1{IZgl-_j?K#$8gae$ulw|t%clSPZ@7-5@nj-^4DVIS3vv;@}RF-Rh zkaUN6%hVSPo=N^2pOcssrp{t1(iynQ^f7tA>1}v+NnLGOrp{rRy8dTK;%%H>Mre$= zbB&qK@T`RpL(e@Uj9YElEza2Mgiil3epo=3$@}+QUyFG#wEV5q69j|bcZaSIM;7m6 zt-kcO_UCS2Ao?;tlPzHLU^;j>zh1^gB_+v>veh{_T!dc$4Z&+^cct; z?6p#^SOn+j_%6SFVXnZzQvfJ6P(s_m4{c}?=2tS^`&I;P>!a9Is9ty|7A zUi1LNNPe1b(lVixtw=23S5iM`?!dsAMhdFi#c} zm(`tUTbzknUNvJ;YF>8^bHnJoG`eCU^&=$Hh5`1DT@Hqhc6?+!HZFmzZBma~=M)L2 z)UHxzJ)UlM3f51LpwX*rAAvqK3GYMoFv1in*If*G>*}bY9)TcHXVvV$L){eyaIA`c z;F{Wdmhi{P0h>o&t&v+t#azKxU)g)V>r{Jt$Lrn zjo96yqvp;h+X}8kHJSOSOQpMfR`4xF2evE&eW`j7cHSAC=RCUwc$Wr8+hS_)sJRUd zeQh^I01yeD8gVES@L`RefqKNS^StSdn(%rI|h(r&rTO z7h$ifS~MfrO^c)PRJJP9Z=Yl|vpFmTA`MaaX^aqVNc(bAr)?@HLk2`(b#7KbiX8 zgYa8Q4`mGuWHZ*4Fq?-Ax0?c6DU&7o{#@WAuuez)j1kx-$jbI3F_3Wq>3?*HfiaU$ zYIL=aujiyq=b_jFowTbUonz_U4=lWe58t80YY#raz?KG!Q>?YUHzeb%KR>#*kU^bd2pOZ=%4o(=^Mk$t~Vw zZjpGRjh6$m&sb|25DIx$#Q5*nc*DW@l}m0j(C4j!Ty8@ zXMc17A@|rD%ADQum`}_;sk2bpve7bnlZLYh+hVg)#HFvDfJ`>WSA6cxeGPUA9YA_c zboxufi%!8h;tD(cYhAlzU3`h@_70Y9McI%Rw>!SGvcz4+_=fn;DFKD9qN~P}`R{>B z&(=q(?={AkN5ZgZn9fb{MAS)*tDh-8cbREO58>+q^n>{7D3x^!qjCiFd`+n_tqq(( z*gZL|QE-2oyP-;B@do=I1P{Wxz&8ai{p2zs_J`JGA?tRB<1s(o#GF3a#|CUO@^6Di z@)fMS5UOkzW=q~$W%TS(EctRHLGX3-6=FGy=)JP=e`iV;1o-RdZh|>WnI@p!v7$f) zo=t>Gg5-tJUGD~@oyB_^zy@$Oil(T@22 z%n4ssnxb>?4e@w&pWzL$AZ$#N7>;vy)<%Mj`znN$LKLT(b3sB6V|k=Pzm4o)qko^@ z>6P3Q5dMtHXLe5>FexfWEqhK4BL;$IbFuzXUO{$lJNnH8Km*;=d#7m();fk^!%DdO zXvVa=x8pE|B>TrdSdy*d1jbkuWHF5BpD|Eel<91lN;7yfWz!rG92A1Gz~5KgteiW# zYu99b_6}xHoY$zD-Q%vSfG5G#5-2DdCssN}pe+#D=`gz)(54Gf`o=eQId_*ou@-Nm zXp*Bw7n+vT=s(}>A81phoE52Njx;NE z`sk%j?)+gZo$@24W3NsHtZ2&d7jMo?$auF)m==#-`r?+=%#|yNZTU)PuRhd1vF}1k z$~CxQyq}m}cckj;cPd#dO4$|}R!~b0WY6^!Q<5qw=Jv`b)&5>mYz;_CpvHMhAZcNX zO4^0I_q|=(wq$1Nx#{KcwL{=v?}Ez7@jnf8g-gZe(+2VBi`fkBzVq(|tzE$QbLY87 znaC7Ql)7-Bx|SW268jyWij3Zh?@4*jiN(K&YM=HF*X{pLtud zSniBG+^V0|7Hd8~GiRGGQ)h#rZq$_?Y*=e3W<6BM)?GNTd!-@Kl{)pttv2!aR!gRC zohrTb;l(0XiiIuVoUWFhe@HgbN1gzJ|7~=qPvsf|7X7LCAboH{Vzx!?5bI{No0oOP z(7H84@f%GF2A|N1ft?GT%d(`SgTjTYNFze0$cxaS@$rQ0TWLSu}Vmua66S@TP{H}frseZ}bqU6L0ghyXj45agr%P1eh`t)v!wZwrX9OfV59Cu~MY zD63ctl2VNag+Bl7W6qWZj6LMkerdW#wrLC?d0^}_EIhF z>O$)Nc`Mt-Avucr#*kg?(W2?|5VuF6qg>)2Pr&i^ZbvjwPDYm=h2H+@VMpW_ebwAY zde1b-&qYB7@VU2}!P|R`%CVzN9g#Lywam}cTM*9fKFh2urMasI^`*cxGB8A{#=I4x zJ)lpx9ErT3Yd&UWolo9T-EQfptsm0?nuq{~R&+dpW*x;YNW{6yFe=37pY z(kcqY;FGUV2=oGG4B{7-y~X3T`tyS!^r!faKmY`GB9tiK{ksXX%W4$iXIiv~PX5{B z;MVi5q)@vOoW78AwC;7IFnRvrMcjcyRQZW6(vIF;xT5$pSts4TQpbF~g|g3Gp*r-!W6CtBdR3^}&9HhmbYHgH{_;jrlor3C1%=x-2|i_g|r z_{DwT^Xq20N&roO4MGV}yv_Me_Sgvr*I0uiFhn-zVjtppX~?5DiNf!Q($Ntl)0;fd zl58Om%hPgJK-OpkerqB?l1Bq)xVfELJdz*ObzZe%<}$J{qFozd2cjTa02UQ)_0o((XtImS1-^ph` z!#!4y;5jiQ<^Hp%>Xqk)PZVFfibZSL%DXH2NprJxcFp$yJe70A1O{)SSe-xa#j((A zZPvl!6COJ+U9hxj4A=Bsu?9mQ469UcX|<}(O|2G>BS1ML-taI=L z+u$P6@!7KKhO;3wlv`S&YX$>c!|NdKyYbq)v(uZiMR4h370F)GQ&tbVqWvlkmFnQ! z@ZA03phwlV61jalmKI%4>wL_v##@iQ#j|1IJFwgr&8_t+Lg4 zAZ;%-o$d@AC`i)vpJk_ka;LVf$`UHaU${dmq$ir87+S0pIq+yCm-#{rpCoj~Fu2@n z#qcF2=uR0xGUn`G)w%li(30%kd2z{poxUnta`3b&bkr=KiCjq@fLM<`%Z(0fiG=A% zWCu-*t84xn7@f`pqhPIf$bO0SgFDogR!!aNfcA@ArF7%s)$z-z3O8*Mrm#fjl!o?z z1HxZGpvc>qy=3FtduWH+*FuY2yewnq_6mgw3~S&q@i9*+?iS;_4BoR>axXyis*#)3sz>2yd9u5_ z*kFp;6C$?S5VGg8DqVenMBhA$8*qo((*(;#<-6Y@P=O)sw=p#($q(X+SlQ2i51rS9 zsj+%v)4b(Wq%WRGT_&7q7}BZFXc;^bRM~3`WD;#g(=>spJ&U5^H+Y%&dUy-fsMzmv zfzGMQnyY*^A%vcz_XKl{F^AjMBWL6*=KjszFB#j*P$*%RDEAk=3mBWE zXAG)fELzB!uF znm5+!_6CkNL_~`EmCNun#LEI7x=)2! zq^e%1e9ul9X^Bdx1~T8vi#qh~ji@_TR7$15j9YK=qGloDoVI-74@fc_D^mrUMO9V| z1qMijYsa-BL=QWE5ub3gEW`nLq636=fsRVQh3(RLUl7CE1xCxQF9yADu2!*W5Lv`F zuNrhA=u!6ipPJpaCQaA0862yIpe$88?lstR$GXm~6ZV-L38Z@R*J|w;Aral zguC`}Lj2Q$DpC`9minx&8S{H@t{SNX%ul)>ySEuy-F%c)ZsvAWZN#;;az@^=b4e-| zZ-;Q9{3n6JpxsatTb07mV9H`T)q^&VO0BAu#Cq?;e^ZAl!gfn`;!_FJ+%|L8tQ$z) z&gnJWb#I;dlj$=Of!E4rtvX1mos_PQ`9zEpK7g%=9-gI%4fy`XiCCvnT;p^T|K;!B zyS!rZ&=(`2+tJ1b8rGU_t}vAJOto9&qxG-*KrHMlUP!W}e%d+vbh7M*5JbY?Syo#R zGhRzC+!k4S3=3##3XUS*&vS+j)aJM$=Lo`;qrs$)uX5E48K#C)bw#R`Rxn6L+F9=?H_WWlnwMIQhPGi9;4MY=Ms1}O$di)U^N-W%G#l}KWvVc zz5D@c6{}DyRa}b?a;U(So_Dd)FF0$OWk7&ccnSihfd~S5DEW~YH-)5j)bn&WcM|SBZ&dJKuF!pTY`u1#Ic34Sa=Y%rotYp{kA7k4*zgdy zZJE5HEpTI059Kgyo)J~t3*wAd3Wd@)?2z;z@h6CA=P{rb!!q2rIs`r)Nn`S-D^7RH z@_wzt@GIF5*P8w_Ip!vo?@n<~w|R)SXuR*t_{=s%WQ^B8Op&Aj#`n&BZ4k06afFn; zeh*O?bZZv}-p5dV0kr|XBeb*7n)q!0ybMEY5MczV9#s#ymCAuVF^CnH$e*;po zB-t&(JtamvbRSb-7Z<8o{Wr{jGoj~a?fL~7<7DEi18u&CPSB1XAv6Q1-P$sa1HY1{ z!_o7$zAJJb1k8WBi7=#V?7^qXhmd;F77HGdc+^Npx0ye2 z!SQ;+W(9$<(U}OsFHu@k9yn zY-lh3SsJd+_ME5kb@u2qBH7coJ7n`sL(0$akeQb5V6?ks6vP!itH4THm(A8(YH+fd zzKLtE%MBGI=M&pyGuxvCaJ$#_Dggdk zU;VBt-U=Tg1xBFL1M6aO#v@ZoPi0MOM@{ELixi!<)^AQMf$kokGc+}%1KL1Vw-d`7d||=f(hoIX!9apiAA_^Wi~PZLu_t zk{uC3?oh0TMUVzmg$hfFXhbU;eZ&*JN~1k}&-{iM_n9!Ful&;E1piik_hPt+6obGr z>zaw}rc^Lu9-)o;RrSs#4zJdhDmC`NWD;+6o@0a3we;RLAZ)*@oJGi z7{)<;QPzrG42PKIE};A6q$?QF72caUR@lRa`E!GFnvY>tnOJ%BQYKp(DnKm1$q{Ng zsUOkp8`?Rta9PaHPT@!d86rPfCn=q_D1g4O(edjspxZITiH*;E*4<)Lwe9rga#8*@ z%Vc?8X6`rj7yi!eatx5wrf}qh@&V^an;RIi#z0=M!R0eeM|f@|@NN{I&bn4;Amphs zW0xlioi zefSHgPg zO=Al&Ul6r2HUv|FiBKx}{bu4Aff`iRvJ7=DCSTw{z3fuD86WevM4VtpQ>**Yc$f~r z%=~80<#ZOtlLo*PC$5!;p9M?A2z)dcj}CfLVfIFjLR8LqE)lefi6)m4PvB>96GZKv zMW|Bb^`*9pnLDNJ65wwm=<*)>$>&cp5X2Hws#R0`X>IL(LSD2qbOyibSOkh7LzZbO z?zHsRV%^ls#=n9-0`5K}ld#)EI|*NpPVrR(b+?@z5FN{sI~0=wO3Hn#|zCXgQxLh6D$0Ad~(#bP$!SOkBB#y+S0@Oo z9owQ|CywJSImj`ynDvee>EeV&juS}3{YTOjOg}pC%VXXhcVLY<*9Pn?w$?Q!a-)J# zUExa=hjhYH6UQJ(bQC+33FK&BH~c1H zYl+m4h_v(`4Urwr`va=+jDD-YY%%1*s{IT+O%`RrnHam;TN06UQ`w(BNB9v8@PI7W zBNj3Tj%4>>F!VR`wSTST#`1_j-JhL#o#6SM~@VpLi58xf08OqTPT#KVz(P*SO>MSLXhN-tV=t_vmyW=^gjtv zqGsLS$0<@6Pz(7fbF$k0OheknQa&wrf|!0&cr3E|Aof95OI9?b;Kv$>-`iq(8~?%UPicqT`da*aVW z5N8`lIc&wTAPe59=aL&(VYD)7kAkq*{n{;;MC)}5*rFs?3Ezw%NnMv}fNA=w{TB9g zZy~J(aeQkAL4=Sb2+=PBL5hN?fM`acC@$!h`22olCnH34UhRHu`+LlXESb%6-w8aW zk)kB~EEhUrW^TkWZS}wG(lM2XF_W2bnJ)ik|<#2;>a!D1#HW^l`#BrN>W`rHMg3LosBlfRGaExf>;i zroKnZaC+(CMr($gOoFwnyU@S*-j&B)7Nc=fiEtq#R!?e`|Ex)r9%|XC)>isxc9QTX zF|J{=&@`!?BiJ2R)~}fM09NN+fi{}nD=EbcG>UB;@<*JsSqJz} z<%+VkCrWcFL(gv5ew;JALEZXyoPN4Mbd?BJbasNOg_EYF5q*VOx{)|~b=t$&9TA$P zM=rjiE`%V`i4hi zK=R*ckARuu8>t%b?!mDk%!)*U`ELg+oMg8&2WR+rEIG`@{PnfT>)P$ikA7SFKg_*l zSXEuuFiLlqq;$uoySq!eYtvoQDc#Z_of1k&Nr$9}5`ut~ba%(u8`S&0p7VU?eAjz^ zobSinW5%dC#+YNx6??64#d2+(2CGS}n>n%XrJfh$AIiArMtf;GD6dm3Am{R8%p88r zmIdLrf13(_g0vq*f{I2g22oZ7RtQEpOi8uLrW)PWo7cE7k* z9Uy$i;-Y*x$fs%XMk46r&GDSY#9=L!0N*@|uE?uFn-|S zB2UbOdvNNVezG&-Rq&uMR2P-n%0%5<^#i z*6Z5VT;Bbr=V}~f-nq2XeWFqVc^?&AOE|P3K8rB zroWy3RVcHRj>80MO?t`2vt%#k%lo@Ff%@cb>7Yl~OZqJP&ciK&aP)P{wDdd6NRM;rUYPadi0hH&xsgcAAfJPO#!k zd(vx^pvS)17RVMpapGjX9){;dJz~JxeO0U}!_w1>`su=mtpq4Wfc`u((F|tfJuZY6 z2cjU}d(m-av5|%{IVnHajkV#G3dxDnrYi>V(#xu1$;RVJ&C9nKz$rD?ilGFfpyif1 zMs?)ZSM@&6g=;(xVMI`1Tjc7|5aT9C-&}IrFO8{Hd!D(N+f)+;IyG|D-5EA^dysR|eM6!ZfFoB2&l&3)-zw@#<-mbn z6XmWhI{u~i&T?N_I*~@?%zD1~Oyh*j>w2%qtTu`qE5}_0n)Q;L`F&_us)gY^XFm%~mva(eFRFF)&k{BPp(u!f=e+QbUx_b5YA)4VZ{8YosiV<95S9GQ{X|l7=D(FXyTB=NMGBc+lJY=)4sWDhcWU&R)=4G2Pb|_Tb4G!hCw8ip&1D? zC2G`7btF!)b<&F?Ak-*oS!bbO!Ed}0jh5QLA$Nl_!G}nuy@(8HT~zBc&Oao zo9!!Ul8*13S_szp7#-B)jN4?vCKiia3HOPU^HHMmgH*j%q;{eN{<78S1B~*D?`V9U zamM9(f3q2cIcLfjs!+nU$SZ{&swPfJ%O;+L_|=#yU2uS}!DYd4_|d>71-hJYO6%~7 zDMt+TSc**^wP!C|d*(a+glI00eryl<^9EHpGKw7qt#?N*BsIMov-rj*_sQ_5d)pe0 zh{@YNqfxd)OMS~9Bpn4;iu0Skw4CWAU>h~y`HwiOQ{O|66PLSUDo(4ZnW&X&S zXYrei-Tg{})YkhN8TuN^Jm+!ALbZ>bC8-Ls!@yjzq1@|8aaQCw7GKq?*W#~~_324W zVg*;H3O~=t<0W5d+zHo>#|Y;~i-I12B}x&X1-5UzO@nLO6l&MJsznXZN%OgT2MMbe zs;t*1`ckK_Vv+xc$lUyWlkbWy^E*_bkGZ<3fsFlc+zxGWr|cBmXe%2;Fy9}2s3lDK zWhi6ZMx(aWm2UM5!~M`ZgoAV66chA!h}w0eAb0>5aJ-GAHguo|A`RvJ$0^K3xn2C! zQ|nx-mzL;&x)-R6eYg@EX7xZoVlUQEkK=B49wZiz+=#PK`U!#_+wx~IZC&P4X)gOq zsPMekCptfWh4EJ`rsPc7xN2VD$;kldVP~QSJGz9JSy2_+<+36aG)2qRF+*iIqS;6{ z^R?Pu=?bxFq?AO7jPj29P^$P>vv6Q|HyU}Nk5SoQ>yp_J;*B`zY=473jyhY5Vtc3c ztie0L{RaT=daW9gWKA!>tE!g{!-%`CTd4z%8THFU$t%6>D>ZR{uTNIvoCD9VNvS3y zW*4wC&XRqQB0>LNR~5RFuOdhwC^4x2I#CJSC;ai6+XZHeE%x?W8jvA!ZQT8(7o#k8 zv0WRXm{D{)iqPv~wt)v?g{?FPA&<@AuKh4)CYMBg@iYxHf-oWH+CVCc<035X;TNM; z;9&7yJs(a^v{{=Q->~fm(JDw|X({kNDygZ;qWIO$^A+!;LOpt4H(6EmiY_%MC z=(WVdbIx>DYK%`S&h_=Cz^C{Y-f2$O!i<8$E>%j)=)@{*lFV%9dB2MMt$SxYeS9#6 zzV;_E2YO1xG?@KlEcAixB^^ShViee(>qZ3CQ0~--Kr97|IvkB158~8>S%tzdhvuYw z#ck@y3_bDy_*;RY?v+(SVLa^q(xz7o?uZFdF65VH45DfhNquyd$6o3@v06d8;V5k) zh{=w@k<30eQCgambzh034h5o2;`c98u{pzN2P$g? zjctv%S-|%C<;Cx$uK_+tMel|$XuU8Sv{3eOq1ORmnb13twiJgxMWyNBf1E5S<*w10%Fh^IIV*h z9_ilGpBQ8x@+AY7*WWPcbFZEAi3~QhCf1~bA?^tF8dG>8zK1-;1CE3R5|ru>~+0Q_seCJp%*Q^_UDB8H|`)(_gewy#{eiE+#`8#+({`{FQj^A-{~ zGPic0f*Z6dWuil!Z{~QLUJx%!xrZn=vFQlD2EWmH76yBsf97w!H~^`_uxOwOSogKscHfRiqW2q0#;U2lXTUF?U&- zZg+owk&^YRI^QS>+;Xl^IaA_NMJ97dQz>afMbcPcSeXn&WaI!ASqaCFXqAhw4A2*( z2$sZAE?A=;sAbcj+zv~IY*h<3%RGiraU+O~>6yFTshi1~#%+?g(x?*`RZ$Km$ar8m zUW?z*vgVYbDsJpS5}QE{&}uSJVUl}5QKW>`0#brHahIZY(!OZFGI^8NF|7?y{RH>F`hH*gO|LLR@-((-hSxwl6`WrFb!I= zoXw;)o<+IW3JIm1rA*wumj?A^RtNWKX_`f(c$=5$%vmezovQYr*Id;WZW;*5f4i#Q z7bjpcuhc7@HqA=;d=FYa>m)C&T@FKF7#QpJpnAG(^O4=Zgtwv{{1BqbNlaBmOd{!T zcH41m+lkp19@)F;lDDIf8ON&gn<0rdh%d#+a+r|_%v4gg36+I>2YQCw3y(!-;2`&; zn6!YR8~BYBeTbxStmrM4;d6OjY)cuk&^yIJ+b=J9PD1yEAu=3^`6Gu!t?-~_bi~35 zd|4zl->l`=^5~9#RK`DaQ10n^{;i_Z;%KYeSR5}Bsi-0o_Y@CXNCroezw=eJbk{4< zHRd}Ah5!|u#ik9FdT$KW*QKn=qVf zMLaB!21)fKDCaG*1b!j8imB6t>bsC(c#Be5`z8%BXsyG#Ral{Q9MMx=6Qib2n4 zH+z7ZyF=TLS^*6~fze`F$w^3t@#2+S{#717bQE2Si;Mx>LP2Lp{7c80d>e~rcomwC zvqC-eEhIhXb#d4=ZNrk|;YQv# zRkDR6D$&#Se+ly(l($>U#-e%c*(cV*jXwF){3k!WD;yV(;SaXqOd`5?xBMO~*qzk; zl%0Z!`lADjV_v~MzV+A{UOEY#7|+ghrD4xNwbxr|&F$w)5uf{Cdrbj^39!+!t0Wlq zaP$+cJ{#(hXTHXUPa%~*zvfb0`N5YtUx{&r0l%FJm%PThs58-{C7OkLa4JkWG^+H; ztmoEa4&C!7PyV&EXFB;U!OoW*A9B=E>3->{CGknp{{obZ!qb;) zHhGsg?5b*Wg0HK@BWY>^^s=#T9_;U3 zebm@Z-Lq`WVw3~uwt2xOJlP=e-Kc2Tm@9aF@r8Y`AdUW2IVR1r#xpE=)qqoiW^WuMI#Br|pzB#X z!(ya7Px)z!b49R{ar$91_cM3wN{PM?4Yl_w@9z1QGCu`o*PwzBf#v+c=t+$hq%6s zhYJ<6Iz$Vlv%7d_nM3)^Xz=i*5j)h|ikTe*!YiX4Zn0hsQrvmn7H65xOhVo7}ygG2(8EAa4`-QV_^oRFL_CsYG3Bt)` z$cA1jeEPA)u)z;y7gi)aGwZ*}`~8}`tr>am>QyWR5AwlfbwCg~7iM_vy_hltzpOVi z{DKFZ;1DF$CbAv=Kw>MS?*)${K6Pg8bMrOv_42{|9_hia!*=7zl1oQbS}Q)XE-J}1 zez6Di{I=3`KD;rQ{8vPr1NKX zF)r_eAjHWTH3>)4R^T&f+j#cx3rF_0L*6LYYOF)9)gi9@zqm7|@69{qTe0NQHjQgl z-{M9yh~kOqBJ1K1O2T47ihaOUOLJSFxY+|x)YUP#%;s)wp}Q^c9Vn1gut!CH*4b~L z<57P(xnV$1`ek%O{ufTzUaclQ_v>>yJx6KuaV>_du|e3K<)wBg@+`KXhd#FB4_{5A z-4`I7KH|OAKags5XVf-*qZkkRB5!W(lx;=WhP*j!PWPxLYI%Mv^cyjec)XC~lyCiG zD6M=PUcSe0smX+4T>fT^aU3s-wGY)f*T9{xh@y(+o8pF~0 zt35PHl1v!)bw^lOqtyGaVpwgBt{q3dmooN0;(Q82P*_E9G3nw2Fx;s{D<(Pa~J(cr~j2 z?TZ^YYor`vmmUiK60axUpzI}UOogW?^{ZV=Nqklz)Jy*PjpRM^e5cs2dM#pjTS;&C z4%k`LXqwpOD%LiFDwohLwOPnE8ZF6@Ox174x?L+?;*`cFb=YpL4Ap*z?}o!_{4{o3 zgb(8x({DfPMWK8o7lJYL+UZ{wn(1NX!FbCrjPMx}AxOM$ry_7PEos(dZrbBWUjn^$ zVp8`&zn_)umw6c)HPg?S-0}OjCxG%hx>1Zd5CdufGhljnbCzy z0a{dsFx!sbzhn|srx1FGduyRjn7o&i-NgbV{bYZRvsE3PkQ$ugga&x2Usfyq{9~fH z(<04lQvq+egOQi7`F#}S`=@G{2!46tn~E-vc4y0JFbDG7wjBkijZD4RNnX`m=igs)uW3+*xbPHQD7{TjO%%HzVjwfHBW{*c#oz%S{50DnsQ0vAyz;;Q9e zI!J3p%=8v;5wEXrk!*zfLeZ)2$lr+1KG5nS&(q1J?~Yj&Pz}JxKvIsmHa;s059af6 zGQkexWqw}ulg78h9x8kUYpVgD#sl;Gp2ofIeXO-}P9F~B zb!qhL^^BD7Fq@3%69gTJ957zVDnzt?-H6D@FXv2^ohL9bv~a9aIY%ip-BD3#y0Vu( zu3QfCzY^H(k*(lVBy?Ua9gkh|8#m;waCZ==b(sz6poDNMbEqU-;cA*PAY8P4MbOU{ zzhEl^Aw`QPSeimq@6o#pRTf|l^GOT6r$V67S5v;6g~Iba!8!7S7q$tLhF7!^@o76enzaAp}Au$Wcx@AViKZ~}fvh*77%A^q`rG!rQ%qTGO zR#pG;-eoD8oZP@q#=H~hZj*qXfUaC|3SEop)Q`QcBN*lcGVvZBTC{zW@#_&gN|3|H zuop{;?2{7;gbA0d#O9JPyE5%(9`WP*(9b@y+y}1oPKv!jY8B*F^`}LO4W<{q0lvt$m0n4{ zreATA>{|Tk-Sx?U60+p=hZ!lYkMdaTJWf789%v#-0EoojbqbbPf8s{b721}iFa&l# zHx%*wri8Hmk`h%v9{ar9PY-6Qbe8VS!Z&3LSzo7wWS|iCWcJE++SvYW*&?!leh8v| zW)oK+^2aNm^kFT&39>P8O!)vw$t1<8n2}eeDSG zRS}8;dy`%vNpw=Y0&7*qNw(6)Kt%;cMTI;}RO9NQw(QbxEqO^l@?HhkN{GMhC={cg zu;96!G2D>5UnVfaS5^ctO-mUFojw=yk+cMC^>yyS_2-po{K|uj?_|gmWw(C^DNvVl z%*ig~$5^fPBZ91Ko8son4~r~D%4YX1n{)RA-_GC6;gdv{gupc>e}^Zta2?6# zo@ug6v2_1MS(CCS*3dsoq=9QV^N@j=DqS^=<Yf4lD$reGT6{Qx zJk<>_w_TVRnK7DarWt-B+t=o;_S5MX`sm#`*4L!NPeQ^RpI{7|{g4Q_b9@Bk^%bk9 z@VqEh^!D|LpjUU$s=_cA^cD0}Qzz!MAFd(3qlEQLbCh_%Z!cLQTWLlN(m~lTUpDv# zyTCaYz&m>G_m48*i_D71ewae$HO+5B<2@Nv9tlt1|Jmo`&&iT>6!~K8!>bs<%ozoK ztmfcBH??Ki2m+fe8RgF_@JZ;NMI3Fz-s6ti-w>r_F3#SLOK)+ZC)zhdZfE|IB08a7 z?m=bQy_u#^My_mJADTfVY7ZgGMPa-JvIq4#QFNxn{;a1^k!Z;O$h~{TGuEGD{j0$H zz63S$MDoTPL&ruW4!T@h>LG`Wu4Oa)$K?Tp$BS8v|MmtWZZcLfCo@|?LBQ`f81b-j zumPlP?A?K`|LYeR?P~w5n*|Akdfsu{OFPv0}_1~A> z=zJqKgc%aHFZHVCv)LkjXN(Ymv~mk%ao(PYU_$!lIdVlTRX@r}k@sTvM834yf3}bp zXrs0)za6|%x=iy)q+KV)SS9ud5BIa`?F}3^LO1!RA~PbVO*OG7|DG?fZ+f#gEYTkH z1e$a1nULD42k2|}eKo2RaGa@Xu);F>OwxH-p=~nlYD`mBQ+V~|xL*vZvn?{sZ%?sL zg#Uo*6$0F|2QT^S0o zBfagzc6ZDtYG!S^EcqeOjbJ!jg(an^INH?Y{KeRP1k~_57iZ+~bOY5Ti<(}OkkK+> zJy4}Dp@?DSuKUDTUPuE^l*)qLq}=7ZCss=f{ul z#MqxJERkd5R{DHREM=~zx#7@^5rxd4CoE6vGqq6Z4e66Q6k1tjKRA8;)5Y^hJVh^$ zWyyGe+f{*#V%N;l(qzga&XBoEVOgR+dfN7g+-X=v$zS!ezJdI^IMb2Vih}{_k!E_T z@YzkI22+oPWT%Rps%H~|Kew~^+6cZN3v3IQOPuN-G<&~>hv>>d3_?X4ct@EV{`ysn zVcL#G0nAe`rVnWO8;xjt_oc}g z()L{mJ4v$lb=&1Qtd#slHN<*#?Erw_^7DT={N@AENw~gdq0yTv@n{$^$3D}1X<6h41=V5Hi5w>)iJ-%4EZ+WZn@`^omiNoZ=K1bt zkZzM=-uN&#^!ym>!gC9*eNQ7h&t4FjDwiYx`}28+K4K#ZB(&}V?S#D$%gqE9oG3Nj zM8g2etL_0smf<-=oLRTg4IbcD2fqIx*yaq`W5l8K&R^kJ#u3C z7WeFs~enh2wyzxwB)zU2DW@PcFhre?f(+pM}gmryv(gbHX=cD$?y z!@msA<~l4S%%;P$nDHcZNQ#BA$&tvCJCwE_$&bO=E)tN?I%uF-vgV=WjS^)@;ZJOP z9K5mBH*|^H%086PJdfJzNv@objbrm=I91MzGWLKJ3zr`3fQ&+PtOQ~YRbPBmv8XjPxpqXBf86Slkm1=@VZ;Feu@@HiQQQ%74Ss|1I5?&V>Q7SY? zZS2e?A)UHxD}V5dWb%4ec5UPCMhE_NLz#L9mODroD8=(r*W*zo0pJ$$noO3#FEF zPf6#+BK9I=T|O$tQT1X5D|0Z&8G@KI+b(>v?r@&YSo~b!HD^0+4CsSHgp?9kTgy3X zH92-J{U5GDhY5Y$jaJ~-9fQv(-e30^>6~@Ca%wAc-lptn)jk(nMPN3+Neoz0KbnO2 zpf&@cOC|Wx6@Ft~&zWe$&?D?f}bo+MRl&r=7PH~@?eOOH}koM)Z>H3aq#3qrd zpy~+HPQgtxQUZ0kX1i-y6Uu{^D$f0K7#)@DkZSwLb0B@`W}LX>2!5B4tDRT zZRoHB`#t#wi&E7b1tEd<5UJJ8A@t{ucev8=`lhgg|f z4)r5yhr=7XLz&sGWhlp?0C+|S4i>gcVXYwg2nm!96(U~$(5P;w`jFa#qEl+EAhjh~ zl*oYWtWuVOgp8cH zJL-Oi%zi_zxx58{n=dnL*Fvt*TZMg|AxcfrvEtGpEVNFy*tOw8CL-G#fnx&d!Sk|E zYVSI2rv*R5(xRsK`)#dm=B`&bSt6U2AB!#Dw?3P`0rXEVxC7GG0kXj*Zx;?0rtXvu z9NYJd$`@kRDzgvfo+X5vRd$H9)Xka32rb{d-xe~MXxHEG6wp=clU6D_O-NbITtL9? z1!fkWW@}G>?9F4rOX8u;^1t13)i!=N?A*#fLuT;oZ9D6_n99`3UiUTq7R$)`eETzi zM`oe)*a0(zkcbYNokB?fdawLO#y!NqOh%E_^ghela%H3QOWcjKCG&~f1Ch(OwUsxS z_2@G3*T9Wi?_C}dpW=_!pHV7bTv#(Z9-wDs9)7AHL5;}kpK_17m$!)%4GoxG6zQt&kw)i#s6xHjc2wsBFVRb`-S^wQU6HYSOa zxxhPmg& zx`shqr$el9pw8StHLVB_#f5hG>WG93%eEqe>9>nA=zyd)-+9iT4V_0~ZlR`&lRg{! z_7Bsc0IQt=-#n4$pLy#Hp-*?0c2A-rFLUzH7f8O)v>Kx;KV#XdxTU{6;#rr^)*v{j zJ(Q$%!ec>|{5alg+vC&1p(h}uFETG6Aeg(C8&ItUGv~vb>G)2YQ8Q^F_%zNIB4-k< z@5olirFpTSQ~)_$qoF^qy7N*Wr)!&0yK`v^-6T-+osUlYyw=n`)WTi%L0Ut_*G6;h zV_y0MF#=%*Z(iHAAkm+gKgH8kRW#%FbDk3`THOpxN~g7wqH|l_z#9`T{rGXTHH{Y3 zDCu%{-&3NB8b0;?K*X!``$Jd3a-QnsU0_7Tc5S{#4Z#DIPbjTjLV*A6reldjd8q`M zF%@S+Xi!tFmOO{^!VT0KQ=;3)s^p}zKs***Y-F4^(P%~>Q#?KUn2T==tYOX2Z6h8( z|9gnyh5P&$yBEUbS1m3(S}LfdhvkWUtlxMu(gd5W?SP8!>?<>ns^iGFoZRta`L*)frPukn zvnQ|bg~i40-2+(&%wQ0F8oj{|T>=Ry6ASUfcZ{BHF23s^ieGxtyzuW~elf-!it}rJ zS?XKD!tffREZGt>CuYDkf(>N|!|a38-&pMuN!=;-tEw9HfOt@U*WMlV{Rd%R#gcu| zi`PodHBru9FupEfXQxylI4`Ol&>+M~UYN*kCsrpb8BKHh4EM#3RL3-YYJvjVuY9Tz zV;qaAV@F&S%q|Ah*8R$NY>V(+Z5gL+h_!Znwwv)Q(HwEErt&9=elc|T{b6cJ zGgUR${#KNSO`S4~So=PIUF?%)^fP@3C$F}*4WQeP_DXn2UoUY+xV3$==}K&q-@JX( zgkToy`cW;7@7i$k>+Jy-E(B+Y!v=%sGZ(_Q1keuHA%s*COgV90)|Z-MM7%j@s0h>= zC_`{!7|y#KmisS4cu^~;?Gvl zNT`lFWt6^}ugan&foEx%Mj3%kq5wSg7-kUFEM{8KCTEGPw*tD!PxJTgSBV+(lcEbp zr71egy*)T{?17XiL(yYv)7wz@!tl$f10eQjyzD_IqL!+5QzN#he$P%(>N=#Fy5z54 zkRi@SDfU5LY$~$n8`MlFS6WA3Pr*mgHIy6iS17h5$CZbiN49n`E`{Wz7DPzOBNw|u zP?i|t&&oNn6iw9gII1&lDS??%Z1e-U!9hKDvE0a^11`+c5QIfP^1H}Nd>|@9m^*UK z5gLb*9Hf-dzZgXpe2{dt9iQ{X3{P=kE?&m*CqErko=H$Og77brsXq}%Im2UKDMt@p zta=#a@kwllV$fnbk94Wf8Sop@=O&e6@tI`M(wPnEu}9Ehk5E43`x4yVQO{4lTEV?e z1ksWM12NjS!wjSQo+uTQC%!i}&ob(l*gMj(gOG({;o(kk%Wp1UC#BoxIG79eZ`MvgzGUAO>b?KmL~)9K#4H++iHsCUeB?Yy3bW5jVT}!P+1_d3JH+ATu#Kil^(ORf z75T?4M-q&PWjv=13TKc+wO9MKqST$Sz8fmDM*N9Br2#_8h($ftFkM+yGW%;a5fBr1 zBDp)1{dFiqbiF;nkYJG`AvTFT+&b=Nh8zvl?*6;X{8lbK)?02C{YcJ9e*Uq>V`eY^ zVMN$m1hJO}m=qy2C3v{kuV9oT5oQshzC>vvCz@f8!-@B2;5)Q%rUGDVzUbHT)X(A( z>U}PQDQ0NsGE$4I_oKyLj;UHrVOn*7G=MGR%GOgn(Wj40RM3M+v7`;+enV>KN8Ef~ zx>`S(@CwTqGx0rY06$O~_nJCDn(Py>>-n>dNX+8~LVkr*Pyg=&<39&25vAaro6z>G zjr7R)M!sOlQcP72sihBn7^6VTy`0Y)F}d$6al?`tF~H~ue>gVsXm^F@9n6X zgmT#3al$|^U{Ej7)E5gr#*x}mXK>)5i_5>ec=M~)--@TQM=K@0@1jb?ayOI1st~(K zKpHCCtXkTQ{KG_K5ogp&1fR9?>M%vhBE)QtrkJn_yLinEjm3Ecv}nau;&ny*GJd5a zAtHWOSwBM3EdU}QKpscj+*JxL=^{gI_M9%O2(Q-ob3oC;|m=a%G> zZjRRB5Vub8`b~AZtck22&bW`j_GPpKS_YLj3oJZ*vav_5xxR!AN9%kRQC;cDueoHE z+f8J~R~u*z=snM=>C}rtlaW>!Yb#Uop#_^Ou5Nn)d2_Ch1ENjX{Mk?vH`i)QKx>*`Yi@t4m(W?g`uMR2B!!4MZa)!RVZqQK+ zk*NE=pTt*0#mM>=bbk`>P~ByMNe@2X!fqf%epHtJCH^=AF5^VXu9%{Nc4J!<)l3QF z{7C=XM8^`cNI}JH6mAb8Yy0gk<7S_)9YlrYBR-7d z8?i)O&vNuTru*l2Vq*nIWBrm5g$ZPtoXv!8w@JVAym8o0B6UnQTTKXS0>(_B|t<%Qt^x>mbVO z&4Zf%PTY>0KnU^EJ2KP_2mY@;#no6Sk{h9luN}gNd;_**b5++<$K=1@-#G|-6!v+!%R1N!8tbOfJ?Hm;e_t%AI@WY^{wQ8w!s!(*iphqgbD3Z}gUj7^xX|S<{#Eo|Fp}N{ zx>bDG6OX6rLJRpBw>aCbC2=YPzIE;^u}C_9i3NAjt!%Wnf-}Cb-b5)y^(VC7J9Iib z4gE%E-OukveeNdCr_NRw$GL?8i|_L6jjI>2Gw`fL7K|4C@Vj`*Xv=7UE(iB3Yk)FZ z5tk_4Ha`y^EP=+h89q~QQ_nH$AYq`l=>hSFw#)E9>y`GCy)#eKGV9e><~fHC>DcQC zw4UcY4@+V*iq_Rw|um%zv!GgWp2F3de*?} z>)w91H+nvLes(f4w>Yr&v!$kJzU5?QHU|eqQO+#OUHasr!k=+s=l0Ht>%m%Ev32aj z;Pb$R;Y&!LbRVvZ+y!Glm*U>7yu}1Uf~m}b5(Ak^eyI8>%mA(4^P6uSB-#Au=HUW~ zo^f1`Rh7%HjMu+)MwdSblbrmt-~A2%SU((_dDXOS3Qs1@uypRYWY<;;`01Y9 z1c^k{Ed+>X`JEoqzb95g-;K9^25-g`m@Tt^LdyxWGN1@-_tbO>rr^^Xk{wpR(?wmo z7_)P}%4px^2$S6T*&oniMj4nRlP8OOMf!(VsQC+`h4)Vl3!;?IqT5 zy18*PFN#&AE;;oz6)Iqrdn|rtUFaE%tf*5dq39;uH%ICsmRZ3Gx#DsTZ34<1by(>If5vD15QfO=AG1_qV14 zG)W9H?Hf5*fk7tSx!8mn%Z%}_YTw}Q_l()j1c+RlYA=$XjpeTGWDtJht8liL>X@@m7!rRAs5qS3;;hc1zHG%D37dL0dlFimkIxM6j zH}|KjPM{Bvq>{7X|Cif$Z2x)pj)Q~y_su(iw7sc2P!eeFWC0Wwc5`o*|^#tZIDlnuNY&Er4D?3xFih)5aXAE+bCH&c#IrcA2^% zD$vmablVk`?N6Ors9auyMBs(rG%ngP{feKXm_mxJFW+6MPR?9TYb1hJY6U z87B>=fAD_a9@gjN1>=x$fhPw7tWV&Pkc{h5X)>-yl)p3M0iir;CTU}72?Qx;4s_FJ z=LDF!0zH8Mb5mC*M}WDFtGS1Rr9IFKVBzF$YHkji0>IkC(aO}-!@=Iv!yVvc<>Uyo z1Gw5aS^?Z`>@9#~9DD#54<~n^8>q`3NXEwvuyQr^1d_3_^8(B~?CpW>01HzqE1>Id zU}0tt0NUHzIJ?=n0e}t`rf${%koCd9(%uQg7+~pYYVK|WQpd`}#{QA5Jl%a5HtZcv1tz-pteu__y&$`lujiI!P{0{${KcXIZAQqIZM!V(CY zFeuo_*m&3h_D)td=BD}No|}gz^;GfW)8Hlv9~t`fc*X! zAEb|ishhb6IQl^}yx>6>4^vkV1-NQ$YH#@@;diGS85yxZVga=5~uQnuJVMg z@-K9i-w1!H96apZZJh1B0V+?<)qEn=d?MBS7pdl78r`Qs4QnS?P$&ak9Y8T^X72_t zeWEpe8aDkGt?83k)4wcCAI)G2TAqK*0P-nlaRGo&#K3$ zr97o(a7vc22CW=WE(d7aSh!oe>GOc{;s2k7orjkUTsT077cMUD$HL3YN5;*~16l`c zWE>nEPX*M+#mo7G3+nqr_lM^H4gSRk@c{FAEFgJotZZD5!oUJ~*x4ToxX#VSM#ckD z4BQ7M=3-@i!~+ZB1u5`|3+jKQ`;GUP4nza4^Ko+ieM#U>0D6$MT!?BjsNzup;0F*f3x!a2w1P ztTed)kIX+1tn8zLpfMf}ka(WodVxF$#s~Ltfe!4PV0}6Ho+N|%A9?YBi~t({!yDYk z!Tl6vydVSoDd1T=Iu7jg|0s{zgRS_V17N2AE|1Xw!h4Ju(Ad8rIMn_`(qFuP^8_jI zXTtvp!As%Md%vCWXZ+u?!Sz4={}qA^1D@pnZS0SeSy>GM%BBuL0O&|!Y7YhY!T;^-1XA|Tr2a?Q z2_z4!71$_`<$sZ#{y6?W;r|)g2{ehnUi@7LPwL<0PZaz&2u|DowI9R_+z;aY@9e}R z?qqNAA1Ugo?|+)7*uW=*|FMq(ZKl|sQlc!--t!-E;1B{K6gRphd<8zE%Pf_fOjX zZ3Ivs=mBUTI|$=ZF)-2#&;=BCbI?}a3AC@af27j}g3k-dcvxA%*IKOH$T-+R=lX8o z6B#mQ4xT6G;^IzT`pn$yypLUE?BHDiXukwHT8KSif*X(Qq)i=c?7it8k00~^2~%g; z-~8FQ0Xo0yTx@**Ozoe|DL~HM)ZWHi?D2${^5|8Wpa0gX3>Q+v=Y9GXZEgYw^nH^>-Z$}aDjNoZR6(Ke?a}{n+L^;!No9cY-phlI5wEcty z0DPzAuekUounx8IB9zMLPIw%Xm7$CAp75yhT#lHR(=hBZo|Kxwn3?>ocFIGN$6Vxr zAf^Z}o2~UR<1eU;*d9%bwjTfnwrkbhU&$*xBh6?Mfmx~ zzv=g1WQu7}MEN~5AcRd|jTc_aoE3|&*i=(4a=mRMKB62%Fq92S*}LI$DDWjxE)Si{E zD=JdH?WCgqC#kR9PHF`|&s(xick1jaI>#i|725Cn7>qPmbUOws>ey3%l@#riLkl$X zPp^Eu4JtcC$sItx9Kw$*zz?R@37*o4P`bp@2d*mnMUd8#MqCwtD04x3=7QL{0_XVa`SWE0 zBRVB9T&?%{sSKlNnqp^~XPOz?r9Kt-Ex*tVGL1KQn$bFklD!DWmQ}pS0qbjRNu4WB zUbKM&BF6#3p9iiu^M1wnMFp-AxxT+pMeVkZ5?L{H?=k+0Dufy8bt(~v((hbsPM~GV z%stp15a%!xZ+HoLM>ACeIAzz*oy-=!l$JD z8RwCK%eaP{xP$w6jOWNzx>Bl$Dkg->uv1l33F>#Mq3W)Bso4Kc!kUxP*yL&)%r!ZL z>+@Jn+n zzA4)s&f)v~n4j`<_SpZcAsQhPP4EXa$J=-ZZO|TnLT7YGFT|oRk}v>6@Bv0+48~zR zCSVe#;3G`K49vnD%)=*GfQ9%Bi?JM^;|pw*Iol!}c3?O5;3piyF`U3DoW%t-09TQX zTgbsfJcUP*GE^buuS%!@RZ5jp){rrCwLnRSorqs-^0vy6R2!mioPFq#{)l z)m25QXrYv5&uWeQc^$*!csx&#`Ta;{c-BjE{5h}TFL?dGoa@_sm+$c-e!|b#ZSx63 zI3my(P0$LJGzr6(3?ECSxknFdZ{78*}k7=HpW=`nU3=ctNIA%ID)$Rh3Is zQ$Z?N)l{`rh-6R$$)Ru+p&I}1XA-jhpGp70Ofsmjok^OeOXX0Wl4%p|puKdA&eK)8 zLrU=NTtz~T2fmcO)O9Sn|ZCO%#TQy+CJ)jWu zqJD<%`$-iwd_sy{WXaX!*E*?Rl3dO7dT=tgomST`T-y{un%C>K$8i2$F|RT!8X=xo z{>{iJT2-!7QS;S(6={?|De3XhU!##C7eM+|?X zjnT#EZp<>~84Hc2#%5!?an86QnRpWqWhGXS{0dba)oqm`HXmgpl(p>9+qokvZ!|8B2YC1YNx;f@JRylR2au#<6I7>UrJ1aY@ zJ8L*wIHR1=RrD$)syHmNbj#l=VU@DVSrx6SRnPP(>UJFGnyI(voAS*8LysX`}>ml~Q;%xGtHGo~AJjrqnB zW1X?pIBR6fnmvY`d^!$UVLen%U`k-R>2H=a%bKRp2@*OX=3Du6;)Tvqp|kpL=(Klq zc1$mz^QzE!%^8?ar-!q*O~?EPblMisnQo<9s|)BH5ISdtPG|w0Xjgo;X4BDf47cX4 zilQQ@pki0Va<5oXv5O5+nQTPg3uc+D_djRWSu?Zd%sS_u`_2A+UsBB^ z7i$x1V{3hDU27d{O>1?lo7LG`%38#VmIs!*mfMzO%eBn6EOC~-mMDwNVu`hcS~gl5 zTfVe-T3js77AK2?eYAbL{Z+dt`BtUd1lt7J1llaJ3CLQlkz#xJ< zr{ILJY6JWztn!BhI1Oh+b185arb0jPhW_x2sPI=<0s~;6&}|S5hM_P-wCMx4VYsMt z1dN2yqSpvm3S(gm{0`&b4%~yCI3E`vp+ZItui!N=_!{S&1Ho_(>iT1c3 z4`3;&^<~fjV=)e1LONW7>sS^Y(FvXLARfZQ7>`HrsMNRPSPosVJXXLHcoI+HX*`1o z5Q!Dh72U9skUtsELLyv-3*rMTkOb%85GE;k}J7UC32@JG*#Q_f;63G&`g>|{xqBB&|I2F z^W|7T3n_pWQ6L3TFon=!diei)KYH|m`+MvC=rN_z6M9O|=sCThH2tZrt3RWcluobc zHNBw>GKCwcNZ7%2PwBTVvEDnMSoiNvQI*Z^6;;K5cZW*m^B#`ky&TOkypQ+u0gmN3KFEjoFvs%|KFY`VIG^B?e2P!=8BXA{oXF>d(iiw5 zTiD8%IEgRw6~4;X_&VRT4Fj=)$ZB%>JR<%=|RA<#ibyXcyM|g&}D4NHJ zyAFW+Qtd)vHa3Kr=!wJ7UsyT^eP9QU!u$Au2l5~u$AeWj)m?cB6?*Ul9?CvEk%#dl z9>J4&3QuKUp2mJWoagd%p20K4k@&y$B!L_xzAZ%D+d>ZD(Y%pI8awEYx|1X(N9ClPMU%aCAKh1U+D5n4?L?*D>F;$< zQEm&}QnwPV9ni5lPV{zEAJfN0yMu)wLq){{^ly5gr-+Rb3KV4OLUs5|uvH&-8Oq>^*&7KMennr^*F?Q;qT!07VRzj`l8=XIy1eMQim14rQQv4FNwAK3 zqMi!B4ahRi(j)^3tUmyqJXEX=n_Ri`(R^6jU&04kVeDZ1C&+650@Oi^8Jil!8RpTaKH*MCuMax#L+q7-h zzC*`Oox61H*4^uy9^ZcVeNX7syHDRAe*DS1U;m$f`E|f=0|yNrGIW^F@DcwRIcoHn zvA>TS|Hp)hlO|7@>O0ME`iz;g{AbUZJ8%Aig#n8KgMvdAFIl>5`HIk$t5&aByH16z z->`Ah<}F*pw{4Huu`_bl?mba^qht2%KM)&t@X+D-BS()NKXDRHoj#LrHu2o~3l}Zc zOG%e=l0r^W$Vm!0Ng*dGz&oa*{$$QpiaP*^`2fgwk*ODk#kr#3h4y<9*NY zHg9A;%RJK^A$^&w{;q8iKAn?#=?Ggf9g0Jm)L{>31`IERd>e%l^PmWHg!xj(U7#3r zf@VUJlIRY87-$YNQ=kFNhGk|1jyKoJ^O?fBG+99sBYXm_Wqc>$U5ZMEZssD$1(P8! z)Pwd|40=jsPK0N&hB+`7qHvU%CbJe1_05L*;0c~)jQJWWfgjJ(=W}lpF786Z>}`63 z12}^(xtodRWvBq%gwJ8JCU=bHrr;#3oCpiCq>7WPc|z$7w51-Zk=`paHG|GVQ6KOX zKF4DrY^%@fN9IWL78p<%TxCt(kb78?wiV=;9bZ_2l?BG z4Ew~Nq$;UidImA-Gx)+DTf$}xyk-2-c-uIi`9tPBY$pfjdnp2qz67f{NPk34^D#2< z=XA-mADq8{wXmmg%SN`F?MGGdK63aCNJ-W=l`r5S+`67W4?S(Svf@F04&R6TGyXaM zir*EomwD?e5m0Xfnnjy_b@7E$_@G_P15=4W;@=^KE=xh9l)m_SU+jiSd z``N+iga0zf=rnZWIBeGrOX`LuUPsOLd+6dcDz&rF$ftOPJ9vd+R3MLm?-~|i4Qx4k zimhfHY&+{g)cX~C4fWFRAOU1RwJ;T#eKBw53EshX@*ZUO6ZlS{7yBpwg!hBztdZ|+nA5^80>iJhh@_C9S@xIh6c_0chQk@rb|;R{g< z#+h3>B%YK1#yxZt(dZTaE+%lC;0(E>Kr~7q%It-`?;AGIt;(-q$Ti}E3lF?n47cJ@N@@aNhQ3xky=pkzlf-}FQaD;WOih> zWY*K)vG+cz%=_#OctjdI{OA$>3NQJT?SUUId96HWThjh zsos-6P-a8hJLxr8^d(rc0}`~M>$rjX-j26%Q#s8Azt!M9O3(6`I7317gkA92#}UWt zhb7sFQ?^5U2jI_V;2XCPCsxyY^a(nQLP*qx`|UWV0eb!+R=p%Mpxt3GIi|A z09O9!|5gTuRt82^GMDNne?_?()>Qq2kfx?tOH&l^FG5;O)%z`Yxdp#s!Q%jXJlLRy zi#kK9&f;oVk8JKthT|a|mvTCSTCl@WQBEm`6QC22UZ{1YSm7dO0lY9=o8n|22d4C5 zEfm(>TFB%;7iHl@yWZFo4TnlRo>)b>&Vp^)8lALyJ=bR~p`dk*t^{?Pb&a~#l!o@G zsq)_B-n5I>#C_TAT66^GU2s;K7C>q@j(A~Y#Afs!k?9Crs)_gG3rdCHYH zq}WtW?l6!&ZZyy_LbD)ixd}C_9MLQ@IntKFAau1&1t(DrGF6*HM>Qqes<8||F@{}w zJ6>e1o)wHIU9~3O+^@@JE=^6|C0Kyge{(D*F^o~lTzAO?O*S-kBh8%RYm#cG@qw+xm5gv`lu1QO~h(vLj4|(`M`V90a}BJzO5-bG*@X&$uSDd z^u=@@Hz~ajDFxp*Dcc@WMz+T_Sn>%%@}UCV?j8Bfbxq64`;v>i%L-dAbt)ZzU zs)m#CVcj;Y8Z#TBSC7z!Aw54B6(xKa;w8eO!YEgdEH)?6Y+WkDuVNW>yDngq7J{h} z-4$OtG{zhr&v))g+w7w@r8Bq8UDm&Ew+(Zt*ZRiJ7mS&Y;VwHVz^~-x4Xav`Nyivk z1OX_SjA&{k8BZqCnQdz{)ukm*@`sXZlnWN!>Ybh26)E2sLD#&$QQ z0&I74OZ23RNZq|EdW)4{?mz(tHT#vT*pRAa1_Bj1MW_M)fB+GZb5z*9G!PmJC4-n`AI@+ZEa1 z;$7yYEL6HhROEBr^AGx0xbFCu5BjMNuxkLr>{*^XPhJ@YhU#HJ6}748UKZ3TOE{^hR0 ztF6A-vsfe)2{8dKg*h-3PP3L?L|N0#ud}Fec(BO$8FL%gz-^aEi4KcfCp{CG+avcl z@5%R^k|Hb44!Og*S>EhaNES?SI_x$X5)0=YyIqi7bvb4_>Kww6W-kOBLM^pg4Z+g< z)#KR*gQoUc`v+SG!I`T+uds&YjjyRO|G?k#8}db!r$EfH#)DO?a>gBV5Gj`T%{Rt> zhDKAH<1^Q!AIKMwv`bkc&|{Zu(IEh@kKuvW z&G68pIt1vEC>eMaN`@ZH<_BKf=7*l3Lm)U8!xJ3K@TAl35J+c$k_paY^Aj9R$)wY2 z^OH_WmOK46uitNDc)n9`cm=`XWLdkNrma@86Mcs(7z_j~7Geti$XE}(KA$LJpc8uB zZdFwj96}o}2(s*_8Ha43|Onpsp9nTeLH)5$U$F?QV*fkC=bO+t!Uc z4%2nV93g7;9o!ouwW7H=|L23ACF_Z#lSsmzB%U!gFkC<|ybpHKY7QUx+9>h@hEuBkR zL^6SeuozYg-Nqh^o8SfaDx#k!R=C&lTZsP9FtOb|6xv=hLhN#ngm%?9NR8Jt(BMwj zECu(}tRQSd?uR@>H8{<=Y6a06jsaN$u(l?qx!g7mM=t8f()_{yr< z8kd`M(slaU`z{FSV@OPQil6fpuP%LB2syF(#@x^skyT!Wi^G3%azESM5ei( zK%vTU@m0hsWzcy_pqODN3)m?THYzy-1vvwqjB{;VFNbqi=&K2}-)k8g?dikUhsUsGCt8c~16ufmcpMQHBPEd|WgXh0*fSot9Ax{LC_EftF$QKXEmrLe-3O zJC#ud#ucC#4ko2Y@hQ;#@@t}w2A)2U?amMAh3o**J=~3f?z}!w$PWzYsDTFt2M6Ps zV%99eEBUOhb48>I*<4%hO5WU+H>ll(CR4CmM$=s)G~oo7VKeB%a;8Qz6&uKAL3W-? z)6%K>hIG=$^MX~2xp>61NvkiC*0k6>p7)TX&&vy*`ucQAi-AwxICbuYeFuLb7ln

    h46BxJI3atCQEJz9QkenS?#R!{IEc*zJ#=C;NIc6T2Me z()UM?)3V^p+ncw4o;|+8;e@X!MQM9^%_Z0)Kixk4J{lr1xrd^fZ8o-;9Ogt0W$}Cn zWKb4)z+}J^01kNqg-`~!y@RC2irky^aLFa&bClCc~@|0GB?I)N!zR{jIXSbBje zI9A~Y316&O9&19*u5Atd${LSFOvW3y!Z=+aM-fvV>e$we#LykSR{?*k{X)>7WhJwlD zsL$05-Gqv*rpJzf{pJ9^`Bbt5we(oE2Cd|o6Fa~0O^v{)s~?L3Q-j`ev$Z=t+t`9?G{0==P3{Jgl(cg2Hfqx0X{$gm5N1N{^U|m7>pJCfUk9h!=RB)*P1HBFZ^KN>At8SeQ?CzSQxi1VajFvHfG+a z<$YY8VJ~04x%N!NbG#F>fI3P4H^g6(vgxMsvX0*MMsh))ooGm*T~^*7qwsPg@%gbo z;KFI%c*$XC$t`#|easi^u)p7lzNPv8FR?)=zeo&-j}a61RUxOI0Q$j9={k|~ZP;_D zp$knt`XIS!J4RYsrVa`PiZg|)#9Cz~{@C(HDE^#*+S>|aB;!EX`Ou7+!1RMTaQyrl~Z3x9tjC;9iK|_0-gV^43NG(H^bfD@OYb3g37rDOo z0COiYh%5RKPoe}}t>2SCGQbFXuU&ob60+bAle91vrPCy${c2MpWJio7gKMzV6(T+~ z)V*p^$#J~kBoByKg(#FU*1OMiFln!m!EY}V`CJ!fz1EaQ3&Z1vJXy@jClJo^SXWRR z=B_AE?J;_mJcB1I3wBh~EuPbtAXdm5S?x@k5t{C|)K@!!r|wuR&wxyQgC1T(m+n^6 zt&jUjyL)?k8{6OZPzk>ZdA5f8-bFyU#IE&oZK+FtdxCp`1dOn4EW02%w)A)23;y1s zi7rp$)y2Xio{4xL+Fk~>MY!D71A9eW^Tvn0BY)uFATA-m8~*&+lY3C4OjIpt4)J#Qcv31tlWly2pYHUJP%!k)kqIHCoX(#`~^aXp`B zdVberzuHS)AIVg@4ce~4ObJ{rQE*tM@HOpDk9=%+4U#*;lpEZYr~uMRv`oA0@KMXP zz3=DDOawc{aA&&s1qhikRX?~%>ljf!M<98@ejj&XCo@*`cu~g-JdPdunc46$?U`grAWEi zefvWrGUWbimyVDkvKHbM_wX0{3F}B09wdbQKWz#J2nhx^6!Nk1Y<6P8Qo6yVZSD!e zQl}%Nn5>2P#SRAvQ5kcw@;jro@vJEK9RK+I-)(Gm;9@0y?g}*U_pC9$;&{MC010_W zWq=a^effRySp(2+U(M{0}e)kMUTM zPdoRiF-F%2&6O)MrN-!|IY>FvvUH`333t-#4Lh~5oSWCr>Lm{)U+eJGbTLDWSE8I} zA^&(Od*#zd8Cu7)BwfDXrtKzv%Y4;aJ2}-?PguqDsiNvGTRYlz4_0e(Cv;GCcO5w@ z0an+)urFVmc9VCvWl;FcFl+wF=Kt933qo%zu|}entkQC#&}!4_bnv{TTrRh6?Q%JF zdz^b5WY(zuT4nBpY+dw;7jKaP)C6esme+EuwZ&9)aU!}M!fk4PwUzjCA`KOVlD*pc zMwIio{z?G}=zytB;8^tQgOGD3>;M;CTLDru!yskEA@IWLz=6ZfU0QFK(aVUT1SB;EqLgwjL^mIene4wC#P!MO>ck9ems%NO0RE39kmiE>k!^vytT4f+ro|< zx!J1Xp+Rb-w;WS)i_-PlsR?Ee^eV@rQ!wTv#w zgk4Bs9?(X%Yq&d`X}WGE8wUgYt7)0z%2QKX9yoaJ^OrU2q@r&0u1}WHyNEq zjV5&`4J}Q!DOUrabEQ#W|83Z{@v@TmNO`f1v|-V1w)p97>XAB>%-;u(`$|6V(U*(4 zo`21VrcGas5UfoK-7SaVRmk!oX8V%3cSAl{>$&uMiEn8oxStE-X}1O@*z?AH&^GAx zk@IH+1z$aQ7+VX5)gqQnXYlko=T*CIs+;@33rDIgglD^}HJdioSGh|!(A4h$x*{eo zw1SO1pGdj2N=4Vux#A{x4DBCY+ZN`-c9cJ>A$n z*&Pul($bor-9o!8jSEd)c4)8{VlOhNNN0R(0p=_pNefLo%M)Wo*_z;4o3)KZ#Wg3I z){5Pust?YaOzTG*)GT@%>8x2A#j=T}#FE)Tv(ULR{h5>K90)Y;o{ zU9HzhV;lQ5M|DE96bdcGI+O;Hc&ap6r%z1ARub<7M=ULM9$l9n$&~h%uNvxH+s<9W z#|p7iLwb?jGo-2-J6KIqkB9e`$L> zwc*Vai#l*;KT~&GVU{PqamHOeE||$oX>h-7Y4fSZbVNt(uI#jQFy>bus6VTy!GRam z3~U0YEMCg3)K6WiWjI$!a}=nh8VZnMzC9!w%256h`_zO(kC8la*SQn%gS0X~d{A{) z_f(j~`P+(lK;^%szj-^#P?vhJgUe}AApwUr2E$f zFk6o{0k%7}xANBIZ`k+e_|Q{_y1UJT_+!!0Y}~^WTRCW{^;^_e^4BO9fWO`VS-@TR z?t7{`fIE;i#L5HiJ=vnt9%wJ}ecI#hr&&qd$=2bpE0RR>uxz4Cft3anfy{qtEf%Mb zuSb~=r3YvsJ@HdHgSN1pjirx^oph-2y$O`#;$Qu5yT(BFt6BZkIjBmzSU|60f)x}Od3{~UBE%!Sad z|FLC3@}Y$=Bif7>dQ1F&j4D(|nlqgRM*QFZVlD#oUx?7-(fnYtrsrQU^#A@BbC3`} z5U2miS=2+~BRdoE8wH5w$6(0+B?J)RXLQgr;u{NyUyRC1W2f_DmzNfnp#O)S0fP|I`y3R%mU=+qhivq={WS9m}b{D)j#`Fzay0gDuh<%Tk!7Q=|s6w!isJGQ1E31GvK7hP>ukKD4E0He*17FX+2zI zm0svM(YGgh#%#7HVj3JStn95Ett_qh*LJGw`_rn1{H$wxM(vrvRiAGwet7-rCG^{N zt(+7`_R`F#$NJJZ6`KAizvr( zPhj?Egd6u{Ox_oE>@LSu2p`VmPC%RC$mm}bEw|aKY!cS+NCOM6Y)8B9_*1PHNHa#7 zOn-D*Zc*xjc}0RxU>ir_aO>9538K)Y)kXLyt}#&ba(+X+)r(!? zFs`p)U(i2+&v^&;_1(TGKKlLYKEdiV3{s)IMU0uBkPME2nGUwYWZk20Dz~nq)}<=D zuBToBb&tD2u(9rKV-5@$$12ZySm@}%suizDVbKF}@~5n4brJ^Y9!FAzN*2X16PJEo zg_L-~@_^VhygtiP*>iltrB}_6EMu&oZrz(smsqIzZLp#2jef>n;qEeIO~koo2tDpS zx_;-E5nF5^i50V*@P3F@sD7%jmUu5FBAb9jSRw*0>(;TqE#co&due(qU;?Ixjj%5T z=6;ex46jIF=YInMAYONeYId9K9NL(7*L|NR%wOO9%1X)a+ALV{3fZlvlI6iM93M1z zmzD6nabFc&rOX-_!bFKPrL+TQTMK0oAw5pwLZRtr@{AYtMI z85?LvyC6VfV7vN56^R;##I=#UrlPPwsL)UpKrufs@W5?HJv^a66l~7I6UVUuFhf2Q zpcB&I*Nm)Q;9_G~mZ5Kpa#Vk%A+d9iRz=F@f+t$X8TJr ztdlbZhPth14v`ZqQ+f<9t??Tglpy$10W|&_=b&6C8|MZ7*vC?nZTmK57)QT$@$ncT zQ?NJ+E?V$0m$pCx;XKo1V7Yzj9A9Zm#leMr(wNeE#9c4Q302L1w z>)Y}A8hBOU(!vVBuGk=ISlBK*bMq;7FECy}B;Ih6V0?cx8D9E7%~YyurmL}p9b^dP z$nV44FK}5q*uK4-Qf?Hc*?4Wp`TIFCqI_g|SNW@nKD|v{ znJZFPC+wk_1`saK&b^~fx3XtZSHL2(Bn;pH{ds_cL58_o%U9^1d@dj$LAxkGWM_}t zdhaNux|W92ymqF#7XO+;rWS^DIJAsE z&T{`&$p4(hLEnU0%G%EIzdp)_rp6`?I1Ds2)It`z#`ZY$bkqWd_WFia4mgzbbd3M@ z?d7Io0IFxBU^GPW?pq2c2C-;@1k{QsG(grSwO zg9#2T3k@qRGxg8(91QLL8McF=fT6y%fg$yO9B6UqX;^4z8M(Ord)vT8LNAhCZ4eca zhNPcQuYvg>QIu5qx zK{k?C0$O)n2P&!(;Nz#Oy@hW*bzUGhr7$^xEzhV(&$zj`&3XKEIsfVPym56ef}h7D zhF|1s+5T+dns>9|b^4lEa#1$5i7o_uAP7x-HyzidP4LTDj;?JLZm-v9{b&i^e(5RA zDX1C70it))i(@chG#2v8L7~d+GMpleq!{W2xC5a;9GtD#$Bn^q%YvOHpxwxc&WMYB z06DAGaAnK!V70iye&|AiZ2qwZCu?lPi;w_iM=AckTsz`rhnSF507reYNB3g3o(ZXG zRcsZnf)Gcge7F^nVlutgAJkk3u$Vf}Y@}xty<}08#5jT2CMI!|Sei7wxcwjkne&$b zI4U!1^W=hnT&gohIkYotZOJAx!dQ>7CbT9#h2#~lCgSHD9PmOWHR$*J;O#v+_6u{y z)8)gN1(EFFj_pTa*m42I@Z(p!^0hIAsO?Nme$JKN#}-`Xqjiq(?IWNMF7J_X7eea; z$&SSCqiYxD>wSKY2`uA0$jv=TIgzBQY9V4 zB^^Mnek0UY%6Wnbme6*WkYO=-8Nn+ zZ{@sXT3Ib1%SXkps8$2hcaT~A_ph8<1L80ETGQG0$sL*9yVtHT*gNT+`h5 zimprPpn@!G`_d;tS}zc9`mlSkA#f<6v?)Fo6vEI-`k5T($SZ!8FKFAk%ulbuSqg}XijN63mU(#!+Ke(#uk3wN(EFfPeazZ7|aO2vNoTUCDH%5`P= z6psyM#b@Ql3jB*Aj7rmG#|!smt!BAurCwu&djWDmoaK+=M~_fh6Y?%;6W8i={r6tX z!`S!4AEecv$@ZR^-uvl4ypMZ+r*)4!IDeG}fgj3IyLTMW-`F7L*r?K!sMM55NCQ2p zEncLpK|T+k!EdFk1nS8IHA0V!vMO-dTr!Eka$qt(K`~&)c#JUF+OorMFCyIU@6-qE z2?GDIwbTOBHU;QK(nO{irZvIfQ%KD`^amcdav7RH85Th~`ceipdH1uv_>jX&@5&a% z##gG-IQM74`PbYN2d8kO65E3O)-;?ozD}YwF-c_4-YW1i(Tz3)A-IKvyw@zuU0=-I zSj=91VH9g&m&K@?HcZ_hOx`mn##!dRCZa?&)50b6!lm@Wr2{$g&V@8Nz1JVb>geIS z!P$d!z}K?`#V@{*>J(VP)ylZFy0{oRPYIR~hfktr#LmG>0qgtlJm;3q6U{3ex9Mi3 z$M=F;2g-S6%ux;Iq`49y+i_tMEf_Mu&I~$-Z6d{m08>+^SVHIcO8K!6gfPPS^WNIL zDmDFX6ia>zQ?2S{tbRh_$-S`(jS3e%pa$IhjD;9A$w}qs#e&c^0?Q~SW%azu`6)B4 z&gL%l?fh*0$kcH=%q)`Yh}AlHXfyyJq9)%X(vN{S=?G&N`BxVNa#=)R4pGr zGa%VOH(mVZE2d4!&DkpyX9#EWXSZj>=4JX5+xy|>Fb=Kg$=L#nbg8B$CH5Rnc((R{ zDbgZ2wo^W0|76rOI1>lPH}q7Yq}mx3vkF=!^x}x$s`bILDtyDZGdAW|YF9MQ^tpe}tq!gBxsIM(-ngUS*i5eS&mnkEV9ho!u4#~hn`TE}Cg+D%M&e}0g=hPv+G zH)}vnPmhd`j*m@_X{NDfJ#QIj_xgol*7zaT z>WW98wGXYhM~g0?Fv6iHt+cPy$}fgsA|lF$;E~`U)#M6YBVMcs4hF@#qBC9t)k`eB zXQwtUZ?xJ^WwaW1xqEFdlaw0CshUHW+naluYno%4OPV{DhcB+GO{k58B?%|JC$T4~ zC!MEuQq(5#CxM1X=!Mo=)Lb+$G&9sPG$k~$sAo_RV&Y@YV^*&Uj(97M4Q&ri4=oQ3 z550fRqd7-X2U_L48GlXBz|~nee0UnNN*6qEPa7tV)RhW(zitR4G-Xf!t|5@X?NjUI zkLvZdtoAS9+gdJW!i-UMy9}o9mTvw~pPqG_@aB&G7*67><4T35D?(SVXOOMIGU}sv zgsKQwr$I;R^|%S9gavh?kuI_VrtnvA`3<3qI1$*d6F3a}OMMrWBalI~fftsTU=4bk z-&^H3;0_C9K)wwm{LY_@02dKo>>bDqc%@4p-aayFk$`#|DF$ccD}Q20-(DI7FC;{0 z|Hd6?`~WL_T?CgNli4Gc7QlUh!hPM}67Zc@{*E+2MEwdWz|T7X0lQ)vfdSyCj2*t* zHjHlhFmHY8BRqhXG$1J_!Cxpo<_4Q8!K}2%M?&f!h|B#DE}_0H0L*(t8xiU@eKri8PT{c$o#h0SHm1B$Uhv<`&`VU;omlhRl2+s0o}U*6hBJm z09XT{909Q?fx)#TYyDE7LLd$U_$ZNs29?ylgtWl=yNm_>jxD~0H4JRI^jL!|96`gk zf3gxDDFMcHR4IZFZxOPF=v|Peb@2l9fht0%R76L-A*TC*M1sWk04ZYrAn$^64Jmlw zUATlz(?DtOh&)dop)`yk-QW@IgDwIQ>$VSlCdZk26Surhr2vf6r=-WS%V0l5R-8cBDdx8AMn zi1c@9mvJNpxu@EqyuuH7wj;UzI~8Qx;t~t!5rh8%D{P1GL)^req{SE)W{vs}eUmlo z?+e0z7@W3v*~btbvLv3N)b)Xt9)a;JsnvIkT~o|2MB97o8GX(#RNMRSA3oT3_+AsG z9|75S^iuoBE`Zi|5MHCzFO0?a=qo_&rdUgUov`4-H%J%0upvRGut4?-?2B5Ca+nIj zi;9l&n~E@ts*b+LDSWXUsvC{W90`k7fE0s4H7Mx&C=c*SRQZV-rXcM?xKwH)EYHx^ja_AXTJcN|&M5H1+h$AKLo$l>_6ZpWe?tI{6oJ}u3Q z7nAWWP}PTydkRbF`A{(W6)folVnyW+kyZ0hZKBO5OobtA=pktA=TvRw1VwXWqO9RW z@8pa6^KBgl}P%fBt1F zDo~ZhmALw4l@N!l_ixhNOCVz3)I3q z@PCRpnEgm}#;_KhG!)PZG_Wnah|aBWmV)Gs59Li1JLYL8}&ngpTG4$p)*@<)j6hvuXX7g-&Ae7^F0M!tz#p7t^4}J1>@yIV~0kCa-un3yoAQz zf)z{kr`8|CPiwclycdomohKF?TolA)BGkq6ImwMkfv<|(5CtWA!`=kC|44@Mu(^_*vUJKxdYhbTwt@c|1msr_85XfiY=;RzXc!JHE8Q^cM70nSFW;L{ zHaWvLD2b#T6@8{%PrH>77(yX-ehk{o`;tkG_qRc{bSy(PDe?nU2vWLp=feTOR~%Y5 zMTMfj^qq)qZ@>?>uVcxvZSutNQ-Ali83)H5B+%w1rz%q7$RW^lpng|bo z$f4@x0ec*@&)PD@@nTXixhFgh^tr(&jhrglkmKLWhg1RK`${Q>8F zmuhHSx%RwiSw7)hU?yDgC0iOn>Y;TOKT}9oFrWvkbS#?;&S+%U$?M!@m z5`p6RFjbe3DNG29D0~9q(WWpaeHVXo3{oQAVCO={J>qmTS&=Or$4p}Xg3%OHC7M|C zXf4C_RXki}U_BSScrv*Lct}NcQf(CIk}&Pw(iA*yzmsGA?n83|f8<)P zy*cUHw$+mN0FIS2r{xkpw&;^4(FIWek8A-2)u5CoHmPUy5I}oDauULu44|8E!VuW$e9mAN++P2s zorvvd5~sMgMCh!dMLRD3gB{R1Hw;(fEm?rgfnmyh&0rwM}^(0q} z#dl2>R^!#*tV7bHwB<}w$?2I_k%c+(-a4!O;%rAj z>1f^XY4bGgUP}|G^XF#8lAY~EY$}X~cgbYrM5liN*8WO@N~g26_4nO~K{K6UkBPyd)m_<1B|q6ca%W3&U;*a00A6k@(4L6(?;Xe z79u#8^abK4QK%C4BTr(jtR)!>J6M0&|4JQvYeOKnGJx(0&xazFy5b-)Ogf#Etyi#a zVx$oiY^WdCSU`$qdI$6skZc^qD}P8NI=!Fp%faV^Ge(mSO`$SIvyALSTPrOr1Bui$ zO;jTCZ`E{DKCWvaW&8Vt5y(5SZh_?etT&2G0*w7P)Ve$V99gKrAkrv5s8*BSdk(2P z9=&Ee^v@8FwicW?8m&Ypgph^lG7b86Qb@W5deOo~;!62gRkeEbTEcwXA458;L@|~Y&RmA#=oC7xmC~m2mE3u44 z#BmG@!0A@c%!lBL%Ms@-rbLhA*%3t!(DDi3k8GWBxlh)GLuGAr;)TZ8rXKjAmSFj>SFfd6Gl!{{hM|1g}uV|!;!bqs;dFk-qE zGm=JU+S;;G*HqmY;K%qeV_h_P+i}v?8$11GY*zxd>R}By6rARzbhe`{6=plym&ONF zB5g-UypJ;;NzO~8CV>|p(1^kgmD^OCXd{}9Pz%E%`?%YY_YZ`Lwm4kLAvpM|G$V)R zzD;AaD$TPr^)`)zCS_@1hh{%^jEQu_@AMw$NG58CGpBTx3AMP3C{P$EtiX#Qo!-*K z;H|JsH%XHQk=V&Z-rIxwicB8boKox|`#8yI{#rQ49a6lW1}UU8FgEq#&_!w*`mo8L zDtEY*;Br#DImd;kL9UlVR1Y~3;#^~l9rt>3wgz5&t|S;-sQz<#s8zk9Uc?X=)laFZ zsZ|~Nu%$hISeA$}HKc|TiP~vJqHubl5HqLyF3&nQm=s%$v79&pdnLgstle zahR`nbj_hh2XNWCad=|I3^{Gx2v4k>G9yRvBHc=iWLe4i)Z=yw!O7(gc?&#SJlq4v z2>bF1W_ZprA%!>#=M~OirMbNaN^BK_q1K_0Iuu+U8VXTU$X047gcmCuGkdoEubsw% z!6I8d+%@g@-ntVtf2}<+O&n&$*REwg&c1Cueb!|uA-_j{n!swq+b55&AJ09KXFR{Z z;Aqj&^0$lLF26BeVcbU^NsJ|rtP~RRyh@%Nm+JTCy3~@q0+(8xKSn7m&My*Ui}S~E zUvYjZ_m$+8ai8B?F8)JzwFWnFUEzE0S}SYyT4|+S$+9iULXvISdRW%Ot{ra(&;oT0 zq_)992I6r6(L($R#gGBVfE}0EK(Rwe!E~B*f`iiu7@`_yU{W4!Qkpche@IHhjQgt< zo#{9=XkLi>&O_9ft<(O7DrgiH? zLsf%rTt{?0PUe_RbqvM@=Up&VIUqe#Zf-tv zV}muI#&e}(InLt=%sc#y8^qT1I~Sc z;V2tQJ-qX_x~kCOSX5b-dibeW=5SRebK|AFCg$KvgHAOvYht0G6PaVqVDLRn%%su8 zf*NNmN2s7vu3P(i7Wajq?f=Pi&Q#f`GGZoM}RdNe! z^QUnf9zA|8(&dr!moZiaJ)&oyhw`Mz8c|=$3xeJ5aKz&k6(uF`?;nahf}r|*p^#e5 zFhL}uedt2~eu`*BmBQb(gWby#b{Y>O8plO_ouWapS23cP{2+^jM16X$BQ1lL z{r8#q&l?CbgnTZI>gFfSrat-Chw zPHuf+(~(XJlO4v)gCfqIJlc5a3)Mxs zm>o>4-{a2k+8=d2y)z&e=$#MWqsO66sF47*!VCK_rN|t%9?m0Ma`SAq6geU4Emo7o zVzt=JdTUqp%}n$K@Wd z0*k=X61^P>Ic7UHFko@HV3igW+i`^xM48ubM?n_|9oE<}uK>ZSjdo;Gfwe|MuI>}VU0-z3st13^!>2x$J8s~s-LD+# zmOG$YtbKS#;e|NaQ5lNjTJe{?=1#s-==Jvo4)Q+@`~l^T75s!JF9iCdq(6VZlT7h= zqp-&5#{4Ev`U{5~WQgg{C+|D1d&y1y zT^pIsyKW*|qtiUuDzt}5djL0u*GI{+aEqPP^NVdHm{(;d9@`=ZLFMIz<$i`iHl8mq zJ9ysVm}bgN3{&nYVR2m%6#`qu#swxBcwRw#6Tu z9J?(287s@Jmx62B_wD+gRM@k0!`GK@a=CE5bn)nShM!+OIoZ~Be9y~+A3xbSymyo0CrI`qRxp{Q?x-0DfixybSy;+9g5zRgnVI9t;l%w7_mlW zF3YBH_&gfd<$@Ls%5hyQqFBm7QPf$($wS$JGxudM!s1z1BYP2hh(Rt}VOj~NnZ@{z zqra(dnd#f*t#tujq}4O{bF8~}JM-m->xRZIy(8Hr$A7)QUDOnlVwR{F79*odo&hsX zVbD`(oNCnp$Dd+Z(g?=qQ+j>Yn4QvUv&LUUJ;RVjz0M9);H+_Bjxs{OGEdHh43%D} zvfeP1S2Ig8auqJB_4fA7wA6nft;V0?yE8u@8*2IJ%gpV2(%+<9n59Uyk>A5CE$E=Q zLXFjo4cnL;My1i|S%Z>RV`72S;FKtb$`y=SrIJ=yV06xCVD(y!+LWWDaxp_I)CjQ- z6EobSu>0SMt%wKCVi5egxut32N8|JmFLP3<^V6}ix zpp}o3(Mv16kf)-5{2LrTLYX!n@bB%d-SPeEh86K=yDR!~CWqrC7nZb*R+bHy>LP=U z4TCSPXdLldfmEYTl+LNnxd_!gF51y{6?u?LZC5C1)pq#G2MWBsjx@lw!K#rfadzFE zt4Y_evo$p+Fb7;|E);YdfCd382Kr+lSn9wd6L>`GNaLfg%ldU`JG^H?x`X@CO~jyY zU0{IlzX2{-C3><{95c8EF@%B}M8}oY4QK<}f%c-)km0A*GCha)&dsvvf3jUIuu)uB z^u0GTJNud0otgcAJRak);4H)r#@MU4@i+msA-JFf18%XL1d9+a6*wj&fccaXej#9* z0s%n_6q-81p%@z*n{_jIgA`T`!5%k4vXtccD_H^U?(D=}>VeZ1h@KZ8xf0#d#ks*t9nV@WJl7UAv4PSB} zM;Z4s?j*;!m4t#R2L8fxPVOdQHzEI9VRHWT>JYjIsDPPVMt54fHltvPgdb~7YfE}T zSore4KJ@j~;OkZ4Jn$-qR-a+WmV?k>+_X4^12c>ya;QYYDiTH(Dha@$!Qlbl`Vw#3!nV4$dM>#Ihv*8i8Qxj`nc=6SbG-}w3&YPvQ)0@s z$h*{^3cnCt#a_3qbglMmvArwqRW5}-XIE@jTwi!1_rq;+n0fhAiyV|V6zH>Ba@8j6 z7fd%?H3+t^EjoHjt5JYcV`6A5Oj_GWYDpRXQ8;R9yo!buA)tYXSargyp!%x{R0Pph zofj9!BYpZ35;_HRARK>X+`hEH4$pHJfl}F zm4v}9Q?&q%S%A7NKw+27Fv69^#KI>c2_|%#LUt#L1ZoJTz=W`?hnCYfNroDY3D}o0 z;{#u?3ndj5C{EaMLfK5@<*PQESOP38X7@TO2j}kld*KRx&6CZ!AAGyN4%b!=xh%rk zbb4_tmmI1hhrC`}wT!8xs@CAP=};6H={`Zn6b<47x{i1Cm>cfs5=O3fvtCnT&S22U zRaC}|Tu_6;%L8~GAcaF1X$7A9reN~2`x8o<#;gfVheu`Ed9Io+&C9BFA6~IZNAEyvqdjwqg zu2Y$0M`xWtdBM6<4*ojR8qsWjgyt!uv?R-bG6J2;t2H&_{dw_HKs;-PP=qt47mR>S zB^ci#KW(S>?jTV?s8^XvMqFHXI4aJ%>SpWSL( z@cy}DTVH$}GG*TA4L$&wlAtwXz`4R96Zbz9BNS6LA;A|~knfZ|l1Fzs3;cSF*9&4o zft)W(p)lA8L&4-X#5kgekH-s9eFh5gpJ>U73Me8&fZxys<${(}`Vv#{K>Q{OazLIT zZU?!&lzT3)RB7O0j*&21Vorc41qf5tn(B;Y1~WpK$;Jk;DQ;;~oRYW_XAtpl7v71tOb&I^ zvi9&G?V)8*NY0zC2WmB`oBsGzRnWJQL_&=5^%mNv%J5bZzl0pXO@n-rVrY4qr#!tq&ezmdri0`NDjkSw5ZrWsYUVOQ|zV6^-`iDEur~h>Wf{uU&DBxV3usLya znzle%A{~%grAv}9i<>3?gy%HKaU$6`QE<9Akw`%HevbEX9M8#wNiz7UUe-(OgweyM zlkhw|Li(M2H(T5#2u?F6cd9e1gw9N1vIe)U3gzskrKT*J>4_ zgelBm9K#>uZ(wlk4E~07y1VHPYp1^i^|OR<80Dp0xuIA(s0^3iEmxCCI@XBtKpBt6 z1Ka)d!UboE3^iX%g5+E_UByXm+~g$3=j4>*D{24?c*gWerYk9Jn3I&ucv2b{gU`uH zOKofNz+KT|wb-Apaw=teM>erT?_9XhkuITi$GJ0K&pe(!0;JwEl7hs;+Mg%<0yK7B zhB;>mh4sm}AR2Q!b-zERp;Wj$Jg>)OHzi^S>V@S9tbxTc)HGxX<`E>(NFOi*iBX_g z+Uv2-&qh||Y|q*2eb4)ebVd3iYIk@;?nfh>qev)n^?;6Xzz)Uh^lM&kzuV(;dwp(? z3=}cF7>MaU42Iq9G5vHbs4fpr2a!IYYNmnVsddUSWxcXX;T0fB$RbIIl8_Q&p)5&4 zErxcEmJko!14&iZ?(Y01vgAHYmIrjHMMnu7u@+jZ!U3{yZHxV}ga9ZKOZY6!qmAIU z9-<9!#S5O71HKTyPXs3rul~@#f9b}KwjJ|#Ol;lBJ{#$py=nJ(YG3j8@b5BZgcSJAaq0djuOyd3fnKN~6Lk}MUKvVN zR2ZlGWT#Hacm<1?<=_-Os33wtOY?%3gA0z?t%1t}%5Sqs)($CswTR^8RG3Z|P5<=p zbmM#4TqDKRi}m&ft=?E+e=YW=eRJ%J{c=DR4cy`h8BW-$^DV){QJ!@}#2XWgd?OEU zs2JrOnL(UUI#`E5g6KK2F@v8iGd0pVzDcowgkDbpmclCTbfF_rS|&LWIh`iWKt-@F zxGcCn$Oi*>FBrh-g5B(q(}|2p111jL2XRdCETw}rjvn5&%N9+^7#4!5;kL^QbjM-fZ&{pji9Ir57TxiR8f3IGLmu9Sk0isCZZN~1Svu~YHLj`q5hGv zF*@orrFKH+W)daFX<_Z}x7;D=of zC?|O5V2=X}s8+=*7RZn{GB8GhWpoNN5oC;lr4D06w`8eK(HOZUL!I#-U@58nYJ>~O z>2tgD|YC=UL(IxUDs>Y}@pzNJz%^Rm`(yY|MZ~$|>FWY9zDaYqqwCJL2 z=>p#Va4+-E&X#vHoA$5X+nsP2e*7Mw?u2xpi*(>r-~*WmjQ3!-01`d3C`J+;hF+O9 z%jWfP>~xRK;xP)e*{BQX(OpEkL@KERi4+%3^g@3qIWc`mK^ezCg(un<`|Se#xLyB6 zyWYO`r*7f9R)i|9XkOlgBl)!+2p1288xLeicP3IC!(;2yd*otNO{O>LvhJ(ctnUr(SC~kUElni?Mo{~z(#}iNl;Bf+hgmH8hoV3$*7md)^ ziz-z)y-rdUGCL9kk}M&q7rxyy+gW!OLrk8Z^ViuYER9{YBYW$!6P9L#%>KwYVCI!QA3XsOUfO>dE??ig zWAzVrH;+CkYF+x_w(Tc7;$D{aq=%s5=~%tZNrVDYtb_m_=>?@sprezMTAb;$qE4$` zQmgKCtWN99bn|qNBqoVVMJ$R5APk`{BP}v<6_7GbG8NHuSFWT-X6qm_Ti+N`ZQ6b^ zMbSIIpKubBf_TcE>I|Jct$G*#pH;uR)_*LOF?k_%PQH7wL-nn6l=v#}CdX!XrLW%I z=xK59^Bi)VaDU_;cHCDUDN~+vv^hE*I6v?zhteqT`baZ5y$YvH_be4xQ<8m#E(t#k zk3(`d4I-%z<^eN7Wb1cnwRI-N>23wCyk;lIRny6Hmi&%Q9`|C?0PR%cRCu%mo9nO-5>pF{nzjR>J}RK zV9QU=ooHxmhs)&p*A{QRSuHq=H$ubBdr&^4{Z)IQ{ax!ieG$(&+;io<76Q4XXD$%? zvx`Y3h{l6lq9a(q@kYdj7#xBeV?rUKYXDNnUbGw950Z??R8agRZa}YtJ`PiYS$0g0 z3xk7$xO8xE^!VT)`R$Y1UARO4Z4vBLGwRGc%m>WJ%wL&VvX`l*9MgPLv1y&@yy*)Q zZ#IcMU6T)S94j*BQ$&1*RUaE-^e~zLU^za-m~zeeYz9-nAccWUyA%&8G%`fgr5w_+ zT^<{Y%KAU!K?3<21$j_g6Av^&SME7IB;Ihz?7VCokGf`GYLTmaCD{~E4ZdLJGQR^H zC{u;~cpHl_%V7gz`%xLWiBZ`(q;h>QOvH6qwS!ael)@mlfeAsnU2pIuWqJdIDDMDQ zhPxp)&|ZxPMm3C3QwKcMrCrf3chTC^!geN~;q=-pP}5irGQ1I_ zV3>jtpTaO)3ZcX!=sH5^A`9F`=rYhXm&il%eUMQUC6%Ik5YiXSBXmcR%NwK`*~{dQ z=Hfrl1Fz~BJKXVK8E-@T8KRUS@fL_?3;{zjW>rWtX2&z;PAM3NIN&xYEM#LD-;a=d zLq$=V^8d&f!XSM!b4P<1jy}Nys7WjDf(0-B(D zp4UvPrdIjoRf-i_t9-G_kh!G8N%kltkCEXFk+}8g9J1>6FG5}*5`hHTbFy>ja6a{X z4DBHi@wA)ZP3Unv>+jF~<&WzQIWM@r9rz4_vK=e3-KcjEZt&Zxit^{Cf3P-x!;#is zI0kPGf4JuTEla+?W|Q`=J}0khFY`Cp8(;w_0pF@6j8|41UT;d!k|n+*7CK+_&iBtR zTu{7RtPhBelmJXM&X|@O2)eWL=A{%nOQ)^$76*z8ON-Yz*QHbhe&nv7R_ovCY<9Oy z+vnY#>JsI!2=Fp0p-fU*ra5dzX5P_{7J_+T5$f-rmyb7kTv~vB;rX#T6=*r09vGNuvG3~i9wCq0)lTY8) zDu=((+D@GP*@jzNYybAnZ*Gs=ff7^(u5}J*cmMLo8EG!Kc<;e^%>xyCe*Qx1pGe0) z86)6U%Jz{d7hz=&6eS}3Q16om-LZ?uI$EU!18l^+TZEe}N_BQO?5#AcI`Wf;LC8aSR8$hCnJcnAPlMwKWR z1BDk7$RmU?y=SNQu)+ulUp=u5bm-u@EZWW+F|Cc5HI*+#U+jztukpBGHIE1^%LEcW%9d4IQ*wXoL z(yKlws_Tm1d*AnayUW`TmStg=x4Osf~b1CT+(- z>(?Y^)O^@zI!diESVP5t4p3)Q%1mdPIJN1-k0!BBt0X$bP~#YD*rn&*w;QegW2bL; z@1A$}@!mP-{(k5DZf&(6(8B0ByjhqSjlv#t^F$vTS@VI4wpkw>bPNt|7OW9iJF83k z-mI?R6HNw-6 zF<1!fvg#$gqQV)PM3#|N#;S8Uw2pzYMweuf{eu7smj?^_xpZDh0WT(*I*!Rrh0~JNb+g2P|QqIkFdY3mm_T0E{+9lhx zXY1#_R8BkB^0Ci_7ocYZ&|i)&BP#<0Tbn8t-xuchsb!!^_GQrH)&$znhQM~TTR6nM zWAEd7?0>MIL6-wx1)L67z!?Z|C1SC&B-hBBVW00=kU2m52g0*~pSoUg?dEnlcIS5B z{iMVBvBQl#$gg{JKM%~j_>(9%I7&4Y^ z)EhZFxNH%tlTj#?kZ8Exw6+>n^MMtJH$y_BxCLjif(MCn6+-99k|MMZ(RxS)A>T7l zll=Xa;pDlu597LlPx1Jw6BPrmANcI>ogUbreGufV%fl5&+q7)ySVbEhG z$)6X{9~ydJr=fQ{4ZYy~&`a6zyO1j{t9!|u!sSS^C<`(#^J2Eo?<1n70uNMZ7haFo z?d8NAE-Qpx4!HQ_+z|Gv&JcnuMx!Ngtiy4N&@6A3*OloZfX{Gf(i97zMS#jZ_}_<` z);6wbo&A#?r#B{#;Mk6L${%g`#gArpCO;JVGXsx5o&3|_yUFCirIR|Rls|g)z|hwv zL5O-ERE94gj~aT@%oK&7EK3sNc$!F632I1|C^`bVt5TZB%`{ZQPE^00SN;#W+Nz$i z0F+8v10!s_;pXM&{X8u%gQzn@sdFD+IJ$?6j(*H-5c)flweKbEos>l&0{M*)gMwZ) zqb!DP(Eih5KnTAyh@lbU*B-)eQ)713A;C>%)KaAa`KgW}kNtP7h#j+c_xWYmda%GV)3KB+6gZhB6m=$zz zp`fT>94QJHf`)~-ik1)#h8$JZj$JZ+tn*>k`QmMMY$uw9I=Yl9 zy!0X9C#T?dPsQ=3*kjnSVV`4PVqb0Ns~UaLcyqe`q$-fLj!}w1;8SgNEMCgW5QZiP zkc6`UuKNeboq>UbDD)=|kfuBJq&v|7KAr$Vt%EFZ=)bs4%|uXq0Zf*l%ilFhfxyswzjc-mz;v)H7yK zhcv4?FvDuvbjI}371QE|8yjxZJ;%Mo&AV}g_VaW}yp~?nPg6Bzmg`tLl3_jGY(+%X zBT#TST1$5t?x|kdG^b34Ks;>EQFT~az3j1-#RH9})}K0!+kG8Bt7~1$-5Aa8{o~4u zv@U|`6XsGx z0qQEMBC7(&^M;^$1Oe`VP9mswQB{#ZcuXWsMzYEg4I{pnOgA&i1l%rk2`7b10x!&z z>6}(3VFOfnm&Cy)Z>(z2K$aWvd_8gGyR8^m!)_6oDb@SNGNVm;N^EF~-fg$P+XQiw=^h$+V zst(*h)^{73ZejfYoX1jP7g;}s61PTx{^Q8G#BWF6B16}byoDOR z1W+TORi+ISsDJ{J4Z0;F@0uAB;U2p6-+DkUi4Vx7p}5uaEsBOR!M%@wreAf!C*DFx z%m7bxa`_0ck}5+DU=>n!*qyAqL2&>BGIZT6rk2e`e-<)qoPscs70rQUg{YdyxT~j# zd*>J}a?v_Ok!R49$YBN)r1Z5pNJkt+ES9!)}(G=ip8!T?of+gd?n~{Z+Pji6tA?I-?rNCZwnnKaNxJujad@O~?S|(=$*PXJ^ zTv&|tDfg-ibc~rhC@gV79OIaWe7k%XVJm&DzE+8@WOBkRv77E?9ugiFhXszuEN2J} z;xgPuFLaw+yYNNP`!s%r9&wLw$LOEAT?&>&aSn?i+cD=8ggGn+kn`Ou-HS|wF~@nl zJm|hC$|O#!l_3Qyo44rbh*iyY^?^+tRkV#-d%&0?WE5)M}znovqZ{mk| zmgm4tJElf}FZ+D9n)$4+xofLu6!U7U+Ho=ilmFpl6ay@%VGJ`)gi1n7PrrK(^p#7& zKsjPcOeMtN1%>hV^^XK%b?|K#jN)blI*ANK30 z9>vZe{t5dQ?Ac+cNK?RWfzqhc=BzdT^+DVww*`CU-XO#KlAth@sug-YMd!R^-JD$1 z-eUK|MN?4(|4~i&e_O!McCe9|Wz4B#OXUG)bI8V&`d7zuLn{M$U8g27>`glD2i!2P zUeD{9^kH0ipnb!El^@ub?A>VFi-)ZxwU63+*l|%=GrIA-JvH?U8tvQB_ee+}%;}!q z&wc>R2~ibjo%!S{{l_|vXpJGv$C)zHjRnhs8CMlsqgLw+*k*OUzJy((w(1t!k?GbS zV7Jj**?sgr_DSl8^iQc1^i}F=_!f0by`@FtY&BKIE?^mpJ)n)~S9K;AuF~tnhTf{R z#ut?>%Cza7T(`d?)D!PXbe46cy2|fk*M`>X+w}eM{rcP54L!nZC|o>ny||6KW! ze5p_kEsNSrG&h9bHBgz1fXp85OmX5;Xoqrbgizxez~wCEBc z{QXmZKDO}$@cd2tJrujKuCI5^A**`W*w*_J>U--=^!4%I*w4Oo)_&))+15d1oJQU! z?CUl>Y`>OY5P_H<0bPF%n6FXg=#H6Ico8WL@t(4^+{QA-BRg)v8Qsp9CCv-jGJ)(A z0lpI8OF$W$e(#JDt%vi6XUg;SesZ12*UQDTR6N7{AI>E7!aO`L7tdtgYz2@L7snT; zR`7lCjq%N%hs8l@r+2sXlyF=cll~&UFUjC=Qhq7u_e*}s=TTxf9SwV3ieDCdtmg5A z)o3KClJXHDK~q&KUGC(t20ReCq%IzG5eg7exJv2iBE3jCS%=F-R_wA;*-hD@ES)Xa zK5t&T{$~x!kY-?MsT+XAZYM>^$@9of4OrutgkpYI!(6j58@PjjNWtdeul#=Nu;Fs6!BHd!&^!v=;*f*#-IArGg>3-%x`dbW> z%g>{Y_?PHb_mae-vW3}}{0e%dyD!mIu_qvAz$-ZACR+lz63|N^Uji8?6orQiAXfr< z3Bbc2n=J%Y2znN0>3pt1s?RLUEt=hv>dbWHHt^pR){AR{YqUXrtFTqtE^o;`nA=6~ z<@X4CrN`u**++5*gb`^Zlq|aQnzXLO^r%O#L^?%PMir*6R;SiLatSqqu{|*y%Y}uS zWIl&-Y?vj&;<#}(S>s72!?aW9szD=A2EsD6KlKeD*yst7^2WvvQLM$7ZQc5IO2$v-%%fCi)AyV7l>k!&%ze!|I1{M6+ zQNzhX0hgz&>YHSkBr5_M`-#N@2qucM20mpmXknl+iRTvBme;d+U7uIq&@dNR2?_~H z=n4hZFrzvoC3>m%ofB4F-2TANS1j*aU~l;9ec$-@M?X0F&t2@e^xW~2M~o))Z?da3 zHj3*C-+Sk=ckbMooyX4ZtZmG!0mo(wHnIUPZ0bqMJ9RKA6*%b@T44c6n?iU+B$3FE zh5$*hRH2d|=|f0WqSR@?_#u#5O0A?QO(LaLh*jZAh=NH&ON)OL@Gd=fc9)0h)!chL zn%%v7&Ue1^ePiqQ?S19;TOXEgyot|S&%VCy(H%>cZl00)UUuQJ-XHyb)7C$|Y#w^! z<)>D+wLR0ccyRZwPj~FRDv;U=df*hWVhkM!4TaQ0!V%$c3sc>14L3!NIYt7i1 z`57-`6Sp)?K3J+%jQ;*xH^gaw35u@)PMbhuA#04Um)FyCR89&QBtbW~%ZuqUc@^Cq z|CKTkk8woo5pw#ZswEmpRg;sunw(hTz(lZMU1TW>K@tba?j+fm+?L#zl#)hcz%Z*? z02a|9tI{E>B8AjWSI`xT{>h1Pe}56beJt%>#{)WMTsaYz)0a_Q31Ev73DV{ zDIQh%llvYd`LMpb^JnU>ew6DxGJrlI`O-~@1Mm9ks}S} z+%m`!!(Ts6qPBGujA*3j7*aHIS zH}V7YfY!&)@atR;csD09(J3i2!LWw8jwpO&XQvqYIe0hIw16rJN)-eUAxeS}MT4)p z8ZdC9y%hHnDpIL8<+>@}NBb!Jk8x;_uqn5J;KStSgb;DZ4wP<%w1NZeQ_d*Y6$M=A zs{{JRx63Yc`z7cmarqW>Aq6rKhit>-k>Vde!!OO9-Y^Hh_CfJ1IFa-F zwmtv6+&X*`l_+#E$Wi5Zo+oWvb&v-kPo%{tau6SHR*rCvBB&uU)XH>OR z#GWGg^^&Y8M2$i686Z(J%y^t9T*vW}Dc=VvnIBM)ABdehw%EfbJ+PceAq0G90%PPW zl-7HG!t;EGYg)bMKv;7E$(Tk*K2QA*%UzT?<7qBW^h zjrE9z*PsA#SUtExq~J9}L4Yw%r$_Li<7Ht`s7ZGfYy4udCSCL&U)sCm@?A|}RbE05 z!0)rG7ueOV$gYYa|KA3kwBNKwM`6j2R-^kDD0Uo*Z3|2|%!mFhBVZQXoP7@gs0KPnTRo$0&gDOpo;_Xq z=%H9DQ91{`+WFHX|ClL_7i&si-8ghodJjx&;kBT5`R!wsj$H}pamirV4AUr$lR9a3 zn%xe(Q0kx^T8FX7obN1jnd1gdrri;X3A{A`yHVM-%1#BJ{Qv@4JSB-`58k7bM!7lG zq|Y`RodxnDx=0tFxPq>g3-mksljd4yGwzk2rqAeG&0c4hyq5}1u*ccsz9Jut9b`x3 z5jyOAAfKb>vDpmf4Jn-S!beSA`2w&4FgeXVe<06_%X!UMS7uRH)zBz{dU z7mo{6=IQADTN#z3J&~|2`&(R{50RkNLD1^y92R2Mug!rZ83#+~mNyyFI8>XX4YfI_ z{h1SWIYZFv^tzl2!dHUJFq5gg>m*YTQ*a1*Nrni#%Xl~!tXhMU)A_W_!x&A=f+me9z;62F4kw`R=y27c(z#UjaGFCCtq zndg=I$Q1c)>D67G-Rtm=i(OMUi9Tn3cYO&9CRHobi{qz~0ChT>wV3i2yhYujkE^l(kxFBls%omFF%ENF3z(i@ zOjjjUlY~@Gin~%kFbpoNa$UtBg|I$C(xJu};0oraIYRtUNP(pc#^LCj6_s`8{ zDNHp*pel;?n?Pz7ERVgP0MAXJ@x>i|_%~An#h-{OHG^t=KdKTx z?wA60al>w3ftS-2n#8ECRmYpjk!fJPp2K9SSE0>|`Oe~KrNy)F%8+A>WsS*{vBqhc z_9ljJg5(OY3^Pe)O?q8B7K^Cx0PM1;v@7nyTa@~kN_18a&CO2ZK{%HT>90kxRvLo1 zSj9Vatk;+rDe4-OHiYtoxzjZXT?*PA9O>ltymiT%LPB04Wb zaxMT?iuuWWq?aq_p4aNy8E=N&<{iSXkBybK#?~CUId();3f;Lva^OTI^v!T4#tn%a zg6k+qG}MQF0nTl=L=u7}F+9Sg2{eM=8732u{DHmjb$KhYH~F%>Dgf{zm6}yVtG`oP z_dm9)HMoiE3h&*gEooOPS=!agYcIBC`5{1lNPrj(;YY{z z`s~h1_n!NG-#O>oMLsly+xLC2Qc0$Tbkdw^ZJie)lBjZQ1m+e|fQj=Xo-39>0Jm)i z&FfHh`$G8sf&Z5bDTr5lisA*NGqd{IHS*I;%WkoRW;2dG%58^iM5dWGYugX`*uF%V zEd!&-f=C4-)`0(8Z0oF0!!tER6gf6)0^h?eXM0GCly!zwF$Lr-*~p;u1_lRuJ>E%) z=*TP??eAA{18J~pIYp3T5qIYlY2HN^9sdrNE_iSQw$6~@e`H#~n0y6C28NW>GHg&_ z41RJQ608^G8*S*Xtl)qM7JneqvS}0UeF1-vd?tJhpGnzHZh~&aSljK1!I^X&gBuQ2 z6x57ZBWdJVn`>lPs6Px*2}|CD;3PZmDA~fDWK+jjgHN9#QD%hB6rdrnQPe;rX^Af4 zs>x@&zW6sR8DIe9r-yIxCjSIe%8X~n*rT)M>~cd6mY2!pA_rt8nHd-A=AXM9W{ zyc!L~^r`}1;Dxf4Wo(%lRce(T${uA{5%wq@${mGMTv$+{=KQM@Ypj9``&CtJQe5b? z6w&R5t73BcN%r80z;2&uBJT$5AT^^?N*q-t=PYYhn;DT7<>G=6dPDp&3`V?Rh)0&f zeJ>ZkStRm5sVD~0SLdU(;;Wz5Vfx>9$tawpmEwNT)MFlezY3mRJxF6_B&XFrjQ3|Fj zs<^mVIYAwKXe`q}h=>a1YY<)L{|sl%P^7O9eP(Z@wtomnpNKwuKMglnkqLGiY#Ee8 zQ0yX1x>yv83d8Z(xN+m@PdruNCOWU>{Y*e%L!ZW7+;<=U2RlU-(^jG1$*PEvPX7j9# zvwVsi3>7<8jG43`9Y}Alx0|0HyYBAyn`e@_3Z3PKLSQ?0Y+O;ZB!YR?B-vzE(C z-7B;e!7l5Xt6T3j{+V-IzioV;chefSj8Q_=9raZRwQgIO>24HW7P|AkjQnZiX)Sp)*d^0#H4W+zJn2=39zEQ5b`7$zG zq}!Nu0kj^^xaz8W)~_-}g(aL%MyNEI^X*PU%gUhGKQnQ#7ZW*Hl6+O_u32W!?I z5>5|&yJPl_PgZB{WUl^#ymPi``-Q(;I)4FbW#jNIt{>`EkSsjH(m^7otalT)lh{ln zvkGb`?=_uLz~r4o@k?2ly+pH@T$sJ2V)hbc_=U^oao7FoxnvdoRaWHM)3RN}GAHLu z*5~ES(^EMqy`636-j(;M`+}}4*>JS7EnKUx#menJ)~CW;$S>rKSkQq9AvOib zrszzkm;@;%GfaQzqC_mIR$?UuUy>a7l0?g^RGAw)htt3aDkI`gw$;xos;54dppWfu z8;JC`(cD4ooS%)f~yY^HF!^yS6X4{kF&I zFxD^JdT`$xtv@51_1|42dBkyuup2wx%U!noPk+1m@h0psQvtIZphyoWvdP}(V0pP% zj>%8SLfjWOpJ9LCnCqKoE@5917H2Q=rOYntvT!Bmy3v=@=ewhSW%N)xZCWT*kBAKNP{G2}Z{SrpagTy04)78g)nswfWV4XR~`->Z4U_fOw;+A#2QA=s7G)^5!Py>_KGg!)n$AYJhWB zK^?nuKs~w*#ffmuo4bIhwP=|O4baeYpAP1 zxJZ(=P?BzYC^40(u3|hssX#-#NI{r3QSSNEqrX1&W#$g?^;{ted2q{dbn~LOhq~E0 zt_kzE{p0|dufN|(EGYIaQkwaD=AJsLygNz{XKr;hEjp*`3|{*}dD_J^SpO&&S$? zyCRai*l~J_w*@Bxf(vG@QJH4G$(~et|OVr`d)V=rK|tbJRp3URnkN5G%GcX`skw21$2!ttPF( zOqT<(y>wUT+71^wH$WlTB9$W!Pv&TemM+@2kCp%@+ogG^tf_W(08D_^B&%gAV2>t7 zN7Ie_cWm06Tf6#8mmNQ@K6+^Aj_QW5q#iRjY`N*s*;@e-UtG9GeIF39f?Pzu9d5BK z%`IDjyUFTtxoB=^E?aGGx!7fOxK~&k-0Ssz>o)6*`R`2P;$pddeQ|yJruLEYSXu8V zbgb+yZ?HBLdRAUrxOU|?^qUJeuiR4JTYjzm-NFaOf3!Qk$1_KjBa;_4rFHBib_=-# z`^a80MNWW`I;sqZtF@-4q}kKj6f?a{C8(G|HhaRSwjcUi{JlOaL&%lu%1CQI(we_S zYd+GN@8N5ZjfmFdySTiMXw8?R;0jsv{+&r0kk(XYBJBZhm?W%-+nj#Lu)G(YFjiQ}TV! zj|5~pphk&!&Id2(q6kedBfDFlu~uJt=kUR7g6&3_N5^;mOugvj)Qi7;>6MqHD?31l`Yv=W zmx818pzt%kv|^`1l-B`UqxPuB;tZG8flc!bC+4`SMoF?s(_PDq1tP3;R2K!E64b*U z(9y9ie67*(XVz? z$Gurk+2)OTusTA|M0$`Y z2ulSeXK!ZX)pc=E&l`+YZr_G}b+XEkgdwlHWd5O0TJ8REWyK$;nCfx8uh@$*{IhUISWR{K>*K zbRC{KMP3bim=E#^tC+6oWUY_1ZnR zT=vco>Ap&O0ytHwYw3JWrE5pZ>Y_ayq^qqQ3HuF!(+z((29I06F53WySbS0uEX^Z|09Ji}Fpeatw)j1#P6l0pVR zJ3-KzkcL?N?ZU=em**N&4Sg7-&s=E`=o}$$!!ML`&GEYqXcw2*u>CTO*-`=~I;7pG zsdzoY(YwX36f`gHRTYtqJ5}IOE>q2rYJXe38T5W1_^s}qPYu(KTNdXaHP;O-3wopb-5odoru@d&uK_dnv_wUYpXa`*F@tbtD>MDr!XVawjDE3@DpXLZ`rHD$Cjaqfgnsc^TVBxsLRhQ5RzoWx-?- z1pry%F4D_B%UzPZN~MUtuuE@`mStr2Pin``Y^e88-UgbfNPqo2i37~!_Quir1Q7J6 z@G2`_4cIiB7H|81Y0+NQ=2{frXeo+pu0^P7aYYl)NJ*hnUTkcz%@Y9~3C02?03J&O zBMx;KI<_pjHQ7xqbZo9Xq$3gS%Y!-!`ZlC7kcCO~EN7P7TiwOb!7!E$MshTV+vS$F z%i(r#|3T=;?Q+;9bEe!bC$WUhITw=~!~I#@I4Ae>h*BvA^aKIyjS(eJB>q&yU-SRq z4;hzu^$vXYoJRgIbg>mjsYpbSydXGAcRqVQ17lMGM`ABqnOWAH2j_c{o3|4wo}u+1 zhykt?X*#0in44~MV@{5y;+b=ex^7({znKm+neq~~Yt+%p8~5X@58uAyq5PiT{P?M7 zi<{SP`{88&)=m4?v9)z z9vu$Tn#$A4llD>jwEEZdtU8zGOj2$Q3TBs0AGS|qPh}Ugti^B>u9pJMMY$I@JDXLuWyiAP*{Lkcs!Ao}AvWhG9VbHG{}){5d4kJXCb(D~iBnVoKV;ZRB*ngkzySw~<-~acpd66tSCP9w( zf!!ush@uRBOnVIC{zIE?w;ud476;?&>${I}(f!94Zd{VwKGw~?_EN|Ey;sNnKpYBF zJMk44BPd!K9j*V!<%a)6A(KdlOoox{hDxVDICxQ)>P+?K<)#(p7fo$ua|+iuYSc>i zLfqhJP#3zh#;mXm=Nvh8nY+W-A*{t6jt+IL`{&3dn2gqyhUbjWi7TZIhIPhu;s#07 zd>n5ll;MncY4-8bZNNjyq1lIb!%-ej9=$&Z{ig->3{U_Lw4eeCASjWN)Jz^RJm!PE zfuA)@I0B9@3WQTLNo|WTk_}?7gO0OA@%2%BZ4}@9)KdOoRElthToUMjWoCI&RY0z} z?~%iuiQIp3xhYtZWRxByR7-MfC&-r2Y-|=*8&?Y)XcL^G;3@(d#^9cyxkjt;F4h)%SD05ySuN{rH?No4 zaEG?udp>x>dE0&4b0aX~90}YBP6X93m%s^EC0B!=;TGc-{7=h0|2VeTZ3fln1D02P zHVb3ZBSRv>Vn%EgdqpltAq-MDiEq1`u>g>wd-D5(f}#5t#gaNZfKY_J7KUbvJxHlw zD;y;ZbDp>$bO4<|_Yqfw(x?d;5a=9bV?@~)Q8q?&had?qiC~xkJ9;V&Mo5AS6N)6b zBE6`t%8e3@_z5D$W8aN@A9Hh^1jRJ<#FT5990(`VsT4?6bvaoGv@yG33VQuVYWDu@ z^`Z7n!&_T+m)nnS-txh*p6-+5ZN_tNE?v57;x~uKAHMZ$&DcZ3k!u&O+`97FUtkLB z$J-2d2!@#Pq1l-M3!7l$?m27&`-)^ryV81tz9(=XU`#0~Z#qz`)OwqhX73thjkh(> z8@Oq@<+yA5TKdL~r?DX^;i_gUrA6#BQVZM0ej$D7{)hUte%JdyRz{rF>G4^3o5|_p z2ymLMf+@jxNJd!B$gOg(%mp$Q(#`-yPj&zk%D}jE7-bW*T~_IDR7j!qvI@Nhs-P1{ zPft_!=&?sW;ji<<`~=Sx5tG|QhA~1X*#ist5S?u`Z+z)I>;6DbacYW6<~o;*jwPnx zG?$<>_lLkRoybln$({mmv`XUnrl4Xdi|>E_-1xs=zVVBTorlJXKitxN^!VmYhsWDk z^PEOhj`#!PuO1zE@U-D~*RK8P)0>}v3JSNAKy!(pVrMRA=FCtK=1`bRaZhv2+zVU} zXA*X_wlq zgVDj59E(O`k!iCdE#eBx+UVNSo^Vg3H?mKBSK3>;zwFmDkBGmO4#$p^o{nCOs-*=d z8Y&dwLJ=txrTKI?c@7leLJ=txev&IPjzD#bIaVTxoF^D{ah7tw=VSK$Oh_+-<`?N{ zy-EM6eq6taxgveH&g$m~HZHO+-e(X&)d{C#ltC;;LnP=Sj93Id->Ie$ zh23UPAyl6AZ}78zpNr?1gDxC&LU8O4hF}v~6Q!TyG*DZ3U~l0GCDj&Fd|a|mg(ck!AXXAkO@-W zuu)==C@F-73$a$81xiY2m<;(O6_1iXOg_3AsYQZAorxt=Jn<;;!f;Z0w9`>NBcE&t zY10p~*~yFSc`fgrGO_7_u+do-wPOcXu)!3v2EB|>%6pM?d~ z^rF(3Aes`Kmnp)2@L35=Tv`4N5@;fx=;HDm70vv1qKEtxV0X$_oUU zG3v#f8u4aYfX$12G<`~bW9zmpl_mQwz0)-RNAX`ZZ$H;!KOuFuZEIK68QvYA>|fq? zY5Vmr&^+Jzu64EZ!tRpfqQ1tuS4xW#^;=(bFUu~g3j6$u7^#@QE!*jZA#Y z#*ObV8uQn)j7auiIGPdw+4-dC)e(avtB4GYiiLzM66rQrWE^5b$m%GO&;)N@C@gH{ zH}bvw9-d=}b2`AE;Lr0zyom>~2Cm}sVoi&02Z6Krd>)%DD68ikbl#JJ_LIsqY0dJk zlK(y1&bZO+lP^3GQi=SI5`TBf>Tnab3|j0jEnPY=XYk#@`i`c`Zg%h3>9=RqEp6WYI$QnlZv-6zk>USTS9@#} z#~GiQy?xB=V|M4(_Stua^Ods?4q>Z4V~)^z3u$;*$RxOwBb=Hll@W!6P^A!v14JTm zAW@|JlbBXjrB*EQ42?d^Ex zo8R~Qe%}O~4#T(l2wBy+IjB+%#0(8<45`#mF;N#t_^FNAu~Bzy6rdraom^^sxJAV% z<>i^=ciYQTNHcSWEC?`NKh(Hf!!Q06(0O$^lz}4Doivrsp-L#AcOy8ES&~CZD7du{ zWoSLiqZYOXt!A6>CQ>jq(=Oaawj0~&GiWc~OZFMh(7mh&_mCHrBl=6mQTij)OJ8HZ zKtEx>Lc@9=dk6iN-9R6(Ptk|$E}CMCVLL2_Dp>~AvsTuD0!Gz9ROVEGO0G`}_fBCy za_dM+yHvm zlQq@T#pz;AY;wFPrG``+Z7U>Qwt?&Rs7tav&t2?U5|dQ{1V}au8PWYoFDe%5aC5Y> zYH4e<8RK7;cK&)iJwKNH^la(LNd5HTZM!=6ke2`)fDR2Ibr{egBDJ&VIE#c-rXl-i zVW85=ImXoi%ML^A1V~h9c}Z*b#f1UK4PQWLl`Ss_`^-}?vOo=Cje|98OOp;|d6-04 z#ACAK%@LgkQD=12y*BDz&5la+NdwD>Qw|H#8RFo9K3)`A$jCbHQSVhx@si>Bjm+E( zDKIkE@FeZf`E@xrQQIKt`d`8D`~|s)X3?k?r`1A@ponHt(=mjLqKdC4jJR0~8Ejf# zWMrKjYSEV)4>%7htF=I1Z?v1M_-b#Rc$7aPcIe+Rwuyb(e*J0VtagqMiO;mVG-G-h zl(8F}3~vyP{xZ}m_8Ko5y~-QbaeRWDFn?|hq9N^^b2)NN`!k)0Oz=;{l=femFg3Yi zD=gixbi$H{r6|KT&Kw>Q$TM^!t@E@a(>O<0Y;2|Nk(p~jt7It~(6=be)okoXHD-GC zEbDbf9${O(onE(h)MFlt02bwO%pT0=rY?rEwlO;ex9q#)@|unQaK{5*QB@!;U8Rf} zkfSiy^MK#m`&A@Bv#bre7NU7;kZUO!bV#z5D=EuE|w`}m$`x#bJCj>}%> zg=NqB`yK9!6`-=maWCqQyFxy)EuZ$&^EYlDu#;Ajyg73dH0@2~%v>2jO*|<8qj*{Q zuh4!vw-G$fn7PuYH{o!gZe#oD=7+b0qc{8Xi5atH9x^hNuk~5w` z%gDLe|8#Hid*4-s-+41P`&lxQMDhjD241x_obBq6$fL#ZfP?o%^RS~rIhcJ zLv?-&e?9WLam@Jvzo1^wF6i%Z%7e;$jS{65c8%MDmz&SyS52c)d^1we3+86$4cyCm z&0#WPT{ho!e&^m$KA?ZF|Kfhc#GG@P77`wh*&r-5$!?BpaSah0F-E{gB=G_gfQDoh z54to>(G5zmrcpJbfaK#4&uz@P?V2Deh;1sC%QQ|nb1$Jwl(=a`eT1k&>`OMb)0W~} zmcl4i6rw>UU|EQD2rSmx2dot1-`41XfI(y!4zvy0Ax+Un$g03eDhEia18lk0>kbpu z;?!)gfLP&vJu_WvnQc(OP`Yy@=%UIqxw-l+Kn=N$9RHR+K?8;KXY4rnI+N zo3~O`c?BNXKU0@?CC9UhJWkc+X^_azMVvx$H_Ac`0-!*^X|9r?rxjWN6U_19(y_n) zbV*`yy8n9VHT?3}jpe0(kPI%}S>3d<`EJRYejl$Zl!~ygy3)hSKLH~(_&;Tg)H0td zrjn@ULNm2!Ab8RYtYjH0)s5Mjv6|RuO|>g437p9=Y{dI{0&}^ECldLLzlon>N?-?Y zAjwQq&Xt93QBi5fM1$F2HP}n7rFM&R%ri406J1kT5QS)=V!PNL-CnUz+hgzZ_WS!Q zUa*gPuZUNoNBmxP!hF*`@165+u}}QZ>}mIoKa-d@hp5V^nTSXDgZwa8c=f&IhwFng zD3)>5%DLqNSAue=_M_3XU_NxX1!R~unQxjbDuiX3nw$V7+yrS%yp@O#;e`&;_k_sm^&G^P)sHcbBHnkNl?eKP8m`?A%1}M9AKLmu+4d7 z%}gM3W&+>OHU7-shFbG1)tYy}%LXg*UaBHrMh`FzXc&M`v_WdzR(X9cVIWk24nF8V zuz1CqDz9EOOHaH#mQBsiemGFt`LzX2-J5cyZ71E#g7^+z8_7%``~LIYd&rKvmrt!M zY?LY|1Ke{JaOL1rfh|VJI|dQ>%c3d=9QuAhp@F{&sug-~2kW4*kYs41o5y*!7C%HD zGS<=#cPs8BoyHcr!QF`;CyyK7rO)E0jc4i0_yyw#y@RJnyxOS83ymzz8$UCyV_ka7 z@c-Ga7TBh)GyI=(udnUvcVatnd=p>C*m)R8NbCeVCfq1M6Ho|Lq`;~`X|mRU8uFlB zX(vd_s*0{j5Sl6^mh#%z=&CRt8KI+-)=Zi-ZPKK&FsbX7O?^b#0-1&;MiqPiId+^h zC9!?4ukZKW^MC(;{)gQap_pE=3Av*M@?wO>jWRXJa*$9gf0STdl;}QP7)_M-S-`?t zP$RGAVXI6hi0uXzL!I_R&qIB9oHeNcwh@PVRdHrVkqvA$yp)>5Ul; zZtptQoLwu3@v%#G$EXwEMefDKQX3^wz#sLyh`z4Y?<%K18rYR;7rN(vedx#m^3PL( zK|1xF`8}^1&oDp7Qrqcwbss||ysEW5VI$>vHb;cA4}GD@8VTm%hr7%T6_u4{Ur^1* zMC`!a>r=diSr!kCRaWkW5umU?+?(XdHi0{Xz2@P4C-Dtf4HMc+@N3}v6M9x!sR=6Ti;Uxf-5OQ8Tf0{Q#ofrZ0 zXwyAd-!{9ZIv=OX+oP%N`qv*GMXoATvY#vY8gixYT}KToCNjqm`tLd_iQDC#7Q>T* z@&c$J#G(fM4r|bo?^ji;Wh}2Kt^~`R@w}i^7B3$oVq6-7ZDbIGe*eldLntY(VNub~ zzM-gNK~a~LQoWVxr9dEx*&!OKudAyMg`$zNP>5eDD4}_7H|<|0sL}q+u7N!|{Zc_` z_eHwxMCw|!GV8KZo8$w(-5pc=j&mZG?Egi8OI@1pzaT-A6?S@282nb zCXIv5O=uHNQL=4;O4nVnP$2O7t(KctJRko8@tm#BbxWUl2Tg)C#kYV^CuGlAig$!#r!(H+d zvK_WuC0;g<+H6t>JJE{GW~pP^oA%N}-YZ_(?j`)oUhhdS^@u7Bya((KxWMrUik0svw}iH?OEf6_~o6TwOSiETx=fZIV!6cm+`hFi20vQBv%su><- zQDG773>C|vIvc zCA3wuSfq|tPSdJ+iXyF=$r3r%I?_s86eFaw`hLWqBhYnsh5egdB&V+o6JTa&Me zHYu4HZ(5=#!);3)5@y9l#BIt%IZT2R>aP-og;$Z&DRuaiDuvn=a$iZaW3_Tj5fp5g zPyd3&mSR{4+x|>UZNZh4aJ5^qp8ZeON7Mc}KlRJpv;Jj1T8?Vw>knO}KDG`AYGCt` zULWyg;J!t8AGd!wehU7U@d;J6hN!Bos)^XtvnmBOAj|006*+?b@X~cp<`{-KLqKy1 zv{W;hXvdXOQYv?Ij|RWt(GLOWYX1B`AzFeV1lQaodX0B8Xv6gaPlO#cYiTf2r6+pw zEheA-Yp!IL1Q35_2~+d$fM*V!h739l(W;K<=tTMw-`l#S1T5Fx$CV_P;HRbl+?q^4 zGGcxtM9u-&(~Nj`oLil_d-(SNKFvXiL1im9P?p>%H7#y}jJsWz93->PMje-C%Vcxg}<=8Klu86dkW8*TB{>N38LNG%!z742;8DI62*{FH25H-bf z#k5%DZZBRIHOo=Wd>>)dcym$XCB0ta&A`3Oqh>jN3Z@aS;<%x(6mV7{p!h(K@uDt? zmqp}c4mr$`m6{RDh~{=n9VKi978x}x5qo&hEQUN2F~{*TvY^}a+Vzm`uF&1#SMly;n|90|T(7ZX4x z?w4bm@eSa@h#^G|Xeq-(4)VDBr!Z##R4~u`mV4e?Vsf*JG2$T}M<7!%7C9z!9K)QW z80S~gi}lsxb2wPhP?xwn$~wT-)Fs@br@;h!v|37xvP@Lb1cGSL>%|^P2L_|0*UPf8 z$E1Qz6bXSIL8B)rrH$s^x3eu7pY*UH%N(&I%U-HVu)Y`naT;)7PmUd<-{p6ZKd1W0 z$PIET)q{_}eU7}7I&khQOtTaQg`d)&VHatF0%*7eHaav8Mq)hfnxI411cH;;(6~(^ z(s47MX+{-Ic)xJ;2=BIM=R0Sy8JuU`QhtQ>N-igBlIopq-UG5`Y4BqI;R_cB`Y*oF zwP|Bl*Tzj<;;#lSTo@R*c;WD-uC7h^##J0lJuk|-4?u-V@|yOJ%j;BV9qANz*^{

    2Zxl9=E&wI>0ZAsGV>BuppOeV9@sPs8( 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 E-~DHMMF0Q* diff --git a/mods/certificate/get_adobe_reader.gif b/mods/certificate/get_adobe_reader.gif deleted file mode 100644 index 08b14102d530393d5017f4b949aa5006c7300f77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1953 zcmcJM`#+Nl1Hhlz#pZeNEOWo#ijtOFyr^xBaOjMvop_m!%iKB?KKPU#Gs`8Xg~Xdv zTjfM=b%;*uYBQH5imsG2_lh*kiKyp&&-*{T-ygm|et-Gy3iS8%ie&?qz!U(WeMvJB z0r}a1=wG+d?~CZS85CWe+~$XlAI?v5N9QU~)xSc51JI=wbf##bc<)@=?zbd&k|);-#Cd zD^DJNy`4B;T!nspfvye@TxX-NQypz7T=r&n*Nx~@o*>;T|48E7f#RFj^B(ufi+NFN z({E%_$%P{3R8M?kgGeH2mYfOx_IX-e8MQjvxqLN78zOvH&rVM$-WmL3YV!5mWPL(> z^ru|GO>y{#m@HJ?b}DcC=eY?{McC9G4yybG9ZX&8O1$vvE_AsKeSd6GHH3aq_|Y8u zWJl3gDO1mKKTS8UJ;B@(H-( z#rV=v%W_Lcp`$~kgJHGdzSNCLL5tPuV6urr~nuJtUD#ji0;7 zyXHQOO@eIdfi9urBE4Uv>4>rMVdY%2F4kmfWR?+WW_$ofivOKMwk5I4baI9{;H!Y6 z_N!uuJt-@wesZa(HfeKd2xOgkaC}G);J3g6t&Jw15%|&#RO*ygdeW|~5)E6wC%OHn zm)yv^F3%0J6Pf2Vb%^>qDdQx`jZ|2sQ1cW=R)fD{i+h>9K)!Asad;_ZwArWIR~35j z+C8F&)iwsBcJ5hk*dhVqjM0c~dKx%ZPecv^Z>J%?z$ic_j`&#q=-r&*V_y<9C|nZb z-t?ULlzgsqmUfyHyPi@9k8zZvLsm>cWAEi5qMr0CK*b!(dNtpQeT1<~{~{wS4hnt> z&&imQW415D7%t0g9ntH*nIz3A@aZ|7T^;S}EzLnHslY%M4-kG~|!xt&3X4z1pSMPJkQ^ zyGN-x2|c_t<)H`5VvID^6WBV+Z9zu`PGw9Wd$?7!>l&^+ECSt)1`r5ZAG$MIH<-(F zxnII%5Xol$-AD@{S4Y5chk=?MwW{(XWPZF|D47^Q(+%sv3K|`yaY2!u z;ugI?>Yn}>!&|GTwb&;L_IHm{2Q;9K;S&Z8C3V8k9tUJ}1J-7iS44JJ*i0Xt3sJ_LL!fAB{tvz@e|iUw-!xHkxjCww3DQhp8&&F!yA zDJ+;eYgp^1YpECZ)t_)Znshpgo)teUY!lL8{A51^bh2yWsS{iWgioK#ueGb4R8l!A zc_L4ru&VENDYL7**RYmT{%8&d22v&%>ns{zzLv8RF2Xx0y41r7ts9z@Bp}BE=zYn< z`HUWM;~<7Q1AJSzSTeblH$Qy*ETKLQay7-ihK2lQcVYfU77=J6^UFUy=0dphMh#!C z(gUoB+dP@L`z!<;k>X9N`1;P|b6+~&7YbWw@F4{F*cg)JOjN$9T4X>?BK&c&xCBba z5x7#I;1C_-rt~vuLNL2%7-M@WeX#QhDMCSqo%%cMgXCBPu1u>zQ^Vo}9p5t$MQKs+ zOiV;1NJxY7m+=Iq3UuzrfNn~jfBq;jEo#K{jEujPO8<_xI^nI)sTeq)N+nIkb~ArHD<=Da_7*OW>WFz-41wutLsw5-sX*^w~n(7li>L zMI8p}twegw(9k(f!PX`OAAFb&r*mwAf~5Gk6G|O3<3Ph%;5SGjgG+OnS45jM|14~$ zgtN3QCTO6K5u`&^GRjAR0t+x2dZ0keIiuD3aWp8oq{}*U9#pGEzDKM7^p1YKY2GC` zSv9G}>g0KwGDp&e6~+aknQX&H=K6j;UZuk{4bQ&D-B~7Bzb@rvn)b&Z@h}!+wA2vb bm;Cl)HE_pX*~lut5`H=8MMIDk40!(sbG$%x diff --git a/mods/certificate/index.php b/mods/certificate/index.php deleted file mode 100644 index efa78a227..000000000 --- a/mods/certificate/index.php +++ /dev/null @@ -1,135 +0,0 @@ - 0 - AND R.member_id=$_SESSION[member_id] - AND R.test_id=T.test_id - AND T.course_id=$_SESSION[course_id] - AND T.test_id = C.test_id - AND C.enable_download=1 - ORDER BY R.date_taken DESC"; - -$result = mysql_query($sql, $db) or die(mysql_error()); - -while ($row = mysql_fetch_assoc($result)) -{ - // if pass score is defined in table certificate, set passscore, passpercent - if (!is_pass_score_defined_in_base_table()) - { - $sql = "select passscore, passpercent from ".TABLE_PREFIX."certificate where test_id=".$row["test_id"]; - $result_certificate = mysql_query($sql, $db) or die(mysql_error()); - $row_certificate = mysql_fetch_assoc($result_certificate); - - $row["passscore"] = $row_certificate["passscore"]; - $row["passpercent"] = $row_certificate["passpercent"]; - } - - // if pass score/percentage is not defined for issuing certificate, don't show rows for this test on the page - if (($row["passscore"]==0 || $row["passscore"]=="") & ($row["passpercent"]==0 || $row["passpercent"]=="")) - continue; - - // if final score or out of is empty, don't show this row on the page - if ($row['out_of'] == 0 || $row['final_score'] == '' || $row['result_release']==AT_RELEASE_NEVER) - continue; - else - { - if ($row['random']) - $out_of = get_random_outof($row['test_id'], $row['result_id']); - else - $out_of = $row['out_of']; - } - - $pass_score = 0; - - if ($row["passpercent"] <> 0 & ($row["final_score"]/$out_of*100) >= $row["passpercent"]) - $pass_score = ($row["final_score"]/$out_of*100) . '%'; - if ($row["passscore"] <> 0 & $row["final_score"] >= $row["passscore"]) - $pass_score = $row["final_score"] . " / " . $out_of; - - if ($pass_score <> 0) - { - $rows[] = array("result_id"=>$row["result_id"], - "certificate_id"=>$row["certificate_id"], - "title"=>$row["title"], - "mark"=>$pass_score, - "date_taken"=>$row["date_taken"]); - } -} - -?> -·

    - -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     
    -
    - /open_certificate.php?result_id={radio_value}&certificate_id={hidden_value}', 'result_id', 'certificate_id')" /> -
    -
    />
    - - - - \ No newline at end of file diff --git a/mods/certificate/index_instructor.php b/mods/certificate/index_instructor.php deleted file mode 100644 index 9bbe4089e..000000000 --- a/mods/certificate/index_instructor.php +++ /dev/null @@ -1,115 +0,0 @@ -addError('NO_ITEM_SELECTED'); -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -?> -·

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     
    -
    - /open_certificate.php?test_id={hidden_value}&certificate_id={radio_value}', 'certificate_id', 'test_id')" /> - - -
    -
    /> - 0) - echo $row['passscore']; -elseif ($row['passpercent'] <> 0) - echo $row['passpercent'] . "%"; -else echo _AT("na"); -?>
    - -
    - - diff --git a/mods/certificate/module.css b/mods/certificate/module.css deleted file mode 100644 index 15da01381..000000000 --- a/mods/certificate/module.css +++ /dev/null @@ -1,11 +0,0 @@ -div#helloworld { - border: 1px solid #ccc; - padding: 10px; - width: 50%; - margin-right: auto; - margin-left: auto; - background-color: #efefef; - color: #444; - margin-top: 30px; - margin-bottom: 30px; -} \ No newline at end of file diff --git a/mods/certificate/module.php b/mods/certificate/module.php deleted file mode 100644 index 0be4ecd45..000000000 --- a/mods/certificate/module.php +++ /dev/null @@ -1,81 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_CERTIFICATE', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -//$this->_stacks['certificate'] = array('title_var'=>'certificate', 'file'=>'mods/certificate/side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('certificate', array('title_var' => 'certificate', 'file' => './side_menu.inc.php'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_group_tool = $_student_tool = 'mods/certificate/index.php'; - -/******* - * add the admin pages when needed. - */ -//if (admin_authenticate(AT_ADMIN_PRIV_CERTIFICATE, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { -// $this->_pages[AT_NAV_ADMIN] = array('mods/certificate/index_admin.php'); -// $this->_pages['mods/certificate/index_admin.php']['title_var'] = 'certificate'; -// $this->_pages['mods/certificate/index_admin.php']['parent'] = AT_NAV_ADMIN; -//} - -/******* - * instructor Manage section: - */ -$this->_pages['tools/tests/index.php']['children'] = array('mods/certificate/index_instructor.php'); -$this->_pages['mods/certificate/index_instructor.php']['title_var'] = 'certificate'; -$this->_pages['mods/certificate/index_instructor.php']['parent'] = 'tools/tests/index.php'; - -$this->_pages['mods/certificate/index_instructor.php']['children'] = array('mods/certificate/certificate_create.php'); -$this->_pages['mods/certificate/certificate_create.php']['title_var'] = 'create_certificate'; -$this->_pages['mods/certificate/certificate_create.php']['parent'] = 'mods/certificate/index_instructor.php'; - -$this->_pages['mods/certificate/certificate_delete.php']['title_var'] = 'delete_certificate'; -$this->_pages['mods/certificate/certificate_delete.php']['parent'] = 'mods/certificate/index_instructor.php'; - -$this->_pages['mods/certificate/certificate_edit.php']['title_var'] = 'edit_certificate'; -$this->_pages['mods/certificate/certificate_edit.php']['parent'] = 'mods/certificate/index_instructor.php'; - -// ** possible alternative: ** -// $this->pages['./index_instructor.php']['title_var'] = 'certificate'; -// $this->pages['./index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -//$this->_pages[AT_NAV_COURSE] = array('mods/certificate/index_public.php'); -$this->_pages['mods/certificate/index.php']['title_var'] = 'certificate'; -$this->_pages['mods/certificate/index.php']['img'] = 'mods/certificate/certificate.gif'; -// -// -///* public pages */ -//$this->_pages[AT_NAV_PUBLIC] = array('mods/certificate/index_public.php'); -//$this->_pages['mods/certificate/index_public.php']['title_var'] = 'certificate'; -//$this->_pages['mods/certificate/index_public.php']['parent'] = AT_NAV_PUBLIC; -// -///* my start page pages */ -//$this->_pages[AT_NAV_START] = array('mods/certificate/index_mystart.php'); -//$this->_pages['mods/certificate/index_mystart.php']['title_var'] = 'certificate'; -//$this->_pages['mods/certificate/index_mystart.php']['parent'] = AT_NAV_START; - -function certificate_get_group_url($group_id) { - return 'mods/certificate/index.php'; -} -?> \ No newline at end of file diff --git a/mods/certificate/module.sql b/mods/certificate/module.sql deleted file mode 100644 index 76ad363fe..000000000 --- a/mods/certificate/module.sql +++ /dev/null @@ -1,52 +0,0 @@ -# sql file for certificate module - -CREATE TABLE `certificate` ( - `certificate_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT, - `test_id` mediumint(8) unsigned NOT NULL , - `passscore` mediumint(9) , - `passpercent` mediumint(9) , - `organization` varchar(255), - `enable_download` tinyint(4) unsigned , - `created_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP , - PRIMARY KEY ( `certificate_id` ) -); - -CREATE TABLE `certificate_text` ( - `certificate_text_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT, - `certificate_id` MEDIUMINT UNSIGNED NOT NULL, - `field_name` VARCHAR(100) NOT NULL , - `field_value` VARCHAR(255) NOT NULL , - PRIMARY KEY ( `certificate_text_id` ) -); - -INSERT INTO `language_text` VALUES ('en', '_module','certificate','Certificate',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_template', 'create_certificate', 'Create Certificate', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'delete_certificate', 'Delete Certificate', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'edit_certificate', 'Edit Certificate', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'certificate_id', 'Certificate ID', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'test_title', 'Test Title', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'choose_test', 'Choose Test', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'certificate_template', 'Certificate Template', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'organization_name', 'Name of Organization', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'certificate_text', 'Certificate Text', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'field_name', 'Field Name', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'field_value', 'Field Value', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'enable_download_certificate', 'Enable Download Certificate', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'issue_certificate', 'Issue certificate if test is passed', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'define_pass_score', 'Please define pass score
    here and save again', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'require_acrobat', 'In order to %s certificate, you will require Adobe Acrobat Reader.', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_CONFIRM_DELETE_CERTIFICATE', 'Are you sure you want to delete certificate for %s', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'certificate_tokens', 'Certificate Tokens
    [TNAME]: Test Title
    -[FNAME]: First Name
    -[LNAME]: Last Name
    -[CNAME]: Course Name
    -[USERMAIL]: Email Address
    -[USCORE]: Users test score
    -[OSCORE]: Out of test score
    -[PSCORE]: Test score in percentage
    -[SYSDATE]: Date time of last attempt at passed test
    -[USERID]: ATutor Member ID', now(), ''); - -INSERT INTO `language_text` VALUES ('en', '_template', 'pass_score', 'Pass Score', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'percentage_score', 'percentage score', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'points_score', 'points score', now(), ''); diff --git a/mods/certificate/module.xml b/mods/certificate/module.xml deleted file mode 100644 index 7f5ce3932..000000000 --- a/mods/certificate/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Certificate - This is a module to define tests' certificates by instructor. Students can view or print the certificates via "Certificate" link. This module includes one default certificate PDF template at module content folder as part of the module, that an ATutor system administrator can replace it via FTP. Please refer to "README" for detail usage. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.1 - 2008-03-17 - stable - - - \ No newline at end of file diff --git a/mods/certificate/module_install.php b/mods/certificate/module_install.php deleted file mode 100644 index 93a325b85..000000000 --- a/mods/certificate/module_install.php +++ /dev/null @@ -1,66 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/certificate/module_uninstall.php b/mods/certificate/module_uninstall.php deleted file mode 100644 index 6f6e968f7..000000000 --- a/mods/certificate/module_uninstall.php +++ /dev/null @@ -1,45 +0,0 @@ -addError(array('MODULE_UNINSTALL', '
  • '.$directory.' can not be removed. Please manually remove it.
  • ')); -} - - -/****** - * the following code checks if there are any errors (generated previously) - * then uses the SqlUtility to run reverted database queries of module.sql, - * ie. "create table" statement in module.sql is run as drop according table. - */ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/certificate/open_certificate.php b/mods/certificate/open_certificate.php deleted file mode 100644 index 80bd53503..000000000 --- a/mods/certificate/open_certificate.php +++ /dev/null @@ -1,55 +0,0 @@ -printErrors('NO_ITEM_SELECTED'); - exit; -} - -if ($_REQUEST["result_id"] > 0) $tokens = initialize_tokens($_REQUEST['result_id']); - -$sql = "select * from ".TABLE_PREFIX."certificate_text where certificate_id=".$_REQUEST["certificate_id"]; -$result = mysql_query($sql, $db) or die(mysql_error()); - -$url=AT_BASE_HREF . "mods/certificate/default_certificate.pdf"; - -$fdf = "%FDF-1.2\n%¡¦¡§&&Mac178;\n"; -$fdf .= "1 0 obj \n<< /FDF << /Fields [\n"; - -while ($row = mysql_fetch_assoc($result)) -{ - $key = $row["field_name"]; - if ($_REQUEST["result_id"] > 0) - $value = replace_tokens($row["field_value"], $tokens); - else - $value = $row["field_value"]; - - $fdf .= "<< /T ($key) /V ($value) >> \n"; -} - -$fdf .= "]\n/F ($url) >>"; -$fdf .= ">>\nendobj\ntrailer\n<<\n"; -$fdf .= "/Root 1 0 R \n\n>>\n"; -$fdf .= "%%EOF"; - -header('Content-type: application/vnd.fdf'); -echo $fdf; - -?> \ No newline at end of file diff --git a/mods/certify/README b/mods/certify/README deleted file mode 100644 index de539c2a6..000000000 --- a/mods/certify/README +++ /dev/null @@ -1,18 +0,0 @@ -CERTIFY - -Certify will let you add a certificate to a course. The certificate can contain one or more tests, and when a user has reached the pass score / pass percent for the test(s) bundled in the certificate, the user is allowed to download a pdf certificate. - -Before the user has reaced the pass score he or she will see a progress bar under the "Certificates" tab, showing how far he or she is on the way to obtaining the certificate. This progress bar will also take into account score from tests that the student haven't passed yet. This is a design decision to allow us to display better progress report for certificates with only one or two tests. - -An instructor (or privileged user) can manage certificates, which means adding them, adding tests to them, and see student status for a given certificate. - -That is pretty much it! We are using it in production today, and you can have a look at it in action if you register for the Medical Peace Work course - -We have found it to be stable for production use, but there are still some bugs, minor issues and areas for improvement left in it, mainly for admins of it: - - * You can upload a pdf template for each certificate, but there is no way to see which template you are using just yet, and - * If you upload a new template you will have to manually delete the old one form the server, as well as any cached files (named typically cert*.pdf (where * is a wildcard). The files are found within the ATutor content folder, in the "certify" folder. - * You will need pdftk installed at your (Linux) server! A server admin must typically do this. - * And you must manually set the path to pdftk in line 100 in download_certificate.php. Here's the line: $exec = '/usr/bin/pdftk '.$template.' fill_form '.$filename.' output '.$filebase.'pdf flatten';, as you can see here our path to pdftk is "/usr/bin/pdftk ". - * There are some tweaks that should be done in the GUI as a radio button isn't selected if you click the table row it belongs to. You will have to hit the actual button! - * And probably some more too \ No newline at end of file diff --git a/mods/certify/certify.css b/mods/certify/certify.css deleted file mode 100644 index 2360244e0..000000000 --- a/mods/certify/certify.css +++ /dev/null @@ -1,32 +0,0 @@ -/* the certify stats */ - -.certify_bar-border { - width: 150px; - height: 18px; - background: #fff; - border: 1px solid #e0e0e0; - margin: 1px; - padding: 0; - float: left; -} -.certify_bar-fill { - width: 150px; - margin: 0px; - padding: 0; - background: #fff; - float: left; -} -.certify_bar-bar { - height: 16px; - margin: 1px; - padding: 0; - text-align: center; - background: #BACFE5; -} - -span.certify_percent { - float: left; - margin-right: 5px; -} - - diff --git a/mods/certify/certify.gif b/mods/certify/certify.gif deleted file mode 100644 index 868f2741e01a51a829bdbbe370783c96ef41d681..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2163 zcmWlYTUZkZ0!Amv5CRzjfq;M$1*BVrsDQz1s6!GVT*RP=fT-L=bR#0hOErrDQUpvD zAu6RQ1vVhMDT_MZM>fI`F$M)3UGz(-;;dCRt4K#zcc-QGe>hL)>3rWGpAffnS#A^% z1^gEPKo;m|7OARCsMRi(s5Dh}Vw{BYOxbIphCWiwhPp?Bx(dPEl!PSaLe*#RKz>VTyDkIi|v* zAbf;$^oYEIL}qs|bGu1zBhOqU|4&nEGR@}8c0&^uAr>o?8j(~YDaOf1P=k$fWeE!O zX5tZH#L31EyV*wmJP5DJGV0p!v@IsfkJR~_4$vJ`HQRT5i%HQ_w}kkWVAHBDya7NhDEPEpkEgD4y( z!g)~EHnSup+tf9L*~s-<%=B+GhCBTIMG~n-S8vA)1=|`>!%Z@~%rrUW)ai7@7XtMH zF?mlc$}$%2L=8=LNxDkkjN;>T&@9-{>mbHRQ-{g25d&8z~2O?F2evqcjK6i1l zy%<7!9gSBB3kQ_PNsJx0%TZB8#g0oFsP%gpp^T5qKVA>!&LoP6Sd z{6Y=xkiLm9U&m9jOmLQ|NN3ho6QFmfbBavfY$opsUcRR-g!9~0LbO=od?GN|X=A_h zr9BiMqYZ3GSB1+{^hO)~!4^utrs(%{=^?CO2lfwlC_4|;bP`y<6HYO!PGayZk=gFV zdK~Iz91euh9;bi_rKOux$I$FNW5Euy`V=b3Qp;s>!*_oOp~hw+Egge+kiq8UxI?-w zLJ%gl*qr)$LUjyFOE;z!Vx|$A7^5XA1;HOd;L}8(@aYq-oN3?<2Uc`HwYX$2$bLGd z3O=pl^#>Rg=i4j=o4vm{^r7T=@7FVDALI}8wk1?-pS78DcK0)zE@H!Vv~aS%->_bq1RhZO0 zd%lhy>i$=ua-}oqO^TO*7#Yjw{C5@?}GQM!+?(dNT4rj>QaW` zR)%=(0SM}@=a)L9 z%J*@!{5UdhA%^01K5mVjQ(=u)3jK?whj>fZ?bG!Oh0CZq-y_0{72h|q!~L3ShFlSL z*x;A(%vINjbZ!+qz9V)al@0}*$?ES-+OX5mx2OZv-a~b^2Nm80OYaoP+(Ps7FXX;^ z@ilVEI7hUHIq!jtm81&FU*pyu`Pr4tw5t^$-F1WEF~mOy8#=6lk$9lm!d}8m2&v)2 z`<-uZ!(8;3aAlB`eI;gfqe^i&Ay*MwR(6^x`24^`YVxw1>YooQM&E9-gC`s^7v2Zr z!6Hsfz}je_bNL%#VNLY?o4ehpgb3c@g6A%;<1p`-D0=cX-TE$O)tw)@ zxIp=x74r>)Qtmv9ERM7C+B8V4_x#8Jy@thnz26moP`!F>##Eo%7nXnXyQX=+DgVC7 z3$4z$r1CbvPe#wX@CQqSUkS$rE}-IFP~2@K0?G66oTF9xEMD#mVd^&nJ;OZa`dQvy z3-Lv@$S-1_coD3s)Q3mU-;?bB>VM=2B8q9~ldXpH6hH0kVbnuq5Bp)iP*-8-($e_Pjr)Bu489(b0u_;V(rB6p1-5#}OSPP9kl#sTZMBg36764pZI z%gPKjzaqY)0!kf~3W{@1rPOTY?(77B6h1TT>T}PTB@fdmzA#D^1kMbSsx7U``)ZGJ zNpO(#`oIwT(31y#Za40<0WX$lKc>vt>Z1rm+D|N74Q*Sp5s|yq>jQ@>cJf*N@+FCU eQADU~IKvp%%#hSS3Jv)1Od9B?=+Xkfir)duKF$sR diff --git a/mods/certify/certify_certificate.php b/mods/certify/certify_certificate.php deleted file mode 100644 index 047a6ffec..000000000 --- a/mods/certify/certify_certificate.php +++ /dev/null @@ -1,163 +0,0 @@ - 0) { - - // COMMIT CHANGES - - $sql = "UPDATE ".TABLE_PREFIX."certify - SET - title = '$certify_title', - description = '$certify_description' - WHERE - certify_id = $certify_id - "; - - $result = mysql_query($sql, $db) or die(mysql_error()); - - if (file_exists($templatefile)) - unlink($templatefile); - if ($_FILES['certify_file']['size'] > 0 && $_FILES['certify_file']['error'] == 0) { - if (move_uploaded_file($_FILES['certify_file']['tmp_name'], $templatefile)) { - // File ok - } else { - unlink($templatefile); - } - } - $templatepresent = file_exists($templatefile); - - //write_to_log(AT_ADMIN_LOG_UPDATE, 'certify', mysql_affected_rows($db), $sql); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - - header('Location: index_instructor.php'); - exit; - - } else { - - // COMMIT NEW - - $sql = "INSERT INTO ".TABLE_PREFIX."certify - (course_id, - title, - description) - VALUES (". $_SESSION['course_id'] .", - '". $certify_title ."', - '". $certify_description ."')"; - - $result = mysql_query($sql, $db) or die(mysql_error()); - - if ($_FILES['certify_file']['size'] > 0 && $_FILES['certify_file']['error'] == 0) { - if (move_uploaded_file($_FILES['certify_file']['tmp_name'], $templatefile)) { - // File ok - } else { - unlink($templatefile); - } - } - $templatepresent = file_exists($templatefile); - - $certify_id = mysql_insert_id($db); - write_to_log(AT_ADMIN_LOG_INSERT, 'certify', mysql_affected_rows($db), $sql); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - - header('Location: index_instructor.php'); - exit; - - } - - -} else if (isset($_POST['cancel'])) { // Cancelled - - // CANCEL - - $msg->addFeedback('CANCELLED'); - header('Location: index_instructor.php'); - exit; - -} else if (strlen($certify_id) > 0) { - - // EDIT EXISTING - - // Fetch basic data - $sql = "SELECT * from ".TABLE_PREFIX."certify where certify_id=".$certify_id; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - if (!$row) - exit; // TODO: Invalid id - how to handle? - - $certify_title = $row['title']; - $certify_description = $row['description']; - -} - -require(AT_INCLUDE_PATH.'header.inc.php'); -$msg->printAll(); - -?> - -

    For instructor to add new certificate - - -

    - - 0) { ?> - - -
    -
    -
    -
    -
    -
    -
    -
    - - -
    - - - - - \ No newline at end of file diff --git a/mods/certify/certify_delete.php b/mods/certify/certify_delete.php deleted file mode 100644 index 7ffc2f460..000000000 --- a/mods/certify/certify_delete.php +++ /dev/null @@ -1,82 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: index_instructor.php'); - exit; -} else if (isset($_POST['submit_yes'])) { - /* delete has been confirmed, delete this category */ - $certify_id = intval($_POST['certify_id']); - - //$sql = 'DELETE members FROM '.TABLE_PREFIX.'certify AS certify INNER JOIN '.TABLE_PREFIX.'certify_members AS members WHERE certify.certify_id='.$_POST['certify_id'].' AND certify.certify_id=members.certify_id'; - //mysql_query($sql, $db) or die('1:'.mysql_error()); - $sql = 'DELETE tests FROM '.TABLE_PREFIX.'certify AS certify INNER JOIN '.TABLE_PREFIX.'certify_tests AS tests WHERE certify.certify_id='.$_POST['certify_id'].' AND certify.certify_id=tests.certify_id'; - mysql_query($sql, $db) or die('2:'.mysql_error()); - $sql = 'DELETE FROM '.TABLE_PREFIX.'certify WHERE '.TABLE_PREFIX.'certify.certify_id='.$_POST['certify_id']; - mysql_query($sql, $db) or die('3:'.mysql_error()); - - write_to_log(AT_ADMIN_LOG_DELETE, 'certify', mysql_affected_rows($db), $sql); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - - -/* - $sql = "DELETE FROM ".TABLE_PREFIX."certificate WHERE certify_id=$certify_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - write_to_log(AT_ADMIN_LOG_DELETE, 'certificate', mysql_affected_rows($db), $sql); - - $sql = "DELETE FROM ".TABLE_PREFIX."certificate_text WHERE certify_id=$certify_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - write_to_log(AT_ADMIN_LOG_DELETE, 'certificate_text', mysql_affected_rows($db), $sql); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - -*/ - - header('Location: index_instructor.php'); - exit; -} - -//require('../../include/header.inc.php'); -require(AT_INCLUDE_PATH.'header.inc.php'); - -$_GET['certify_id'] = intval($_GET['certify_id']); - -$sql = "SELECT certify_id, title FROM ".TABLE_PREFIX."certify c WHERE c.certify_id=$_GET[certify_id]"; -$result = mysql_query($sql,$db) or die(mysql_error()); - -if (mysql_num_rows($result) == 0) { - $msg->printErrors('ITEM_NOT_FOUND'); -} else { - $row = mysql_fetch_assoc($result); - - $hidden_vars['title']= $row['title']; - $hidden_vars['certify_id'] = $row['certify_id']; - - $confirm = array('DELETE_CERTIFICATE', $row['title']); - $msg->addConfirm($confirm, $hidden_vars); - - $msg->printConfirm(); -} - -require(AT_INCLUDE_PATH.'footer.inc.php'); - -?> \ No newline at end of file diff --git a/mods/certify/certify_functions.php b/mods/certify/certify_functions.php deleted file mode 100644 index a46840b83..000000000 --- a/mods/certify/certify_functions.php +++ /dev/null @@ -1,88 +0,0 @@ - 0) { - $certificate['tests'][$row['test_id']]['passscore'] = $certificate['tests'][$row['test_id']]['out_of'] * $certificate['tests'][$row['test_id']]['passpercent'] / 100; - $certificate['tests'][$row['test_id']]['passpercent'] = 0; - } - } - - -// Calculate new scores for each test - - $sql = ' - SELECT '.TABLE_PREFIX.'certify_tests.test_id, '.TABLE_PREFIX.'tests_results.* - FROM '.TABLE_PREFIX.'certify_tests - RIGHT JOIN '.TABLE_PREFIX.'tests_results ON '.TABLE_PREFIX.'tests_results.test_id = '.TABLE_PREFIX.'certify_tests.test_id - WHERE '.TABLE_PREFIX.'tests_results.member_id = '.$member_id.' - AND '.TABLE_PREFIX.'certify_tests.certify_id = '.$certify_id.' - '; - - $result = mysql_query($sql, $db) or die(mysql_error() . "
    " . $sql); - //echo '
    '.$sql.'
    '; - while( $row = mysql_fetch_assoc($result) ) { - if (!isset($certificate['tests'][$row['test_id']]['final_score']) || $certificate['tests'][$row['test_id']]['final_score'] < $row['final_score']) - $certificate['tests'][$row['test_id']]['final_score'] = $row['final_score']; - - } - -// Calculate new percentages for certificate. - - - $certificate['available_score'] = 0; - $certificate['achieved_score'] = 0; - - if (isset($certificate['tests'])) { - foreach ($certificate['tests'] as $certify_testid => &$test) { - if ($test['final_score'] >= $test['passscore']) { - $certificate['achieved_score'] += $test['passscore']; - } else { - $certificate['achieved_score'] += $test['final_score']; - } - $certificate['available_score'] += $test['passscore']; - - if (!isset($test['final_score'])) { - - } - - } - } - - - if ($certificate['available_score'] != 0) { - $certificate['progress'] = $certificate['achieved_score'] * 100 / $certificate['available_score']; - } else { - $certificate['progress'] = 0; - } - - return $certificate['progress']; -} - - - - - - -?> \ No newline at end of file diff --git a/mods/certify/certify_student_status.php b/mods/certify/certify_student_status.php deleted file mode 100644 index 868319c69..000000000 --- a/mods/certify/certify_student_status.php +++ /dev/null @@ -1,140 +0,0 @@ - $b['certificate']['progress']) ? -1 : 1; - -} - -usort($members, "membercmp"); - -// -- Certificate update code end -- - -dbug(var_export($members,true)); - - -require (AT_INCLUDE_PATH.'header.inc.php'); - - -?> - - - -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    -
    -
    - - % - -
    -
    -
    - -
    - - - - - - - - \ No newline at end of file diff --git a/mods/certify/certify_tests.php b/mods/certify/certify_tests.php deleted file mode 100644 index 9cd0be3d5..000000000 --- a/mods/certify/certify_tests.php +++ /dev/null @@ -1,167 +0,0 @@ - $test) { - if ($test['selected'] and !isset($certify_selected[$test_id])) { - $update_remove[] = $test_id; - } else if (!$test['selected'] and isset($certify_selected[$test_id])) { - $update_add[] = $test_id; - } - - } - - if (count($update_add) > 0) { - $sqlrows = array(); - foreach ($update_add as $testid) { - $sqlrows[] = '('.$certify_id.",".$testid.')'; - } - $sql = "INSERT INTO ".TABLE_PREFIX."certify_tests - (certify_id, - test_id) - VALUES ".implode(',',$sqlrows); - - $result = mysql_query($sql, $db) or die(mysql_error()); - write_to_log(AT_ADMIN_LOG_INSERT, 'certify', mysql_affected_rows($db), $sql); - - } - - if (count($update_remove) > 0) { - $sql = "DELETE FROM ".TABLE_PREFIX."certify_tests - WHERE certify_id = $certify_id - AND test_id IN (".implode(",",$update_remove).")"; - - $result = mysql_query($sql, $db) or die(mysql_error()); - write_to_log(AT_ADMIN_LOG_DELETE, 'certify', mysql_affected_rows($db), $sql); - - } - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - - -} else if (isset($_POST['cancel']) || strlen($certify_id) == 0) { - - // CANCEL - - // FIXME: Is really a "return" function - need a new text for the button? - - $msg->addFeedback('CANCELLED'); - header('Location: index_instructor.php'); - exit; - -} - - -// FETCH INFO FOR VIEW - -$certify_tests = fetchTestList($certify_id); - -require(AT_INCLUDE_PATH.'header.inc.php'); -$msg->printAll(); - -?> - -
    - -For instructor to edit certificate - -
    - - - - - - - - - - - - - - - - - - - $test) { ?> - - - - - - - - - - - - - - - - - - -
    - - -
    name="selected[]" value="1">
    - -
    -
    - - - \ No newline at end of file diff --git a/mods/certify/default_certificate.pdf b/mods/certify/default_certificate.pdf deleted file mode 100644 index 0776f9e7ba2bcf9887601b241308bfaa793f6fb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 526128 zcmc$^1z1$=7B;M+G>Aw@58W{{%)pS+9n#(1-6cqOgQQ4+2B~Ti%Wx}Sm>Nk5C_QK$O^>A z$1ZDWXKLtV>1ApH0<+74U=TPM!p*J#;)Jt{fxu8MI1Irq4}7Hpdd`=HUDrn>is| zTtCmt$@!}fIN@A~U-Y=Se|ZiV2lp?}3jp=2j1&Iry)eYDdR&lS{0u{I{9-fU`d@qn z{~Ijf2pGrD&%p%)y#AB#x!~Nt$hbM7zs!pObNn(df*bO)49vmF^>b{1!C=_0GA_=a z=YT?hsQ<}6AT)mQ3lxF?|Li{)0u23m4j2N;{WF$;=V3q33q!yWzsk5EKjQ}H0E2&y zU0_=H&-VgZ1pXOIK=zBD5fBcJpX~!=&|l_&a3Wwo`2_*w;4kw+{%#KLU*ZJ;g>n6i zIRY5&r{@J=LqLDh14B7ru%9vF_|8gy#FdMap{0$f6Bar^a>@X|fxsLb?21mNZr_Ov z%)zc?Z|?%)1P}x%u}j&R*@HL%Z(W^>YV!f0$1FK?(Aadn;4n5Y7&QP6+#2)y zx61GLy?IrAjSY0OBMMU%cOBEf7L&l>0UENOI5swN*R=`^BWx|~Va&37&(mV6Dn6Wn zQgTOera8jFv5pwekx~O3-qax5(+P-UY~$X++Cpv%p^Z`^v?4mLx<^9x0cv1-jrgs` z?&)o3G~>XkYe*t?LD)f*#@Ols_Fv|*^6c1eJHRGDq(uX-TE}i~lH)iMv2^tWU~xb> zq$~q0k&)x{rvfhS-hUkV@P#LK+^VrbGT#f+jnF(I#{1etH}6fY6q&H?!7t%s+^0HtEqqhyMn8W z4N&@=L07d(-ZKi({7YGP^lkKd|TxY`#At3noVFCMo!&^lK(EQ<^>EQ;7xQqDP`>gMFq;H08{)S}0JOgc}uq4l|Sm1Cg!Ft?BXC!c155Ey&9YS!BzXo;9~0RqHkwtYYOBEkUKx} zMlO{s59@7g7Yo z@*vLN0Qrj>t|UJm;&=0|DB%yD<_0Lm#mUm+`+&bE&eg!bodYram$>*Vc30DWM@K`! z$O`ZeyYOE_3#fr?Fd!D7zyopV0s-P=d!-Ee3&Ddy=IB=*|4kM8Ll@*^if)GfH-z{d zz`wu&0YllK0B3;VTx?Ll%P?*L4xk|cBfxB61meGe!`ay0>3;Wjs86tKa>GC{-*uUa9kzQzrexC#sy>t1Rz~*C>VeP$_9Y| zpn|#oTR2Q@fo|uonE|wZ-|Nc%iPV7o#y@|i#&^j-;{ieZuknDf0S)heNRB_i`=R{L za9k1EzrX?g4hIy<#l`{f8;l$B0}d`Axxv7szq7$Vla-mPjm0}aRL5X&Ht4m0_NlfC>>yU zHV79SVDx`iMgCRypAq?~sB>|%As`44Cs3z2fnE;5h5%|PuySI9a&!MTa2NwUle6j1 zY4W4bg>e5Lq_1BpJM2GH_Wu=q!C?S{KtND98{*1E{|=KMs(&c|BPib+ufLEN6w1j4 zhQO}Ui~DNNhZ7ETBM3OKWe21S1orQ7QDL}hD#1VM$iJ*k{-&q;_wCfxcGHjb#_yT% zUGmTD1O*zj|4BOqc!LcAtT@2ntA6S~rNVb*fM$NvhW@kT|19FaC-zmB#=$OX>TC=w zL=Ej+u3CF%5cl`$$u4Z@Y#y@6%DTGYt_-KxE+o#oX6A9S^y2lTwZ zFWcCqOn_ySrHd!4|NF||Uw!%yMtskKKaCI;k(1U`|6## z|5iG+*_BNl41txGrM(@yqL93bg1i_tu!qC}2L6kv0X}iFG&U8H)4XcIML7OgX8zGB zi-3RYqB$W51mdcfziOkwTvr!BqPW@_Uk&}e4TfCpN3#Kbwg-A1J8hts2O4cdJ9E?T zqyFB1|IH`Rb^ozI`MweZ9QO}~gW+(%aMl0H?jNSYp@6A~@9PRc@INv6&w}{dP7xf~ zj{kL!=+A8+$?zm)TZLH;oYm+4oxbk{SP-*o9Vv>mxCS$vLmJduNFvJPw+K|UQbJO< zyX|>r8ClDXYn8m%_vZKqo#h)R-TF^0-oM_q(_*c#mK2O4c%Fehl9x8uZkc_3B{vhv z$pL;3@0>P_;s#|Rx>M1IX!jW{pO6yCUP@uaO*9Uc*i*&!Z899v>u+cUcRn6sek2Jy zROTmg?YGq(pnG1|P})>SBr+Rz$ojHA4MTA9O)_dCt89lNDe2y)!>WdQOY7Um#Xc_w z`MqT=5tbF9lTR7(zP?8b!YsLG*G0mcB7(NmfWl9qfb@y*l`|7%h?z?^NE+EHDx7Fd zI7G5*suX7d{n>unTiG6i1zpGsauDGwGnC;hpdX8cTIRTkx3XD z6V~G*lVWe4^kh=88oyS`kjM^E;e1)68=v|dk|fd@=nHpJ0wtyQWu3+8Qo`J&u)V>2 zF8gx$H9!xrDFN$@#er9%3bsd0>r|qe@U!dT>6t?$2Q^9ywBW90RqbBZY zf=?Z3fhmYMr!{iynOG|s-18pWWd5Ri=$jSWfQi-ZGIhM}{m31XeFPK7 zDwT13)zjW-9{#0kuHQmw{Ftoy?8v)l?iAuXw{evAAtLB)_)D7{Cyv4$GJ@SoBTL5k z$AXF@a7Vpxz3YT`ybm9WwZ`x;-JS9_>wHXHqmIhOe0a#mimzRobtw^lMjOGMWs!U- z7O~k#qrhGm*llZS!)&Y#*J^lF?v(4Ctg$R>Q zpY6?W`NhfopYkgzQOw`Tu9pC4+}lN9Aol!{?7!A7!P7D~#J=$A*f z=IUiV@g`;PFVel6ygN`R#WJdzaTpa< z5$6&@D4Pt8SiV!v_uGMkG+cmG-;XT2F?4}_cYAOlBQ%4(=$JYCQ75Mz6Z;- z>X3&==0w7oR)R1F$LVYLr;E?L+|Le5^3Y!97U6#IL=(q<&Ba6^b6EN&z+rVBYkT7h z`Nxy;kdLPxkJZA?(ZO+Xh7@SUmQluePsDH0(k7ZnMr+LO@P58yyKVuerPVVIm&qg% za?~lRHJHgNtA;g_CsB(Z?M^vC`NM33y@WphlZ1r2+`ti%n4dK_sb(@FNBouoy zKA^U&*gMXq7L4W7A3n(HRP8Ms2RgC_S0%tP7>kP@kACu&&SDx$sZH(3GF@s9Joy@7 zZf%}DYChs?)#EXNLULh!{4ocJ=`SN<_x~=Ye`_88ZQ=MYE8cIFgA*tmod3(p@qO3z zM;`uOIk>t1L*-~z?zc-6!rVOdMyHrX8kpI*Oe~d_)4~ZQ&&}z$g{JyI>sEoKlyb)? z(vsXADu-NB$)ruMN$bHVTdKSzoDoY@c)M1Wya?)@vaN}v>TdS+wr(Z&)3BX!k;nBLG~?*Irx>CDMf0J^5y{s z-?o2ZYHvn&|CTr>#5}C}rn%`gbkeYoSP{518cEgYDswAIYBOPz|sl z^;296CttPpU~~N9R^2$mCdh8)Ue?sV?^Zp>vR12!ov7~6>Upn^_+^6B*gfub0{V23 zklF_bWLjm#{db~^u=oji&%WfWb6u2GAoTvWD<+aELFl+v)r~1 ze}S6(20>+j-b0Fpj~|rWFoqeDsqL~uLn^bsF{0?f9Cg!=;v>OzHR1gaSWX@ex$vW9 z1ZM=o@xd6ifh)S`6}gZckpY1!&Pl7D%`?nNUJM-gHu`55yw}iHMkr;VRL5 zc2k-{zkv@wQOQRgs5~Od+XqmxG!{LEm=25*KJY=7t|54NRTu~ zFU=&M%XNky?C|6X>8E9@IW>{?vafM73OB0?7H`$cVY!rJ+<9(Y8TBsgW#6+Pc_IoPWk zitUz?Fn%eo6xhN$CpQyh&B+n{f@?%ilO=#T^q!@)PUM4|GS6zeLI%i%L{g3{Yy?mZ z^A5cs%hjc0SrVw}s3X+Gni56k5M#H+d&`RWUny0*8kb?xN2eEHv7x$ zQ2`wtRsnH1CIOm-(PA+HF={DxRt7^%*kbvr$!Vqhu;wjVEu!~B&J3|3rZi(zoIJ;l z0b$6b6-0ViT0%;aV?61Lco4^Vr{eU(heh4N+S$3lEYZIcyB#id36t zAvXDNU7NehE0g~+;@o?9l5Haa8oD0R(l`T^oHR5$ALM^cKjz~UnA3T zid8DZBUyv7#&zzjDW{UDPu0)X(>O2&;$q1SjlNU+=tCdM+&sw7MCdV%@|gTN@~u%M zm3kW9!%q_R0x}Ld_B#8;(AvgF6nK0%s0Tcg$m_Fw0nL&PWI^2hOP$SMLq$mEtn;S| zJXA^6DenMpW$y8bS|*xVgqX5JbWE zRXlSwB35YwU)<7|H2hP-bv93sSGW*ELk!DA{l{gbz8jd~XYo^6VX_)q_mgbgtM%w? zsx_1eJ)VsBt}pN8(24rrymzg)k>~R7g7eSCMXTtyrERBzS8_fniuLDf?L#7c%at7YiqGe&o_2vo@Cr42 zR>|u}kO@N8r0l2%EOVdT8lEU02|GlSwqayf%p zzUX>-0y_*;J~xj=HSw;4wd0LjPU-7F5ku+xs>waR;1osK+e&4w^V&zGNJbWxs5}8* zh85Sh6Nj2^kUh!6OAINIS`8a}MXcBRX0|6gUa#r?hp=1Mlt?u1j$_4?77u^yCc+Ze zmFbtXs$6ZSN%l0oy1C^yyw>`i?Zopf z`L&I+UO`_zZ^?Y4g+QK#_3o|3)-%FmJ>4Sc;ogD~Zn=Isq`uPVO>yy#Q85;a0=o0C z?uS0)S(9UqT1Bj)HT=-8U5hU&<^f&t3)^x*WLEt~^3z>t|>pdPQ$^ zK)74Vz}&qdn)j3~*vw@YtG>D}tdp_t;dyZZW9QfZrZil+ z?z^9dsZO|WeO;d*-iMw;%@ zGXcZlkJxf&Z8tElS%tFA{#`s@?Q#4I*#hq{{v+86CENvLHV-miT*sSDu-TA~SnRmY z?NF$6T?sZFY!Z1qy5Es*=sxHzDc49l%UZI9BmCi=%CnnqO_Z($*J#FximBmAl|5?b zM77J;x-+OkWl(^}&#%O0`l|iV_>Au|-R=DJkhl3;?QLaD+7(6CQ1`EEPMNL2q3c1R zZs(O?(hAC82Yx=#!OiVn$FE;q&b;3X4#cL8o}RcM$lk1QZV6DGuDLFzFm%J^`9ut! zYPhJXptijdf3Z&%p{Tlb^d41&zZFX@1GztmM9t8>xS7&~i*7a~*-A-Y#}g^}QR*RY zeEE@w<)uSpb1?0M_E~hCTKjuz%P+*QPkK_qPEPLS(i~ek3*z*Dgy-hONvTY5E0_Da zzWIs`&2td8X&i6Eai*`oz3|A}um5;nkfd|uS%-$+kT*sDtD($h-Sm6pqhTp)1(PGl zhr{>wC%6r2miuG$ZZL6eWo#UbW~LSC+kX(~RiSO76Ve~Z>M7ufCwk2KzDSgbyh%xMgtNmH8NmvYG9!N$@n)@5~6xkt?nmBkIMuj1BfRx5H} zU6&kMmN2ubTHSq#<~S1lO$bjaC~fDFeOeP`KmRbAzY1wh@;TONo4)<7faD|Qcb|ql z4bt)_1wkyc8$|W5t?E(lIPGm-C(t1bt=JOAt!vB|NS|0V{R(Uzh~B(^UsjH_O4ZxF%DoeaMQZ|q02{3u7T1?u1BfC4 zrNhO%xTKqD3`|X*N@#QyF&rc87R*2`$C`D4EnO}b9v@<>MOvnpJSieeXy}r(===9?Gf9) zpbs}K%o{IJGC215aKBTcuj+0l|NT0MXUfN_o=2i7xJJQrO@MAVagC94nyYpH-2*OpP2`IEQM64+%B+tFqN_y#Qa`$$fmOgRubj85Pqr3M~#&2ldN3Bv3v8@s|^5rXV1dI2L zBUe)E%Nu+@?I3=@TpM_b)&lf7J$}8n+aJq!za>ANxE~Xl^DVZ0ojn7&^2d$T~8#>E5 zlkVkt*vkn{0>g$hHj47NTTgK86=Bq8ak3sbP!=s(?^VI}yg*61vjp5ExAn|>RGDg& zr$pq;ekT+`($cZY+?Z3I_>uWHhJ_E!xtX#^5mRwAA~{AVM27tD-|#XR_Z^aHHbk0j z(SJ(zm~0?4(h6_ylroe*oU{@Q=|fX%T@Y5pZG;6|@I=ce-ZM2yiBr@@Mn!YDYuvq4 zwdguPK$n!X%$e zqs7y&D_b>oo$EW36KQ*o-wFRT%5F65S%i|fYm(&@b%}?VICjc@l9Vki&7vf|PQ@z2 z0x5h%JU1Pw*@RhV(vzNVuX8b0Jb&>7+%IC@wn3+Gy!OTn4s#G0)>Gj+btpNp6+1l^ z3AlbunwYEO?}F)<&0z=!jFa7#Oa$J+o;t ze~L8X98`Q#`Xy^4I=PF@&G_de@#x`F z#Ayx&F2}*550yJ9ARK-!eFKg{#$lh|Q;!HEi%DSZ9!sUk;VCIE!boYz{Eja97TXy8 z`i0QiC6cXn#q&>=!kJLI=)c5L<(x!{+Ny<7Wa7Y>N=%p+Wb>|fn=~V6m?*uvvp%VJ zwuz{$G~{;}wy){%(oV|9rOEM2i9Ai@S=nh6uZ8MoPm9biXa!PPFj_tkd3yE$yjSZc z$D6LAIdFnw@`#P*{<|+NT0_QRx-4!QMts3DGYoE$n+_3@VdOY6tVTwmq7O*4c{{qX zqw?%T3ZBe=88<0YyZ5%trp%C8)HQs|*xTv${?q$bC8kbjE_<3fHle=H=q?*c9}|B* zio2ApWUr1;9{0%Rswu6IUGZ4mB>wycyQ0&zL11A;^MaiHL+r_2y)I@?YWu}!7i8aF zd3y*_tSDH2pl3H8@gqmOMhl`4VjW$>R!x)dyxei4^=gSuugC@ zOqbm@J7T9IgM4&m61js8>I3v0vA7&bj`!{bqst^4Uk$Hm}uuLMf_H&K>VbIFc6aV$?XI zsqc~ab?fpy!XWQ_Cy}f&SXNV-=Or`+S2Qdw`do&5L1svg;)u%i!J98*Z6D zu*~iWwO=A@j`Uwd@_D4NYbnr;@JV+*4cR!lL{synADt_hH zeBv^J(l+9g1t|?@C8iA0p4U2|A`O%Zi+I`ZMm_0@oQT^7*PG)A50vy?mwCV{Ke{$Q zY+Gf$VD%qt@}!_xG`@i5tgy89sGl@$zT}SG*+uf}P?)m)R?%eTZ%y=O z+Tvo*Rv|U*-o^fa8uRg{{8A=yNN-Ok*78Sk^4HHKiAvMTq!=J z!GmJ`aw-14W9eh2`?pF#_~oCAaqyXl#w48>gvCnDzMZE(%KTcMfT*mOS;`K_4>2>U-9n0#*>cDAF&X!Ek;rRrM&!l z6sV@UcAhV@&5tMdu{&>cn)Y$2czg_`F28}@!Lekjn! zcJ``C?I<*V&xN&Lo9wO5Wa>zWzx-Qd^30l!NT? zY`>K*r#i(iY%I-STJVqfX8gQXbN-Mk%Pc^%8xy>dVQ5xQWLU>>w;yfQ$+@6m=DLKY z#I4ZLJ0FUdJ}rLQO55pi`7FP}vUTX3;;!bV=04#x;a2A+j(BSQ3HENxLBnJ{rBbzv z$y~LjR15aZpzI;OU8nY2wFubUW841cDH>(ZuqFtsGhX!0*pt-_XsF+KgG7b&_|_rT zCkmXq9NdHr$xiM2hs|DWbEb{Njc;`CR1{VaR2)^5vBfqmjM6FWEI0AnWjvK4f@fjc zK66v_rgCw^$QqRub5VLE&%_Spe3~>o{K+<-XuV6=xTLyk$|e);WZF+Iq(?~>T3*%4 zG$=SN*nSA>eT*-s{OKlImf}IOFps0KdHRs%5tj=OuNU`7#3w#>7d?kF!jbh2QiDO?=1&o65zE7+*--P*q7 z6#hixz3#y#71)2AGg~&I(qr(kA=7)dBdSJ^idO^aRNWUC{7y_*A zbm;b**=fh=r_Oac=mS!~ODp+7=|Qc>ut)~$;NzLi2u*v_qdV+0%#e-SUwU~87!YdK`u&v#GnuKoC(}&CJAXlX{8$ibUD@EgmWgm4^f|t0tu!;zw8pS@w)VBwwI;Kcvvw_u9G}+e z)9Q&x=}tjOX-d&fS&q_6xz}qbQ!gf7EegDibklsS{aAxo`<+%Mt9(jA%$*p^n8~d- zD{V}s&u6+8x(2%@yXX%rqrJOQg}D?jpO-MC-!q3>+05D6k(dFinFZ9T<*1ECdry0aGlZK_6Mf`0U2 zmy5A>3LW}HyKGuP>qC4860>%ywA(Ct*wl~gs15NvUReyUYSd#ai54sw-jKy@*$#E(xJB2ll7@Wz zk@C?Zx=#2bbRt-Du%H9}SuXq8YhFnSBwG%Yv`?{R;A@jTjn&xBMr?i2btlXfp{cv* zTpz^WKgw{#u4%=&0pFqYFm8m_<9AhS+VL2gQFd%MR)V@GkFyv7qs0d@kk6<(!F^R(h zevFWWQKo2DQ^1#$x*t!rQglNl4&6|dNmi_iSgk0}L;-tQva^^wIX6KiLVEOu6P3A3 zJFyC~wUQ>2#7fBxRT{!l(F)E~z86^o3K*7mSPN;F#bhjrJV%|hD9@#}!~~XQ{FW8U z7y~AT62C2+KX@mxz0-31wCFG@TbZdPH}x<=Z)4C^_wrWD6HYG~{~=y!dgc0u5s%1Z zZzuch;BNTthP!^-##1dR*L$FP;{LK&=UYE}DbqLSsCQdAd{4c0Ehmeu{Fg~GN=U_> zp9T+)oV>Fz^|7sm&)l<(b^~ZR2;e6Z7kFbB*C#U7k1Id10#;>#T6su@YdkV|jf_x&- z7w3k=9>Hd?L0I5A4w|zH@3@|;5}As`xT>r2oa*gyP1lEn9-&koHTBjM9yDch;u;ZH zhG2LX_!BLQZiw;6Yw{fuCutJ9lG$BPRTRc$jtH0zSJF3M8+#JOew^mZUfb3Avh2y1 zL%7TRWi_}tj4+aV&ud5OVoKjfJD~oh>SlYQ2Ug{Z>!Qj8$y2P`#^u}@qSATRE?Eid z$aDGHE*aZlJS1Vnyc=wdWi*8&@1zisbmtq_y>dU*wruC}Mo6Ep+aI~-y`N}|wqw?c z92w>jKXjAsUiTQ@W}plUEuPZ7JxNXDuByUTno#T+m|aXCp1?0Q=qx&TAhw`PldMXh z>MaE?D=jVgoG@fn{J1owm{YZFh+VAu_7U}^hKm)wG;18V@KbF*ShSXB>_lp0%C{sm zueU3&uQ2b>`m9l&;HWVyggGok*A+ubz%FmyDQ}G_Z_!KK_vu5L*F2var1AYo;w&>w z6ESJ3zM{G~J*bA;I4$=j&%zbvecVnl@K{vpB_DXBbQ^WbB(bQ@yls%3c3NRpaVc5W zYLFhc8lSToD_3nAFwdF1%+tF>)`#1S)k}?<^=sE&l#Wk6o2|8-Y!&I2&uVhnnrM+2 z)N46EyewRJx$ye<5(V?Za40q?6!UU@&2YP2B8n6?W8638xa6PC;W)C)s9YqM19qO+ zL^$)W_3KwT3@_5^$)tL+>sLD^$5!Ti`y2qXp1f@IYwwcFcxf|Nr+aIAs)5Qh>LZTM)LbDE|=7wjGBMgY&bw8WYasl+{ceRvNBR~Q|ggN zpO&KJWi+7=-pr57!mCLX{#|ITG-UVzv{K9!gp`WneeED-Y%a?9%;3PT>nMtPjxd|- zMDd!o0SYz&ge-(Q?FLbqLviyr4F>f7SNa-@SkA8k^!B6aT@rMAkLN!bAdA4BL?uKd z*3AXO4Ha*0^?M6vYkqD%e03@dlX5u6B4(L>tIW{VNqcD?axTw zqL-8q`p^&PGoSICgVJwcD-vnF-9ZcSh*DhNDJdk=^VD-VLr#ObSh!Uh`e*oSI)4nL@PFHTq$Av1<>4;fbA z_a@wA<&vVSjGw#obCmyDW|KQt#v~ghjfv;`e%kBL!}+M<)DvklbaNj{N(#GEzt)wc zF;ES>of~Mx9MW*#G?S4vW>ifpI1h=7a|-L3a+elw4EmVWv#qE_>sm6R^(e(&V|)L# zZQR7K!|VLVnddD78@vmrtvheNHLuGWOj^gmHlMEHw9{7+PYl=@U)HAw)fb`M;UBCX zJfWI@yCW*QPKdN9RzOrB(x84yUhW-xrpff!3vtvv)>iI0VLXQI?Qyg0+jXZ5!>PBL z9b@iyGzCqtO)xweAj0m|C=bYu&g1xdd<^eB&ori}X``OeGg7~!iZ(n(PfZmuz;(bH z=BlvwoMG)`?P4KMGHFqupAc)8_}D--$Vl*=)ZRm-8~VVHs}68@{Q^DqGM8viixw{` zB6TYD&!>+fHg*aaUhuktT&Z9-zW0N<+i@)nd0+-dXi3rBJ4jXaONaE!T%Ftx(IX00Vy{}&>2PjX%{cX$@3R-vY(GD_ws>^cC+%Ch z{vG*_M?Mc2m^zGxsn0rmjWW1FvU@yv+o6j!^&v)#cBYL=rAf@!O~GGfcS7CIRZhpM ziL=-4jz60(5GbS@_vazxCdp#X+!`QXTN)tDv~O4(;cb`rW@V%GZh-nOYGmS}uii7+ zRr3>~se`RC<`icQCc!su2V^#BgAO*T8=m~uPa~xfE|=&|VZF_IEauP3gW&rO>%(K= z5q(}HNejcbR=B2SiK3cS`wegJv5%4RybhZ*8d!)#NZ)T3_s8FX7VUFh$~jW|H@&(Y ziC+~+m@K|L>bHkSb{EM8C2QG`>R5GBZ_1H`7rkxh?P_)9BeB4juOkQ|V&nK1-hK;| zthv>2a9gvohWykOHXBoZqWL}|gVeqK9KS~W6uI-mEt|CZeT>Zt0?!-=*?bAjSP!Mk zz_v)6lk&yFP< zbB^YBRwuQD4owQLZ?oX`3NePPumtJ4ycXdL-={u7yG2lY-Tgv)*T~#LV{2JTYp2I} zm*-^Gll4VH<1_R1+!xu~b=kR0CqY8iyyASqIYUb>kG7=w!!~`1?FPJU(y8AJ@=&Sa zbDcCb2T|PfZyj$W$JKmLMfwm0Ed5`ibQ zi=3)OGbeHQcQUFLj!WivY~;-CKEG_0dr4&`xa6Yvh6pvJk%#bB265Z4qQ1KJbBC|2 z;|Hq)>AudYrn!rSn$X@}vrh$nwr8~^%09G-k&$%x@+@f|j+WO}R!y3o>&TBkK^-WD zluIl=)+FajcJh6jz!biLhJ$O2>Zpvw2+`{rTdYfi>p@W8@_vLfmlkx9)`rmi`)zk(UK-Rt zv2mBYebi9KWZ9F2#X%CMnQu>QBo^I=?D3%9E-aCmFcKnjm{Nt%w2x=z5Yyxywyv;< z4bk@T^Di$QF?r&8rj>YT1{E}jRP4#_QV}T}%@&^pxr=z$K6y9VHJ=|k(S?L)@v=8^ z9m5Mx%WNlk)y!%(>@L9emALc6UE$%^)jByGZ#qdh!->0c&A!(1^Q3H~+OmXzhf-6; z7R7HW?*!v&^K$lexp(H#%?2~V8tyif9ezDKtjh1;vNB7VFFz(BS>k?-+n%31dqFQP z9Y{Ul$%JMtZmx2iAt%6}Vv!EvjE_p5^+O81xaelbFQT$4_+yNvdKa zgO6B1k>Xi^-QDWOX~nh$_S+r`5J~HYX}q&fEp?v0XuXShd?&HsGngOf;GgxD?((*q{^Nz2Cok*VC0buwxn z5~qn1fle`a|2@48Ta?pLag}HuqEIPB{Y7*m*SgDVCR_ATszUl!nz^p`e&4=LGg|5< zwQLSf&Ov%PH*PHLojIP=udLj=fgyg+W@{6UdCW~N%gX<8qz{EaA?raK0i*p7Ts8_>8;-ZsO;_oGCo@H6P_CF<|zM%b@ zP|Zl%W(fR5XpB6EXqqIb;!Kl_?N-q$W!9D*1$xaK+1&7*+wpZxP_IBJc?4H?h*G4OJXxlcMp`rx^##Oc|EBx&err5vSU#g{>L!VPs)@;{4wpsL1g+=e)dr!ZTt-W+ zp~ANkXK9M&F6Bp4>JT-t%;}QnL2;41;TL*sFEO!1xLXRtM<)ZZ8>JsR5mVkKg6yd$ ziSLh;y*``1)%TP`w?Pbz65Jxvpzz>%a|MgKn%zS#=F~@#rV0{`E%N5l_C7(^Ry3hx!7;VB_sx^^$*mQOuka1-8FSk z@)H2T=uw_Aa}nCkKI&vAMBz(CN-r`84LMvID-5P)2o?ed#{7&{b06=Mx)i=j?A0v~ z&u!Ar(|um0E#tu$1S*5fPAMA&rOK>_+dO0SPuA;T(f$2L)^zg9?{dgBl-xa57Yk2T zH|*nm{cjCl+KO*)onocx2&87+COxw-3%-bH=Jz>$x3{suzx?hx(2PwZjZddpJ&g;k zAXP~A9$AX=R1xWqGhs_Dq4N)&U^rHy{H(O5GP9^5_5dz9cfnwrsw!KMyU%AEviaac zrjN?xjSqbNBi(sOTi*QUZz{utE>*FN`Gdnk=a zN8JIp87YSEyhz!;@zwe8{F!jA;=A0z>qml{sTdB)o%r3~77pfbN(u`z#9kNm#GrYE z79obqI;i;I6%Mhbrzs1urFBWv76>i+zDK@@r6CSZA|3`Uha}cGq%KgoVCuSf(UTWS zMOskhf)|T7c~F-(zHQF!IGqNz++3F}I+#me;BPwLTH4&6es1n=4DEfncYY(qwkWgH zhivruG@E*nG8OC-TS7exMW5fq=Tq!jY~!SsDeqM0Q}lBdDrQ8NZ_?c!yotAY%^Bs8 znA{oe#qk4P+EVVXOpNqPwV54$YP;UoXOE0qBi6~s+6!dqecytdZ;NN>?&6wauj%7v za3KPNA!{d@#cdNMtYEStnm1s7F*~q?cYhKiTH~z}bdG7_aOrnWBZ;!mSi|^B(|bCV zMVV$AH@4&_*2$cTbVEw|NXDE)M#ESW=#Lo)yi+%Ai(hCt@V5C5&UJVuIkucOatu;- zU+{)BTs{ywC+_~5nz*%jVE>N%or7REg*;-!P7Pk0P`;$`?Ql|RBII=C{p337MqVaL zU5*f)lRnd1>b%?CgYmFbUoNw{7_+%!P4l`}`|J$d?$uJ3)LYZ){tqPDj&V75+aWnP`YIdBey_cf;lx>*UJily? zrZMmoLnUYT3o>~>v#c53^)-R55X?9xPnCaKlhGushP|NUyQ>u=m1bSRL!IPe_tHYU za=)OBz_9^`cWOJ8I0Z88jgqC_TuG* z7l#55)?qr8vaF~)Ny9Roe$B;NegbCryp>H%3JJS-MEu7atjig0l-myI zjwF@yH+VDrvdtf^bPhCmOqag4YI^J4TP#{I{U|x!rf-P^rrQNk$diuy%Gj1{AfY~` zGnC@9K5MNQF*pey4;@)K<*o44caF&{AiL}ci+0R7F?SUll1NMjdmjlz&#pb-lWCZE zIT()Ca_W-&W;Nd&>@Pbb8VH_~ z<6|NXZE(kKPcUUm zq$Ez)&{?qu*g3KHWLelQ^YrSf1Tk&cc43UT(eRX==Ut;6yDVl}%3@M_mx(*pR1|Mc zI66r#oW7adCvq6y5-SiQKWuXrP8U_>-^DX6Y1*Ro0y%i9WK(!11^RVaOOya4oRRg8 zXGA~CN;yong`9UxtN2TlSVyY~>r_!j^g2^EceHt?QPM8vxERxe?pz!`!ltS2=Qipr zja9n0UG?odkofe+59P)W5sF{*KkHTzbLVugPll_$g<0L_DoU`{s8|&kh&i27b@D5p zy9a_V+T~NEco6xx-m}|^=J-z@yZNZQP){1(3fXJru<&kq8+MPWP4+ok2vcvE z)YHo3hx96^lFgRebv#3ME7+F>Eu^=nq4DO?_uZSIA=CD|<=Ne8%w*1+lhxyXcQ$D3 z%?;x^Q{%>arj*_(d=OydS}^g0N^gN}^rP*koU5j06lTx)m9|hCCT-R(0^CMow*(E_ zh?goEUYPCMJTp0Kekt*}1Weq5`#SrPVX5v7Y4x0dfmOT;?K{UwXVPcrz9rT=3i{n; zpNdu)FKe>Ks$Uvme#oM_G_G-dtQmx?Wc?LQzh?Wjd$jJnkTD6}y?&DnGj=-0h8)=? zvK)IB+V(A<=KCp7{-pg$6MdG!DOL*mMEuQjj+KLbHk`gDury6?U1I;T``4GECgo+x z^oxgw*n07TubM*cv1W?&CNGSo^%AA7CGxfe-LS2ebYLE$t+}aN{*Yy--|b=ZXyV%X zwKLjLdZI40CpOm)juL9K<5~X}q{wQ*wUTvg86tI| zyItQ%G!XE@Gro1K>gWB!c78tnkrF2G8%6or*AHzEwp;Eoq+J$U-?nUrN-Un;>(YxdjS;{lIgPOZ2U!G+9J|6Xy!%J1YII zE$#D2W*a}PzWF83J=*?bcd%pK^VM=`CoRv5WFn z6m`bE9KHai54gT>J4yGI&z_t!etQL(pMMr4MPJDKd~+j70f}$`a%r2w)wwI%L~rG) zGo5AHHe~y>v5lzu3!xu|&y4Vw&KdnFIdZczOwYh|L1ps7_kCv+HFJqcl^w16kJ~SB z_i+!3()}Ox8F}%W!dDa%#30jtiJ(2n4EIl1sp|gzI%Ot(H342{_t94C0v@blqcg&x9^5s;)o>bpSQ2TCmWQ$A`Bd;_mYjt_YAd}yi zQpYH2-4cYntTYFB*7_gL zJI>3kAC{OCS#RTv&CwkbKbgx>Tu|_0mmzy++;^PEx3OT^YHzz_ocP|7i)Ue;cb{i_ zjITfQT8`?rbCX#OPIKg}Oij~yw_7`JDxcvj+VgsUrIpJf2$v5DaLIL z$uT_V_QuU4iOCMi8)me%_HsZ|Vos1A{W4#~6>{NrW3 z?#w@!M^0gl)DzWnVc$;^yzgOO_cf?Sw)KI4@z}Lh#18Jkg1JDuK;h?sktEvZYq@jM zJ{5~173upy8)E*;aqJ1QH90K%$6E7or01-OFDsgzx0H6ueKT(wy~>AB#3r=#6+v@i zrtBqqqPu#q(Ek27&FQ}O9(KX}3Rl#C3JH;hHkGBsuhEBex4h)yC8$m9h}{yYq)Q_U z9>3cBbd;cVm2||C_eo5U-GBto7FGY&v(Y;jU1X)B4=}@6#@F%6*K0+Jl(*E!dJ?t+ zPA%JA8>z`Z@>tH}BANkcA5dQu`yJoV2KqQ!F{+5==}SHdlBp>>TTjzyJDXROUdi>4-~V0WWLT zKa}1XBk73b<+skm43+qm4O#ssM=QtatJ16shG$Hp8M68ZFsItG_@}zjq+3?YpMnWu z|G2PFrTAH2KCe%LBzgw2wI9SFT7q;h%nNI0b#o~(TdrJUe7D+&P9%rNw zng4|*R2PkHg%#l!gefH%$7dk;M#f*Zon%$Al*g)v^xm8i zlOZ-UJ?)bR{a>Y}kRPiK2-op1tI`X0#q7aovhTfczxQ^R)M)3u`K+adm!{)0QXZN$ zj@>TPIfR}!r*jjc-tu_o?0yN@aEmyoLU&uS;~G1h{(e%3?Q?0p%F!afgQ z4x3}qn*V=ny#sJ$-@d;cOfa!++cqY)ZF^$dwr$(C?POvn6Q?KEoB5r4{`a1@POn{E zy;iO6uHLn~YxiEC@AGhF4V0kG*6W(2)Zs26!eMMAFx~_>YB5~Vs2QoNWqY~4%XT*@ zx+?7{tV|KNX8sgOddfP=UM*tZ-2%6m@fcgjvQL%%O+mFm!hh^NoIchK`@^LZsby>dfIrO=(-_)W>V)jrnYp+e&o2y5kreptu60PAoQz9#mn*$EeD zb$SCI&ppGy0~IsSFm>nB zJE7UHCfUj^=L601b^w}fCig%kv&c4SRqucbTe02LJ^z7aOQ{5FDE16Ym+eeami+?$ z@-0X2uT$B#Lzib)9oD-ibFw#<5M5M-z*z4X?-qw;+}IhmOS=F%EZ16?wu-Z0tV8s> zE%TBmrkuC@+{zO#2<*rQ+N=BJ+CS|%OCL3i-b89Irst;(%bQW4E1VmnD#J^`+VDLo ztuiTQw9-4&CA;1ng@)~dB*AOx};7N1N-L!_&+xyAM-;a4vXL(Mr zTvqEF_s(Rp>N08W#sBJN0t)~ybIrhRgIwaB@8^(9`LoP1M=ZRZ|krQ4)5 ze`_Mmjd2(1Wd1X^)5zo-So+~aZZX3hLj5zq%+VI1;xu)c_^si^!^bt9-@lqJCx!gm za>belpt;+e4jF?y6KSggsx9CVP#S~4-fqha; zqo!(HkuxGN#;dBz16CXC-)M*10XS zSe3kpBzH_m5c1rVKv*Zupo7TOq0kW1PYTnTOryp`nT(1xI9agB0aYCmW#wCNQ@kYU z0~r&xI4E_Yb|}}JNc>T-vIPa|pHxATXf+c>i%I3l`g+76R@KJ1qVO10YXRNuKuPCoOc;z7>S!s# zv=<~Rm(ud~Pz?oup`xjHGc)=vw+}A~^^t>aFAzI=)t*jhwfg&Gb zE}!B#;{JI$cWp>5dDxHD%stux}H`@;dE zb#hbI`f2RzTH5OCL=l@a7W?S>2q*V&IJ0=r-5uCHxV^ByU`Q`SSs|^YAS zH~zBZ5!a+NBi}OeO)%QfszSB~6xtdl?sbHo%9CwrYM`#{NM4qpM^CdXBoniv4s|ZO zzyWHvR!IRGS?H)eLTVX;N(ETCxtRNo#Ux9vf&w9t9!^te+^`6gnW5kM5J^KCGoPe# zU`{^TKPwAj6^iyGODhKwJu5=Skb(fipvOKX7Zq+T%0PE&q)&Q1Rt7O1_tfD`7RdG~ zRxz4v0eIWY{1?KBk?-6$G30Caa%i?d4a`%Xd&I+SJ5#!XswiRo`_0pOY&G+}wusrPe))UjQc(%Nonwn8nxHhhx2e)mB%E9mrMO(<4d^5{w4*qCC zN^?$G_w)IoX&RW|Z&0ijwjhOv;rrVZKMi?1K9RPz#>nj1>&qpb*eUsxSjf4Wp7fxi zoTF6UJrF(4UwD|<>4crmq@O?%?nKb}flpF?rhVdEe;!r}H2V&uigX~&7n5dv8h%th z_fCDH=JHQ}x_>;<>O|0kFTe7ux8^hymp0Y+1mn|G(er4zb=(;7wDwg$ksF@Y63=hq zpZGA-KSi{Heq_~}6&=9#`+oKi`_R%ociu@69&e{*q5}*CyC`eI?7}PC>gXcQ_rd83 z*oRw(wf4F9Q{1$=h__K&hZ~-1+~mCE-a-#N^kEvm2LN?3J2u;tNNg=hZ?I4js9YYtvssg5?hME zv!K>Ot+ZV3LQoyF)TFJnapoCV2H39m1+IKz*xb>dvOK;lE>s$w`z~9Yh?Ky6f+(5Q zn(9<%u8!laEP80zof~;q=iavhv(168>th=V+oZv^BC;)ruA5^U8QEk-w|-}vCtEkp z1TkB*?wA(f$TVrRfg9N1$+UyE&Zlh{ZW&7X#iV6RZCza5!rHR3vhJ~=k8P7^(?Z*_ z+_LVnVZd#JPPB%%VfAX=i(41yG6uJS$Za`#(Ux78=rSR@fyr%ka?z#JB;~SRv!>E% zx_TM1)uiRJakZw?c``i<>S-Q(QO{dn`Y@F_f&Q?dyKd!aWOtd}-3tFO&$n*&YN&Ua z>D`L|u;{aH_iE&85EdpL7DW*jVICHP5f-i<7R?bB=@u6IO+4&}cod0vgt2%Gig>uP zI4pjVKmA)A+F2YPW*lOA9Hz!@Y}HuE#h8EASn%dpVAoja8-*XxS8NqUlpultvY#Tt zkRk>NQcxmE$Rel!W$bdu4 zfKM{HLT(RLY7cH^ z4|ie@jBfuu)gDaE9(L6pl-(Y>)gHpt9{%wb2>uo__V%0HEzImK2>mTo?Jc<7E!_1j zF#hfL+*>fcTiBgjQ2tx!-dhM?i*FM1j5veLAjC{a#LQ5IOjw1?;6_YnM$B*rOgYmg zUS#@0WQK-h28v`x4kh}MC5DzS4AC;h^zUgYXK6W@Y4Pc4=^CfARZ}AuQ~g;}!<$os zT~niPG<`s5#)N351d$A3{WKGXG&4vr1`;WT79kBVgX$?q>N%+D@yY7xD(cD0>e;O7 ziOuSn&g!Z6>bbCManWmOGHXfGYgx2w3Ds*EHft%DYdN@U@!4zXI%~;WYuUVOiQQ|N z-fOAvYq_8tae*9Z!W>D199hI1356UPMjR;z9689=WaJJ=R><+ufnr0pPCh@U8*C_;-l- zfbY3?n7IHjy*pGr0PM~k?hXKy{|=cS0Ns0s-3x&5y+ii}z<+w|@cxjH-9ynuL{W%G z(NI89nMcuKL{X|o(XvNTyG7Cao+KZhq%M)9Jf5UYnWR{rq{$~qtoKY=y+GN`L{Z2@ z+1N0qr;#kPo-E9nEY+SY=AJC~tRetRRVGALC4j0B7oeg%tgKCnQjkDZya1(w8C+g9 zQQk#WRzOwWP*L`k#OkmtE3qtZ`CV4?ySxXhEdNrKm{k?|Z>5SFbh9#bvnqD83U{*_ zgtIcavnsl?3cIr!{Jk>$y(<2_3jh5o5bP2G>N&~k1%(SAHT_@gi4YBUdS)BQLU}XtJZAvZLg@ zBR{jFc%!4Rv!nFYBQMmWXw;*i)T89YBR|!nc-5n@)uZ(BB`@}+X!fO`_NC( zS|6BO0OcW6r-0fJSi8R35~|}c?`lw6LQRrcro7rnaC<{d)@$rpLrg4IWWfy`?}=^l)bo_u9*I z&I)d{hnpF8=fFqb719ohwEs>wY|@6KwkxR}Txk#cRd~~e_aCuZ*In7o;7)t^t6}dp zeE3~Ko}kcMNW5XAeU2c9f>Ljxbce0naP4+wzA8^{;kJi8-SF{u zg}s7eZ@=>mn?2#^?MitC*WSYR47)zz@$ZVg1?ApC`wZJX;ri~%y#@E)!ha0=ZU$vG zpi4m}3}8rMnqf|A^lx7bPOqhAIzroySGTdY?zL>jY&b$(jb*nnyYAI&Mt3^GUyXOS zu|MwhY{tF^pGd zk=qUD2`2~qt(|e>n%zz3i8KS?{4#ytT@x)YOboVB~jT@h*kEZxa-H(tBl z=&o>f0NVD%h8y?wZgy9sD*$hM^7X3%YB$g;3?6{UH!=Fek-MAd6(I+}F zU9%1vj@N{KUF#v<+k}5z4=xV$h=5c5Wt?z9kE&R* zf|QVzNdR238YV&bh=Ef(CXV=sf>ZPNAqFOmaFK4v1cODKC?*}TaS;x6VUdLBBnBq+ zL6L^0aaYsCw{(g`;|A&YaweIQNtpQ}nS=x+(#wRDs8c2-uA#W9G(!nl({S3Dwtb0G zCyCan6iz0!<8dzy0%((XniSFo<&<#;4MJ*@4YjZjf6#NsSGBKCC?UADU;?Rn{@li#m^`i&6b3!97&CurRMbtrEt|a_3Y#p z>1D)4kYqxMX+6?%fe?<6V`Ibn{CKG7-+`S}aq*f9j>#DQQ808^VEy9!L{VOA3jH?B zaSHy)8gXt)6}0NOtwag+{%dcyoJjRVKG( zs3lCEcJnf$eysNZ+J4JoX|l z)s(Xgv1m7OKWM7Pw5wjYl_bjo za~yZsAI~Ha<O;Ur#sm7vT@4W~5&=RUeN@>kV}`VPO6R+PwAiiVKsrSRKQtJSJdd z;~n%Wm#(sthG1joHqGi>^VcMpWhfvCvuvJDVoMf_swOkr#s?s8n=@b~tNJ*bpQ8K$ z{F_Er5@$BaCHX!U;SMxA3m->f(8@^E!Y3@L#)OtxCFeftM!uYnca8tP8!Pm2!7L?H zbH+h?W5VPPcZ`OomFkQ>+Ul}{FRy`00bAjcz~aW$OTU>#d1ZwJq`aI)+}SxjS;;ic zw~Ef(mXUVuuK(Gx%ephaV=@sNGY|mpxPWhXzXyd{wgjOgkNWN2o%;y>Xwbt=^6`d+ z#xDLLbiqKOQzBG;d(KFvWHcj$ZCZ2$zi56rIti(ppnik_op-93aZCiB%fV>P`d(l% z^znwzkvKIb?CumYzhKZ8lVWjhDk+Bs7juh^2m{q0Q%Isaole1&YXybOIQTm&*mn&u zN?h#f#=?Nnd-3rzg`bW+`s{i?rR3|-Q8tlY9)&(>{e9^v+DK{EprLIq_qr<~EZ{#Otf&mhMv`nIwr# zqisv6V6tz9^egD(VB+&n-RICkcW&d+9V{Vo_R0>u^u0Z{-#qOaDv|k%slS{*`{LX} z-qX1k5~zLYkY+zVUxXKLFCJ0GcP3L)7q*a9UEzVb_(y~>(HIgUvIn|Y7KeHM(?>R-jP(gC8(qs*KVEy>Mt+p-e6B}c z;ct9Q?Oa2U$?3iT2)ws0-xWG*htBbAQl|a+KZglb@V2;z;mBm{eo0)cKEpjrAaidI z$FTq0>}9(uil@qx29hAKT^7KUhcou0kw=uz0r4k>#}O*b5kU2)`YI%;5Lb?ur^=Tr z$O+;LpFm0`rJ`0=Evu5(=m!OZ``-o&_wV)~5-9w)HO^wh8~unuv0(ZRK$k$e$hnwXs{a-c> zRqXdx3$|O^aZfSf*NzAo*sZ|0T`sOVoxE-o=*uqYRaCBaa;isG&uzVw_|)u%THScI zsrMb9?alXl<{KO>Hjf?GviYO&8|MjMWuiHW5MSlqw3YK(&na&-JLmUfm+plt@7?V1 zVzJGy61U2HF`Ih(ZPb$070YAqu<+-$ybiusW@{B5npck^aNdJb&5w#QJl3tY5Ylg- z^Hv8*TxYM{qK}zpHg9uIuCp`wt)P!5Zj^g-{RKN@sYd9Vi0`_!va8GRC&yOz7cHCj zL-(cWIpEdX=Z!Zk9PGEhy1mh1ARyqgJ9Gi|dSMYVUmrYD?m1`44bjBQa5M8ay5&Nl z{{p$%k<>eviwpc#Z1-7E_dO_|rYa~#=d*mH9?V2b{=u3C6M=LbmS4>K8^!rbSe#ZK za5l^&3s2SpS9}yu%)8LMc&j#O#vf|II9d)%iM#m4D;r)Xz~#=6aA|q$)u=6g7oqMZ zJwNs1MzfE3>bdFrXNj&_reo3R`n}DD>7t&y>e2DpW?{?O;(Oy~3sa$a>3CF0ZKoJ` z8DyA?Q|Rg8Mf|q`buLcNB;X@~vMexN6>$QvB7deloG~DKR0^4V7SuFSmc{fe>iEVK z2DU{(!4d}eg#;<7YTo_LJo?oHoZkw&6uTh>i+Og*1~kehlrKkukxY~b#|FE}{%YVx zu%5xsSUH@_iAdXKO=c$zdD^jKW}z@ICUe?Am;^QG4k9<}DwJ_j^YGU0X$mO-^^ADs zp^ZWuqjtR5F~2$bLG_AM?m!fTlL$YDCbTp=#Fd2x(~jFVoNN=iP!-zKm4((24^<|p zE>*%&yTl_`(CdsNRo!45BTUrLt&WuPEX6E^t^$ryH_jn1AC{r>UWEYgV`j@X7}%Zx z=L}iO846uRn9H2KmzNi&uFrDt2|tItT_Z#)P67svS5hYoPo7!kvN>nBRnuY=CtzkX5MI=wkB{Z z5Gvrzv+gu5p5dxr-(Jl+Jha`53glk(C@As~$Qsla`joMK>HTJn z10N}dzEbWqUJ9ELfDk$2EGR6`Z`b2pMjNMipm1KOsyFIYh`ILxI}*xh>hRm0w$HWA&TnS!_aN(8_p{wQ&Ok0Jt4 zWB)$F|JM2m|EKx$irnNBD1Bhzsv@q8PdBVrC60Xd-hXy}_?8893+rDaP?cgkgoPO1 zPI@3Vl$kV>CUGI+urBh>PUHivJBERME$A>S65s@v5*ZoCJB>6K{-wWgRvrQ;=FB($WvGA9#XIdUqoNF)JGLX%`#Z~=#OT4X`n z_$J0@Pkez+qLb+IswfNm*dBAvID$1h$q#+;)x&Y88ZWn!|4o^0V(Z7!AUDF}O?a&W zJj#crPePQ{^D0Tr5pu66Z@``2WbbiIscUA19&G7NThvY5V+Y0c?Q>jc0^sg|IU0av zo;7MF%r}>ljE^_!NN`Bz_>g{%KjqyXnE!j&YxU5QopHyx`m00n;5<7|hk-MDr;?ouGJB^kOQ-Ip*Rcp79sS>(eGx!7 zy3ffy2sx~9?tMW>Rj3&sG@{vb=%_&yIsS;7+wVsI%ck($kyZiRKbsEyF?+O9=NQ`! z6EP~=KFaIf%I=d?+^X)cf+mlGN3MCUWp6WJJJ07&d|tTMe1AIAxHW1hW+-*xZ>fqY zC?q2y3QE!xrYNx@QVa#{CGACT6K1e9{`nOSdFhBlK^@L2$mb~LD0GvsPs`0&c%qEX zouPySEH@?<Yz#oC0^Y zxg$SV#>QS%7;=5o-r?-;Zj`W5%DvA1)RCa8xa@p9p|id8biH1;pfzUy-j6PQ@x~aj zAQ^5<86PLEOG1R0Jfae>2#FN)0!&y@F>7W#BS8v*3B?+$j1Z9YAq9>^K6x|ur0a5qfmoC59=z(0M|F`Y`pQaO{|3 zA4fE65Cdi^)8C!>kYmJDoOeA{*ZgGO7nT24c0e_6cP;TYza%% zU(4b|m%mB+%>m#N3_Y5njSEaBg17`RL<#rFrBh{xYNWmmBX^_;arn_ada4@RMBly1 zyFXMkaNRRW{-A2caA5KtX{lyQd^k1KBsy!rmn@ag7f&cTN9g46lW7!8C`D($$k8gT z;H;#@c#4fWvr#&7M#TS?oi>q|8r4vr2fwls7L{Iybm0)Exa*2aU1@4*we+N-KPYCc zzRda+GcI-RAj4WASncb_fyufO9Lx!6YnsS~YQnHjl*8xFBX;MeduVTls*)jyxTsTVVlsp!F-E=Rq^T-e zl~^=_Ib={0Nuoe$TOlEnY_G&ZB_hsRUY>SMBvP^RN1|l>^cH+FRv(|4s2zFH^Wv>CUx2zq^CL1So&j!(kd^gb27!d3e)T4j8t36 z3*tAawpL}3ch|bjnczw!+3Y=%>A=8L(kb?lgkAxz411)gS$9fmyaL(HWtrB~a?2Zd z)Rt%`T6NoIc>g*2T~NJxo8xVB*@2aMYO|??)YE-RQ{Z~PS{+@Zfx(tKo8lj%1Ir1T zjW#+aE4G(r`*-U<^u6Eo@;jnGZ2s64`eMJwj9r{7>v46HI=k;gqevu>%96qvVNk{o z5zvX@h%yoJ9$eDSY9l{}OW4bsoH=crQE8O?S}1RE>bQ1-oh=9E!G^HL>Q{2m4T===hb?KS7ARH`Lcss*pRH53ou@wi*u-9~Te60Ern zu8)jh2-W26XWz%7k5>m&W~Pvo1(XF=1;PgqgUVl-kXjc)9Ru)baD8ZxT;oA?DDB*J zO6^cU{IQz-w&X!2zkyoTk3C)*iw^p-Hsi_=%JYPQ1TZ z9Gb}leZ07D^uVQ$ihzVacujnZ$W494Fk?6e2Z{z%>4)tHE708r+6%w;=>Oy=GW=Qv z&j6DKP6MP0jO|zFhW{(g4Ze!8_x{Pi58+x68~J*`tQ*=!c@zAqr42U!z1Z-OnVK*0 zN?7zvq@)=){WwKh<*nVpu2T`!S5LAencB3sZCu+A$c(-JNhal+G>|C}Iq-eo7RVKv zBM?1E4Uo0~?^HXOqiuhdbKi!aRu#THkTej{el}EFc?5Q{vI3*lQ0~yRIyK3C?EWL4 zw^rBLB7fM<%OBdj?|J9@(~?34$Ep}+4CLS};7#x&_(;9Fzb#bRrpfA|&J^-4L192g zfEWGT1-jKyb&?AunK9Z&R)}F(s4tLnKcc#k41y0N2~`4kQ~qQu)sXuKni96hAq6iL z;|s4^DWdCv%vdSzyaNB!O?;W*-0dQ}-=zGycmBiiHNwRJo3&ar@(2teqw@AgjW?EZ z8MTy6rRROquyZj=)$*X`XIysNH(Y>lg|y&29c zp8o8>O$kTxne1<_P@C-|j&V?-=sxax?0V)0GhD8^2QxUXikoLgvhc16n-t0-W=G{! za@M&t>AE_=-VPMV!5G|xh1qr0-1!%3`Q5;4e>}nDC0)QK^d#JxtSm-<&iQ(&9S5~* zRrL?Cs)w*X5az+5nZvfsV_|53f-0DYe(j-iKiEF9JiMk(f*beVXrT=V3~*`C84xz0 zdmj#Lpnh5Xu-aGudxNSh6QKLuNvlm4yKeE87Sb z759TX^yts$f_T<6*!_YuGu%1^dZO&w&2#yRH?ia;)?u%p-YF#Kx^uUjVmJCZoJ_zg zR-_nDMMIk#s(A_04*X(4@{;TkmG4?+bJb?#r|>h0E^6NgvyaTPR)gj!^@N__-R}km zW*}6tmO=lC7jkjYgr!UQPewW zcILxJ)`gDtt+@@;mt%gM%x7e5X&oEgJQrJA+bep#?%q=AIZ6k;65bNIVvDV>_ZDGK z#j6Zqe{2)=n1Yq_a&(9XM4H5P?7ynaJjkd%mymPqT(PB+sbQSRoamW9o~q6E%F{Kr zq$myA3{DHnJR_b1Ps6mF{nFd;_6qg1u)Z#Ojf`o?yiJ>qxl4N;>>e*4NB!XZoN7^h z(uqwXR}&I`bM%ZQhlkZTx>HZSe!N#t*a72RV|4ZI77rlh!@wq-go1= zimOG64U{Chs=N`?*i;J#h%E`~#JMY|Ts9^lSNeD?Y_4m)Mg z!=}VauQzTzNVoDrr`hN7J6BCR!;vROicM?_EWj35BHZt zz{t4|25zkoWi~v@(8;2jR!`^~%w6#rC#Q;%D9WmhGgNMGhOQ%FQs2q+~VG{ zY-CbDD`9yiWU<}+F-VHf%g!MaK#nQnQ1Io`@To`@%&IB6BkjSIC4net$}WcTbQCqU zCkXa3&Oii*1%ObfD8axuf|lq;!2BF)uyK%dBBU@dy4cOZJnib>qaxPEX5dg{fZQzt zQKh3YH=IX5K@kLb^YT!|>L$(I}S zFUnBypNU_hT@xoGb9&h?1*U=ZKSOFJ7G~yu?XzE~Olt$PFMlu7m!;>gamk5*mifzy z{Pzw1(P`4MeMx@)4iS9$PQNTc3=CiXM!|p0{M-3wrl^69g|$1yKQboDFMID#@qfKO zJ0lyt`u{v;W#s%{_tO75OXwxORKFHRg0^PXUz*zg^@#kV9{CRz@|Vl;zknG3FM3fs zuHH6~0U_iS#3vLR*@VG(JRpv$BQK=|$|BS@#+yKD&l=ZsYy*Nj$-kfcna{U$hrIHo znhaaOr*V-M{FDZBWL~BUv1UyR=@~I<*`U3+0^%q*>*#?G9LMrE4oYy`31*D{b=~We zr`_-0HxsH`8Iyz?f&H>$^lW1(9&0*xxjV({vfDd91)$=JWi|K&mnpuks(fq5P2~{y zfGN)IpQnzlDic%4iXj~$ikk|lo@w6T2_c$9JINK{{cxJjCqL#i)fAINcT^v6HrjqR z@AnFFbN@0lBR$!R|FU9Kp~k9{0L*MNk~Y*jg<%l;+FlYKmrUDh=?fY2m-Jn z8;J8RB-E4qKn(P@iS1_o16WyG+3PuTxl#K1e$~EJDnVROkt8Bruk*sUvp2fW{91Iv zUJzmBd2fTL+3c`JR3HgmTr~(&qqKOS%|cHZGDi9+Pfs$<%5_jb{vrKm!UfX~&as&ELaM{@#~a`Wtfxs4 zJU-*=LVax*S}2l;Co>Z=QvvQR(}yy3!SA!f*V<%?1l5G&2`AVRsC^6G!d&L^9GqL? zF-RS8zog68rlwJZPNBP-Kgv+e%{F&+hlnWYDG0gJ*+_|@?PZzO-Aajx+DrUOSP}KJ zWLnJ);(R7ruv&x_Qr7$%iB@s^ti>~$cxpoYy+^1$Ewjr-dZ{`}>3r~Dv42zvRVgb7 zzo0m((Mjbvu{b(%?`!>nn*oDQWV46tZiw_pt?sC`d$I1wzWsW)E?+C)&jk2;MqUxn zUu(06dM2IW1m6lFJPPqYqWr@|ctQwJF){q--B77-=~fJR+4hmGQ{p#nV0#8_FHVRT zKEjYW0vn$&Q-6Z3{^eE5TR?sBAz^rxXd9l?kiq^jzFUGs~*rQ}PE*W1^+ z7{bHZEnN5rN*o*Id<&Rti@^Q@R#GT@VLTElsDi8-m00D=f4f#>V-@WyFZhxhOiOTD zJ1D{J9pg;cxFMMVtazf$e!|V}J$J>W-Z8GY8en8%ts4dKs$%@%NbMlkQh)bFya*6 zK#}Paks19%fZTVU8o^Er1yc_iR*x`o!=}E0+a82?5$(NU2DMWHiZQQxqXNF~myBv+1Bkqo6IS829% zt>TGV%~gS(EJX@gjN_@AnLK^|BWFsoM{k%mwxd0N~qL>%Z@9Gp^{-NsX0-~3zS1Y-=&52KAF$>(zeTU?+`D-=qI zd9tdqXm(TmQjkIZGE0FuliDIfm82|%5Ix11oDs--khC8vY+2&&*FX}u+4?4LP~h3CK)zx`IlFzB%aPk zb|Kf{lieA%y<1bj{;V;twJGz5%@w`-K&$daXW^-=XIbrwR~af{q1@YagioRHSPRtM zkemPNqbL%coneBm;lTQQFO8orI;i62E; zSDBv-UPIX>d30l^=Zmy6WoudlH)?qixVVF7>`NTD)`iGJ)i5&@mQRg_FdU$lgeao8h_r}2dBG5-Q9)m3ofP~)sr8LiTsrN4lc&|kpHbS5rJA+zK;jaPQ37cOv) zYvV^QhLdv`;_TYX>gJDs3wp&TL+xleW3<^reXiX^KT(z)Hix>UQjo zz%83#*`&_G&c@fUje~G^3`(a4FQ=|M(gEl$)_dL;HrqYk>d93F3D)td_Foh>WhrOl zsQl}xo}|-~0a5{yhgRXb#q}%+iWZRfac1D|aPAKtP`shM5ak!HA0h>grBaszlnwM8 z+<6S0Hy`U=0}A^#2|7J(P-ZAG+^-ITlKp7|v?sz)j!<_{Xvg$Zdg=U$6rVaf?O@J# zdK360x|45ZZ*{#5ddKseIyx9Tp1Iz(FoFn52oloaX@-`l%gW{MIZ8G%Ho{u0A+ySs zQ5c3~fs7%L0SE!&acO3TZhDO1jFAKZn^%xKtEUS!*PmIPGaZjLo>yEayw{FjMUhC8 z8ky?YTIX8ln&;|Pnw45xRdg!}s-D!Ec$!xlSLz8gtIRtMLs}2&1++|&q%%l{>*f~L z&kOq&lxFtz99lTIhBynjHR~dityEiNV`Ot=eWvx(1y##f<0B_u(8_M+US=mh>u5N$ zd+SFt%J=tf<#1~m@7vUKyB`J{&n!SvSg1ra%h-oFAFH=q(jGrlKh+oe({<>*UD2Oz z<9$6H!|)z<&ILa?8mu0Y&lrrl5HoDT0#F%%$tvs&_%;J17(hz|5vqcd^&xs1oPGOn z++gJNxoG?->(HxiAOi?da)h9YBnw~z1BD9i=b$|XX-+{y^XYN?gn#11^eJ$Fx9&l3 zfRP8OVDE|CbWW}Ie?9mUI@ZPW-aMqqs#dZdB<8swfj2<}h( ztI-6-bE!h&5d)sCAg4As_Bt4@eCCc_V4kqh8wR}oLdBgJBMq9+qk52>zC<@DxdTid zXoW9i)bO*#nIHLq+2R*b^e{l<=zgUB*(+6#S?J+*IPhWen>^DpW!u^VIMC!G zMdb{fav08de9lB@4}DmwNY-+kj9~HvU@RR7hEBAtsH^+_ zy^ozTUb5P{>7`7{CyNhLmpf_b4VCV+l^bp79T(iez0h(r&P=9TV_PibS9p&@k)t!P za47O(e+y^YlOx2)o&NgZ9cT2`%MbpJkZ(%ti30!Nz$-xRj*@TM?1?7#;2R%(QqNfG z+JI`$RJd1g?Hy~+4Eqxq`7LeFv@1vY^&M}|Ec_E8|NiJ(kkS)n=^b;IKl?Lh?=Fka z_}Lp2Tfgbuux1@hh3SVC+PaMQ82VPZ2`PGC}*<2v`jr_x2I8PM$ zE#%*m531KYmWP8qp43tROb%tt&}TLI_g#TooBsW6v^yfaX(=~KdgRiE0SrSJRnAFZb?WsUx2^?_Gq+!BTkiZc@;EbCg2^WGw*HcnbwvdS;nAG(hy zM=f)-&eZe2d~iz-MC`=w8NIcexYZ$6|@^q~;V%i5C2+e97pc`|XSjtA+yGc}|w##q(qFNMu&!$MAjBizui>fb)`4 zGSwR!!6b*&Kg>!Xr#tz-%*vyg#8o!E4-gkHXw(*Z#U}MzBsfy3WEYx)!wbb0?Pn-d zoh_<%wHn1{P3KrFR;%S2z<8-Mf2CS){|RjG&0E8~T6Ct@R+9z*jaIAKcCkh06%Lo% z`D&qA%eB_d!|QeHkvCuMn$O$!>6ZN3=iT??Xcf2@7Kg=cY|emhQ0&d@ux#FF0RyGW_^jcGS~a9fv)k0>lnb@xi(h&3 z1+e^Ky@l59Ew(hH(^>d9G<3Dq%1`&v*Do9zi^J>kHYCB}{4%xf`2B=lyUVyW)Zc}M*hKHj@Hq*Al|eeI;=F0DUpM&PeTfQX zHr3wVKV458`7RNVxEb+JaK01DO6CCzK@O3$0E-9+VKg%f*(6B&J0tK#h&I7N<@@Dp z&UdsZX+(A?V3ciO%A4gmt&=s`1}l84{uN`3NLx7fLu9`Yi{#|}3TeSu@m9n2`g8m9 zp!?A`HwhlsCJ4XBMim)7E$CfJ16ON$h3KmW-q|tw@y6~)Wt)x{!Gjc-N9zYcJ%xR0 zR#Id~3+Vj--|5`VyYF0RnWpU`ukn?`im8jnRux1$eJuU)<(N3cvsM_)YY>0<;*jNS zXqZCo0Q$oiqQoEY|~l9uUh5P1QcZJ0k0J=-5#1yvm?Y-6ze; znCfm4tTnnPqROzw;Z0^-!W4Pz>^@&sM@nsIPD{GREkUo}3FrsqXO!>oHB>?z1iX6a zMd^3@JA|2k8F15@0_TEK=7W8DWhx zC|u9J9CZBAMxc#U1FZ+u-NqWq0jJOi%6Nm|FedUN7Jttjl(RvqgW_Jo8_jmSIjUY- zl!w#0ol5KQ%pto=tA}Q%rKK>13gl$sCLrac4`TF|*sG~6_#T8YCEPgh5N}f$v}>PD zaIDO&ZO($ChL~J`aHD_Qwqb8i3oG48?RBcV6sPfw^!S72c^YHiZ%kb&&=0AKZ z+hWP?xww8}L-hqnyaS#$336+APkUWrlg~Q*-N7BFWR3+yIZ(c*$!vtwxPmhGHBQ@1 zV85=4)C}g;45r89@-THqWtJXQH)Y^Zl`x-ZA+7~IB0__hl>>9?aQU>tICOa_#=$Qd zV1I4E`|^SAv;}k2XKfe9&KqzLC@{~o8s=)AK1)pbAhWmO@(yTM;f8YDqaMnd9eEMY z01Qi05t=*t7Ezs4TjxSCyikehp4ONy?qPWaX*mqImg_NWcWpAl$9^Nv2<{-KWmn82 zzJZ?)+{`&)Nii4CVwM_uD->kaBFzwtlKAoaT^tpxTjRFX3C8$L7)DxT^nBydzMIkc zU7f+)>7Y71b%(h)ftSlw>~v>DI-FA=5sVCdM_%S`Yx34sZ=~JMDJ$l(ayq4e>7wPK zX({QDpwc2<(1(fox-6hR4>gdXo;Q=LXBf2%i4boPR#yUqioq$SG;qvfawtu2`my_I z>H%Tu5o*fRsVI?5Ivk;=(gfgB32z*EA=o|fwiKWDka5fZ-m5=g;kRW=BmXwTmRnF? zx4#OK`K#cg4t`@;F~MpnW92ZxFoLucNE*0^bLj!Yams+K5BDPigWL)$ZNWh$S8r0m z8yq4d?mD)~-1%OxclO97R5F59b+M{uNxXW+8qX1GIc?ND1xto4RzVeWVGfT}brW?9 zyLEA*j=WjKCY%P|Qi#MjD}JxPoo{;nHW;u$$cC?iyvdpM8>ztOglZT=w2&LMx{{A0 z>o?nWKEgwvW)4227$}DaeUkb{-Y!cIG0M^!98Nh#0)`^&*lNWKth8Hm0crWNrIwR3 zhFT)_viZ2_WBsP~_4p6=qnG5o*Y*kg#7<6Z+qP}nw%N&vPI6+~ z=80|Fwr$(V`oINtie#Fa|%e-Dl6-Mf4c#Qw_`SNujD(EYuW@?;82JImjmgA1jo+I# zl#hyvNk+7^E!VS$w=BWU4C7fnsK^u5dvZm zy21sQ_{v0HV$bl;>_bf41Mi>O2SQT|4~;<5YyuMe(b;k^Vc&FK?zt_s+?sRo7;T8- z1~@BQZ)1fU@xDK;6}ntTECTfSd2m8nX0i$nH-aH;pz+Z8I(#fE7@*3mjQGCcmh-e} zKk``+WuPn`uiyOu6e|~>ldO&_TsDe4j$<08KApO3!-Z-)n4DRxMm+v)^M8N%3;^r3 z)iYwr;t9eK{1D9tQiT%fn~~tDaV;!eUO1NY3BeC*eCtD?XUXDd7%BvN3?dN0F8f{M zR2o%cqwYOE=ElkbF25R@pey}nh+~g+=TyN4*rF$%LZqE63BfQj)+pj{QqOd>W0|B= z<~@=vYe`-x!_b7I7}@0O&!NAZlMoJW$iezhj(eA+JQ6QVs@dBzO~a0Q2NNWc^I%d* zqM3?O3q&V6?!l-ENL0GyoV<^oi64pK=Kw17M|CAs15bQCWvLC!%LuP_jM88}(c{xQ zsr%n3H88FaqDV_KDtbbkAF+TLXUR74t4W_sy_$E{lUfJPgUXnMY?TzP6gJEIg7f0S z;`pria;Ktm2NN!wc=y;C`jNm{`oiS+PqGZz*wSUA{aI2sqm5ykjNQ=6JmWQQ-ONr{=R_I5~uV8?B~lKy1f}-dyh{cZbS?@6cTRB~0`U>+d4U!ukHRw6qix zMAbm1^L;g(75I`Ifr&bkng!tWuI{o(C(A}bkoq9fwA2KmAgsp3gZlXT{mzqX98G4w8C z%X8}}`mOfL>u5O&E(+nw0(Vz>_IC*aBqpeWP%cf;9TJOFC>v{voxiG)h^n-ptvX++ zq6UdlB=9L&Vh|V-7q}4ieKu5o!KF0rhS-=ARuBH){6G%RO=k_(iP;V3tDzU~PM@wL z<hQ+sJp1PcHeR=MJ8cJ5W(}0W>JkDby9ZW4G)af=&~b6Z`vkA1w(X?u8It(N3pP zcKbm(9R8{5UMdU$5=WYaMx7SmIHP^wewM0&`UC)O0a-Cx40dr)O5Ibb{Z{%agf3l; z*Q@?DN(TWa_%BUz<5_gT_F68pPqXC)-9S@286IN4q5c;&dyoxr_@OZ%nM z{h!t!W8kcrtghh`R;13@E#W+aQMJj--5y6%OqlZQ6Uv9+bCn-|QC zWXnE?O+P@MhTV&S6RGr%KhdX2rdGtzB#tn-Rq0}HbQ`4B+hV`-fbH6?bnbAj`9zZ@ z|6p@=RH2kz1m6?+_1c@-+FZxh!6=(_p@g}qFwZ6x@K-=Xp-?7)df3Wxg#DydEbu{s z%Gi`9DU+9a?!3OfzEPkoi1}v?&5)I$gm8+LrI@_@+EV5FFB>q`C54Z1dguAt{Db_X z#SfdWD>XNSa*goLxm(TFhGOr7+4ghtubbl?b}7$El_5QEOVjd&eQqu>w<=#-(Q-me z?G6{ghqP4_jX4v z{!x4^{(N#}o_N+~M-7II&xJXT zJr=Zg0d22<^LM=`GPuBtwyx~In?kSq1M5JtXPm?XV#o$g|Es)tNEV~MQju8b7 z+ih^aokBwpJvYSXk+g3U=Urd9@=-kFxk=WM1875gKsmFWfbUp`&I?vSGPT+~B!2eB zG!aMehs~+qJLiGsUW?WmG5i@+SWF}#di@1Vx{qQ%=n4JRP<<Ap1&|&p()yOKF$Is4&4U`g^Aj(Z-Fo?-*|3Eqqhkx9C^bFUNf_ z6S$0PQ0pPST3dIVloAv7=E&|$AX3HUZ1<_C55_`G+Eh}8hZWoyC8fKZIr7Y;)C zEobg`+u(q{p6pTbl)cWUz^6aPidhKxru*zG@cQbzBG)XQT)$SH1h<8^vVotPeIfoZ zQWmxRMw&oH6`!57R%emAt0h#tFTenj>^uY~QM^EV6H#JO0fi}^;DR_%tupD4Z}ytx6THw<1!K?7`zZC>$b57bfj+3$LOMX|2=(ia1>mo3QPM2j!WOVO^S$5wY!(AAr=U1q|D*)jCDx?b$^H_rPRvt==(7tOFt^;T3!`ftIa2j8Z+0^wu~L2K!y!);9482`PPMrh(s z*1Uc0J+xjbWe+} zLDSN_iqR%UJAxbBW9>H{UB(P6eS_gubjNhSTn^U{xo1+IT|SpJ4#MANq66wKfp&g4D00x~0cE|mekJIy0hzrF zG7KnVg7H#7b1nUEc z;g*0*)a;4k`67=`|GZ_o9DeE(2`Q#1ilAjQA7An znBWd#Zp+jerDt6=hlo?5YZE&jgExydiLM>`j+j?;V{u^eWPNi~BdKk%VW-KM(wnN) zWXEz2W5Byd!=w{+p5X`@3yGHY_?yeAsaW2sL1X;Vof(&*hzjs_&h`iI<}@}5rWQS8 zy1^KS>sP>cnP7M-3z8Y^O*9K2po#VhBucV_IkxRl8`A|<2db<;(71dLl$&fd(ruy` zDQyC$4Xch*%V)KnN#Z=p4h)7%(0%&|zABBj-R0T4^5o0D+O6|$oZ|B(arBa-3yqJf z4@HKh(fT^V{RAz#&)F>w$ zqFT0iE3U~JBZZz4hE?!WP2`;SY9$~#Qq$woW2^0HbL_5tYUoORjz9OegNr?2h4@8exTu=;2FX2eUUx@V->e8N~(DYUxMUbF?J9V#bUlg|S7gO2}Vg(&}YBHb(CGh*~UxsN}P= zs5>Y&w>d5oOjPZu&r2q|M|DXU(Wbxqg({xXy6k z5u1$bS%TEX2#Wx5>Qnx_GDuYQJcQTpOB`X|!jafq{&V-*WPf$G*4dFA_he)ye|z7w z6o>y*5VVDfhsVXkBXfQs`x%4x!xOCAGfy4%)NgiJN|@ zw|;!DL9-8_hju%Z55x@8V_rIEfkI<8GWClKC|omq!YrH!5=(&DEidz$6d*@pOMX3p z#UZgXYwO&A5xrj71e)#2fD71TKIV6b>o@zI)BOV)N~F!$mEMfX=VKhSD6WZ2>xs1& zk$dZW`TDf7n7s>Je661GC3;`SiS0$S-s3XN&gfiSd@u^18yctun^3pG?5$dhC1)rD zvuY7=-1gAQq+R9_-ZCdmCZx}`H6!m<2qrZi5n_jpwymel#S@-xdufCkc;iA)CA|h$ zTst^hk}wa9fpN@hKG%pw>JM!S&BE>+TLm17a~LOZMk=Motu(Un;tzd@PusM_R3qg& z%lMKh4g+pF`RkxUAl5Fm6&iaLw>7u$w*BlQ=Y`QdnRyL!t9p@-=n-(vE`^dq;m;Tx z=zv=|nWW9p7u_Nuy`+QRg!*dIZO^#7@;LM;00@2Odr$<kgQJw=|I?VD&HlOY1+$l$2$9oX0QlP5>Z~yZAdz31(N58%`2``-2W_z`@U(HcsB^`&!qcWF=qdq0!wTp8Oz}X^>pX zZ1+UZtt3FkT#9KU(!g;y;=WG zu|_P<&Ajwc7vGnM;%!hv#Y4+&yA9YE;Ud@F1-f%{xrwT?qMK%xaQz~^C1>*y!2Xf1 zeV;L#Ip%Em@^9Ie>$ZJ35e!ElIS6q^SF@%cZ~Fr3&DsP zdW}iG$oZ^e5Dmx`(Pblnr36-@%S8?uX(s6OdjUv%9A^+tgy3F%do1-BmGEEKCc#94 z?T+C>WfJW=Vj?`$Ep*q5UAY_d-QwN)zv6iWhoJ{Vw5`0{L3V#aUuUfTB8TV7$q+EI zwlE}#Ju=^58Hx!%D(L0z_RdQGATCG6G{GPGu_roFjO3X1P27VEq2>ZpKkOFNFtk-q zHtd+ow_~t5Rki!`);lq_94^G!T)h|!j1J*n_W5=^ue6OU_3+yZBx=f1|3-i>o7Flq zv+mLxVzes?Dy>;mepsX&&B^tkwspy)35F~HO9|g~AW$Nhkb@&FIGOkogu>xQK+xcs zFna9C;oC5}6ozp04Vf8-1!9>VuPh}J-iQzP>2h5gMqa+qM%DcE`q>uEX8-&t!OxoD zqPt$-T=RyM1)2gIvjoBMSJ2oAFCpA)ev!U~n#Q!C!$nh%#Gbe<_RL6syXdZ&pd+Lb zWLTt* zv^*q%kyD2r!S73*0oB7uckGS}y;bc2)gOrM!5~~4ow%0brWpEgB7xRyddycuIo?ne zFFNwwfi8Jx0LKsyqGtoL5a#z@06+0OCsV|pk6B1|N4WoQ#@}L}EiW5eIuiAoR+V*j zXt7&0RaQtd`>^t95y>gd`BCy0Dm8X!2V2I0iOrkpw|MV1z~Fy z#uL=Q>*poDq1dz!214&0hGv=Ntq)A;pQAzsAL*?)Da`NMiRNGf9*C#R>kp89U+{|V zr?%tDc~uMu!z}ylNQ(Iq zTS!I&fiie7E>K$<8B9Z~92r_c32Yhyp@Mp~Fi;wb3k9Jw;f&i{O0~#_c|!{nh>-dQ zGEu1NkLs>}szSyZfj89gc zDRf-TR|=16Loq!ymt>?FZvxfwwd~_t_7wtK4qv1-a!b#`i4fZ`?-1MNxB7}rs#Z_yX@Fs>ulc3v*P0|f z)AWizw-^Y zq6(IZIju7IM58(*d%py4MD6%D3P5i%n4|T??Ue-Dn|_6DW+TS10ln5fVfjHyd?srB z9Qb}&-*A(jNGEUhtzqRAJI&rN72K`rGX_E|VX`SF;5R<3IO_n3OvT<7pMugBbXRwo zE9=Y^^##mE-HWVhL!9ce38qXt(mo8vD!GE6`b#sn)IDAkm4h-x@~f_uV-Gwu0HRrg z{TMz!lb1OYL`;;9Ne$#o+w%w+p;D0V8nMJ+>~kJib;bxa%i%q~2lE$_qp{bGiv8!e z2ym6_cAuY;!u)5TTVj)@onl`CCSIde11mG4Z0L=J0^pBWNk+`KmrAP%9qw0du~<&a zM^yz`kI%H;z9-oG-ix1p_ADjW=L@_GM%fSwqAz{je8O&A6eiiR)w)52&uAW74fZ>{ zg?OkvuLs@<>~fnD9!LF8U>AK%m0whyxW2Pj4zxwDPh9c)F*Z>(Yrf)E<(YQGSI3S= zs7+){s}(iyt*n#zmxIGLfUdf}irrRbZ7-{F&#`?zuuhdn$#SMABF zk7JV$`0muHH+6qYoF~znGAD!zs!i@o@*(YVwjDgxXsOdIqmNl?^(G?yO%c{;%cMKm zBp`C*9zu#VYqgE|DINs`&#VkC_stMRWy0>$VUxU3>jPR1L}!;o*&yM z=pn~~#$~?+!1W%?m8S{3(v+>U`yN{Lg01d?BMK-r{Q%k3i^zv+%3JbMnk4960`JHi zdq!}`H)DxQ%-c7@sgu+=56*r4gxE3CaQd;5Oqj>ThmewZjMqi8lswX!V-Td(3;Z!X zoi_fF_5or(zTNYTVel0!ZeC^(fxKpUd=QB`+YJ!L*Js3ksEP)zRqPP{(D}$OeNFx^?)f;PHhHnWok3DLR9?4S) z)D_v!qROE^IGzXx%(uD(DP4POq9d>5!}cSwIdpibXG#Y*f15URZ#=ls^-;!YI!`pw zmrfqf7*#f=031Ubq#AcIBpf5d5hAgci*;U1Z-KXu0z7$AE0wt3t9={+I32-w9yivo zlYeTDOs~Z<&WYomtgD}oqDzg%cV6g7w&vfufU@V!rK3;U8qp!S+Ol@l4 z-X`I|G_*L7)2+j8CN>Vf>-z(a2v)>>zG^0gx!DD@NlOf5o}l+4Z6j3ikJt}k{{EOu z1ex&sT?e?q#S&^sG>uQe6L_JMG+&{S`jvl}FS9k&sxC>plEWAI_R(C6ez(`&dBpa* z_we*8-NhW?mKN;sk)9mmD)Z$xJ(~8UR9RqS^k#d`9#|V;8crF^q%SbY{3U)Uju?M} zJq#tpJH-^inLhD(Ho_AsPIrU*nw@Ct<*QR!5JkFw#&uZGxnmzPmek|XNZhxD)$`Is z{>MI4ZFUP{&JB7Z>=w{4&pVXDl(%OwSj%;o^gNTywOKiLQ;=&c z^$n1SM$;j2OTSBL7IxjiD`vMmQ$3`WKR~}rtgl&_8G@gj^Z^jqYbVC$kMIY{3NX^w z$p(`W{h!$`h9EyKVG=04oU>Wo+GG5xW$JVZAZhT(z4?+0xr}cEOqCi&1n%MQk?{=Dr>AG~E zV}4~K43P@*$&|e=HXaQyW47A^<$5kDy2}rhDm_j0c*D6sZtW$#p?MM0^vjy)5WM)n z?sLaUCcSOxexwv3xS)slhG&V|xllW$exbfJv~wmX^K2c_vAZ!O@lAB&9pRhs*k@79w5I)JA>5bG`h_GP_w#HxVZzk0pvXdNb+RxmL0xBPp*7|GGR>Q#7 z;@&6IiMKq*iy5+kuK-iz$i{nM<27HrDt^JT+K!ztBAD^6w~|De5Cb(>$FHaasg8=H z=6>^hcpE6we-1231*UpIvsEg8Q3?8kLLrez#1Q;18_!*XKQe-^-|WK6SCP58={{rVFujB<*Dzh^&jWhW-s=9R=&%xi@uSsyM*-eU747jqfu$%i>z24;`K?90=02doblrb`JvV(PiBK+5=! zdLZt?5&3k5jiDDy7|o5~7t6o`-#R_oj#ymPXYh>vy=9PF&?aH`d0%pE}A^0(@MsVCAG0P@Baj4X61pNrx5Y@X7-2l1F zw`yJlFrqU1>`JbwD=*j6UpL}JU8fWDpBnp11PG!&8`yMYL{q=m?Px;1Cf2lnsqeQ` zo!Gw%@3Xf@7OL!fTwTuEi|9SS%ABc3icscE{x9$GeK zW6j$OH`i#Cm-Nm)6!tOgYnpm)&*qaiV~3AL?UN5Q%cq{azCUxYDX-B<_TgH4Ru!-7 zn|c0vX0oJD-uB70@~|{g*(K-ppYBTD=NvpeB0^T99J4p@u6d&V{-&!3K4Xt8#up)z z-u)&Tee%PnPqObL%G}J>{3Lt(e*1Rs-k#y`3n`W1i+s%9iSG+B_4b8*Y^(P*eat?T zXRpL`X^V7Le-jP!b*zl0Yv7ffDE`wpX^RY=2A${+$e3|b*VqeAsLV^Vo^SR8KXU55 zZ_h142*_9$8YYg$C+XM~65p6F3g$D-SJr{*;~jeJ$W*pO*2OmeT90p|@{&z)-TulxE%lcILya}m9TV-$_Gp{DSr9os$o4Qg$mX zXC9DA!k(;~U9xx_N7VXy5vNx)NJ@hDG~$T3)BnAnbPQ->nnPGLo8 ztKlp9XT;(e%p+LDz)`%1s^h6^4`rRw zsbq}rn*@xrJz#cNS5S-ACZTIS$~z$~6)7O{m}~wX>Q3x~vP+Zzz~%`}1xs^}NdL};7xuP&GwiS7IeP*PV{v76g1)7!4$>zr_#$cnY zTvxjfYUhWZz{-xPc;@cYA*7P5T7Y3&6#v17KY|edQT(>t^hH$i!r&NC^G4;DUrW~5 zN^~l}xoq~=Qp?pZ<|IoClfj0%Q4ijM%$)Y?K4=l{6q~P` zg!kahf_OW1;b9Vdy;Ljwy?4TTTYaNYSuXH+dxy(?TR>It?O^s%{2*p_H?VqTW*esG zt;v$UYj+N)_<*azZUXb5fO6d>W%;i(W#P?Cp)M<<*9jcgWmTKCNq%DTfFc#{x{dN` zrfis0eB(!>v=`}RAEFtHxQwxNJT~_1aLvviscEM1W=L3^8%3P_oKvMrW*OPB`+0X#8xC0 z=uA~v=xtN$@?6Z`zY5XCHZ5Aohc-~sm`5=*Tia-|o06Y&pwQzdaVqv^PY^IH*IH_B zC$*QP@-qSMYn|ln7?h)QW?!sTvoN1z>tD>5W`MN$y5XM;@1ycac z+}h5SoGRJ7Me(~Re8=CsB>Xp>w}r`tD-V}0Ob=|Ag=TD zf%8MgRv($(lkDZeM%70Pv*o_`-fo4?TidF5u-cp3dEHdmQS)U=XTZa;wCP%&7i;eT zAUqrs)5Dm~QGF5bIO!ioMZ9U>+kS4XcjE8$dUuuTdRDquuwLI*$&;T&r7-}6JDtdW zr*gxn?5W-J`73~LpLhQ$4)$j8nti8>Z|e$OzI`hG%Hs)C65+)~4ok0DdwR6KFykLb zh5KG%vq8xty!h_KZZ-oz1K0+gdfX&XoAFhDy4hMt9`lTRFz(mttJ{YX?9ke4J2D?f zdg7b0XX#pnMD~GjXg#D3Rl2Is-8J6xWSAJ2coXxk1kY83u#8L6P-?TxDr}*%P5Vo8 z`*xa3_aL3HIGoBQnIEPG-H_dFXYA?ejT+7E-GD55x*XM4t1wi=@X`Y1HdnyH$T?D6 zI?d4Aid)i+;+9eVH*@_|;$?akE!{B<8&$1F&PI`nf4=2W8Uv;90Y){5OK~~9)TMwX z&!hz^!aj^>0;Vut!1B53T|v{)6j@a*R1sM_h=E;07NnMpb2bFXGt%U=!O19Y7R%!8 zXQ|h!I;`X`JEzFo(e-1dK{U)~R4Ez?jo7FdvSNnPJV>IWuxrOK0ye19ynUr`C#+OD zr1=d0ycC{BDC_+b%yp~%D|N^O2Q$Bgy@W^dT+zVXP$q)7(i&d&@^0NlDqtKcwr;u_ zzIoRq%J4&O~5YTfuUQdHikL=VN)9I>xTOzBh24!XKWK71+Bj0CAZAx(t zz;eU=Frq&cwQ(le$rC9#V2cXvZ$+qvN$u6>dh5f09Uj)xLb09HN6C3zW)18>FAQv~ zM6`IKK58!*QHw~=X6iPaMkD=XU>pNDTD=6Ii^;jIR5x0?T3oelZP)d6w{-No+%E1x zXe#Y(Z0vShTmjOy9RT~c&BtCHjii-74GkkEv(aaRZx;6>8*ZQ(}JHXP=oz&w4Op9Iy0y2RMa8jUqRzp1w7<>Bwu17m`dj zCPx1zNF47by{6XLEf3v{|c$ zuB4!@mPgv+a+07gJN;%{@BNK`H?h9h&p?EB$9Kn1#jhzZ$4|ufDR;*&DX+#ehnOew zAJ)2TheXIBl!B|}M{3K*aQ+;*qzo0V$kBwkX8XQlb!XS5v~2p;hvt=n37I->+(XkG zSRDhuBdm=9b2iP>E?OOeHbSJ05^gm^(>hR{f;MKPjT3HtL(@s>P)AzZpVS|x#UyP< zspAM*wh=%7i(9wn)+@J4$!%+XUY^+m<2FOr0zimf6#e{=BfGcIk0&bCuiE9{)Vw6NYaM{mp9YyzQep`!V^$pO8d|kfoP^rk9Y1 zh=7QQkSULVDvyxMh=9z9kZqTMZkLb`iGUD^kTH&cGLDc_iGWmzkad=Tc9xLWD+UNN z7AiFsOfwd4B^HD;7N#W@;(G<`MezriBII`ih^Qj$fFdxdB6Oi5xTzxifg%v9B2=Ox zn5rV&f+7g3B20rKgsURL!_1FPix4pjSbi2kWfo!QdI9Nre||0EAOHVd7PPZ!JnU-3 z^lD7)YSguAT<&V*wrXt8YV@~id`sn$qtz6 z4ya2Gxa-qjoU;5HUkzF#{DbC(M|+j2Xy`8QJz2==K=- zkQoS(85!dlN@UHL$jqUOOsI;?u!>B%ii#1K8Hkw~nd=y+>lnG68OWU(+3y(W?-==E zstI6f7{aS5!fQCBt4XA5SjMVp#%g$|tBI&Oi<_k-6(&+G?@e>L5I8(LL)B-fHpRoPR(# z{e*Ca{KgT2ok7K&P{f^KhnzBGkKE<9MdWr(;_WEn z?Kx&`OJ?m_X6g}lN?YVAl%Wm%4Ztm!A?s@ZV3-j$7^X(|}?KyXD zOLy*CckXC+?s@ubi~H=F`|POu>;XQvUl(Zco7{Pxk}cd8tJs)AmsygaI+U8>xFSQe`MTB_pP z(wwl;g3;2v($b>S(%iJt!qw9J*3#lvD*}C172>s$!CU43&a%9eH2}|x*)GUkEC}K* zNMMqD`EC};1NOvrVdoRd;unK^%O8mi1h5bLsEK9Hx^E4BSI1>vz6HCCf^F*|Z zNVE$~v`f$x^Hdd!SQQIg6-)mOW?{2kf*;~*!vVUO(Yu)Q5f_GVl?Zkf5qFgtaup(X zl`3`>Gk29cauq~(l}vUORd=C{_8=j1T6}Ua*>=Wb4cvF?!4*wl=T+( z9YmtOQe>mZ;_?XU8Y+^rq@KKM@6R3WxQKvyw@fpoHHfdg9Cwz>Zcee78Rl> zEZ1Q^H25xqA)y~wb!@;Nl+v1?;nn|Eq8#|>x&t*rRW%}6HNssrqT!Z9WS1jom&3vx z80mTnn_-jppmjpO<5Mbo8k*sk_Q2Oe(jA!XdMcXXn)cw=L)#qKFMB$g5uWz`TOYSO zZ1f%!PiXNqOIA;vJN(ohSbIqFHIrUXnLAw79^Cgo-8I{0Pn$c!)gFjfNc1%$Ur+Hf zZ1x_ESLlCqa5p`}Z|y<6hh$$f`}9;j!*%T;*z~!bcgwwp>OTKNSNR&#KN|AGZ{y?i z6XFbZarozR1nqJ7#Xm>?qdoooNfHQj$T;kUR{ifurkW7DhB3XGGQEaVyP8zHhIOr) zR^FJq(Hz3fgxt*x-OZHU%^V?XGV6TcTXN~7F+mK+G=h4o;fHV_fVhE$KTPEb7j|d+ z*L)+*8D~m!L=kn!`5zd|O-6TUM*m1gZ%M}BNk&g<#=r_svNK2WojabY8pAjws~XcN zhU=s`D%_yutdT#A1+!!@rJ6G#x+7z<17)%!r~0**UN=ljTv>CPb#u~La~5`UY7jgeljv z#485j#*nX9`~?I52-z!6{>GB8&-?`^`v}G>mj1@Hvse8EOaBPlE8hObwzCiLg12=9 z@g9SJW9-u_|ANVXg#I3_Xa9oRb%gL9%YS43*{lD8?R$j3K6tU-lldOs_WX}t z^>z5KX_B93SeR$r*CRmOBVx$IpZq0zJ|;~`8pTgR1UQada3mSHgx0m7az6fbRsc(i z*pf!JpoAsgleOp?LKC%u=qZ1b5{ISDi=kv zCZIs%Rnixe0K_yVgYeIR45xI^@CuVk(1-&jVIh;!Xn~H{hy|zk;IIZJ`JSo2OoAkn zX3?-pD%qTA(0GC-llEjHC(}2x;*lp67(hytrXrCHXj-eIHvHn`r$g~SLM#N>rtvmOw6%#H6A6a%?6l04tE#P-4Xos*=~6tZ ze@X6zOucBLW)p0|h#XmMw9TeV7tc+WYgt3jVnYswr=hjW7DXlm4E~}v$W&0}{GuT4 zEyX59L=Yo^W5t9?Fw3kjS1xHP^- z2fySx?@!W{NgRZm+y2WMp3EazJmzpZ(jrl-;a?BAq+yh)iIE@0tC!|RRJMPVol})s zWa@Y{;(*4buG~YdHHrrJsEYep#8t`qT}s7>ikR{+qp+rtBsUxy;(xJJQbnaHAu)Ey zjYgR8H&WxxqXojTW|^5WB~IIH)RN|s>bB%qtt|=(m$?9ACQ0p^PcP;(4rxbdz{p0c zYRJ)~xQ3@RIF}QZ9B4NpOJ|2#%`eIhO;iNpZZN^rgHd*9v9d6iGny5~Y2iLq!%>$8 ztM=7ryw^L=tHF`S=A+7O?#Bjt&&j8um`QHoP(Dh=$_w#fZpZuaogBq~@==b&#Z)Qp z2PZ#MN_ia^=@$=YQ{H-qd1WH`mJx2XEN_V^Mm?{Dzki?{g><3ZDx)06y^e~0stI$N z>vQg3ktcZ4e?JE&@9QxX$EQLSAfX1KRzf$Mr-=O`&Yu-t8;Qy^k%_bzUlu5!`qLxT z)V*<9i+12S?k3N(z1)f=OUhGUw-<7ft4L|M0gtVvz+OhZJ|^ruOT(QUab|~GYB)ig zbGj}dStL_3ziS6YXqzI_Jc7ukgc@O4nog8g<~SCC(yu&X^Ig~{zhk$sgvHvL#MjlW zf~+=MQz1g*4U(Grr3TZME7+j4^oEKS2>xu-EkFs7Z}+W9K!>M*@=#Dp@!Q??qRvg- z`~(s17^BVkrNO}S!B*m4m`h6q`IT+#{%Q{2My8M!In9%xbcHt0^n12G`!LPFRyiTB zm?E)|H?MMp`mQS7A_*lS8wr`4w5VOE0ns@!!pUXN*GAo1nV21|q8FpfAVu=fzF_p% zec2;&UkX*+21jB*+Juj_gE64Gt;ep9q06VLpo}=O4`TX+`XtLadS1y>F>}5VQ>QK| ztwD#Iwt+jg>ZQ6um-~ft^b^qCr{5k00bY#Yf~hjmYJ>K$alO^)dC^ma#{&DS&TOSD z?Z9BtUki-|;IFj?>-%)q*tyM5B-!?Nn_spklk#~GwH*Mq~Vk1-@SF?B0T{pK`Z>x8suZi=#QErLo+GJ9Q0aVux*8(UR?=wR9|=-UTDB z5q-(a5zrTo{a~u7zGkIViTqw&rB07jjy*u`|~`ZKQI+ zr3LsUET&>(3je-f*_0RP?9Sd&mCehyp;$BsSZ{E_PXqu|=Q^6$Wl@d+wsV)0?No0p zoebznfyK-K{gvRIa_5;D*Rf-l&XS4I=HPUTYxmBQB)jS0v>@N1=_c5r>|?1j-^M4R zJDjg6owR;u8;aMigy?8eZ*m(u^n)4SNAa%9=ud5gl)K}m)~C19i!Z~fS^lw)-!GoY zWvx$Zm3$ph?o%yu{Ly0yCaCC|FGSY*`$Hd3%C^_fiy``HWuMRKh_-m#&PVv^p&t;` z-WLVzZ~0ZM9i(ai`!*~2^ACFPj23`+7}TS-@v7zd(hJawB{p|wG_L(l^9GyCoWy}5 z(Qguk;{^dI1?Yb$j6m@d6iA$sqn}tWptX=Dh{Hs&qD0{VN>JWNFC_PpCP~9Iv6_T+ zLS}*E(0CLM|9x0E{Cj}vvvB+~T&^*hmBu9)i3cK3n3?{L=8*nLg4JR&nT+8SK7>tW zHkpj&6z|~VaB|q+9`1?#LkuAfABBSh#_>O)EJX8&weIk}0>F@-fYRSA3cv}#rUINl zIY2qSQ~c)-%~H_2eJB5l%rb!7nWvz_-O>T{t zms&<^7uiuKXsuT>noIhN=~f&1)6RhU(qB^t&R^OuTI{@BcfW8yIvT@wyk+?*@kZb9 zJ|05bcBhM0?~kW=S>B4oeeaoVlzGdeWaIoU+{>fz%4z~PqU5?eKejxrBq=5N*|1L7 z=k6?KF7220r|+OX5a}TxGifFmTd)*`)$gr4IIT<3o$gAs=3>_(EP2#_9X4oHZM~2m ztuI?OJ$4{Wb8-;4irw{-?3x&d)4m%ByO97oqlwrUn2J^dv9R|kY#o&O7UhX+*Wj`> z<}kI-aPcasAjDJ<0BZx=7Do_K!$`pj1b`p1Hr_aetVSX*`_m=bWKRx*XZ=h(Da(Po zsr5SWkrPr3uxPN{NjxMMi;F-D)^5AMSyGdH&eI05j0QfgEAqA~AM&(WZSMfu>PvF4P-W17j20qVe)AtbMJ202|%cLH=%MN_HutnejeUVSpM_F z5<2gCs1p9;NJ#xw`o?!m{AMW=P6Xs|j?JX*ab?79j#8@Rrc^KqnC)`1fsCneC$r-BJj&>4!t;gt zaIe$aIeEZ(fp3C=7zt>9;hw71uB(3g14}s)TL&WBV3}=CLIUb~U)Tm-*x;OZ!oQ;= z?0ankv<3GfAkCdPYVMA?!ExNFoe&R=B71e|d$UB${2n09+1+fSyt84-gM-Y@t8qNp zlQj@BbXs7Ub3~1JSvW{IYGV-2{FLdFdq5~ucgoN zRK(vr%m2FX+ib}p`D30M_Fw50YMJ6TagYB^UIEL(p-%n7IQ0+P@}HT> zTwq87ND|+O6(|MRKP-y_*=s- z%D+x{`}`->0lmqV**Y5kdPDkJYf1V+sV)BK+GC58uF+`4uA0Lb{sz%YNQrKTp31?7 z?t)8}VjpQ{8`P~+vqkzrr5;;fV@a!Ohi*h`@}fWPnO{CssRYtxn~~8-#bJ^)l1{t< zpQ6K97Z&K3)lX(S&g^|5QgjMa3Y!+%?3U`EG*^$f5S(*I2**108@3I0`W)!#So#LCL!{ep;cdS>o3_@g%BmU@ zo(>ENunciS#Fx8=EI^TbX|^B-Th7@+omaY}XCSNIhiwPe@b;36+{LZ&-Rsfms(;CkTUa?hR=cno5g&jxeut4ZY z={gX7OG3XBre77NKeTtB>D&qA^{D7}#LkJ-Qlzum;l>UO0bBs0?V?Bl&NMuAic@Zj zgYx;z*$*4DCTldR7jO22tWT?*J3zUwxv{Iokp??p zme!#fg%@`5y7jYciLF2Z{ZqoQNT^6gdwP9wF-gBPW7G)#f(fCJ1n9eeC-b?B9<=Q- z51sCfay@YaF1?O2IGN4O)_2{}#KE;g;N!^7ly^)DA4LfKwgkPUj@h!VLBBzlkrJz^4+tx)hZ={=v8$)f+~i9K6SYpIXa7druV>>5p)pS{a`lHODW z`ymNlE9PDM^Kdo_t|1;}CuxTEG{Xm4kV9-JV0RR-yNlR8CGD(ontYpLS)TT4;X=IF zF9-DTJaz3d^}W4j2pl2Gc*qf8WzWl1i(Q(}5t;NZs`uR8w)R0ErVDJT7W)hIJNB%% z1Z)PFI?urZ3G((vke7ZnrGQ5@QF^(6YYQOdsRu>R#JyyyJ}I!#0Gc{6fAvQ04F2x+ zygN#$i8Z*Fl49xS^fKKbFl9V+gN#CXn)oKqj3t7l*pD>;C$|ASqM_fRXzqPrx*mqA z;r?pbz3TyK5n6+ZdZdG!i==1X8KV+qsW;XzSWsZiq->GX5gbP{&6T-6_7J#k9PbA) z>?6%UiQXiY2~u$oYdhf?#n}d(+qZ=p8uy65K<~h9LGR#gk!wuy)gRDXWu+(p-%hIbc&(DRY2|NwE2@E{m4vr{RXAGnx{bd1X~bYv9YN zdbiqI6tr@`7i+uI$}wbnmz_**z1!4V6zNd0vWT{rENMDe;2z0ri#0rKcM!~Qe;v#Z zhc(j%BQ=;Fwhbx>BC1Jsb(0abv}`Pb8aN)4~GK3+V)e2_3+mReLoa~kiv zF#??rk47>HtW4wfFb?k+#~o+2gtbI=NjfhPaI2QfK5Klem^@OPIZ&KwpxCGU%Zsuu zO4+EZWM-_aZDKpoQ(i7EL+RHDc$$;+`G0vDk2e)d98HufAvT;5jZ4rQ$5b zqE1x9f@vQ0l#Lm)u=qPlMb%)t%;YrtWW`M84EJ=!%=&`Gy(EE$0avQa)kL>Op7cC1 z4Krr$@_|KX&a>XNbHxJ%3B%O?D%v|sBrBCc?h<0H>OL|fiM{iaP!?G-ONDj|)vF!m zy?FV27%{5b`clsM6!kL0YO&1v9D?9g+>BK^87Untp(*f#l-UR3m5nG*vot66JMe?- zkdL4Tiu9d#C1u7%d?(WdO4-^@%|X2Y9o1qJu@<#nB#s(=#?d{4hppHN(E(daoj1q1 zdm_25*|VA^XNGI1z^h!!!;oW-u2C`>tu?61!Rys?{S{a9d97X7WXdFpX@D&I`X1c# zsqa}jN0#U3w%M+3i065=SNut3C+{UIb!?yi(pb{HK!aUhK=ZhDb;!>Z4t2hf4;YtU zz)R;2Pf=ZJ6N(Zl^gL5!I`QOO?D%}u0(I)6sTQjoiui}y;f=@N=+njpPR97SCtHTM z#Eoq}o=d4c$h-pqPeB)nLSnVIos%;9%(}|)dsdc;hsSipLs?q-f;PcIptYBWGG|@bQdBsUS;59-gfDLB z*;#|#icij_tdl)Zr{dJ9kp1=dUzDFzs~D~G2-)SMYfgKpzK)PacqjuI>jRTQO))*N zPZ%d{@y%bV^FVfJExDPJkccjvN1Cm_8EGglTsc>EjHfb}EgrY6oG~>xPGA^41zlAx zrh=M-4d;#I{KWC?zy5$|@K^C`4lq~gTP)MFScV!%M?&OT?@iD=aFkR>6t`0@6JX7{ z^d0UYV{9&umn}RszZIs7kV0~eYQt8Eb{xDnj215dfjPCDU3GsxeE>Zw+W`_HeAqva zHhLM0PMzg>wsUz=6EQE`dWmht?P>Y4Cr$MMIsKIOWwH}6%|$}H%|=QnC%3?Wd zPCO6UrT)a*kZ-)!kjVVt{1$q%wNUYX`Oxy*V(iX<`w(55T55a=bdw3_v2Eo9&5GY+ zSQQ&$bY_I_X&z|Zc6+LR31JJbQ~AVpB)-#e zHVqv>4*|XoFpox7mONMOH*2L_%sIkO37Hmjlrt-GYPMHYVq8?BsJT?N;$MeuiQz)3 zY!5TRCl8+c3B@|OQEj0(?tkk`t+f`a4K-9Xk#J{dAi1KxT=+Dy((NFk;UltI3#i~% z#Ig<2a@Po2|JDiUtkz5>pcz%R!jq;?*JJK8vk*awBt`$}q|YsGYsN;_0S_ahOX^XZ z|7YP>SBRnB`A=U2C=wJMh8{D04xj+=rxR?#+-v4LHya85Zxdr8r2n@~h4%h5<^o_5 zh)6_qk|}aO`CmUBaV819#9ngqV32=X5e6#yKP}lrP4B0r%L5buhyX_Vn;`d+`~Gxt zF+h0uXvBumeHj1@0fv7wf$Bl`{&Z#|0nvfzLGR9amSTLMB=8b>$-Sh{0_MSr;3RYv z-*O-L&lYA=oEV9dr=&+AjZot4Ja(UY|N3n#Y-a1|{Jh{_-#NenAQ4d}PCduoQ{TC{ zNLX|ndd~DY&;l3{tjK1Q#y+!vpH3CVpDx><`MAABI~vKxd=gB7oDYu~gXoGeutc~% zJ%P-|rzyO?${jBQL1;v?g`%1v1S^_L9YV#CF885daPbX9i9F4sZVh z`$;EEHg@PW8WD?zuW~FPB@ICU`;qfd9%g0{rCp{J8RAjxQNo7D z*0SPhk;==)3P{=OVwGvFTK_}@_JEzF|cd!rZI-x?MU~oyuvmsOubQK#ZeV8Xt-?W*w)o; zkkim^Osmrw&Zf`BO9P);*|lrkB4XsJ+NCkzf2QrPG3(~UZspt zgq%7YuK+JVOL?yxuj%2{h1L>ZH>9U70%EPFAG^`xnB*x?+xX~(fvQf^Ds8I4gL758 zc@Wk%V=%9|v1P_Yzt3e?^OV*@^LY@}rv5o?%)m;5r}rb?GRi687HAS6&8)Ns@D*o? zr}B0~Jmx8_;7<20xs%-V&|Ezss!O89ULJxxd_M05MVw&V*X6Fl9G-l` zFIp!MmM_|y;X27S5Kx3rUYM{2yyviim?|d^)yFMIjf(P{tHzC)-X%qMmND^Jb5LXS z#xnS5jO?Dr(k2Wuq98zeJOSnW?zcFoxvdC{4syRA8b5#zzF59L8VoSVjBK1L zkAlNmc{yaX%xK&$_Sqpe7$vAd!;+a&EpyWPXnu2XcvMtq5IT@VCIn>Aj*|g_NDw+6 zU%{#L_#uU{g4ydSMhFW#&;ZSJFTHK#_gXkcz%pV|(}0%z1WKb8g1ev3-6?-4pSt|g zxdsRh<+Csp)iWMGEt;D!mC0**vT{Y(0PB^YBUz(W6816b<$0d^WIF^?+(L4L3=NB6 z$#+qcUAgg0qq-F+T7x`QlJ$X10auWQ`JzOD%D5Cn)uv$OyLv}?Y@~x>nIB6T6#$DC zdL(<=L|4U1UGBv~-0b?U17BW8;e_prFwH=~>>P^h$ik`rPr-1ffVPq|$SP@3(42*> z;tI4$FOA?v1<6>W+cAy^(L0wv)F{@pEqo1#tb4F=n*-FHdk*T3u34t>3L7fcE0jqR z5Fz36goFD9ZV^2!U|ey=v6MzQwNXu0yg9YXTwD&@W0JO*wGbL29GMu4zR>A_txjX} z&Lhp#d&+rQ9f;Yk*I=&xJ^(mZcJqcV+yvGLF_way+q&aTw_~9FpU87vh-m;p8i)c2 zkD%#ZcBxipnzvPl&D}UVGS0qEK46hnV0cAWFVQiHQ3_ND^fX+tR;#GzUPs-SsQnx4 z4A3Lw@^Llaq#4ce-s!6f4omTB-J6`T!CgX_hrtV_jsBEV@Ozb^@R{F4y#TW54DA0K zZ-$-z#}xXH$)otMM8v@KAOGiHib!5SLxo?F>R$wiM!?3(NLuMXIM9DQqJONK|C2|= z_CGx$=KqBwV*AgV{1->W$o|6-{pd#j#St;k|1TU7!w+ZlkAU?5KS#vQ@ZUpsvbD7` z{__u&L{BGcZ)9w5Zf!~~ZuGOl+|iAKPQlpJ{Kwb%;gF1M42&uMn>1qo!F>P6^f?(g zy4f1j35pB-bHGYJj~V|x^#6vD@c*4{1v&wJ2jhRXq5I#>uc{`KCL#^9PgS(Eb@5JJY}0 zv9oA0v2*;7&Hq`Y&A{=W7uEjfU=`gQeonl&wTTV>zcZphC#3q12}S?kwA24GUZ($y zSM%S2D`>+QTmQ_61q?g$|D1>aVvCsm&$QG0mPG(PGT6;Kw=nHSgh8WsBYwXHnQI-~ z@e=?mhjV`zm*%Uh#&nP7O<*6Dxy*<>v`XOlr}RO0?VCfRh4n@j{8n@qyN z6q?ey%G(O#K#iv?cQymv_Lls$I68iJTWibg37r{&kLeU#Boq}+Feh14(G5H5kMciB z!U7?x`kE5`Wu7AA-Lf2Vt=$SAN3J4VrrH@2Eq9JGqGJwDz$k2#$_)($00*Jr_xq7~}-J;niP6{=dW$9^r#TMlz7VZBlAaxQaBD6%2kP7N@ zwN&ysH?Q~uNU7$RS9CmEprR-tvt*WPWIsGc$vPNk#z=;t>Q1kShv6};Pe!nF|3nH> z#8_k}(UY5PJ{%%K`%S|64AjnF25)*7+k~ViLUI45C+=cmBF3_YkW(H@$Vg!ERJ&K09%;o7mZBx6<6h4r<}id7|3TwpoMNFRs&$Y9oZFvZ+{WIMkX&_U z*<;8jSqeMfNr>aMc<6*0Aw~LAF1t9L!N5pxaCV1-7J9XqVEPn)-J(*UrXiDVS!fBa zj39fld}W?+$PEH-6i7?_d;G~uW6m&Co5W4YolRQa)EZ2)=tz22;j$*@N6;fW?0BkjTGr*rBlG7YS3#JPwS!K;cw?e#!Hl$eO zjT`whk1bTKs1(f2kFMULRO;wuV6AB}0|$G0s+C0dAmtUsJ8I{!#TBGxAMQs^>eszd z?TmQ7C8WHe8k~#6Kf{5F_JD&sNB3kXbB3zT zm+w%zGpXek_AB`Lmf$No=3bokxIwGGXIzIgFe4YsJs&Q60H8J2*QjvMt<(25H4sHD z=(!daZY9&zgoO1g3M3{<$m)Eqr_#_=6b zeQ?;EWc|mG%J$h6_zIi36<(urpwKpwt4rjW!VuoV6yvr~xWeNgWr zR~XEvh+BDhpcJKC3aN-dslcKF1BxQj&W^(drAj4r~Dsp6uzpy5}FwMH#YXGH}i_PvEU)LG`bU7>BpU<3iJZ!yDET^_n zvh9!EO{Wr3?fD`YIkLTB1w?`jTmDE&LAQQ&L+tumu~MC(jOt;JBt7}ccuwL;A(P;3 zf0pU5nFOUuFf3SEeyRvenK2DVvT&uJ9V0swwT){X_!cA|c!w+?oSU7W{zX4kJ0-V0 zmpQ83gLd9N`5~lEpq#yo9rY10EuX=2=b6odTcXpZ~Nt zy|O9m2r^oBv#MZKM?D-y~IanhLU}znx^dbYR`48bj=x!qZ*MMN|5Q1OH^R)cD+v<-OtST&+qK- z>^};kLqh33=x8pL*}D%47<|wAyo)a1U+;g}e!pZ=ldA(#sU>8!3X?ZnLHD>ew}?y+ zg^|3}zFaM{7>o`N|4GFn!$Ymg6+A;e>B!aPG1?Fvcj+aMxqmY?Jf(BFOs6qDPrA%p zzn7D-NR+23EwA^lZ))sltZ0mAENE<<8#pziHlWt$AH^MYA4MM(A8CltNmd@^lJpZ6 zs2NaS&~Q;t(MVHA(HPTAqmoIAkBE&hk5o7#-03FO-?rQ~+&10T-A;RI98}*H&B7@4 zM1Es%3M5BG8>=MW3rW1+YpH}$XIMO>%y_t)opwfrM{zb(d46yoZW|!h0Jj$P)V2C zo->ySci4=Y)Y1!rI*b7ws)hijy3dI^sAvu%>lS=?Po6t?A9aPeR};!xeT~kWmX6PtT9I6(Hr7p?DWbe?-wUxa{SZ?mm@gl=*46 z%?(ZWfaCuikK*T`KvT)vG?H{9r#m9z8kYqr#YgEcS4s`nW2ux89?QlajSH8zqvR(k zLryAwJrtTg4Q45YUM{RxiXK-4DHo$v3ez%&b+h2g%0ZnK&=86ki%6bT&=8q054xl> zM{!GldyU6?RRpLi9{C54N{rdu@wgV1J*D6&P;!@{J0Vx0@fo4tgFW#X(sY1bt8>(w zw->=PmWU(#CxaY)j2?YNggx?~Br^64gy(;SkvZaKZr!@^|0f9qTkdN9F!~6r!*i!3 z)Y{>OdU!IuAupjJ_u$#%M9Q*Dl8>mA4@Vf6eTJ^2F~{oM(WdvzGI>S(| z1ayd^`;XfRFZDSu%>Z^b6{{I!cNRJWmP2KgOd=S#!{~Ob;)znKr#^|}a{1zlm z9kNhoQAmDnp`k1HR9xD&ihO(dB%!H;M_?ZL#7heIY#R4$vbSvNvda3>b;)}5pQ`}n zlt2~1C8Z{zqO!L(Z-Q{IT)cD9d_^vK3%^JP;S!RlzWgPE;hFg1D{&rpZB|rcR+J*$ zIn_rN`I-o`R)4cq<(AmP1JZO_GWTji%4*X^HcT}=dmBIXHxl?$eM#F2XU3$a$FPG!xVw>cO^_IuOjTBMDLOReCv)eDSJzZ}4#vs>7V%4^H zfYzudc7B$mj!LG0DKm3r>^DehuR!RgIuedEUK33w-0)F!!=vi$TFFH`N(XxY+Po?m z2B0ZqTi@|n32#|&V!c8MA2yaQ{a~J0b$h>d`ym{{!2OcI-|~mmf1F^{k$hN?^59$f zRo&L3=I>Fv3&rbYRq8hTt$w)~>vS@jU>O94MhiqftxB`+$^cpbAI2hV8C}zLJ_jn> zKNIUKl-?W{zC2ca43o!s4^2|p6mq|W1BD?@uS21U?lW`8tdyPkpx0pTmX=d_UUk{* zkY>QF!QXX&+qe-^W`Gm>5)9TFHBce`7KnFFL0tQ-AdsJoJQ3q>Kt+7-E0KlTSEra6 z4Y{wal3N;NduV6L;o<;Ehwz+cM9r$}aP3HNk<9gHKs^fXnVTR|V z!xQ6f5aiZtFefH+O6`&8Hw@P)%;C*kW#&>{O&x3IByHvb&uBK;sxfZ}+YRhtBI_K* zwqm*bc@oRG%kI|3;>4KPUCP)F>9=)~hGrS;*9~>!H(;$a-Nzxj{kgf(GSnnsBR!aeuELRAP!4iKyR z(()(3tOVbCptj%i+31PF$@`0=&J>=A+dnka;RTv29pBJ5N#-a72BD@DB3wA>9A!2< z)*!8ZI9!|)UFgL=X?Rg<;_Wzak=QL2+`h>hjZll^ILU~DPWlSbpKU17)o% zx9s`4tX$)&6reK(U4u!VYFkpfynE<^Gj*i5@$Nx6pqRYXt*4c)Nb7hfV1vJo$_*JT z2Ow5~C%4UcB(bm&j)Jitoc>GylF>i{yjU8g-? zgoy|TCCNJw$dFxUDKl?t2*Ys-bejCg%!&+=1sD7NoCF*iXc%;fcvL1mv_Aey!pC(~ z$70y$Z5Nwa;B6*(MV@_U&&+JF>L!|u;p$g`V0$swnQ@8Q)K%+%AAO-CZ{?9sIxsaN z&ynMqYHrr-32@m70Pg^633uyli`m<@jXMtKrIe&Sw4?=)IdzQtT z1-pJS0H#4+QzgQrE(Mjg*Yrn(TqR&{-@G~(*UBjgS#dK7lo2K|t)eEnVUyAXiJMIc z;UqC0wrKKK7pc+l1&acZB64uL=A^JwoLtn(NklSo26d}|u64Z5ACs5Aw8)Jm3`@CZ zjU{s`V@tEFG&-B6RUZj;y6bDHTXB2shMNe)JD3^q||?}vEz)@%$fr+S4KGG(gh zd7aAXR+u6wCRbGvn-q^@oR~xCFUe@Zh9c;SHX#U>7c7&*EkZ=38~zk5ZHR5;r zl8dr^;a?X}h_l(E4dVed!~`596ZvP6q>Q=OI2T9IN?{(>@CqpXdNeV#}PZk#SLo>#x`zH)w&u8EJ(?D>va3Y zKH#!;53&8IV4)M6kURT9pPCahFGBq&K@_>3L))Q5v6Wdpe-m`X^b>_F-wM6VeRL*T9v(IpeeJ8M(cP$c z@WYalfN|oML%HaUsC61Q=C$kR=YsQ*7kf|}t1P(kVk8 z#9-Yvt<@#BZ(>_UE|r@+XVhAmS;_vQftPT&iX4p9PJ<;=S)g6ZTuifbj>nx#O&sJ^ zzOLQh1#Aab7OhF%qj_*;;+Rv_<4#?T#<;QFIGwLIk}tLXRREyYixkSHDv2K)p0V-vE`4Oi6|2(9^vw7Lh`@~|q z+WCGMc9Z@fR$K+Lq4nT0&k`q1xc+v0?zjvYL#xpm@+$m{P}V%^&KUsR?%i%Xt@0)P zb(Xfkndrl$Q`IM}rTVhn0aw+S+^DfuPfg$!RFq`AbWlRPL4K=X*n1?;gdWhBzDN*! zXV!<_zxxY9T#7zMU_Cg|{6ZiNRqQ-)85Ef*3tFn=k1I3NRBUXq{(2-qph^}pHa_qK zj|+)0V**~)<(5aIhWNAR$$PiM1M-?IEW~Avx|I;OC_2&4*Qsv3c^8{}4uZ;FkAwst zyf|WVZTq`qlLaVFVY*UbI`Z5~lsWq&i~N<5q!DuyOPUnH{P+RLk6Y@ z`yvJaAX^Ai+#6zE8^UNzEU1gRs_gv$M19?`s1uktGiDV*Uc9s~=M70b6)U5j=hNkV zRa0%($h$iyF$UjtNfM1;%ZW^T<}?b2Tu503wEz}1BSod{g;c-(5r1#XQ@-gugxRWa|+o#yMGUA8JagYvYWn` zyqPvnTG%u^1W`x-2Co=qjKK_V&3}~kb2bezO{?Kq+@7D?{(A{q3C?qNes6X2%$4Kt z_wn+Urv_EMPzA~Wm2^yf$_Pd!yowM3Cc43h)k45wbSVl z6~Sfi0}&KwbPcDw$H0EyTiF0uCxL9Cm*6+mS>8m;{6@7_AKwS^{mU&$iN#fk?$=Dy z!|yk5#SJ8{7wqM$10Jk)+N|#NPV${hXYK`+mL}7udu@#wi@&Ft#yj2Z2Pdt!H}!+E zr0q`{TYaJ$b#C7b+>cAo3sg2<>A2i>_V49AyiI#=5j`G0A3#<^<3nsAw8cNgW(3r0 z!Dnz@>=qo*R4+N%KYMd1T0r~MQ|t>y!?{n}Rq~JzNcF=60+;4QvnH??G>r^RK#ub ztZBNy_)yuw1_mc{SCN?V@nRZ{L^~{Con2rRy;s7L331oCL{r9$T%%~ukgdKO>*CoE zW2nr`eq=o7R4ZO&*aO>EXk0Ga{NdvYT1RAmup=ZW3W%5Tf;uzga8xBp&w!T()nx1I z)m5&Z>!69xvz^^HG;j4K?(3qa`;hsR*12CZnU6UilU78$ARQCeQ zBYV%9e7j~s?~U{`ZXo)6vnxM^)eXXc2V_xfEd;a(EkAPD%?*lkPLFdkrA~I=h{00A z`a!s7Frb=}UiG@}hkrl$CTZ!$g-RkbjW+j|;Eklg;p&i)k!iHe8(JwJBDAy%W+{m#48 zz0c`8BG#eI5^411^6_U@_6`As&e@fB#b~Y!xXu^ytA0sX$Z2Z+lb_%!^n_3otyNR8rnXk$WMiZ4Pcd1rq`K0pR za#@K}5xSi~@?NF&_?29>js5CKn~<1zI%bp@F4<^V+#j`=aLEAnH)0N)IKHN1p>YNJ zBBiC0mS@NAD$OC~R{!L-O1f(!Z38YM9!*8J0Otmuz83oKaMq=fTS{$sf`DJ2A%l2? zxx$bByM_DOTR8he_0Wwd4#5P}O1H1?{*VsfC5zxCTqd>PYpg4ZQrr(!Yns~BBQ1&= z3tS}ijY3)~LchAC%{AD^#Fk(||MY>H7N=HIB0izTsq?c9KNf0H3w{!W1s*C2c_~(}?5Fb5WBQEug30SLr4rPb(PmyHWP`Oc(h9zanb5JCf6dOCZ)-bMJ z`V@}>AW6HF4rYzKPufcf4ml2z8qx(SL={`Ak6o=8xZk4U`w8h?ncgIy7OS^x zk(7{o@J0DU0;oZ!%aadY1gb2Dfy!y)G2O%`r}zu|nrA%rSjN)wOLxX=)11ZktSmY6 zfNz(sCaVFYSjAba+%in{DD%)441qX_Gdz2Axb#TthC2BT8Sb==3a3T#UewggrL&xQ zuc(~4HJp%+=Rf8Dn2txj8vkrfKxuN76s^#zHQB%a#l!iuB4e|_;k3IG^TP4A8C&q; z;`?61TX2Ehb1AyM()@Vb#+ag#gzV_AE7-c2=BYcMhn>j2zE*phN>67gT9DysJFD7` z!c&}5@;4FTX98u;P2<=H>Fq0bi)JAezpkaljhwlGBt?NX!RHNXKsu0?UJN2OQg-Ab z%Z78XcTZK6*TB0)_!QcE$fLUe-vv&=mE4ToSKvO_R8HDmMmS#?%zmovSg@YvW`5X( z-Ks)xcY?ZHmXR?hDAh!84kacIxpZP5UW9NO=5z=kAso3RU8^4L)=0~yrr&}cu$ZnM zzNG9euL|-la$$IA#IQjP8xMvqGDs6nDzFNe#h;hWq-m^!$Wzp^Fi%k3w{~u-711(2 zOJ=L{`lUQ$;@03r*0E8$@j#e?JU!~8w}ZTGTmyNnz8%MBU<1iU!**D6`{tNs3e?Vd zs*Ze$A?E3m3aTC#=2nWYYoBiQL71Iyl@~WiWFX=n22Y+V*BODH$Ruv;oo;Cfb92xs=y^NIrO3-%Rl~e#e%*4dp2RXJhw+K= z7abs%FT+m~L0S%h0GM97*E-K=9ae6f${17D^c2p_Qh^-FOap0KuGmgd)?{6LBn^~N z5md~?f~~Mh(7W~OckPx(jjiCHnyWZZQICHve5PGKu;I`#-gq*1bfw&s!tZ9~kRw1e zP=M3#UCl5BdP2qc+bVwH=bG;s^daQhqEvP$Og`ELU{7g-sM1vhe8LMLb6`8n#cdqv zrzOvkhENqdvfNlRKbwr!Cr5=mHji1EDd9~-8_U;Lx*Z7Qr=p*JT=e-jOI++e2g9la z-w5oL)cvV>&LuWwyvi#<``~0|UNlx89X%`or57Yy1gnw%c;E?H`6HLVp+Igxbhpig zSNHik6g2P3VbCE-$lC9H)2Sb!#x6DR#1$-EAerc|F?Z#8o?@?4;xaYBEgTtH-s8~Xg-IhR{nAf?!X0Ux^|{4v%*z}rj}Q2}hVzYxVt}VA z$>Qq{=oM~CewJQ!nQOp<`k+vIYazH5zO2<8oajI3;W-T(}$r zps=(roRP<(gVRQDRy+0YKL%oWG9M(iYl#(Clm#y+o0WSZ3nVP!byD7n z%*%3hF=KJX8j1B_;!LnZgru6NnX=-2g9Ht3E-A!8tF(hm=|ZB*gZmU*6;r{b95O3d z%(@M_IyQa$#gwdzWw4jt^`W#|21~>s(Ux zLDQv>fG{BVD2R6N=?Oe>MS4T@Ll=yRKUyOrZKfBQr$-Beg4b>tpg2gNTr%r07A%cP ztLEf4Jw+;u>&6g-a?8^`d0tU16Q07c;3-CN8|8Rj&EZ-yLGLtkq7RA(hEMqC1N;G* zKg^4cm_(sY1;J>AddV`H=~38 zqpA6Rmps)&PPe(Tc31H^@kFag!hlV6pp(YZQbD$OKcHgz89%PA>)GaGP1Kq}e<-B6 zl)rgDGxf=;@ceZ4{(xS7O0Ra$O01EZ?Cjx}0=CL)BZ|9q#N^6q)ar^4qQ)k}C#f(7 z$(~dhsW=vo{qcJ2@mkHDST&?7?KJ4NOa!o?wyT@#^upDc$yb6CGID0PPw}dxW*fn| z0@E_P1;Q2hcOUn*(RR!st%Dexf6w=ZO-z#HqI09OqpJ}um(WqCiZq)yBzh@C>Wgf2 z!-KpgrKFp)z%Lp%VYAR*lJNA^pwsx5FEy7f{d#X7$}d#?Mt*b~popm7R;eJQ8-oHW z{TXVoHUQ8yoBL>+PN}i2U?CtE()_T-H&K@us3jxvR?d&cL4t zaQ?`pP-f^}65{W*doMXVz4!}hEl_wL$4`qs?tEMy7hK1_-5yhU4JF>QpG38~9gNVB zfX}GD9$?#{R-eOoydS4q*M=w-{Hb12CJ_R&XPNuClGI2G`vP^jI#p~c14)~ZO#`dI zy40(uYq`gf{P!k(G~e1@i+tt0vtMN~sNM!L8T<>4{b_ono0!|yPia;pkzq-F9JM-D zK~n}1?W<~2Rfue11(PLxqIz2K{JzPqYm&lp)hOXm_-`TS0LsO#6GpEF=`K*1(3zh?!u5eP)ttg+XLEg5%7p`|YKEL3HD^Z-H2?rYh`YQ+Kq{hK}WjHlsA06+o z&ZL~9t1-`D%^qmH_p-XIOTu8(fq z4bd8?=mE(D7*T+A!}QEshx1LhfpMi($U>8PP9cX+0R8U z=dc$Gui>dE45)9ahSJpIA8cf~(|E~#F<9lhppB0&xH=sh60rJVR3;c!B1smT#!`Ai zQUu^9k)`s}Ln3yWf_krYseCL^U4^?366(y8KlbN+0-QM`>j zg^hr?&EzfZaLkMmT9ra;7uLAJ#0LK@`Pg9=y#J=0EAx(%qH>&X_G0LZ^SK+8KFq9x zGeN)Lg*=NRg|vl$AWfds`U!0JPLj&5bRIS%I!LgrJM>z3r=1Dx(-Znm0g0mg=l6kkXIgD6^GfYHTh~-x z=R#AAfgyufk;;q3yx2?!B9d*p`$=hl06zX2gD%)Qz0Myra_ zIB?8_Xg;~Bx#rTsTru%V*kSQnmbyiAkqvVyQdqn6Vnk!?CUN6o%#yE2_TlETgWn&JRj0BCLtj5gf3M=!)o;FNxFY zBtzQ(>&QOAt6tZk9cD5M&DzZ&%r4q^?t9}G*FB4ESMDP@-7m%`&3Jg;&qc`t6ZI*B z5zE!7YfTx6TdT68mhYN)l|3G9M>zWDN!bf%GoG%X_C{DE5IJ>aDEK=(V`-JQ0V)Cj zh7q9DGLnIidrGK7l0_=y`fX}fP~e1n5255>o8_pgnfn-F@<9*egM%1`oB#oL=-!|J zzd$NW&>%~4AC>C&c%7ZtLBbFL#E{YHtzE10e`)W&AINDIjRVtagkglyI*cA-O~N)z zV6&8sf$fi~j_COezJk}jSskN2rw)p4H~jC z=sRQ#*yg6|CkN^Jv$f%o{w=rGWjwIIGVxQo%ICU@=i%az@=I@HxyYlLOZI*33 zxx8}x0ih_|EbO|lhZ$dz`zibp2WCOnWn_JzE82y~$c0FqwNg-tf)Xodv6U5r|9$AM zFr`w0DtjJ{F6l~le8ZyvcEVjW4R1xmyq-dK^4jvt^Q)`k7CPN-yh4!YZ$PiM1h2_K zmu@$$K{QnUWK(Y%zY!tv^OwViMFzHLQL^cERWye|AcGvSinSlZ>@XC@pn{!JVHt;# zt`HN{xqldfv531j4%bBUb@Hl>YmO&@u^p@;cG*Q$V^fhtFG3y}*}4-|3&pDyRSp`Q zN)FcOvv|??G%{;zzs%!)J~I(A74#&|fvk->c}mY?CG5e!ZvT3k&_#t%2JF=LF6_}< zs*@CU#B~B?Lh;g83L&u5ObF6nXiR8)0v5x(U-NI4?6f1 z0O%(E@`Gu_AMNq(6o}=)4;`Ybw}OE!)mgZ3dG6BHBQ?;j0hp^L7;^qISwRSxnU{ibj)_-1MxqmOn%Zj(L5|B_|K{yt&;SFu?pE9Ye$$ z*gfQ8-e0wL{jC%q3w*@T?g^)xKnUZ>hmZW0MLE-05UH zB3sS!16!rr)=Dje*YU z`N#eeWZ2YlUD9@p6gT&xfk_`8+qSG^7;Jx|**+owKAV8EOEcAt-12b3ms1nO2St9|{WQF|>WJdmINXKd=Df^N~r;d;Gcw9iuY|y1w6;WRjWK*2K1T#mU6BbH%o8+ngj5+jg$lwrv}4?&sXkyUtnb^oQ!b zyQ}I$S9e#h>b?KJjsD5hP?A}{_zZotUV6`3?3n{e7_H6Zm| zBhB!~P2W*L?-C?aGufR2Q?StTA6>kYfuV0OV=&dizkl+u^WqRegFAt7qRW|w zSXeMu2U2hj{X@Um%}h6nu2s@1Ek|0UNSvcP+(PeSOz<0km^QRaBeS^3&B^SL8LMb= zd5nV1=2>|-nFdzXQ_P!KBTJ)mlk=!2;U+TO2B(uh(<(YajtJCAk0 z5Ns=ZX1*2dMf__1mBod49uqY%#-m}13Mpw?!WcuxqJo*zY9ouyxTb>ulYk`W#=K+a zkS*t3B>_7xuUb|?6-5}x7^rB3)o%wLTbc#p9JuAP}dKf?kCD;!pIi+C!oEU0Ig^<_|a9v0G-VMwuE5YpW$MB?#7PxbPJ z)=N|M?F`Ds#9@@%hTY2B=AX>lR*__KJ6r2#Mciv!4xRJ{2E6vmZIA`V#3!6uv)(_M zBNI$)t-vwchvsKN?^523sy*Gge>Zw=#Y}Vf=b_o z9HWY3Ah>*0^5Bc3vU`;*QN|@LOPb2tS**#6Z~dEWH) z=c4^l`y3vsS=<(_N@K$@F*0Cb9OLZJ9|lgGXWVpDFOG5kR5zC4HOg0Ay=KuJ5i&Ov z=9%jt!@opQ8LgKs2%;bNePyeYY@KPDZ?DPYSz_r;?W_ueZN{o`sRT&B%!7 zHj1*E2U?l`^$iZlBSFl6PGK!Ch}Xv@qkR3O4x+4lq~Gi;nx+5?{fLlP>h~v#{ZkeS zQFOZF(%)M=@8K~>;R4?r90A^g!WHLa#!!Dr#9{vPqQV|b6{4%SU7p9`E_ZyN)q=qN zX?xj%*h%5x{2ay@Z`3Ji@f@=YOy?^Z2R3s{C-v*8?@*wMPZzXF=>$O}AS1k~z3mh?6-* z`fz5}q)@d^x#xcQ{y8g(dlvk-?+osJ{w=Ohcg!{AUBZX_(fY&iVb_vH*C?-~bXtvd zMp=jlTt`AVYM?Z(61$-f#pgP!bz)wFE}xk)drT(5f4t#Z|Hd!pCcXRlUT69A!F%g{ z;dM??s%m5P#Oql6enS%fdg69TYS-=hdoNEZlIvP8fDFAe5~>%S4Aa${M5CAJjIb@x z&O!D(SwlgSSvpA%M{vg0usl4i>skL-wbCqZdCacs%57hb0=1NlU+t|y5>hEBLNMA@ zJoT7VKiQ;5(@lQ5AY?c_X3o)1mREV!t;H9n8hVU^->r8OwbW@OO0!5`fsiiQd2{zN?$=OECd?GEEa(01<4l5D@P8p2ZPYqrq}OumWs2?TiUz zj+}fcN(m?>n|ZKFDvit}Wk}djjPTdTOR>jpq@&>tTd{gD))vdkwE7fdXC>?(Rg66# zBDzCkYrGPcSIcMO+m?>^wpHd3KDQ2!3-BP-Zcx%X7=UigH+q&<{kv$!468kr#Uq(FM+FbTwVLfp11M-6e^y*>u3M> zyDM7j?peLx6`svl5|xNM1qU2oRE-@I{%^5J1leu{HzG>~s)T;u@R6(FJbrFWxnffZ z_{nH#AcupyByXjT9DP|h^f-34LgfC|Y0;VKp6FMt+3h_qxBe`cign-j zhx^z}AT+VyaoFC>mDn=sK0ahD2;oG>6Lk2_)4J$->c3s>6mmQr9pa8!|55LBe^f_3 z?982ALlzItCq;2yJrI@vG00eK7f1I^|NiNa(FWBZ!pw-VC#+?Prdo`;`2AOradujt2snf(K(*iAC(28x?F#_F12>2w+W%w_NMip7N7(V zDqPoGjNllhd!U7w<_)FxSpMa#DYOF&vh;C9z=x ziPy!w2NFy^`VRpW78JQW1V1kSl}JH}Ja<=BKJ$&Tr^v-46aw(}&61t+oEyJ6)g-x+ zsu%FeunJ6Y-BE4g5 z3kCpnbGvG}kJv1Bs`?BlMs6rZxzyNiu#&vUHR9b$6J;oN)+v1mT%CTPF0&Ix!a~79 z=yvl8nDkKZ(8U??4)rbAcMN&;brFN&h|DQdL@2&^ONy+tLh6AE!C-;52FN|BHi32{ zd1irnB1SB})oXb`-h$^&*`E}-eH?ZpDL)N~97c=8cXpMo7IFwP26i@FFI{bT*w|KJ zl)#rn-Qc^8(o!z|u4&<}x!6^6LKZ1!`l3c?A+1xp%U_m4uAxV_GIRG@VSXN5ByUC; zp8!Es6B}L%Bhds)^-dt!A%SdM9&XgYJ!T$m+>*w4Jd-%^F{QsTMA%78C5)A@$HAsG z?3^O|$ysyMd|H^$>N`I-GVQ-hF(0JaQ{nZu3WK(SkBm^~0?T*NTvtPh0TdgLN+!Q|GzekGO$!&M8N;z+1S zTfuL=SbR!(wUSVB!BInoNpd(aJ0uvvOGj97OJujtZBKL1AVT;H zZ<6v*{-CiH>J8f^yMfSIlp|P_~h$6Lt6nwRSndROvV&4U;!OT z6J#{pmE1zLS$foleVtyNTS(aigE+!gV6^#k96kwnHQ3smD}w!udc za-%)liJRiCxU}3o0xM<7(#Bm>BUYkO^Uy&~U?5R2(oFLjB@=CL5wTmT0%A`ou~}h7 z2y6{+$Zm6C2~}b=Fg+L1AkIevQpd!S88XtBF*4?vW_kQd<$;CRGL`3G)*8pAA*V46 zPE|m1;Paq;B_OZ8@~LIhqD$N8SxrmdFKP=#LdlV}6@EY(7%3r7>@PuLUQY(ch|P$i zS1iI-ObHZ9+SHMPTyCrzd}=;+Ckv@|GXPURRMD>VzNPe$eWp4GOAEcjur z>XUhy{mOHgy{MgA72;50TbW-Z;$rZKt&R+F(EE6_r3i}mIQ&P=J96*$8oOtZ%S-`L!olu(poc45`w%5%yFHs<#b_?VR9ZvN>it?uw? zGm<=uVEuc>kO*O2@ZWX#!Jo{_O#68yPlG&qGvvKye7jvCp71fhg|@hsry&KV_1%i< zUmgdc>LWA`(H@-*QZx$aX`l;;g$RSBT4>pvafAGpWo_EV4DR*KP&!gpy=ZiG<3?^v zd`26Xl%QhAg&SFg-$Yqc0b#29(A@AcR>V3R5jC&KUmn&1qlVY!@ZbsjGTS+S}}o4Z)qdjwWJ-l^Ygry<*&yuc@8n= z*d99PZpL-5-zqV`USCy5J_8;XPbrRyT zA_UV)qZJ`t%XKZ3bbo&ECW|*+CulELS0u`%v9j`Hu?)RH+Pm5C;QlnPxS>IrSMGhS z2Pocf(UOr}?0p5SxE+Xk^|q=nzg2s@TL>-@OBp=$wkk~T?+R`MdUxM>YFa#Y9AqET zF#XIw9&pY6-i&{qB^IOUSk>ZEPs;i3GeFm;Pq_`Kr)WCHs)&5+##N2gnU63HEBKQ4{d*E-p&+# zo#@+h=Xp6_NoWvCupPTKNqtF@N}VZI1B% zG3mLK7sdDvTuzD~ce`rR8K z1UoZ<`}Yz-jro`V-msZXcEtwgq&f5~tb>2eu4Kq&iuXrmGviF$( z5CmF*C|>a<#y+YM5JIV@-m7<^8`S~2k+nKY3;$%cP~gYU$t|MqkmPc*i+EUprd$2Zk9&IyQ;j*z68#>?Xy`yEdnE)2PJ_5M8M)t?aj&PPM`z06{RTf zfh*R2%*E0iv-taG+r{5?0ro4_vm;uhbs+ShNg4rSz8{{vN5kd)@}V*pm~Ph@S4hqwCVHR@s(n4V=hH8WvN33Fdn`?Ly-dsx+%ub zYmnjLrr8}=y~9Zpi`aW!6J_ow+#Kv6h8($F-~{~g+F2`Dfj;u&I}gVF-hlk^3s4>D zM0Dv-k#-AqDC|UkH`Y=dOf}b)ud~%cC=vT?07*NrTqS{TPo;Qp98uD9^e;?<(BRxi zW84K~f93XcF|JB6aYrmuKmFsJW8i5xz|KkGClVLcx&L7@at)nU*$_lVRtRIePDdsR zVNQNbp8|$Gz#OTOegR^E<*iOW(7z!xc(bl($C=3A5?xV^{LV0bNyYKAbt8XplE2%(oZPV`(*<4r_LhU92pTJ}PY zzzgK@ezfi5y6dcp@=b@E=5hIfX@Et|fBevW4~8$kuGjL&fj2!gWp8Q_9#PW#?L%!Y zd9e8xVoVjl- z44UL|c2Ch|8no!uEnE$~G4Xv&d)R5*BEGZQ8s54zwJOda1KS)UK;V%%1+M~+ zp@yH;p27d#NI2*M@c@puP4@!0`gX)t&-Wvn*=x>P`_5y_Ve1`i;XGZOtYHQvV@ zhix$M1Ux*yppAbq?~4l(c?u9YL?T2&Ae%fcP0#%rkD+Y`W<^`(*KDP4wBhtN!Mg{A zyKJUtc7>EMII{QxoK?42SOZ131HQeSA5B)j)I0Y+VHmEN@I65T6mCCnVqRap+mcUy z<`i}4sPWmpZOdzn|ElV7@7}C>;jAzg*6Cf7{6ZtJOXwlcLgN{vZ3R?--iK7ojecnU zKGoU?VE@VSt{95+tt#ogq27>+09gcn6Zh`^6zesN>{{8fQfT)kr zf7h+P6sV_9e}?gxCII*L{m`8z0CNriggT?Iu<1cgg}&<=*zzje;kmD`4tMcY){BfI zhh(zn@kTp$ed6qdYg$YqSA1&rt#m1A=58W`DyG3Z({zN^AGI%=Cigq-EMYu!?ugo% zeZI3A!7WZ}joQD{+~+smypuW6OpvCVX$~<*ovK!5wRnq+z7d2gh4OF{E)I&&jpJ-A zVRJ~zeocmTjjz=Q=Xw?&B=(BD1}B_z>9WiuO?EoqTaQJCAC4bl?U3hCcZa#WCJyOQ z6(Wp{!ZK|e? z*I(f-)UJ|;cc;O`*Ur}dhj)tf$Jgu%lY<$ppPer3%2!PyPpO)(npkg_OKvs~INRSU zZo%yIau2485b4puZ@=vozvW}TI?lJ%*Pk%ZihN@Fw!2+ln!dWipR0n$AVO@8=<*{&X!l%-V!%z$4Lix2nvk zz-$tl2dtgbqd4`(BzN1iejFHpsz#n{x=Y8666Hm){{M?>pQvy0d-`wXxs0X%ezVGv zpA$hZsvJ@V0;XT4(BFbXKj}ukGBQiy%T>7kIHCC{aS1=Fyr~^mn@B^f%UuW0AeBap zskX*@BbzC@_cl_es_ zCwk={DH5_pq|)LA7Dvg2LK2I?4=kN|j(AQiS-vEG3>F=Q$L&*SmT}9oLD5%FXU4f8 zg*wfkN@Vw-so6QvU^X_U`kJ`hs3=&xhjPaM>sVPDngWT1aB#3zmWHMV{#y@ec0T)6 zCZ)|1v2}o1huo!0>4*fH7U6YlbB?9{k@@;2vW-GL~= zI?-tt#T`*@7nx(*lvrxz&5-UsXW3UDz{?pS6c$0KlOjyewCFL`-w?>4i$WGSa87Ns zf`%g_{#zT^U2%0J&=BH-i*Kvq0B~`rWHydQf}4R^IDaCYW`He^^^i7K`AJvmT!J=f zn!6hK>)iPa%NLe&xdHF3mLIZ)RKSa@YmGt$boZr|0tF{h6Y$79sBfO2 z=t@RL4oXsmB{nvZ;JAT9Zf{Xig!;z z+8##+iIkRS4luWO%4!gQ7H6U-p|mTI2Km6>_RSDrYy`Nw3oaH0rEsoBBS2kdnv+Cl zPe=M_!}FlzC6Q?KaaR)O=b1Goosyc>NQ$y>k-VxaJVYm6)ROlbeWqro&t=?XP8XI1 zd6yen8_&&KC^Td&WRMuW7vE`>8H0c!!mYzzy`7om4j9>zP<$z3kcVfAX28hfcoRmtLEEN2-5*6LovLeaRC$1NKfx1fyjOK&^gd{vIf@WNMU zPiBEf{WbGsFYb%AYF$rmDu8X*5gWC43W^0Rhl1{lRjBkM5RnT3B>)i`}q3HQ`;wVAM<4lY*3SZe&3o zRn>;J8hfzq`?XKwMMZJ`m>b)|1{i$AH9lw$Cy%w7P6*PjP5Gr!EmsLcwFHeH@Y^GGjd>J@w?YrJ}h zQ}*Hc(YZA6( z9QoB&n_M+MvcrPhfJoQDzvYdOHF29SU-|Mfdhf*!#%p1@qAvNhi&0)sUU;~cE)}`Dq%nL&|jIeT5x4G})aId1g~W97ob@^K_Lr zUs~sxg-H}CkJg&0yr)ji3&yK`m9QSMQD1LA^2r&PXDsO%7}f+OHFoZsY#0h!MD<2mKBKKpn~qjQ?)KI_;b}&IJXyPX{97HHowiJkLl(ft(e+U(lH>(=Eqs?|I;lsrlJ&v9 zJO3SDq(Su40Y&5Yoeq5mX~qvQLissNFwx(7&<{*$9c|pT+;wAP#!wHHOE^@M!Dwwu zJ^mewCYK$L8=%h()U9KW&i77B@|C=MD5irjd8p0}M3AGbpOB#g*5y+?16LajffZHCDoaLbVRVjI}duy_Sc-nXm7}p_jJmP&4xOROU8~;X6 zHV+ocG$^HdH0cJK{D|=-Y#*%KW~1mK>7d-*0jJZ>ot6**KYYdRSSUFF3u0RXGWcHNt#9uf<+KTG`3UtD!toRaLvAy0wvz zkDjlJuqWSCOe03*=fOeq>6BD%KK_QA&RWw<78HP)lnh4(l0E zh9MWWDh&m`E^WM`xhm1vM)+dF8Y-e>m-V<}Fne1CWLjUF?jIgfap&l16fzct3G8a2 z<8`L5j10>a2_c9{z}ifN;$%rVzNTBt%MBCokeB*^r{KzD6*8(z8dH-Vlc3g9u{y?! zi>lmqlk~t?Q(U!ml~iN;L%kZt`Jnp+z09+~EcL1|ottJhK6pCVqM91*>{-bC^(n73 zBhJ}MC}VI|o884?O4_(xt$tTKmL{b*1BJ|mFlZjc4ca?+aZ@@*UzT`c3v84zyebZ} zvX;ql9c7|oFncPmPr7V$+G?7&iVO%$5f@D>8;>4o#JBS?(_OtLLCe9O9v?Iii_uEv zj6Ao!jdTL4XwKJkAy`OU*qU-vuYlR%Q{@9W$L?s_3OY(5~`A7<52D>$su2Awwp*51OsKF6JTU>RT)sa?PY;l&W)zA80 z#*uMrkafYTDX-Pv)nj<$^5sf;`H+e19}l#TqyWAK+)fPsp)V9t!m9jBLo?u_ak ztC!H`jLRMGJ3rry>>cyFVAqVz9rwFH2LDmG^^lOu9Y4T555qkl;U$mY1^5lp01*=S zE7$-t82Cff0F^`(2s>baI{*YDGe9N-LKo(J3kv=F3q;YwA|*y?tVcG&0JC4*&9;PI zSA*9$2w&VEUEGVS1f)CAC!fk&f-Veb6t?)gv)CsDB7CX6z=Li#NXIX+~-sZkB~bBiB0Fu?8?JV>7dS8VGK zZcx4*Y&6JDEo|2gOr~F)1FL9DDKmK14sxQODl@3g4qj#V3%qu??WyGpQv->yZJ^~Z zX@^BOsG;RYZHHDlz}k$ycn#1B!LcQ_?j3K2Xxd>bAB0?s=C&oj=oMXy^01}9=zDkl zhOk4(6Df8@f#0|53MRWl$rELAWy2G3c*UdB9pMT^zl+u$zIes8(VgK6W3!9*B|>}! z0DMWh{UX>!@eH55;_U2Bd4ks6{g1-!6|Z-9%o7yfF2-B<<`wrxH<WKU$;=7|CCIw_zk3lFVRdCq0K_DijC={h=1fxMY zrkF|CwSj*s1zFgzL3k<^v~X@{D3LskL_Z6oc49b|K_SI!LSO3?y1&L>3TSTltQkUo zM@g3e-#?NrE-pTJp_@F3rO(&4)DK!I=}ZniJ5T6Y^r=7h(|vvIr=$2szaAOV$fo z)C*|Ve~IDpi#ZCKI0~pb{^ur>y%VVSaA@`3HZ8} zzz$7MJPl}urmvP}kX}6-O)XBh2D!`FNJU>+1?aS(C+*#*Q9jO9KI&dR328YbYB@$` zIbv*yZwCH<5%a4xyxi5q+%?Q?)zob@+#c2B9yRQ*)%5=b%iA%8*iwYpafsQHh+S(& zAGo|_138j+IkHinz{%~AefDHC$0##L%rfz>@37v2m^mZrI71vbV{Th~yKdM&CW5s3 zL2m&*H}rJd3Um=qpZ1ko5|umVmD?+y+{@*tKSIM3^7*}G1nZjS0u96ER$C>lh-`-S48yJOjTD@Ro7fLS7bKVY?oJbm)8J- zD?);6#+)n4oNG?qD^lHS*3B#0&1+u1t9&BL+TRkj{&^Iod6caN6om$qjXM;TJCvOO zc`#BXB2pD(Qe`GmRp^4q>OWLog;U|`LslJ^+e_6L~YJQ=3eTSL`}Cu z)#pTA2qn27B{dPEABs{S<*!6Xi2`L&BW1c?)_r9GG-69daow`o(&Ez6l2-HL!cKYG zc@?~QW!`yJa8@N^RuvRhWoA}Ym41{ItJW$p&mpH52TPAV8q%Ir?62=_|#_bLSU z%6#{W-{9tc!!01f%`?C){)(ET@G6^rk=e9}95Bxuu<-Yu5|*Bcc@a-w6;WiBp1rR# zKEfEEqZwbo9iQhJUj%zE-Mni6>bt@xPk(kQxL z`5W~jn^CW>S+BfWugzVr*jBIUQLp-1ulv(cF2qqy%u#93QH$JBp~z9g#8KtYQ3u0O zKE+X8)lqrTQJdXSvB^=>#ZmRqQ5WG(F6K^6_D*T?PK*9dq3TY<=1%4EPKV%bIu3W4 zfp)b=9(R5kcbyS;wgz|A4tMbycQc2>?<=?yg*z;PD=mRLNbyCn=*C3moaJNfOTOYb zs|PD0arn;%YV98O!<7l0>qEySZW#iK3ewKeC}!}q6q>`#x-5ckv&k3cc^#IAc&pTkSu0U+3&6Viqq4dTX?Z%1K#s%KSvG&F}@5ZUu#w9r5NCHl+ihy%wz^Mb^5~lM=vh$3(^TeX_0;ls>v-6z0^VFmB@~8KanD-gE_lb%3 z1%~&rs`oj&_o<8bCBg?LQP9wLKY<>?Kng}#STaxinP5jkuOURHU@1a}A>`U%OG1w!B>P}`!OB?f zJt#M!&R9OwUl2mMavZ2oB0@ECJc++PcUwntzJM}Uk)-}yXDRJ6pV86%ikTl@l7TxU z^fD-IZsL#7#@D^_mN>XHQxZ=+SUqWwy`pM9MpO_+kI1PzgKOs zw)@#^(Q5T_KOuby#M?qFUICweZT6Bs!Sea#^iFOaUco$(GN|=nD{NK!(Hj2Vf?4B- zhe(v`fq#$_0;hGfg>kV(K)CwV<*(akv(Fkq|eww`}v8zoa1ee%-GKqbw({`r~N_*%|&I-O6zNrv({2h zR3hmzbQx9Ft}h;(t!$Z<@(oUk8Pwz=Y{&2U9k+x!GKZ9bP@MdN?0t=P{nN_*Sc_{> zY6sF_n^?P4$(1Je*14UEMye!C-9qYf-bxz(M~yk-f9Dpo08^v<{v-2o#kfPuIqYw$ zE9J_)EtNIWGUPeC76vDw$93p260m%ukp$P#WBYBQ zdzfuVtNw5r3vkY99LFPbEI0u%&+l9&LBd9}=dQG+*v{=ewm_A|dF=`IiZZ#T3<~uK ztA&%{`c`UI4P`4fHe)k4Dbx8Yapk5oEtF(}h*}ZrPHPcmndeTFCYrgOLyDN(p; zkFn7II3#wR+mv-GY_zn5DDikl*fka^u$rU?6fTO3GBzkUH?|-L*Ok|0SxW6d>y7A^ ztLOFQ;~caNW9-%F_gsfS`Hjk}tE~!Q(M43SM?y`9HU1_ROcre@9Gxw6?2(Y!vslmO ziMFH!yI|B3JrU)?**uG}!W~^ay|sHWjH>AV6tiJx<=KUKx&(5$k`2vH(M879Ur6H} zdiv8ueksj6H3;;F5e!pAnbg~_3Fd>6SzR8b2<$0loV*G1jv%tb$62SC5R)4to!vfd zY=lZuntRHjBuu&jyurackifrlfqxh?1`#pSFdl1`aH*Xh;t-pw_yLIM)g1N^HDdn#z2G%(hV{i~$kCi=S;uDP|Z z8Yr8YA$)j3yf)-D>Jb1r>ZjW4OtI=7-MyWA0532dHnJBFM3xaw&5pyOua5>LXXj+N~?5#+JK zb~C&6Yd9=mjTZjXvR%e@ui2Uu`_977E+lc1vw`-uSO0>APNVF+w8LN9mD2Kbl#C>7 zX_@_?f~{+XO;vLSjYbXb&SF@uPMSb1EZ$}S!xw$gvn;9;-Sh(wQj8HcXFKVDNA)pp z8_PR6h3p2FH0U<{+!?kDC0uzVy7M@C!&z(-deIiY10~>5ecw|~^%(6`tB>zXlxs_y zIGP^bH78Y^JG;8`kGC30lL)lt-ecQkE7iU&X~O16nfDV#LUNzV#kCi{8P+Z3(vWo`^;4YPjwa2279uJA`|82 z*L~gh+*mnb3bOj&iE60hzmUWXIS;;rG87XzMbZ>eWAa>4LHSa=Ba`{A`1^RPmh>2oC zd5CU8Da%sr!zfe!Q`k$z0mE?>_fm=IDQ^5vv=ImWIneuSen&&t(S!m8aA9`-gc1`* z2XY|)uMyuF4G7=omok+JeYhASM@58&5(zXAgc0m#B##ChR#!=T3}JM8Pdw#@Y+Ao1 zOJ8{!WCYukY4za&YD@e*-u%sQ$Wa=WxUB+A0`g(;jKG~+d%=G_te0Bg{8>(BPgAsg zvvz@QG|A8(XT#;i?sUnJO1wE#$?q>NiLE$(5NZ!%1Lrx-te|kc_{U)#!vttHYMLPS zK-~W}*)9bz~r;uoI(AsU)Oi zzv;2}w5t5iN=0QqMIy1?Tab!bbhWX<{CQZh`sE-@(CTZovV5b0;bB}HWx&s^jWisJ z6g>?EFRq1?^yXJw)z|JngGpg;>h|7GyoUn)D=3gikTDkkZN!x?W#Uj8Z_nmpzc-l= zz&OQ$WDA%o;*z3^YhtKFzURu)MRhF{LROCsY~9XS<)3h0NU4Q3F~nHbdUF*GJqayQ zWxS^%+ibo>o5y)f%5cpV>p&P!!*dIp7B_r}q#$dHwU_w?3Vd-@Nm&8_69XNYYl$0& zR8U1bs!E1#;i`m@o*%B=V`34PgZ3=J2DY?-q ztc<#}_6q}=uDrGFFgcFz)*5#n0S_yAIp?Z`M4R}e)~e7p2U*z9V?&3cbWuFBOd8Sk zJfFGpn1e@YX&iMZRK3rZ&gOf}#FLTrx8d7wZ*OB4pX&S+B&bNWUQ(6>pM%c#Z$oxU z+Z#IVHH)<_=a{d)iBWRMfr3|aF_jkw29INR5(0uaBq~G56p`mq9b0E=(d<1%dlTRL z`Sd=2rrv`xaY=q5f`xV8^gIh7PxNSUrZuf^zLq-IVt05~={j{h&Z{a{nfDXLsJNB$ zF2Z0Sdk+plFgmOswQe*Zf=+2wXwJ9q`TW&Z z`Ve*i`lO6#i(M+LWy-WmObZ&oBVYrOk5PG7D?DgW!ji{}wIUu}79!uGa_{1vY-(@_ zS8N#X9Bwx#v?`CjaR3*IKt2iAE!0c>oK{oPfHExTerENE_$3~<+TLCAVq`G+PP89(hDW{h`(Y~$Y0`M`g-y>3r@wO#1X9Unzh>Df*-|Gqkd8)clel0U>(Q1^ zTS{?2opeW8Bq7F`5G!BTszF=yGU6b}PHpL>s$3tj2dK4B;dmfM?0dQ%RFBCIxMm`# zbc~3?ht7dC@m>egwlh`jRCYZ%b{zW8LPr>@fNYbvOqwZ`Yt8QJA6n^sykIRJ9eN1V z*f~oF5TjKv8Um}537(py&RFMMQL5z5aZ79maq^|0$jZs3tf8a%^=)Ksl19lhq8eJ} zkqY`@eB@OTl3M&ZDwIO4-bBe%`xhsHV3-VsedPc8P>OW=BcxJ{F`3ZjjKJ#ux-Ef} zDgW;}!V2+qGo(__fs{E6Agtt*N|hvreUw7a-bC5d8z@D9{s_4gqbw+`Jhi42`Tu+P zf7*Q24Hc$p)?lS!#++iRr=b-aoux8`&>*b{M|Z$HU>MU+?PCbhhwsA;=7jx!4y5%l zg&4t);wE#dDN2=7dLz2zFVWS!`!$TtT4??(TzBa3u)YMaLR*CBpEJ;H1(&x5R>tV2 zcDj2zSU8-{>>uBmB;3v}vcHfq`#MiSVy9RuX6h}TW~kCxOVMd9Ewxr+@v7e_Z}vpP z>ttGMyIbAPEc6^N4BU@qEYjh(ehkzz>wx1kY1pEQ_%$k%G*01T1DP-r1OSRcUm&=i zF34Fy;%pE zMMV4EMNHTcJ^TB~N-4=0qM=Q zr(O(#R%kG0)#(-A=|kuPxBh@pGS3gFW;{3)YqRBHH2o zqItSxor;Wn6tgu*=ltIFo7G?1`hbTi2uEMKT|j>`Jyfpmqj_*MY4nFM`K9b zs`z13&jqX$NqZ68Zs@n3ckGCnp!;|yKH(O7!4`3qk zF|{9s@^u~lt+@dZ+ZJ+y1rw^ zMWonX(CF}qs?g{USt=`<3(Y~JoKe)|m8lx}rU{AR@?nna{;x-{%dCV7ov3Hpq4g zQtXG|9UDogv<>H&Liw6!Qt@YY!!kT-ufj7-d64X7(eXVI!sZ4qkEv04WvboLF7=dL z24fv`5!qdU@)XwVlOj{iWp}Y?7Xw7TNk}Tr0lb`o3rM0|g6CLvnXNxX)wC-*fsOupGNkH5SG63}B5#ar0GPkW^V@ll>byi_x&sy4M*a8BbIO zzn#(UM04)8BEPOyUHzZ|mTRq{gIo6rJg%q_>)!#Rz@2Sj;70~9UyauUiDe^}m6A2b zB5D_iY$Bd5;&jFQHBC+9xV`(@oq(itGRehcDjSD77F(B%@4iO=a;wAv)Ez7 z*k>z|tYVP`VIB16!eQyyKr5)M(&2RCN8yjvhKx+UhFeS5hsqLNr;`cUs-+9(nXZqc zq4m>Df~?c~$Ii{u>+pBe&11fJZiV75-m`o5&iT{b$(1IT`yHfL7e|M$EzEvmS=xz* zS|7ny<~H=2BR1nctZj60lMLOCE+0>srdf6Dm*YNU>FJY)hqd9$qq|Lqhb~dLb>jvf z96kwnlPWi#d%AaY&ls*z_;u{*mj~IVT}Uky%-KHlU6VJHwd}XDbuCuvS*F4^VQVPv zx_hz1f*+-CA7ov!H?p;bZ@Xvp!&tG&B7bX1Z-hT;c#?0UNi`ODUC&vF-9KW#E)k5? z2u2;Ld?*+C-g5b04`tL>H=PG>i}lNSV0Pyg^>F#jFAqMKo;TT5FAhFCZ|`ntn$iTk z`M$~_S^J9o=KWAVEJ@6V)IwcLxByavZ)6+#Cb5?^Y#j@Be9QmB6Z8EttexV95GN!9 z&0Ty?@1rNGpe4Pl>vqkqkTdm@_fyeDLhN1h<4~q6xoh^g>%iyiPFI+Z>}CBeGqYHw z_Mp1nbjI{+UioNt#+&f-J<~L*ipM5u|M6EAntK*HCrRytkLYj0#z^9@3ElLwR&xuA zggJoaC07(inl%opLdGDO4mTUs8Id_MwQY48ptNv?7|lFhRFK$;j2cM*2UNk2SiTfO zNnSYu50y>4P~|36tJ#-h1_Z)``rL0O{+Z>pKnXNd{qynj?bGDoGJE+xPb!Bt4*=Qp z>tPhC5R5{d&xg3jtKKyS$uyR@- z^*B-&;}HGL@T9|Q?aXp0TAS68Cl{J2T1NU-gs&r71~SL(RtCr+BF9kobWdzgsK23a z9e9TtG(^N@))79ScdIbxC)1Pi8>gb|wPu!@D(^AT z0!o=%!!8<%f#}x}rFT>Mn|ZK3l&~U}@8g0gVI&Z=YC(OSOOGK}QI^q4{7B8d zz?S;ByyVk<4=PjBRI=$McmtA!4-l!?b12aEwlo~U377L_51=&$$ z1HI5ZzI-<=Xw8!e%4*m5eF1Nfx34dbNye>q3AZ88kFmiN2j36H<@1>F>wdOno8Sww3po2uWBz~2zPlGu)e$nSQm);@X@6DeOjGR zTNM7Rz{7_%nJh>r9EJlP8a4 zx}2Jsu8D3?;8m(YF5VIRg3$J}Qn@u+<-8D)6Z=q|aCT~gsW``{$;9jO(iAJpALxr* zn@`m~wJhu*#|Ky<@^f5P^Os?_T-vasOrs{@SGJ##k?u_{tBw~xObHxcex?f_aQFZ8 zo8Rv~RBt%a%O5>}k9Lx1Q?RNC_yG z=1H%9U5`m!ZdI=8lhXFgw+rczj~X8=yK4dh0n(}dF7-cAq1pbE3jGh{orB|VGWp+( zcR?X(33b(f81MfZ-kswwmh}G(?+*AM@$Ss5f2aR1ygM7~7v7zj^*`|LjBNjgcW3+u z1pogB-ktrw3jO~X@6PdWY5c#yyZ=?s|Au$}Z&mvrWOpX^zX9(|oL@EaHQ2=|Nr2||5erhXKp;_KNYFT@mG!h7dM`h@gF%455s?O<2hLvM9r<7 zj2#$6t@NFYg^dkujg0@DPp%cOX&Jze7`XY4_PWFaYU?S^|Epi=Di_1z6(l06R8CcW zJm9nQ6kj~ozjtWtEQrpW{P@J3Gi7g+SpP#i!^!lYZ&OxI znvjV>P?|x;*1=leia|(#kcpm=K~|2?MBmEMm_bom-_i0*X=BV_sQZ*&0~DaWemBesT`xE?;p7Ia&U)F9s=n zM<;1pBXbjTV6_aa zJE#~tIGWqq5OOjo*gD%7IXRfy{fCH&nL)_GSl`L^KO=of1jMC{o%DtEo%9Jg0e?S) zfViBn=)WH9FF6w-=RZyAe^)RQa{kkD{C5QlA?H7?_1_f$Le9S(i9yEMTF}bY(2@}F zZ>9Mw`+rLFFQ;N-`f8B>k51*JxN5P=kLZQ4M^Jz12BHON}#>4(=Y^id-g@d3l7l{4~)j2uHK_JyD|UorYGvD}+u(`zXRmKhsrB z>=snrIx7MFpusXgwO6d*3bz6H97Gz}eHz9pOmp{XUYn!l^M6R1AT9p~p zzI5y|OA?Lq<;vMJ=>Q|_S=?L9v>nk??jIT07~$xK=DI8LVrjj;)&AJ^`wS=6Sp$Yq z03@XlpB3t(K=``2T`a=&^*;I4PF;L`v3bHE8~C3_M`X|MobmLxSga@NSJCTs#rUGiqey=5mdtBp zYFpjHF7vRYnGPRd)w)-*vW;VUTjjQV+sDQH@3g zLgSVNjjbmTEH=@CeQYK}5;_uCRCu%W8>wl*pvZdYqAlV>2@oT2bggH8gx#_maoC<@9uSQ-X7~(JnHx%?Og08|J?en`oFZPA!4#$BH{-8$lie z9|B2lO(bF%frg32g;caNyzhC6C*5j2LrN`C+!Mh(ujt^IY0E0=gi;&PJUGNOmV7{t znm&XNEs=Om^1zs8x)T=sfX@(fdO(qmeKxJ{TQmhsQLP=H6-x@P%W;xg8rD2`9U^$q zBzk!U2}qh&nWh20d-4uu#T8BHOxBwHeDGLMHhdxXvX-UN;PT{64j(kF8d`ePRy3_T z!3Pmu*5DK0e)EN%L#$B7T~ z0)kWVF&)<5PLdiX-sW4td6|ZUq zwA-W!Rkq--b*0IDclw(<7m9sxA;2F5vn*X*S3A$Lgs12*1lreHb6|8v8)KK18up1v=q#-$!J2 zWa}*NJhuf%%s^~*X;7~lCrz5X`?9QqNUnO6da}1TDN+{3jdE2eju=-oETvk%Z)mqS zHSO)IWsVwQXr?avTlylU3MP@t9}>$68!byac=g0|E#9(MVFB{Xu;Ry0z(53_RhJ16QTDeFv$|s0a#r`dQn$_@AQ(UK=09$O_V_6@OGu?FfNOrjw$a z={QHW!P@V8fkfYNu?}gCguEnEcKslgbIGKQrN~HvF0mc@wdwfqF*8g~QKvrUF8y(9 za4(FG^ca4)VeNN==-YEUa9PQ4zRt$fTX-v7bOl8f9u@UWrd&n-4wy*7L^0VK-dCfY zY~7>Ujk*U&WGR?|SS1C#eT!jJek!KXZ9xWB1!iYlBw+nElr^l5m+;5$$6_ef!8IcZ zZnI3eD}+ZxC=J1e9v}?MEY1q#5NH=?GW5%KCX}1MpMc&!eL~VG0nUtY~{qtlAIDy_gBTNs~j>|dTNql10%6W9eR(#_Av@P26{)wZF*dr(+G9^A) z08GqiO_m8=V*S?pst^U0(YdW01&4_U9NjT`T2ADgY8Fq}d#&FtPu9;#7hqlPrd&!# z$!Wzi#M3A*)BxNHOV5%)4btkx$s)r^wz}>fZ$;KD0D0zf zUrbId1(^KJRV6yR)`k<;S*j0x)h#e>LReH8O1`5s!OONo&AfRL8|?U385&hOR5y>n zP6m$Epp1+_m=;GypkL0!sE{GmjP%H9*5Y&l|1*&>nPPBJ-bLIf%T(ow^Wb{H7Sx!# zqqDQRxjD*^C}zmrgd!spwhAcH{>3k~l-qNSa7nxOF#Brmzs0_jKMrObOaz6JRx>EUz8IqU0+9Zn!*iYyRkD@Bxp{%f$ z)u|Md>slw)^dfD-kkL3=(22>|#Zuh5mblR;ob^VABlhu%M@~*nzhjv#N|11pAedA&akq9mOq#HGzKWva0y+7u?CeK8W$w)n zb!GmB<+L>y5nNFj#+c29--u{pqr1R-Vy4EMTwcXS`m}K{UWFqxlTv3 z13#e_&KtkB998QIy{Me2I)gMa$bI$#9xCcZKHpe&yqM!htK&Mgeky zs*+@9e>yC}Z5XrX2fbxmIhz<}4Y}w2*7PXZMq{E%A2qh{qB>Z>-GsQ=^qNed;9n>a zTN&t$w|$#mMUn7*CBB+nabI{9qGLwvvDIbul*jJ9fE%}E&K>w-eJCNkW;d!()2mb- z1d6RyJ6de}?ZF!C?0|V{vUNSy5?9HaQ+{2pbY_Cf{-qReXz}!UT%~iJk;4jhye-P; z6A$}1Wl-h7N$l0W_QcmBSSdq2?SVb;-6|pI^y}Lro?9|Hsd{_y(0p~J`|b~$!#*WL=o%dF`fDl?<>p4 zO2>r9`rk|6=0t$GU_s{KqvUCQ8W zgQ-6Sp+WAl41VcG(j8`d+q+S_Yspn6@rNPU8VL%cc}bf~?N-f9xAA0YG0NluK{1t_ zk50G2;>6EJTt9J17NJU@xU58NWHck%u(kyEx0wFmOVuLh$CfuFB-j#>yT63R79gK%T z*U>tz26#t=Pg$UFuj4Jh!Si55`CO(OPytn%vZ+X~C?|F^=1WC?M%b~6PgEFJVd;LH zK9y;Yq}lsp9EblPi4U@v8m2m_zv>`{fi5-M^)4cXP8Sd{fUbj^%n_7w zv*5W0jB-k{g4}YDKRzn$`*aT>DNbRt$nb5Wf^TY>q=jHc6Xz9lKVCg>t!GTY;`8Sd z;CZem0lloT6gb;R#LLvHxh()d%6gRgg(sP$*RuV3_?f;YEKu_FqVzlT=K{zEYJN?Z zvkGn7Lv)2>DI?a1suh#^JJm^0pGm6>Cd z#A!Z!0am(iAJ8dGI3e;Z_zTfGly z#u^#QE*0h`1}5EZu0TyhkN0b*L=58I?xbNB4O3|vd8i%rR-xR$Kam-AhNxZOc))l& zz8uJiUSY?eQ7>sLKGxmrfX>+R!-&k}czKY_P(9}HanOqoKH4Wef))02bj(&}E$28~ zY{l^hhV;$4cf;xCwto;z7QyAN&m}h;V-qwF_V0+OWGb(+o;Tqd`*upHL(q2e7wOCr zd;>Naz?N{L@1pQ~QQbI{tBbb#Hl0j&AdyqLJ;)xHbNhqQFpJ(to>7ucSnAs5@8|f- znC|Jjgud!}3KiK~$vq-|uW@v+8W}Z@tB}zee^uZ$94VjTSm2*BYP^xmCP(yTK`xVu z288YD)U%F&q`2hDgKwO_?=YjF@Ncam5_(r*fo`9v`ADjB`|QLHX;+GTV7dTzKrR?{ zcI4ISn-sC8PC~@67wtO@K;;ZGb4h7qbJ6q4wqrV)qDLAA9_>;y-{rfTNjv!dI&qop+xvV zJo~r4iAZ|;g4>a<9eabf%c3J5XilsaYQKZac7dFea0#j&U3mHKcx|n_jWjW(+|_ig zZ340jg(9hV5AEt-* z7Kz=f^3o-dp?oDxtxN5241yt}pUmH&Dg6pV4Q~JTxq+}rRG=+!e;0Ema*q-yiSSfA zn*rxDwoKsoFqHAmWcn5Ca++Yn=XUp$4e)^RdJ2zT7&rBSY6jsNX?E{2ocTFw6XqPE z!#hxOr9ZUR0exYRs5!s8SVy!yhk4S0CDQ@?TDratq>CeBwc6f<_4BuN^XcAuhyGso z{Q{EF$1s?J37=Ji%JOD`N{+Oz%lF_78=;MZ?qXE$_!CxGSye3R+pGHYQ%kV{4TPUM z;0!lzWQ}PsAd|Rs@uhnz^PA9Il&b~bjfh-dv_#bf134*zfV})+{H^8N$|Gnbef3?S z#;{Xhy)Dc+t=7fVJFY|F*!RLz9t#`$Dpv<`*y)F*jS}g33kN98om-@5It5I5_txw;`GY& zayIrV#AH-Qv$P`|rD`9vKZaUVM%2~e;YDY7 zvRm;^GLegxn2k)&zccj_g67cH?SEAsbF`OQb~DaQC;gZ}?4HNICRRekba&l!Mf_&L zfG*6$94H_g>CKkKgYe^H@!72vyzK1i+dBF<(m?Qgk8v|%RK2a z-YaW5htSvbN_{@sX6I&DpSxHk@I<}LNU$KM*b*3|YJ&}=wi)(o+Z2-nvtSXt}5zn4G8bA;tpvM>H*)ur_fx% zut1q?Vl!zlU4~4=%MJx z)Mfz+5Kk+IYGCw7;X_Go8~i!_;P)ZjOPmmz4r~#gbj#V^?PY~A8YdH7&gq0`Plgn& zIRC-U9BLGTn)7REz^GG*=aYAY#tt$Cre=Qu+C+C7F>UESb+aV|!9fZFJ~it#6e`18 zt7lU^gOQ!#WsE8gH8Mzp8T9~H&F}y@2DRpRceyUW>PkIodsXTS`Sjz0rr5wxr)6}( zjm?qI2=S-~hz-O#+z;@VIS}C8UVoJC*zRgSrV&kQ7LqO%5Z%$VZOrb@iY2LosG; zoHVJG=43^fG-*&}XJwLNxsR z`8Vd}=Y2162myY@nq5Sda#$?UryxSJ)pR0>K)YeN88V@$86%BySUA|o5`M%fx%|{4 zG-D1?h)e$HsY2|OhO^uTHSusv5rkj7ZOmli6riIDSyg@rMRp~!lp3N_5q%uUB>V*p z$V1zu!lo+`ckX5{GsxsVnY3A7G0_5%C4`V^SUjRy)G zkZVc z7!x^u#^b4%`cu;ig`7CTn5c9DLM`d^x0oBCB1xrSdV22a{ZV9Kgoq^ahes+jA`jFn zUB!S66)DFWHIN9>@{S*ztJYoQ3fqT`wSx-2?>a5uY7o>>WlPT{kpb2m@H`A2B8J6_ zQ*wf_oyGhf;xT6l3&$%(0AkC86X`SBbei&d6<})Z2k&BvY10A{1GrPm2ifE@#U(#F z%fk0tw6@lvc;-1W$4Grf5D(CnD+#+FF$EyH2DDT0n2pzR2~c!&ZT)$F>% zsJO|=#M1QM06Hk_?0O{NHEd+_>|J1@5r!BY)gYn*yIe5{uuj=ibZJ21=aP+4i@)_@ zPV11_#!K`i>{)uUyIGA;7`2D*x?AfeXwtZW!0-o__r71r(oes;j^&E1)WaL4xo+~Y zDyNWc9&jA^hZ(scjEAJ1Jp+V%;#K!F^hc$>mT@HW2Z<3anj7UQdhG>8Qb7pI;2Hr_ zBZyQN%UR~77GPjb!=xxilDZFLb3>ah`}MJ<(tfRiX*ujp!|*y#s0|5cVedCYWa?d8 z{sD_hI0tf+6?qJ5@G@~>T+z=e7H@=2`tEcU-a@*I_|oQb^MOm5#!L43kVJ_s7oEqD z$Et~qq%Y*6Fb0~3RS;|V^sqvUYsUix@xW(qM=C52S;B1qJN%^RI}IB|Z{mdQz7>(< zZa(sebN-+&019}|ta^^$czs)%%QD9#lxZ%}Xl zSfC{zy+55@asMb-^IGDpBGII8NNc(6qodE3HL6Q`qK=wb9{1P}UH`2*Tcq4H;eeG_ zq;qUTh%n#Nd$byD(~$=89^|4GFOsy5MR$Bc%@^7mx3of?d?8cw^g_9J`7ry2>O$AK zKD4V;ky5Q`;O$7*e!>lsC#qDJsb5k*J`=0a`fUH%t;@QUKCcnbd}G+bWzM_s2c26w z^q8(Kkw;l6Z}3|6bic(k{A4$W^vL$j?`3wR}=LH)cN zHm|^q<*T$6%{iR@=aqB(5V4DD%G~<3z@R* znN|~a_r~vaC*<8QT1k`_NlDiEizVf8V-^J{^K=H|^U{3CmxYmu?-IOAKbyMVMWN0X zXfm&Xp>&}0?HK@ zu(3ixQ@QzME{gqflIe@+gR|EwJo2@rVbhND{Y4CCI~m9=3c-I$DBC8yI@qMRIqfY( z&;1wR) zo+WoRhnO&RE$#LO@RP*XRX`o){-m*j+^O5OK~kf5-qF5RKB($nOeis#*hq`3ucJZ@ zUgV3SZ?vg;))8t(obP;4@$saM4#6h+yggZVKGK$NvHb2>ibLe{=TT$lbgLz|1DyrU zxs}y|b&facsro^ITATVxaa;e>+GFss)zg&DUX|0aWA}N54mj=Gl95k=j7bE1cksVJgz94lT%*M&IOwOAlH(j^dCi33cGaHP*>d zWe`*)!Jg`K0P}9)LWHr(J;cck2W7v_-W}^%Dcz0l8t1V9|d6i)TS7RH&IZ8ZuuK*j67p-^;ehGnm@?)D&tLU%fc~#@xjn4&b7^nFyUgqs_c$q4*i@LLL$q_(noGLkJ z2lJ9K4Kx<^CtTN5ni0SD4iBmMDb3JPK$?gdK1=t_%)nR6*!iWlS@DivR>j*VLk&q) zk)?kKs*c;nZ+Dsno{$q4W!y5%1mQ zs;T{M+1TIO7jK^e2Heu>9JQD*RwCJVU_+|oP4GLikj4L)k%cpyCxbsk|zLs`bC97;_3Mawec^_N5-k1uNxop^kV zDU_+E8e_HG2&o-)!VDY8+v=sxWinedsa0wEd6FX@f$=Is zB#lWrmKbM=vFqlavim0;$ayWxcPC;WmTBSW2sx2asPqEjOQam_X%l{Y%$=<>)?SZQ zsoac?AWF=z_!M6Jpwo8e+UdVk|A2PH7`_j`V(=!WTQ8=iLIkt%(&E!AS1-SL54^s6 z2df?0s%zSz+A`MmoO`XdQ6nDwgUp)#p@p>b?f{k1kSFewzgP?E;>}an zc_iIlbmTeJ&$ttPFS1Lf5r6{~%|O{{Ah5;kX1w{Jg_YW3=SKYEUHdo_jX6Ai6klit zR)=6UhS4A;3O6ZGwm`LL;+!aayRI*x7?I~ z0rSJ({ZZ~<5a)j2N8naqilgy-7bC*iJ8N4g-XF8_9N%JDKI@B#dgZLgh0o0*zf>A# zad=AXAuAZH<6Dxm#QyAX(RPK^@_e53)P*vw-y?v~DZN#@{oMH@C#0+LfDPA~jRi>B zrd^ueA_T^nUbRFYAB-*l2{KaK`%MGTUL8+_B{x;cFipxkwGJ8rj}yi5odqKYj8Ns; zatc{E3h61v-CVmN@i{O%s)`n4Q{vge1HzvrtkCW;U7D5%sCh%RS5K@q9zWx;Itwp! zV7O*Ts^IQz4^R*F zVkuf2EHJCG&9X(O+}YBQ=&1LE{e?z6NtCYna>8IWp#$<_(_{Y9`ZCfC*BGeOfVaRW zNqomfE=lJ9V{3b?%mZiaAq2i|CC33mpWEA?4Hi`dN9%6;Pd65We-l zbLdgC<``>TLf-hQLx$y%bI`JHl8hR<0t+)Jbybl_w|~gSNV2_~HFzKyoMR2{VQ*S4 zwg)^D>lP4XRXD#vylTR6JDDMMS2+8L?f%(NU0kN$lv+BjENSL*Ic1FTIem47jL*!=x_P#~Ru&TA?l-D=2xy*}1r+qRD$>rNfKZqH0iFVKN z2cjF7C71OOtg!N zUQT`n-<0O4U%MH1(+07UW5^LImH=u>^{ZB^51}BEW_BN|!`N$b#$eN2va%s!ak=~U ztT5n0(5y@t53e-#a2J9s$G$$3HiGf^&Ft$?B3zmKTo&HxF~SapoQwnTc+OqkRP6=D zIEs3FUbGSVkEvCCQ1dXnpxMX|XNmw0EEgMHMXO&-Qreq?R_$?j&FesvIROGuY`G>LajO79{ zH`U;@mdZQXwOAoe*&NFu>bfJ|sDt7wQBf22Xmqef+$B*FJt&A-!pre2=Mmu z=N!(~VI-Vu=rIPVcJKkhG|dL-`8${o^%Ei;YPeBW+dEDgQg-Q=%PSKWN#|B69Iv8S z>YeyFe&T2u1^D*d5xv;&2#3lmNzF6DpAt$&@=2upKm%k%P~psk;ZYNmK?OZxVuDGj zr|(xE4^3QFz{?JN$3kUoWxr)IxzHX%&~($(8>g+hdct}_*U+m(@s9k{c~H1yGSRuqc>#QRcivzI_KyU7b)l8Mb z=EcIYkz(AHE5)i^nhJf%5QMqy^3^tl3AZV16S?p0rzi+J1E2UIvQC>==5wc(`E z^&YHjWAo{O#b5+%%s>9jj99YTZy040atQEI&X#3sE&Z|VQlz@!@MB4Tm7);)x9SAB zfqcTbkcJD|yW+{(3=rxwPtTpEZy7a%|C`gTn?Tnl#&g@Ej79`DLc(TqcNDOgY;Njz z_uo`%H7)`UZnxyQL)_s57bmc3y)swxCzFU9002JPX4GLaqgcU4&0#m`*{7!tkoBd z7L5GP2?S_C_s*@2=sb0_hR?B@qVwGYX5;(^ zy}a3MpUZBxt{Tjg`YW_Myv~%!v=|V~O=*OgW(7B5zRSUFk;|6uXi30Di@2TxW+!ndOM<6kNBx(>$)1;B$KgLx8=w zq3{1Z5Mk45qf?O>Nqhi(-K1cwY2iWC_kYB{Sj{;AqylH*q*zJH23C3BVhl1n1|A$w z(!a|6?AM?qsTp}QYj%M}@K5^S9?-hO(Pz_b#G{Y>g!KbWzB5pt&D9|hx$YqHLXTv+ z5IUvUYsWFIY{T*+tFkmCFgrlCoK$HvdBR=OS||U0vqhsr-?hixrEgL#`^Jc)qQ0AN z-?%1*{)_dn4D5$=sI>}g4~;*&w7+`y>0B)s_F0845q~=-p2Gdq<|2U@8B#ohE!jp{bhMq<*D9HQ~D4+bB z^Yk*;!VQy+le*N{u+91Cc16&SeCE>}sY{3bjbKB1927-=hn_y~*(XX5T_%_@ST2ek zYfxwO<5Po557SDDnrVj>kJQc`;sH;hk5RlHbr1C<^Ug5)$0q2Z35%bf6cz%-+N#xi zZWpPSS!`N>$)qy|Xu!PBl@uZE^{*OyYW6om2b3TwDGnbg1o}JQ~_2gJU1 z8~JYSk;&P+Phn;j%f(e?W*fa%vQm%^zc=?9XC0+4+wSf%Huub5UW42e9_6Q49$*ucQ$O4@d$7B^bx$gb!q~sz~diPnmt$7(2QmY(BZXud&mJ(%g z#MUDjg-T-g=iZ@3D@#n-*)%|1^BrS+Orf26mw@avyqQpe54Jeas81n=`CSIN6g>_= zoEC>Wr0`l9aF$RO4OkWL&300l!Bww2QX{+_(?7UNPA(LKMfw_OmB zs>tGKQuW>~h=Or^vv>xYICjpRN4Tz%S!FD&1J$I?on*wNd(fUXU1U5w+z2HTzb9|y z)9GZ+!E@JI*_F9e#4kot&Kso;^!B=ys4 z5Kc!3lM?SH6Y`l6<2b|gb`=T%OG+rx!9Osp;TBsXe8_%6O$#>Wwmfa(nGe(e+-p>s0e#e1 zhO_<${v-&M1$3tv@5=Ll#h`ZXAdxFG!j`mK=<~&S04BKib4X`u~AZ(2_~6mdEs z%ydL|-FX)fQyT`0E0P)Rq=MBVqv!dDC`D;E!rBkQ%>YmlXTrBQBZ(|Wv}GpU-XZ_8k|91_R@=Cv^*n3egZT*SC{ zlk_Q7hvA8I`3#(oGZ?jJV6-P<^6NDS7M}byD%?*O>z7Z2$m^aUk+x>dQO8_lLPG;A zchrbc`S5dK6jl~PEsw3aI5)w@5z`0AR=9JweUUvt-_W-KmYhCtmU9Zh1QR|`_&WhP z`Z;h)aL>$$WAD7!91sFSeQWS%R>#;LVc!^r%jks``D@dHis)CYF{YSw*eN*c>YD6A zKMc$3HhOtJ=#;|N_Uq3d>}}xI&Gn(-RA$k!zh!Fbb_!mEIlzFba;EOe^>ktkiNY)=I2CdXX?an;>2kngBw- z9}9OoigQC_xBO|rr+kiEakWM<=c6>e2||3iQW6@7n1I;2n-k`#ra|L=_gRo^?s~!l z@7p!Wc}oD9!0QY33h!54ufK`?&;YgqE}?fY)!cW@%T!8TpKLPnAqLd3Z_q+g*@@JPYB~JEr2;UasqEr%P;SViihw9C}yeO?>BE? zb$=}Vq4P+#A783J&nJsO+9goVk`^3Le5Y^hFK;W%R&@N#P=0AQhE3%c&En(LXr(t& z)VqC+>j^E7fHI)yM6QL3AMS&fsv>RATW^ZoW2Tb#N^%RGKiE=x)1*%91Vgf{zN)?Z z{a}b*?F)F$(bwes+^p}|R_U-zbpkW)6<5fikp zt{HRja_}I!}DDklJ#@9K$)q7qsnmTpYe@$L5}pYgUPt;?3% zHObp!S2fm3_SDaG%R`z(vyy7jMSoeBVxhojy`t}u0f`lv1D{2P`^A~mkk!-t03Jvm zxVS8JdxB$#Zi%`I9__>EAt#G3(z`RwDR&EWr^7@dC2ZKaO4LR%E@FKBOXsb(Dt#w{ zyu0Zao;54&Ldtd<P3E4XiU^%gL0j7^t5zm_^~f>11+X#?-b+&vf2|{zv$SJ@M|P2u#v^D$U-X ze5N^G;+3f@|*Hi|5)tslM9Pfof2Sgc}6g_y3}B8~3&n!=nij1Uh!X6~B}h zi_Tgi{_8CuWUU+EwMs|_T8m+;y8zI!{JL1z7Cr|7$}P~CTrHlsbg8Do&Ko)vEdmxF!9t1MSt2_w=uDbb4Dwy(P1g##6rOv zCWg%@!clr^T%nZYM$S%DN)FEDIG)LncScyVVjL2M)cg#dR3>p0xGo$)F3}HXMTIkl zRMLkIdzJZ7NNfq%no%4btYX&|vM9wmkLA&7bf>%&Epo_@-boA||6g>SQ;;Z4w58j& zZQHhO+qP}nw%w;~+qP|6r|0}P;>NtpyjMO{W>)6fQG0z$E+X+-6N`Jp)!5GS6ZO*# z7obE8&WlRFG8VOJ-|^fgHl%wuP)anhjMcp#=x;S9W0~6Y83jE}aoFJQtS%%m z6%|{Lq!dxsmUB%xI8qDLXC91nfzz!Yo7c2))uV*<4DNg`WMU_?yGNP;Zs>pqpEI_i zVo9d;&W-rCRxxZYPiD7V^5@rNl zko?2Qb0xhlTJ=?yVZHGS}-8$oiJJQoYuBs@bAl{S#dc>xSM z&9h@r_Sgvm(07}FfyFH^{&9fbRLG3U{3$$Y`P zon%5u&w2l-6FRvrT?ODDhIDdU`+z`FCNfEPgKsW}ixRBzSR#XN?_$U;aYlv(aOi z1Z6(=HC(r^^{OUTAYdH@DJ9wzLX8ZcYc+L37aJazZp{E@-fK1YCi3Xrm=FsYD4=o& z1EjqU>%zKw0yRf2PxG7naM@7A4XL_c(X9Qs}2(LQCXlYC+pL&HVZf{?El&R>ock@ zmQeo4u%fH;5uwfrf>2$19pJF6DLO(>>}Mu+K(!o4T2@eJ&lD*=*f|) z3F}t!!y>F4CDoRo>$?YCVAOSm|#OP=|bq<^o~CM|(`b z-*XnD^eeRi{M=)4X>ys4QaCD00ncro!v)OsQ(vUHC^a zpH5|gRdJ&}{41Y5Iq+XN}c8j17i- zss9}mKY+6J!TRa9gdg#d<6`iXVKoANzMSo$-!23t?->p%uSnn(AO|3Y;mMI2ew z7g`G__{tH4hy;=)N`ytYk2H*UB%!eS%dfh!vZK1v!g^mC7rxZ{v*WFAUpG7T=kaiw zXFI#-qbo17&b;qchO(mol9(O@yUCbAE6+-mww5uxdr;sHp*6E!q}3BG^Um{=HXZ_`B7|}4cC-Z)bt$cR$qLD~39{fuyhH(3&D8^RC8(MvZFxi-(0{)~D-g&u9&ASvz;~XfKik&A%(^Ni%W>r^*Vp z<3_7Z=q4Pk?WUy9ykb+w{cC1vtA6rbUg=FsR5`oGEZdLpQFeMTqzX?^s(G()wIQQo z^b*H|^G4L~uBM|=;PYPNTi)}5d4?8wf^Bj(;8r#NGB#O!?s z?yLv&-ayHm45>JvUzi^2B<;@e2N8i18!u+~26=63{w+-^+G4C3lJHMrNGUWZEhkDl zMFBAA9jz}#0aJ6d7+Hs;h%c%hMshV?h|drlz5Ye8(hA!~@ujzL9^oc-E?e(~J(<$G z_+I|icQFEv=;_d-z)KPP4pw0973o5!-s|&fwBBoq`^K5A*9NG0&JNsi_JU)~TB1)o z3QQ8KOHi4WMgN(YLa%3bH!mon=NzVj0J)umF%;Buw;K95XlRInS+R{&4{UMsQ>q`y{#dYt89kST+0>hu zZm$$Sc4C*JWvVD#`V4HpaRZQ8bHPCCx&d=^B@d3(sY_4Y*|m=~{r z^MM_uDAaU&7fCHVC@%aDWg$TO!D?7y$M$B0DP0Ym5npWJYEp;dJ{L;p#<#;`CqUoG z>9k_|6%d@ikRHoPrM8v;Scqv8ySvYglz*K{_$pr8N?cXgeWEp@MU>`1E&>*vyc%%f zjwdO75OtO3Lk7Jt5%ns=V9|{wMIj=bOEF8zHa9(w&Tp(MUHodqQitn(%G{Pb0f_Nich8*wM$@>qi#r4yD9vGazqfNAN4 z#vcL&AeWn)3j|6)_-hEVnP?R0GDZpekSJ1&!vTas_!(@)tgi5R%lvRVkF=MsAUjRK z3b^9eV*%dYg){<1d4?1GJ{Uh2?%C;P&|P zwF3c&u6~4dA;6#3`crbCYLkC?Sd@oE^P)KmMEaQ9ZoalHvLG@~IR)-v;1(mQKOT#2 zY#{V}u?_}oPQw3AhYokWe%RO>PJOT3hSOVOW2o2w{TKN5bs2_l2){0rJsuBxmyd_^ zuupaT(0iyY?H}Ya9H$idEI58X8qAkD=1?zU{1lt}DM1Tcq-(r@)c{mR?2kfL0}1Il zN=sObNgR@T8sWJ4nYeF=EH|2M@h}|5b&8J$6lt&b29%{lum~L6SCmI$h*Lk}&0G7- zi?V#VUvw(c1>)(w4toKc!|K$kvaU>(zsGd3>eETg6#MpbfvmEKGS6b|XGf`{c~jwG zG@BEKa0>G?fYtn!fo8Rk23`>7d&rKtt#R6fO-b=vH841Pfm$SIPx)+(e^-L<5_4c{ovrM(PExu z2KE6h!ZS{;C@dtRN31M_HWcH1>}$EOCIGjw<~R9k_fVgujA&kryfg=*`{r}!UbN#c z0RE3J447*|^jluV7=K^89JOy(`byasqDO5{@)d9D7&~is zR{F~N?K4M3Szqo(L|Jzv0j&Aa*O!%#>2V+6!%Lmmdq;p-o5X@l5g|; zM3^t04%}KkvD)QN==J-!OyLG}j`rNj#Lp0B=0cd`afnSv=6WMs_7Wn zOV;S^#S`lT<$Ko#Eht{GY`RMl)r&0F86UGOx7F%F_2h*TtA9I@6W7S|)FE=yjGx*i zO1_LR2-mKxbfs!=>pjZ`Ll3r2GH+JCrByjFg!Ob^X})2)F6vt4H&W)U53e@9#r9uF zP_*)F@GdX1-!j0-*@ZZRe zR*)3h#}DGaH#Cl4HkY*iw5{`hLdSbYzTr}3oh>obCWnSg_uL)w?vH+=OifQApXEE< zA{|xQ+59#xK8Bl(Nclx98w1kTlnA5lpDGjqgif4CcBw%Z^AbHR$+_s2#s@Wuhd@a|l z+kNr^Xl_yPu{+2xVlR0ZE^KP(QYA9niUOY_uV?#8r`E&RbtPp8SIAN7k3~+}2IYzpm-%vYI+IS%Y^#(b;`!QX3rbhAK4nJ9N;p)r zTVm(l!>J&#g2Zlu*9Yg@1O>FiiVoe$QC;->Tt{s;{CfcqJfHbYz<})q2?rb#Bj+3J zN=(EG3<&psH)PH#8;=4-_cIM=gt7PR7-)m5^B~KTeSV~KK=@0^%l@5|bdklZ*Jf@Q z7l-6I|9v{7wenj%V|N?*``?k2aYk|#rrm3Be^c{v>^!ul!X@=&!S}v4r!XUjRU>)2 zt$c8`2<^n)-v)EMDgVT7Xw4I_L6l~#K;q9n~leVgqJ>a8k zFscj-VD9_Pl=Zj|)mH5IUIRTdd*#9HLJ{}g@0vN^m%AhEL?{$+42~62lzM(Av z8UE0+8#!($-Szg$dE4V!ya`sedrzIS^eCNB2XED}sSR;$cpp)wZe-&d!C7IKm@gb0 z5Yq_C6o>MV)hsm+F6L0_$&l2x@Q_d4mj1UJZDs#FgtZVX9A5YU!|o*DHQL_JkY_d% z50uPoZG0YWx(LlYmG50+Fon#9OE>)a&RI#hvsLdM+9iOWsY}pt zwIsZGAwpOjgyFrzQ5U&oL@u}nSr#|2_ta&37k|mCZppmtR7iFJXU=tQvvICx_=2OR zrX32{={;&I!BAQJI`e)u$w@(SORoa_=U-Z>9z``UAlN=z3MJ$Bo)F|C8_iKD=C4FA z^;8KKu(UfiUkS9t5-Uo7P! zii0*3CKaPsy_{jezVlxiEoCtv2JihF<}q5xw4?+ZP;4H^gsda>OACmO6HtDBUCbLh z@pm?4_~`I>c)B)r+)puorGtUgP@xXfYW(Y1)%8iUvflj8 z?4cu;Lmj4Xil%~QB7~`k(GMgbpV~CU-x;Sq32fqVYr&L6k}qal}dmnjFBXd>5nK&fx}fR0?{s{PF1hM$Oruuo zeFnXcFU6@+>PKf%ZcKgLesOAnVVa% z4eI0@zw~DIqle|MeOKiQ*p>#J+k!%F#SsmK!Ke`RSZpW2O}SG@zTq2G5$Ste>dR*? zIMk{cIBg*TOH5)spNCT(y}KVv4#*7|4zHQ6r0UWH8jt`jz;+|dT3Bt=YhCzK+|r@| z4GOPjre3tR0MfXJW;W7ozs0b?kVTD~gHC_U5^O;465 zS(W~mr#2ba&0j(FtYl z_fkc^KsPMv!jX16b4b~QWbpgGjR_uCKpbY3tB0vm1Jb%!)G~0{-~FN!z1GxD4$Il# z1t@1aEj};3zNafb1(3>;T!-Yc9Xx#8!tjbyhHggAmFtp+ZHYq1G!1l-^~~rkAUlg{ z=929s8)zo|WjShEBz<(bB;yXLw)C+5JxJ!%+v*H$qGgPHy6wZH>yH2l)jwt9rTv)3 zOxe5`vaq7C+6LhU0bc~RCxCrdlIx&U*X_CMnhPFqQb z(ZP2e(Chciq-w4S-XF4Vi(DC@2eoIG61lQ?LW1I3p$qy8K?+U&HQ`IuE6Nf#J$&KI z{Tp$LkE1Qf?@GwN>afL^frhl3Svf{d-D$$wM7gyhDY9iTPI=E^%hhc+zkN%t`Tp&~5(A8!rzed{M1t zc6$kG(2;z5R_~vzGmTJf04z1S>T`qcd7;}Ft}UJLs06>Gpch9 zS>-i;m7;0nTfMd`-@@kaq0L$zF+|l4&>E6{?KX%9y_8bJEm>T@OMhn@ym%z__(;)h zszdeQHC@%qZP(=<>0_-`yZkC!IMn2c#G7o)j~k*+!Lacf2V0VBP&?Gruk_mx>sA!_ zofgUJSnZQk16QuFN0t;E?3Tv)J|Wc)zg}(IK-cqk#YdSE4!)uh-neBzR?Dkz48)Qs zVYZ8vb|At0>qdD&rg}R5wA(UjFw!Bk$)3<7G|s8Ij{xyUr`#6UY5Jf%YUXT@%9;vF z##LiVgB5~H$LVp+aux?@r%Tsq3;Jkv@NI|}j?u2GI+FWJ{;R+A7X~@TP)9>>jxCSM z8euc4%xF#xC5H3VsIj07t6 zDtq0TE$$jj)3FPSZO#ci?Mz>vBQMBZ+`~b@EoaW(i2tUC8ST*W$Pb$XMvX$z78bOxcR``(IiS6V z9oNVe`==thC%nXDV}{l) zu6U2b^bk13JZarE9m+VCP!xsN(>0SYlsjPHf%tO2KvZL+HG#hFN*tiLVP#;}c$lYa zc__=>akNR1Z;$J!T6(NaJZjZ;W0Kcxrwa0%)#|ZH$DFi5r4&2U0{&$%w1YY5jfF%Z zUJ$k?<2B)YyBBbE)*<~lk<8mjkHw$bh!hbapki|Pb)`<@LGnh6FTX(D;LDkKv&1p` z2$|98L_X{LD|`1z?rT)-r!CwxDN*m=>-184u#p%Nkc6$W??*lp8Z<>lkyRhH8G2YD z7m@bU&Cnt*oAtL+a?00g@i9Ck5)!Q~+X`9mq6RH@v*)`SjKjhr!mEQZyy|X3>srj; zZ6>20E2Wq0b9iTdyTSa)54P?zYk3y{;MhY6!>EmuYs1Yf6g zFo*XnyHUPR=+&i!6<#>8$BF}>l$Fx%XL3e5nk_Gm`;e+o4q1KkdV0j?2m-gvXI8Zn zn799CVkUy`Ur6Pl%l;+=6VkO<$umrgje$xiLAkZmKJuAZh?W3L{Bx{^j<@}=)Ayvh zI{>;NOKW;Jvz3?dUW8v)I3ZO7T6>~CZUxAUM$CpP{gtc;0Vj}d4m;6=pkB^x$3!~L z61M)tK|0m7@xu6uC$yj4zvxu_XWq)lut88T01Z5 z*{ccp&0Vds-SgQ8?+X`}d{3PNy<7^*8)7;DNcot?K;qPBlst}3@Ak(60!TRCl2g}6 zCbq(8DH-xwd#0jCvtO6+RX@2!m?D#-#HP2+25HWHYkUhAGL%*>ME}Y>o$^JScGhmG zvoQJTx@?TOt5OHy>fL{r2P9VQ4>p%jBl*Y!Xp5*oTJ#KT!rh$e;GWYL1xfQhRW+3k zoBiZPP-Pr|vIyKw1Xt3L%c7gQAdFYZ=RZA)OX+0CnusYW3KtZ8hl#T>?>bx_h?ROE z8L@h-rV{}X#6m^k!{;HsiC}Z&v|kPwvRvGuPmVfsrjOywc0+S?!6CqcwX2*v0eGZZ87%@!6b;JGLZ9Gs z*0dA&3!B~6@gmU49ZRS<)P{gXE5z#Pg5ws6FbWKI!6gS#Ug6cfq@oCXt{78k{fPtD z`vsA-07#NQA}vMBCS%nDvZd+coiJ7Qas7D`%8REkAy~hKf_dNFzM+s1X>l3V>e+lP zk2Pq-7WFz*`av%#5D!1}%Sxj? zUWq35Ku~aM6kS4It!yp49k^IfV03Dehl8$eu>7QeAAvWXa}oESizG~JC(TLHGd4w9glZNVwZi}^BN>y z96n_v4{r0|-%|yiJPK99X6mG;3&BS8*zofMPZot7LlJk`J%Jui=Yj*xqu@x>M|JmS zRel=SA!;9Y*KYDGG<6U9!~L2DW&0XF?&J_w=Z5dI;+D!^M=k@FjenE6FoUmI3O=8C zN8qcMp8qVnQWE+Br~nEgD*5Iwfsy#&q$VKr$2eH?5^{P~pm{c~H!<^LK-^%`LB)w7 zRrJ-55~-7eVAV(zs1Tn4=vp1gaz}el6lNKE7&}F+j(5bGWII;p=T0l58=%0dy5S9| zu&U1S1nspz#!CXCdfS=Z|WMPFzNLc<8G-_-QVQxgYp~Kc=|D$L$ zS^yQ2BlH)yZ>=?Z{}VNEn=(c`#7UCW==fOqF5Ylzn;sk%(nXG~){J?EjP=%HBv_iV zU~fk9MYIZy4z?jhj?KHOG5hXEo%Y&#zLll>NHGy5)tNZy1{I|Mczrf; ztIb{pmn`&Ie+R_9H`Ffuiop2jYEe&hnth(T{m#P4%5ADLl_AyA)~5=xf?=ScvJ49y z!CJ_V1^Cq0lY$S@Otd4~gBIsYk4C|n;oITduU0PoSF4+89r2?6rZqNS+XgBMikhM$ zpoRh}YND73plH4SCWkDN*)EEHC%NbKdc1kxa!$ww02`I{k635op=ZzFA2?5l?jf<# zso9|JKd~oTnE-ixc~~zrD}YDA<5hY*ce}DEt8iBAM_rp)QkK1d%tXyd&|D% z1z;x|4^>}M&zY8~SMu2MG4wn-+1{IZgl-_j?K#$8gae$ulw|t%clSPZ@7-5@nj-^4 zDVIS3vv;@}RF-RhkaUN6%hVSPo=N^2pOcssrp{t1(iynQ^f7tA>1}v+NnLGOrp{rR zy8dTK;%%H>Mre$=bB&qK@T`RpL(e@Uj9YElEza2Mgiil3epo=3$@}+QUyFG#wEV5q z69j|bcZaSIM;7m6t-kcO_UCS2Ao?;tlPzHLU^;j>zh1^gB_+v>veh{ z_T!dc$4Z&+^cct;?6p#^SOn+j_%6SFVXnZzQvfJ6P(s_m4{c}?=2tS^`& zI;P>!a9Is9ty|7AUi1LNNPe1b(lVixtw=23S5i zM`?!dsAMhdFi#c}m(`tUTbzknUNvJ;YF>8^bHnJoG`eCU^&=$Hh5`1DT@Hqhc6?+! zHZFmzZBma~=M)L2)UHxzJ)UlM3f51LpwX*rAAvqK3GYMoFv1in*If*G>*}bY9)TcH zXVvV$L){eyaIA`c;F{Wdmhi{P0h>o&t&v+t#azK zxU)g)V>r{Jt$Lrnjo96yqvp;h+X}8kHJSOSOQpMfR`4xF2evE&eW`j7cHSAC=RCUw zc$Wr8+hS_)sJRUdeQh^I01yeD8gVES@L`RefqKNS^St zSdn(%rI|h(r&rTO7h$ifS~MfrO^c)PRJJP9Z=Yl|vpFmTA`MaaX^aqVNc(bAr)? z@HLk2`(b#7KbiX8gYa8Q4`mGuWHZ*4Fq?-Ax0?c6DU&7o{#@WAuuez)j1kx-$jbI3 zF_3Wq>3?*HfiaU$YIL=aujiyq=b_jFowTbUonz_U4=lWe58t80YY#raz?KG!Q>?YU zHzeb%KR>#*kU^bd2pO zZ=%4o(=^Mk$t~VwZjpGRjh6$m&sb|25DIx$#Q5*nc*DW z@l}m0j(C4j!Ty8@XMc17A@|rD%ADQum`}_;sk2bpve7bnlZLYh+hVg)#HFvDfJ`>W zSA6cxeGPUA9YA_cboxufi%!8h;tD(cYhAlzU3`h@_70Y9McI%Rw>!SGvcz4+_=fn; zDFKD9qN~P}`R{>B&(=q(?={AkN5ZgZn9fb{MAS)*tDh-8cbREO58>+q^n>{7D3x^! zqjCiFd`+n_tqq((*gZL|QE-2oyP-;B@do=I1P{Wxz&8ai{p2zs_J`JGA?tRB<1s(o z#GF3a#|CUO@^6Di@)fMS5UOkzW=q~$W%TS(EctRHLGX3-6=FGy=)JP=e`iV;1o-Rd zZh|>WnI@p!v7$f)o=t>Gg5-tJUGD~@oy zB_^zy@$Oil(T@22%n4ssnxb>?4e@w&pWzL$AZ$#N7>;vy)<%Mj`znN$LKLT(b3sB6 zV|k=Pzm4o)qko^@>6P3Q5dMtHXLe5>FexfWEqhK4BL;$IbFuzXUO{$lJNnH8Km*;= zd#7m();fk^!%DdOXvVa=x8pE|B>TrdSdy*d1jbkuWHF5BpD|Eel<91lN;7yfWz!rG z92A1Gz~5KgteiW#Yu99b_6}xHoY$zD-Q%vSfG5G#5-2DdCssN}pe+#D=`gz)(54Gf z`o=eQId_*ou@-NmXp*Bw7n+vT=s(}> zA81phoE52Njx;NE`sk%j?)+gZo$@24W3NsHtZ2&d7jMo?$auF)m==#-`r?+=%#|yN zZTU)PuRhd1vF}1k$~CxQyq}m}cckj;cPd#dO4$|}R!~b0WY6^!Q<5qw=Jv`b)&5>m zYz;_CpvHMhAZcNXO4^0I_q|=(wq$1Nx#{KcwL{=v?}Ez7@jnf8g-gZe(+2VBi`fkB zzVq(|tzE$QbLY87naC7Ql)7-Bx|SW268jyWij3Zh?@4*jiN( zK&YM=HF*X{pLtudSniBG+^V0|7Hd8~GiRGGQ)h#rZq$_?Y*=e3W<6BM)?GNTd!-@K zl{)pttv2!aR!gRCohrTb;l(0XiiIuVoUWFhe@HgbN1gzJ|7~=qPvsf|7X7LCAboH{ zVzx!?5bI{No0oOP(7H84@f%GF2A|N1ft?GT%d(`SgTjTYNFze0$cxaS@$rQ0TWLS< zssB&@%D(f{wZE%g;>u}Vmua66S@TP{H}frseZ}bqU6L0ghyXj45agr%P1eh`t)v!w zZwrX9OfV59Cu~MYD63ctl2VNag+Bl7W6qWZj6LMkerdW z#wrLC?d0^}_EIhF>O$)Nc`Mt-Avucr#*kg?(W2?|5VuF6qg>)2Pr&i^ZbvjwPDYm= zh2H+@VMpW_ebwAYde1b-&qYB7@VU2}!P|R`%CVzN9g#Lywam}cTM*9fKFh2urMasI z^`*cxGB8A{#=I4xJ)lpx9ErT3Yd&UWolo9T-EQfptsm0?nuq{~R&+dpW* zx;YNW{6yFe=37pY(kcqY;FGUV2=oGG4B{7-y~X3T`tyS!^r!faKmY`GB9tiK{ksXX z%W4$iXIiv~PX5{B;MVi5q)@vOoW78AwC;7IFnRvrMcjcyRQZW6(vIF;xT5$pSts4T zQpbF~g|g3Gp*r-!W6CtBdR3^}&9HhmbYHgH{_;jrlo zr3C1%=x-2|i_g|r_{DwT^Xq20N&roO4MGV}yv_Me_Sgvr*I0uiFhn-zVjtppX~?5D ziNf!Q($Ntl)0;fdl58Om%hPgJK-OpkerqB?l1Bq)xVfELJdz*ObzZe%<}$J{qFozd z2cjTa02UQ)_ z0o((XtImS1-^ph`!#!4y;5jiQ<^Hp%>Xqk)PZVFfibZSL%DXH2NprJxcFp$yJe70A z1O{)SSe-xa#j((AZPvl!6COJ+U9hxj4A=Bsu?9mQ469UcX|<}(O|2G>BS1ML-taI=L+u$P6@!7KKhO;3wlv`S&YX$>c!|NdKyYbq)v(uZiMR4h370F)G zQ&tbVqWvlkmFnQ!@ZA03phwlV61jalmKI%4>wL_v##@iQ#j|1IJFwgr&8_t+Lg4AZ;%-o$d@AC`i)vpJk_ka;LVf$`UHaU${dmq$ir87+S0pIq+yC zm-#{rpCoj~Fu2@n#qcF2=uR0xGUn`G)w%li(30%kd2z{poxUnta`3b&bkr=KiCjq@ zfLM<`%Z(0fiG=A%WCu-*t84xn7@f`pqhPIf$bO0SgFDogR!!aNfcA@ArF7%s)$z-z z3O8*Mrm#fjl!o?z1HxZGpvc>qy=3FtduWH+*FuY2yewnq_6mgw3~S&q@i9*+?iS;_ z4BoR>axXyi zs*#)3sz>2yd9u5_*kFp;6C$?S5VGg8DqVenMBhA$8*qo((*(;#<-6Y@P=O)sw=p#( z$q(X+SlQ2i51rS9sj+%v)4b(Wq%WRGT_&7q7}BZFXc;^bRM~3`WD;#g(=>spJ&U5^ zH+Y%&dUy-fsMzmvfzGMQnyY*^A%vcz_XKl{F^AjMBWL6*=KjszFB#j* zP$*%RDEAk=3mBWEXAG)fELzB!uFnm5+!_6CkNL_~`E zmCNun#LEI7x=)2!q^e%1e9ul9X^Bdx1~T8vi#qh~ji@_TR7$15j9YK=qGloDoVI-7 z4@fc_D^mrUMO9V|1qMijYsa-BL=QWE5ub3gEW`nLq636=fsRVQh3(RLUl7CE1xCxQ zF9yADu2!*W5Lv`FuNrhA=u!6ipPJpaCQaA0862yIpe$88?lstR$GXm~6ZV-L38Z@R z*J|w;AralguC`}Lj2Q$DpC`9minx&8S{H@t{SNX%ul)>ySEuy-F%c)ZsvAW zZN#;;az@^=b4e-|Z-;Q9{3n6JpxsatTb07mV9H`T)q^&VO0BAu#Cq?;e^ZAl!gfn` z;!_FJ+%|L8tQ$z)&gnJWb#I;dlj$=Of!E4rtvX1mos_PQ`9zEpK7g%=9-gI%4fy`X ziCCvnT;p^T|K;!ByS!rZ&=(`2+tJ1b8rGU_t}vAJOto9&qxG-*KrHMlUP!W}e%d+v zbh7M*5JbY?Syo#RGhRzC+!k4S3=3##3XUS*&vS+j)aJM$=Lo`;qrs$)uX5E48K#C) zbw#R`Rxn6L+F9=?H_WWlnwMIQhPGi9;4MY=Ms1}O$di) zU^N-W%G#l}KWvVcz5D@c6{}DyRa}b?a;U(So_Dd)FF0$OWk7&ccnSihfd~S5DEW~YH-)5j)bn&WcM|SB zZ&dJKuF!pTY`u1#Ic34Sa=Y%r zotYp{kA7k4*zgdyZJE5HEpTI059Kgyo)J~t3*wAd3Wd@)?2z;z@h6CA=P{rb!!q2r zIs`r)Nn`S-D^7RH@_wzt@GIF5*P8w_Ip!vo?@n<~w|R)SXuR*t_{=s%WQ^B8Op&Aj z#`n&BZ4k06afFn;eh*O?bZZv}-p5dV0kr|XBeb*7n)q!0ybMEY5MczV9#s#ym zCAuVF^CnH$e*;poB-t&(JtamvbRSb-7Z<8o{Wr{jGoj~a?fL~7<7DEi18u&CPSB1X zAv6Q1-P$sa1HY1{!_o7$zAJJb1k8WBi7=#V?7^qXhmd;F77HGd zc+^Npx0ye2!SQ;+W(9$<(U}OsFHu@k9ynY-lh3SsJd+_ME5kb@u2qBH7coJ7n`sL(0$akeQb5V6?ks6vP!i ztH4THm(A8(YH+fdzKLtE%MBGI=M&pyGuxvCaJ$#_DggdkU;VBt-U=Tg1xBFL1M6aO#v@ZoPi0MOM@{ELixi!<)^AQMf$kok zGc+}%1KL1Vw< zHHnC=s6EZ{!690*df8Du$@zcsZWq&pbWwmLxUrAHlk`%feJdOPgRt1DX2f5Tq722y zG$UO{Z8I!h4rtXG?2Jn3lhic2-d`7d||=f(hoIX!9a zpiAA_^Wi~PZLu_tk{uC3?oh0TMUVzmg$hfFXhbU;eZ&*JN~1k}&-{iM_n9!Ful&;E z1piik_hPt+6obGr>zaw}rc^Lu9-)o;RrSs#4zJdhDmC`NWD;+6o@0a z3we;RLAZ)*@oJGi7{)<;QPzrG42PKIE};A6q$?QF72caUR@lRa`E!GFnvY>tnOJ%B zQYKp(DnKm1$q{NgsUOkp8`?Rta9PaHPT@!d86rPfCn=q_D1g4O(edjspxZITiH*;E z*4<)Lwe9rga#8*@%Vc?8X6`rj7yi!eatx5wrf}qh@&V^an;RIi#z0=M!R0eeM|f@| z@NN{I&bn4;AmphsW0xlioiefSHgPgO=Al&Ul6r2HUv|FiBKx}{bu4Aff`iRvJ7=DCSTw{z3fuD86Wev zM4VtpQ>**Yc$f~r%=~80<#ZOtlLo*PC$5!;p9M?A2z)dcj}CfLVfIFjLR8LqE)lef zi6)m4PvB>96GZKvMW|Bb^`*9pnLDNJ65wwm=<*)>$>&cp5X2Hws#R0`X>IL(LSD2q zbOyibSOkh7LzZbO?zHsRV%^ls#=n9-0`5K}ld#)EI|*NpPVrR(b+?@z5FN{sI~0=wO3Hn#|zCXgQxLh6D$0Ad~(#bP$!SOkBB z#y+S0@Oo9owQ|CywJSImj`ynDvee>EeV&juS}3{YTOjOg}pC%VXXhcVLY< z*9Pn?w$?Q!a-)J#UExa=hjhYH6UQJ( zbQC+33FK&BH~c1HYl+m4h_v(`4Urwr`va=+jDD-YY%%1*s{IT+O%`RrnHam;TN06U zQ`w(BNB9v8@PI7WBNj3Tj%4>>F!VR`wSTST#`1_j-JhL#o#6SM~@VpLi58xf08OqTPT#KVz(P*SO>MSLXhN- ztV=t_vmyW=^gjtvqGsLS$0<@6Pz(7fbF$k0OheknQa&wrf|!0&cr3E|Aof95OI9?b z;Kv$>-`iq(8~ z?%UPicqT`da*aVW5N8`lIc&wTAPe59=aL&(VYD)7kAkq*{n{;;MC)}5*rFs?3Ezw% zNnMv}fNA=w{TB9gZy~J(aeQkAL4=Sb2+=PBL5hN?fM`acC@$!h`22olCnH34UhRHu z`+LlXESb%6-w8aWk)kB~EEhUrW^TkWZS}wG(lM2XF_W2bnJ)ik|<#2;>a!D1#HW^l`#BrN>W`rHMg3 zLosBlfRGaExf>;iroKnZaC+(CMr($gOoFwnyU@S*-j&B)7Nc=fiEtq#R!?e`|Ex)r z9%|XC)>isxc9QTXF|J{=&@`!?BiJ2R)~}fM09NN+fi{}nD=EbcG>UB;@<*JsSqJz}<%+VkCrWcFL(gv5ew;JALEZXyoPN4Mbd?BJbasNOg_EYF5q*VO zx{)|~b=t$&9TA$PM=rjiE`sCAb7lLa?C0f&|y#vNMq6y7u1t-FJV_ ze%Src(^miL>Z(gPB{BLuiJd*QE1U?7hEzZrjp_yqJs0aK&63W2V$2+VEaV&Z4v=JW0X!35PGi>|XL=&#(+komqq9gfY#k0+DNgTO+bB1y zH;?%xW9q;S_qbnNs}2&rV{uWw9OBcocq0+?;pSw)V)Ce#N`P;XMOWn2kj)Ejtg2F! zk>o}1on|t}5>eF}gMnsswQo^bt%X(egmdkt4{9KKr%sZEMre9P_An${MYYB%I#3!+6kMNP=4H+Ue z{h4zUsfkPSpKws@A|9K%1=@IJ*f1Ja+`}}yN)_&%!6dqKzHFbLUG6U-94FSO3)(Rk zr|^gGcFl53s@d`!Je=PX@Dl3|GQz5K~o!Zl_+ zF@TCy3&6w<}ah=|mdFWWmh%5Y{;#Q|dmm@@~9} zo!-vWny4zaldXPko3V*gVTH-uqR=5sIh9f~ZXyqH)Ig}ugHXn2xaB7WV&n6b)RXA& zopDv%R(6^Xa!#<~O#9Lsl%U7H*_OzbK62t@y&i$*MLlM~+Iv;3DZ|p+hx+lth^+)D zMu7f2GSLiX^gS+w76+mr-h0srWwFu5GC3(f*R73_wF=3}v*s%X@zTqxV#%hHDb35b z7{F;Y*NWi;qoCE+1x9t`*H`sE&xLC|j$lMkU|Z$t(GcUNKEJu-wqF@jtM*EthAX+8 z+a&b7o|@u-GM*T-G}DcgQSVqRzF(RbVJ`I(7ZIr-x)3+;chSArT%Kiu;$#Uhs}I=i zQLeyZa*Kpw8dhd?c+k~h2ddc1MtN(tTs16@VjG z2hSPn8s94FO6AajUK8c6E;|0D_wH(cSvrwMp+c!$zT5y^9seZ0qHLY`u0y+7{ zhYxyk`prV`-ul#I6hFYc^jJp=5j;3WL(Nt+cF`X=yfH9STp%f~qk7)S9!Yw;HaY8+ z1A38bU_iwoPkP3Z)d%Hqfe`UIABal6=YAw9`Q^Wz zI_y_z=&9N?c%n}tCL>~)&wmZvd;3xNYmp_&n>ac>yX%m3%}PQ;eE%-9 zsilh8PZ{BoY1$E+g6O5OSc(>!hFRGoUc%`j*t!j5)tp8F%7^k1lrw$PR{`bUd(EJf zIJP%NM?x3u0%j*pze$oGeRR00DasRJFwG(5{p>2wmfMcmwA=A>&kkd>K~{%feHSNw zLtB!IIxZB^oWYfkW;VXMzurOy?PQ z?Di{Vr)&C8HStineK$K-(j=YVIJFS0^D#Q9$r*RZf=w)zxf1RZrxv3`<%g*HtVr!d z3H)WN(+3&l72nbLJmZYZ^&Ynwf;nf(7phRgwa6=l9P-#{-qANe~ktJmVMl=bOJOkxGsrwc#L%Ht(pY1|3dO~eT2M~i|UfF(*1paphpy-kB_|0&d= zc~y%Vpp)iv_YM+PFH~8tU-YF;f5kHYoXEoBeY5YHF7rE7p%1ybsez0GZ`_V-a;NPS z+-NHsMKIqVH`EfQ{4kU;Zl_UO=}x!$f#H7S9m2tRV2TO)J4Ed!QV=|V3pmkEQX4wh z3z3HM{=+opvfLhi>X~(})k{lsK-~+}<$hd=Ewg$cAh8c?xYu#7Cl3;fM{d+vDE$;c zk8Smnn6@r+sWg}UB~*Cc>rX@N29MNo~Kl8QPU+D_5X{3}yiG1e$>_e&IU(LdS;oW59g+4}Qf2~VqLx?x( zq_Z;)eG>I+BZ}>v*0VH95d>dhmu!%J6CGr z{$3xgCO8M5Uz1WzMa(Z@XZ%X`L5c+ZdtFuNO1_F9fuO{o{_A8V@PKgcHMa}QHe2lN zwKO0@~e=TLNTN0P86Zn#e5?V#2Q;^4niKA!Cl8u&TKA;`tn&CW&~kE z&b5J57RNt-zt;{dzu}oM^LlH@*?u2GKC(5x$2b#IPaz{vL@exdp_?c)F>0 z|D%3sW4`nLgW6h>px4{^pXGz4R56jY5f=<6a(==0Usm$b)SXl%1);T<^m3m&excks zV%D5lJpL$Bm2Ts^ZI2Tcs1PlSz@AZt!Hzr4Af<21q)f|o`|$FR7Lo0&VM}N$2ALq& z=CJVqH`r=5YO5?L%F%0uhv%H>SE(^RtvJ`$n*yKWTX?4hSqn1?4!cw-Eu&Mbv?(&P z-RA=;^0)3?@$~V*82Z{D#T@7<5z}A}lCjVScUE)=nTkQ^TcWe>4u}Uiy$UD21hdc*hFb*Qr3MXk~$KoP7vsYnQn_$t7=$CVAXDXV7~b)dkT~kY;)N}mZ*|XP z|FD1+<;k68Ppc-079fLE*cRu2SJ8)^UPa9v2*rB6f0GX3mTP1Ldgwq6b&<0>m?iX} zmLKr4=hpg~9*sSj$$mf~i<4n-23BV-I>=m~Ls>nQQB0HF2$v`!BCSN@{-k6?Oe4Ao zbXn3vkpg1K891YZ7ar-}JCGP;AMzywme=1f=u@Aa^QjCrv?kV+gCXuH_6AdUBEE+_ z#RHCn1rnDMBrfOFw8Z(_qs5a^+cv5*dG|F5CPGl``&rB$q#qlSwir*x19=M}yLX~A ze}E`c>0n&z9r?mL7$%RmAC8r`L%dJm`OM|ygNj+ow{gIIIMYfk&7os^q*V@T6FWll zu^*$4rs5e*tY-P%9W#)2=^#|c@232nS^)fOzh({j7*oj=$|8p5Hr57hUfWkLJ;XTX znT?&OfCF)ug+&Vq9GP3YkHL*vl`_$x&NmCZ%`b>oC0(G%%MW!rsBlMfaHi}O;7-#S zdcW@S#5Y)3O$c0Fx$Q&#*kKGwilprxbS1vMEeTGLukC2Y-Z`^?X029-6cCQ4MHOj7 zXK1p2z(M^$f5KgsrrR?xP^4u2s?Ik`0=JwiRL+#RRFTOX(o{;?P?0ni7*-|&5g9p% zMOMNw7p-y;mI3;L6v2u($^~oG1GQ`#l-p6su&rvr&oYk@RNM$6V|wNucj^|h<_Vi5 zt~BbzWmS~JNirT-j@RNhw5&O0sES+rki=$CgS46qRG8!*P!uU)wSbhMF5H!<-Lx;- zuT0+Lbxzfj1$rp$Iiw@1;R~nbqNaTAF4NDc;Y^bmpwJ%`R1Y z&}*)03x662$&X)EABYn$nOEwS&X{JUe7XlMpG}gN)-FdOFbs@!`%t|-w)x2JU&7na z4(EiZauQQj5tB#;THJOW+jnCQgh%&py5;RCWG1lc{ANj_4dP2NvK(e50yCAAZ9-)s z-+`VX_rhb*89dBAEha6X=mCzCq7RcajTODcGJG!2i)|@G7J8>RWc%eM&uQp^FhqtU zF@NN+s1+WxjE-11fiH`s=9`WDS{~hr56bvQ4$8gV&&MmeERMH(jK%RHk%}rZanJCu zg=BCf`MX|4OLxB#-C(|hUc^e?a1(}et%!#u(jckc1m(PCmcTD0S21;(Q2iG&3~x~?Yu}_H25od&w+Sn> zjoz`Q&5Bg+PBZ8k?PU*Ab9ZX{Q7fP!C@@;ADme+sFkZZp%fHIwhmN9ab&)ZETPo-Z ziGS%>lW$}346j1dabBpGo?K3@cEspKu)N+aK?-5YX4FXCEK_H*3${8HrXb99v4y1P zqAm`*rfpbqJlyCTr%JYPL?wFKfiGd6L-KYT*;q8MJ^RI4xzVS-n}6qrcZK8PF`Q!? z$t0qScgyd^g56EcPuVS)tUo@qIN=rC=i7{(<)xF*iSg`8R~qpQRC~Rh*3xml67gx^ zwbwL2m;f6syGnv#A4fmY>XV@!dFE?u_!Lt4^J^}}wK=}b#Y&7T4EUW?xa1AiWu3`h zEzvC0!!u#Z;m=AR&3bP=7SKJv^W_XEuv)eBp*L0dK&8r1besGvARXPeX4u8DlOv8=D%~%= zwIn`C`d@&OQF!`tEhg_0M_g5HPVse>cqC0tVEk}S1ESu2PW&Z2%;Hs|$5>RVw=^QJ|&P!+Q(5c|p%X<_HAxFxHrB|{h*msHh zmGkj1+1`+b3vWn=;!^SJ4_fW?LMe2)iL2R;lDet&T-g-A<7M6(T&L!xFdvcD zO|>_$*@)yW;*Dp>o@;w(Meq7;PI?R%X6b@ za0HlL8Sh=G@DSIR@o=GHR)=VzboCVPu5u{6v;Y=?Y zNl&KBxrbeg>)dZRO_@+cu=nSraYVj5ru2_jd(#2?^O_FTjl+4TTV9>G9Sk%+*aO1Z zH~J$7B?qChO$6cOGGxOq6+X^wGi>og*@YEJ&(8b*L;=t{$OGoqwfWeB0hCy?Q`=D@y+s~{9fsyuOoI7 z$&xF_Ra$F4vMwsgG=8y%^!&EcbUwT>nEY2noa8ij9N@h6cGH)Cd~2ag47-ky?uNu5 zK#A745K%DO3Vl-Bz>l3Cw+<3F^{4#^73`hb*Ph#uiwBNq|D3+uN$UdPz>o8sM+di~ zIyeKXiQ8|Sb_wG>H?T8xjWJ_uQff@XGVdn3(~D;>@ViBkwJI$J@C6r>LUJHVpf_|A7E@)9E=%qfcltWQ`5M?yjzM zK#^y$1wHh$oiuzkjdovxaQcAvR{v0{&7D!(^o?RX=!?9$wbQm0VO#R%usJ=SHBrm+ zW1-)OiNxcDoTQ8ojG?sgad`Qjz^T@@=_}Bb`#neNgF91INQ=UCPO)P)>1pzVy3&pI zk&;$VVfd`@bJ>I_uY|7k%ek37I|Yf%1Ajp*tf80UX~z6yYu6TbVWa!Vx%X=|TXW$D zL`H~v-~{7&`P%)p@Fc5W>UNvV6?E!qrgB*Uzy>z^glWB#+w5K3prcP;rViH{d4CSV z1TEsU@zEFrvaVr&wt$_V>Zg-Nv!MrU)~y42Of0Z1QjPV~G`+xfJ9=3nrb4U8MB}$T^Gd;Eh%h%HPhF_mcd+cjX&Lzo@MZ(lNrs#6F(#J#o9Cr#c<%I;wSlD@M)$JwrqPDl+- zaY6&U)Gw=*e*Pg*+-aHSwW)x&+~MfU*Ze+;@&nT~Oawo?@J&TmKlfzIX)p)!+_oPF zsEtm)*iBy7-Q?e6x~Z)^vHhBmxaVAVwFm9-`JL8UQ2I4?F_g!JcU$pyKK)^@>wq89 z0RjG$^aU=WP{dWMKXi~bikRsw;38gM-y+!v_lKfW-I2c$pMRj$MP8(nOWzx_DxeyK zkAb8db8UK779Py!<79#z#>@P?>N}hL$-Urd76EK%y}#5Y&D5lUYCTl=DAsl(K8*+F z`8|z$-TPQ;=bU~V$m`PR*P9tB-(Y?+qE8ZZCUU@dC94q8`t=|pBfnfQRd$}lz|g|6 zO6B}aq3Mo_O4FUa@?q_Ai2s$qUaxEgry`;Adg(;$ir<7GZ-u*qIIYWkNGBzPTbV;8 z;Tl)-v;pC=?JI%-w)iDm83-v_Ji*cwqI!?MJ*ct(bC{1>=)DyJO}?7)72woAnTSH75`VXJ(Z=` zM0X~QC@Cd$vS&ttk+-V)+P3Bh}`2R8>{qJ#V+!PLP!QM+8ji_vrG zJM$0p;u4|${tPTO9;BwdyYTu*j?5qvx07HT?U(c{uC@tlAsBiSBqL34k`M4}BbEkt z?FihBH%~u@BXL>_6WNdePG0waQATVj39~EHe&!KBaRB}71IvBjTHln|8>BWtUR8fu zq}X73;TzzKd|T8#V&`%4nR}p#Bmp22f72;g zVf~I9MOSEBmckI&^W0Fxb6g2w^Ccy!emwShxt|`)bm=_ZFALw4ZDf6&5|Y6}*wgtd z*BN8`w`I%70{S6{`kBpKfyf`OeA1tBF0aAf#pri`9#a`}s&86(SMbrz@A zC_}VQ@5%Rq4$~%d{3^xydw#}^?Am)eE7k0u4{oO-uZb)QQ>8=*{W|H)G2|-EHgK{q z9iIhk`<#@kIUZ<7h_8!K6xf^e2}z=p;uTn{GET9THU%mwFe)nKVWJvW54UHRj<@C| z&E>rcu9Xmf+gT_^KWV{pJ8QTlcfU$thOev$V49IK5ITD<<|And*zWJzha1Q%)A*4G z8Q;Z_C(3UB4pN{l=Y*48$d9pFYc7JUY=`3J%hdbryoO~KBW1Ju)}IUagX8CK7Vt@; zOG4n9lE1-|S-6hobI&&0rC7TEpsY#R7i%1tC(^(*oPEf^OqH&h!E)$Nk5^?lW7g~V zh3cLG`6|#|Vn%!u&`5@7@6@o(@Zn`RJOm}TkX5k5A@G>=U88pjy?(rb9{s` zZ1F=P;Lh<8kk?nNp2qW{RM9)oBZ6MvMXL(KT+&z2Q%#**(0;gv_=XbJJHt`p0l%|i ziEO1AF+>Mtzk1o|8|(t-TmbLrc`)#q0bgWZM7CiXnb$PG9gX*NNO?3o{os4Qk3T0% z(sAUAv4&SMf|;`l{8%l)LvCuTvJnI}+cL_Z*5H%SJ&QQnN4zH-wZ{>qWG;Taosiz< zLQk}Bf!xXbAw_gbz1oY)vUf8>p^RMFv^hMBNYoKRl#9Z63uF)KbE4=Xd}h#x)fK zOTG6|;{FGH$o@Jy7JQ8Yn3BPjuu0!`Bli7u{bxMUypEpN>=@i#hy>^5lHa^gSWV_Q zP`O}Jrz15NnR~f)KxuiT^+Or)ZXk&+!|uo;PiJcF*N@Ko{khJ1Ml6oJFeJgd%4%jdV2%MjnG5>vB-?b>8F}l zlz;CR*f)LITb5`KdIBvu_e@9~)PwZ32fiBB2{_JFHCSO8{U+(Wtk5=@b~UCc>nXhY za@;S5)!CMr7I&uEr^7AQKkaJ`E4ioI8SgT15JeVc=LAjZ{CX}tnLg;&s=Z)WqEW&p z#Rhc%{mB_=d6tfdyNwT~d>Lyfy)G>!Ir9p-jZW}mjE6&NyR1*U8sVAV8(1gumN*1v zEwkXDt>ER>h>%QtO_S{LoIR)B@A8aMfwJp`ZFI}M$XUFk=tU83v_F-Qa2?@4lKToc zckz00INCV2A2k!{R9B^@YzLAr%^usHt!n#*nh(3pFB~9|=Jsd;yF&=pQx+Gnv=|u> zQ(rT5pa7Lx=v^5Ku_L|h!}fN~Cu`a|gq0qWaaACp-Cn_PUJ&ZUwfdFJptjHvnp29cFOU-C%+7i_LSs!68uXA60V)JDUMLElm zxFC&%axx3xG|*+gU8Cn*Y%X+$dw`tDvslSl>8q5JU1lGA%XBj8{xS#pr+q(puYR7z z;-P%uQP0`2tumV8jA>?R9WJZ6vFbjR##;?Kntf#P<8FYP`ACEP>&V5`$dsfc5?$Vw z5Jf8~r7t1?9L^6P-ifh4S6Cs(#;x@EnpnzQPjkbe86ygrK~Gqo)^BQ|(ihS%btJU5 z&VG3I`n!wgv3QDJ9?OdHAh)Xm8O5HNrKQQVMVujXmBOk-ee{g&F}c%-iju$TCw&9? zcX6hpZ54-u)T1r*RN?bKks3`smXe(+a;lz93Vz?o;%g`Pf-JBjTrP2@f7s&v8XlrM z2Qdg0ZSWmsZusk0F@|Zo7ERlOGbUvjT!l{D?(jS$ghfYO;oHp8*8JKD>J4>(I~Ehf zv5#fX5s}||8))h_$2MxNV@8{Os6jZ-^)g4-lXZo>uwFS6TksDMynqNA6ziY=Y+{9| z%l0fGUsOTR%H5YHV_4gFE$lSO-q&r9e>MS!R6=wa^y_|(ON+#g_w)< zshE>5x61CK>-$58F+h;Iw4KN3WgTG@;sMbmkz`Re1B6Q;qiEdOSs+Z#J}R33I*v;P z%y$<@4V#4ZcD3psJa5XpS?hzc+Mv;!EAeO;F~>g9d}&?g2RYSI)TtaNB8i~GYb@S@ z9-EKj39AQXWQ%idB8++%*y7AnCYv0qzF0vOyrphG=z*GXiT z^kH`!_&xgF)I}lEb7JrU#CVn4=?Z>5a5_q*MQLJxCmKFW8}2 z3U<9kC0sN9MLJ6`U(JeGrM@aisCMhDReX6Mk$Hl9B8;xO3i>EBZJsYZb!lh-l-1X* zH)4d@N1E1cLxho9LTlXe?a2zyPDuDqeKIlI0@Rmb63i=yW8pX;YVPbTi4#GSq<=-^hos+smtft@!a2&g9p}ja8ZZNxSD)2{$G-6YW;r zo+~JvW3i6t z8S@oHII?+5`IG0{`DYbCh8JSih?UMqdPcoh=M7V1Iw_o7yK*Q5d~HG;oSa(5n<+v_ zL&5%h%16+lpP7Z*DYQ5Opic=fQD;)fwbJkalLamGg3S0R+^AHOJbKeyl$GBrD~JNu z;(irEIUwP6lM$stbJWJpUJ}x&%eL_czepypXEp9Yh$6*Qtm0~yja9uglx)3#W<>7%wlB@1vx_yb7tFxPt_eQ(iw}NE4=3H zz>NWYaEOpn0&9CUXQL*^&SjwC8g!V@$K7fJe%&?rgyQ{mpOMa4r#q*%GUsi|zEpYQWaDkMcOU6X+cV$F4ydEEo(-3@KWWuq8H?C5i2cg!>ic*7`ASn z!1X~j63uxqRa=t}D(u_f$$M&8#QD|=lR3a!Bm^&!gEQ;1el1^U6OpD4(@es>us&I&vspU{Vrgk{Gp*xb9?_Py+91ehIgy3LdyA;+6qK}Y3=~N-&^$(5e zajFlgJuEt-)(TQvkwv*YG>7%_$$jUK%-Fre+rM(t0GZ*k(Q{z~{RuW8ob;iPn=JLb zvPonH&eMP6@WeCWi}iD)F896_M<8zw`d&<|E{no|1pm#m{pooesn=3nL_L9Ys5$$1 zxR(>e9eBbtL<_0h@v*Zp) z+XTo4m%Lp%T$;X9I&|#VH!5F>*{IAuTzHlcZdTbT(ptA*8Y8rN^L|IjV6sF1pi4kk ztzTNH>?|Q=J#z^GyAPOIc$Td_^Pw+~1uuz*Hp~BZ+g026-H3A=|16oov$q|rn_?={ zYx_Od^xG_>n~NRK03Mlz(qo6r6hb08Xm$!E0qA}5TN(EdgR>b$Rx<}I8>^K~&M$Gd zeyx~K-X4lvzOAji$*f10iN6MJ-Folwi1-wLu>OQn`QpNw+3^rPEA!}M{U~ZgUKb}Z zyvTDEVYV@&F}VTx^Mc0vi|4>k*8|mAI^?aofwgauZ)Pr@-)wGM+h&!G0gUBJ*|=Xu zvPj?8S2l$V_Csb{yZKv2gPnj&vuL}uw}jOLrdyj1DLIi0H9mH=5&K4Sf{@&4NbI6f zd9LA(3}ZW+vR6Flj_Dc(aa|6v#(_EugVnSmJQNq&;p?LkE-X8W45s53WzYdh?Y@hg z-y6G*#oR(om#2KT4(uOhLIGC0gT8qp&p+|j8A6}!t?ZpfMPBCQp)Zkqp=mQlSANE_ zU2#i)d(5*bpRGY~SbHQ%>x9RGD*0ie&$id6l|xTJNMB@8KtM2eKR2LS3ueKGH`DQ* zHlt?JQt(-vEkw=~TK}=Fj!VmOL8$<8x<=zbUUk={K2G-zqjuNIHo8fm<~tvqjzz8M zd#I(m?8CIiimy%P+$X&B31S4o4Bou98$qJqF~5tatEyMk&%Vy8CWqlVyt$|sc8 zE+N4G_NQZsM0u$MnK2b-V`xxwt(H88^U@8}22-NjhpObHUx9cmy4c7#?V{0)K&E(l z_AwXV7+Axa;oBxWe*X6m#Y^}3FZM2k$*)>ncC}PcNsr1C`B=w!GtvZGtnGk`@9Zlx zkgDUzx1HSgaXg$8>Y}(kGvpcp=P=8na=3?5+TUCbg!b*QV}s@2DWl1F$bYbx+S!$g zPPdrTll)pae(807?(E6ydtq_0clSUR0y7i@pGI%6OP4@G%EUta@C~E4hl}qzh~kHy zG%x&nm>-OBN8c^taZ#MN)T*{i>=ydq6y> zzw79U`Zh<{U$J6e^y0OWb4`@97mTk<*sn9H5S$m)4rmbKBri;4cM_|Um5gS%eMb6Y zN2_BRKQ==F?bklmh%t`E)Ny|>fUzU43T77rYU_UGJF!LhrnZXHKFnG>G2g@Zm1u!D zS5x_;#DEw&{J{vdq?xLk>p&aI!%v+uj9B}Ae_ia;7W7~G5Kdn0ZyQ0kAMKU!kiK5x zjB;!HX493}Cck<6rWwI3*7bv08sD|y)YscXE?fxC5Qi-W(Pu7%Zwa6sutNx`B$#sI zysR%Z#fW%w&`=SmHBg4(#4w!qI4lodgz%zPP}?iwjD8)*rF01j&rU*`4L2A?96(Yt z%YikonX;gMy#BVL2Qf)yPcG29obvA9iUyLP0J!}I=ffP4UL z9PS`y#Dd?QbDfbgn)9tQ&Sj3IY_L6q&NY-bn!F5oUMMt~BE6>dfht+33$>65HXYQR zbvxNWX&w4=lW02(a_NXmJN<~r7Q0dd7~HW+-Kl2!Ak%{4v;@%KCwgY)td5!epq&tE z5m=?;zo1hSmmeS)AQGyhP8+4K=c}@4N#I#prcp*c_>#cxp z@-zH>2UTLm{G{l@QE7_Ka&HfRIrc)zl%eRcwd-xEdtvzH)BzBCHD30j6H!Z5yQvXd zRKI7ZD0LlHOd{tCsG3imZFJz9!GV?EhR8hij96SH#n&GE|wcPbkK!a8iKHB zF29?s#0R1xgt;@<9HD7A$w5jP{fkj#L4%~L?ZkpFW_XGVbMY#UKl#~b<=F&PBMAQ@ znfg<4lwWwvYvt&{%T*6UJU)pXPz+j3=aDWII)i@0`rM>aEIv~VS~~L~z4iz?>=DXG zd|!e)I_vq#*DJU;i6B~YU?4vC?=r*az9&k>@Z}hSa_sM+;ZII z3x&WCY%B>rZGYE5NHz?ouqz|HQAJSSYFEl^n;M*&$Nal(oKm+zmM}uOpj9AC>nyX- zNC@6Mx2#CbTjg-gJHe?0{2K&A_vax4^qFgzo$-48g7PNRrIwO#-|(CKVj|(=G#nwv z5kF@Z+vE=uugwi)x;B|hOptu{;%0CyD8@zi-1c5$b&^gDGZc>^4%1toNhEUX7_*PhnbjfHZ(D1M5tw_w1MnZmtR8RkJ zgA?C}ED@#Potx42t&Q}^_(s2A$x=*L4y&aPH;hrBu<$V*{hY3 z-hWXgV!4;eVO5A-Bp?kHZdNVrM&2+PS;QH&7Qtt&ygovavJ5ewqbVk=!Y*DjOJi{! z0WDf_m3UndzlvY!NQj7^RW^W-H1&|MuGYhx$&&*eeI_3Z`rnFN^B}js`JCz4mafCs z6^*++o4{Q!7>FENfZq(;84I~2=GnLf?ysB7TH^+G4Mv6&liFs&(9<;X)VVCRi6B#3 zog(ZS;Z#TiIkzO2baS*$hqz6O*KexRWld!La3*{Nb}pkG&@!mJSzzJelZ`!c&GjX0 zINBDoi0VpDe=H=c-2Oyne6@wvh~E30nohkaG#P1)v9>ZLA4&k;T0YMzj1|HHcjr}A z7Ms4#7l?j?&tm-ocX8sY8(MJd9M;yb^9jUuaGU>tRTi6Yz$bXile~CZAfXg_U zvL~jfpxx9SMKxQ(xHvlSHjy#kYIii=9Tu;nQDDB&T(2E(sUgSm7%8Zjjl%6AWaFU2 zWy0*!wS%azd_=R0YZX z!t98k7M!PWG?9wnMumD=;ZaW8MAdk@bS!^+nz$EM`X(vBYJgaOlB&!d#kTaw(X^{s z$5~a7y)GR&|rLcUp6Cd)f-hlW(j^~*x%2E(R1*qj^*$>e9$Nj6(~ zZvQjFg?#fjwhp4a-aM%J@5Jr634{r|)!IupjBYUnteGVC9(y~D;@OD?{4*8S0Jzz*0s7(WmsM{= zYEetfU!jzzZ_AdUwoEwj(7;xiNnj9lB>0LaE->k`)o5f##D$CYB}EO!4e7|94pC)h zBqfuG`W`0!B4(^cZiC!?b3*Ljg8mOrg-%#3Z(n%XsD-MCzD^Q!47 zu|*sx_|V)SrReO)+1SnquJ))wL|qZ{BHD|F;glcR&ZOwOg_tEu_^Qw5MH4B(24mqc zo*(uHe2&S3qBmPc{=oOFqrSSSp|Ib}UDm-?*sz>`fTWPjp@b|O+IN^Om&t~JJWhOx z!Jd1_?WZ~~%&$~jiO(6uOp84!M+A20W@76X^14_UNzeH`;9uB@A!>dh?)|`=4ZU=( zAZk+j+I{||Y-M&Zy$46lJ4gJ!|^MKRfsbS{%@zuVEi+>co7mTELfo>BY@xCOL ztT$0gQT-|Hw@#g|EN_F-~v`1D4o)XXkTpP!#3NvfQOlFDm>Q zCwFh}oVXsWwH4dO8it++E{$A5`lS1CUF0qq`?(bNZRaf~5E4vh4we|mRPsaBPh$pX z^_}00camiDpPPpZBznei9T{~HvR75EzB1k%?}{#e5GFbOZol^p0I+^IG4rZv|0z6` zG|SSp>ylktE#RkndJ`lPQMVKzp5=FTLjRsv34Jf#`Wd_#Q((5t!6_{#%-WzLu)|Z+ zDVTy!Z&-Fj{Z1Ek<6_Lt`6{Dhk0VTS_xnIVs~Kfrj!d3xdM}&hF|=_ei7q`xXU0I* z=hcp_Efr%y-)k?i#MF0n=_ z<|u}*6yrQ7=qVI2<>FN2ED4~w#hE3qbGX9AJ0?;R?{-opNs%Bg;h%n?IWY0kC9RGy zfr!EvE8R2(PyQ5KMW-okm?Pt$y{o%Wrbq172Qj`M9)xH(EAYdiT(+5;McI`?4mm z!|USam$77vHIohtsmRU!*}4BEcpNB_8r^P-8+4NoTCNM3upn51bW(-1Jz~3 z$=JEL$k;*M>V~L5M+?v`K2&h+|8%R5gM<6`oj!oHy{S7;5@_yZ0TdQ?b9V)rI-nxS zMm4DGr;3ZARKhZu6yVhah3T~5)nFj&bc-{YKqAjs2--jRlq#KOWKMlC3FpXiY5T7G z$yKZVfYLJv5}vT7evv$!*!Jf;TN!+p;-pZ{CAI-#yFI99{5rZ{8hp#b3=eE)gtF0e zoD0H6DH8f$D=-_XXX0uZ*laj|+99-i*XT*FEg>5Lv~ET6q5s-5QpZ^C9~}gtZTzK_ zQY`r0V$Dzy0;20wgodSQZ-^m>tyYt{%vsx#hI+R+Ka*jl5ASR+TH3Bb-ej5N2We># zDw%F@W(YM#aH7yKI~$2#zsPWAm*j(Kkh7^MhPx6UqF!H|il+Bs)s2tN1WdD@N z@8n!=ik2f!!_V)+<=dbD=}W(}8@jXcmA;9Hh%stXraYUxd(XD-hZloCj{St+@A`BY z9bVj=Uioz`FCT6NR(3%`V7OG8{}%&t{I!X+jjNkG87J6c00}1#M|UzdfTHQ&CJk?A zAV9^#-QLC#=q4=u$EINVC!4C8x&lEUFhg~K7#Y`Nu3_VD52Vv{bO+}a^#9<%-A_14 zeNOI2T4@`1L%<7wjFX1bKXl+O5S>0J_&%{Z8P}snk#Vs;)gFOlT#rJNaXpc6Klc4~ zx_`cqBWYu42?WV#4s_FJ=LDF!0zH8Mb5mC*M}WDFtGS1Rr9IFKVBzF$YHkji3BcOJ z(aO}-!@=Iv!yVvc<>Uyo1Gw5aS^?Z`>@9#~9DD#54<~n^8>q=1NXEwvuyQr^1d_3_ z^8(B~?CpW>01HzqE1>J|%)-nb0JOKaadxwD0{|T?Ox>&jpoIa>EbW~@i~*LersnQ8 zAaSfbZ0sM|+5;`!|Eam!SXsLR9Bdpt+yKr%S9fbC4>wasizhKa?9EKwfPX8G&_@A5 zJx|ET+CT08YJ42*5$^74Y5{aGb+rRn+JNK&D7x8$B~+0Dym(TTu7wRqiQqZtJvD$7 zW)F08vjNyYkvaiEcL^W0>hqY9v2n8kq&!@mKm|^KxrZy*1m2(uH^>A|c0flnQ&&)p z7x0&{xs$W^lW#>T@Auy?YuF*mh$baDrob5f_o^<8@(#g#Oq%a#NSAe@UsPAvh)ZD`z2ypNqW8>ujtJKEH z0&Mz6ZstG>8+&_G0Lbot=|S>1n7WyJfENJ>!wc?o@i27-A;3jzQ+vy&5q>wik+Jcy z1H>L310eP^n%KXbP3+N?0AhcqF81hPVp0H!Kf_Bsfu)|nQvU)={YA+=(a1f~$o-2( z?k|m$yEQ=hX*iW9a+N1?m4A_|{3iH|a`3Qsw{f=j2Bx z!`jIe_2qZ&*>%kz&KKsE&}E&%We4Ez@u zWTxK^Y4b#5^F(9wFB+S_G(eCVK+y=afI&<8k)_iUxzoSMoqiMiMOoN*+JF&HO7M6B zdOQI={sr{-i|~Hx1g%k!61@L38v-7~sFWk;09~;0k`da}*z*7R}f8byiV1mc=oAo2| zFA6LOxB^xT7zM6_*@A@zxBnUQPYxFLQ9w{14+m&?p5JnTh5y~g1vY05qy!M=4{vZA2ltbg@q!faCxK`2XgILZ|06w057y#;c7U1wJ3V>>i0;v2Kz;wt z!J7W#Nq_17%@ZWRp9%kG4qgh6*86RYKmGq68(jX={$F#DV!)I9zx4evGApYgK-ts* z2ml>POzi>Upe+G7fc&mL?(rVO2I!FdI|zZIhohLIo6X<)->CCXc;b87g@GQ@``?DA z#|_%!#_|7;;R)Ohxfn@;m0_T6i<6{{#??3+YCkMBK%i#3K7s2`gmmkCT z@4i1Y9AN!``v2g-Ww88zbov+=Ks4;UpaAh(myZDgi~$9TKXU}r{ZFD3XsAaPV3!A_ zKdk>FI{g;#|8aBz3HxVK|D)&x8V@WLSSgR`e-WMj82&%=|9?a$&?Np^@plM<*t6Cwq(k2vJXM|I;|d20r(DI<5R0s6d-3wx^IN3$*wA zXE<;T=ngua_!|kyz~_qUPg^u_(EKO+Xt;mE_HQMC+Ca}i1KB|okAi`TUVtu*xSNBv@=l~-dF&7ti^3rGKX6JouB4Y>d3PAfM(9uHdi4t6S zWG8LvU}Nu1_jvrE2S}JY%l_ui#tqQ8?yOQltkZ>|sBkgykS`oU>ERae6%R}Csnk%QUPuBC z3(`-u2vLU>UyHCOXIh+ip0{l+cKCWOALh3Crg2g*NYnRE6?xyp$Ej=?2vP|(MbbsgoL2BGUFF769;#mcQa+TwoJw?L{b+(Vg%FCM!cX<2~VV<+&U&FQ;MH zWjrZ0gE2GtTkVvGB#(v2LqSXtUN&3n6UHA<8L_>Z7VUEY2DWR}y&uVIJmeKqG<-JQ z-8MX5_9*(elIbS07e)B_CdTy#E;7Y5D5Crx8WF-Ku_g+yWquWluh~>nE_1zYCqAYe zLNJsKO4+~Rd_RcMrn(qZ41-kLC}z;r5{#3J|6L$HYoPyEOkrA6lTu_%T%qz^NrB_} zoJD0C>2R5Sr75GNN7TNRuPZ82zU`Ev{zs{=Jx*!`-_KjK&UWkUD!RrbHWfPV`x%Th z*K|9FD(cu%f0PvMmO~4)@XxG$xD6^hLdhLOzT_|(Vf5y3THSAt30(2_OH4SC6YlGB zrZHaKz0I~qS0xd%4r}@uBvORzlh1Qa204r$S%4o*trI-06QOj8r4L+J_KP5`C5^Z$ zZYXm>d**`JwFc+-zl zE*{_s-0&(^eyXT?Rh3j_)oa4Go(ff6R1ekr?+80Nh--5_e#ldKCV$MIayl>LRs1Dy z!6pKFb$4i?4Dv-;(X25UzpNXorq?4_y(3Xv85A?_&^#VI-DfCDvd) zHsdRNBO|}X_t=XAIKro-{Tb(xfy=mto4AAfc#P-BRk~8Dh$<$8%dk^bR0-;Ls-fzx zda2m|PQsd#(%9r`9LzO2gzNKIPUR1IB2VTtp3bv*F3;yhyo6WqYF^9hcmr?ZuX!7P z%ir@}KEOx#1pmzEIfF0rHNGj^9nRtV{FtBebN1N(t05X85>4<2G{@U`2W`+Ee?n(; zM=!*pFOo0-L+}AcV+_V&JSJcgrr;w?!wk&A9L&QfSb&B242!WGpW_Q`lsVfX9Clzg z_TVQR!ZDn{DV)UxH2_zUja$gULp+5?kup>v<*!Pp098trQ{`1)-bz+gl%-x*)m07k zhN`9NsJiM+^_Kd*YNR4n6V+8ksc4~;X3uJk{COS2<9Iwzkoo;cW_Z?1bNo54;V*do zzntsae3$R>BYwiq*lqI(LpUPP7){X(E&fRsj6w>=A{8HEA|_)h(l8w}F&lI7G3Mh_ zEc&mc?`IOS{+~(z!Avr!u$@Vo zrc32eo|0)3?V!DMjLy?lxvXqcAeM~rjbp0MT7roCdL?7_mq7S*H=p%kd^s#TP>Q6}HQ~C~H zbtH3LS4yJ_c`YBO7(Jj6^rC)-?)ymUy@wS^m=eIx1CnkFI?Lc zL7La=wa0M&UNNsSD;go5SpLn(C|XsnQ&IEPeHCexHd>pe&D0ia8?+0WSAS36r|;J< zvc}AXxeAYxXU0@n2}cZnqm9wU=x)q1<{1l(rN(AsyK&CAA(?m+4`n4*ko*c&9o21> z8#q4jnOWQ{Z3dc7(`D8)Ynye=P&3R7H=CMC=4f-7xzb$gfTN_NjKk@0IchpOIJ!CJ zI954zr*al|1~^MQ%R4JOt2=8rTR5Yf(N**+C8{_qvUJPeDq)qf%2^eys#dU7&kC~= ztQ0HNnrKb6W?74^wbmwUo3+E*V;!`PTIZ~5t}s`GtFfzxtCuUr)i)d2<+4L_^qe|w z-EF$-yTjb!?nrl2_eS@1x7XA2MWYw@b3I;<&C#TEn@+m6UOTKk7dm@|&RM1cI;lb@ zjh7mlQOsy(bTg(KbB+1N5@VgQ)i`Tp%bGogoP0VCSz$d?PGCx4y6JD0G|QT%&!Q$m&}@}4bl2){XOa8$N6$Ew?=MIZuMOGTA~p&oCZ?@^`Tbs%plJ(&p}U? z=Y;1d<^Qg9CAxee&(0bz`$SkY&T#)??5BgKjpJBp$rsGwq3#B#4#QL&2+QJHK+-wS4$toJ`> z)>$*N=FB?hp8L)IeP2?|Bo}KFYh!DDYh7y{YfWo)tDDu?TFP3)ik1hKyO!IQWXrY8 zw=8j%y_P78%wmbPgjzOQ8e6`!cv@U6&K4(&gMGApy8TtVDEU^U+XUML*#z1wvI)pq zt&w7UE_4IcJM%k3d&t%(KC5TDPoVVo_fjRYHTA_`uD=n5?cmb@ENN7TutaZ=^QOO! z*J0Abv--!H4$16#$-BFtkB|J@n?v-l|6ULJ$B|vLuS|y-UBdSONoJ zpwMj)42GdFM6~Gxw_&)bbOelq(W2J~SPEld4Ezq`;11k_oj4yCAfZA=4X@xeF2n#_ zgn{q|GSEO9%mpR}VK9c^VyPQTF*oMHyl9Kda5+4O7q|jLaV4(8)wl-N;yMh&^|(Rm z%O>26TX3te^(^}0Gz`aWxE&*K2j;{4xDz9>0NPrp9nlG$@gN?;!x)c8@TkNBCISk%~|7 zDL%&+n1(Mg9o_L2zQ#A0ft7_TVoHT#ikLJRWJ9?qH|4=9l$UHNALXY4WJd+55EZ5( zSe1%WF|3BwsW_FOl4MV%s5F%!2P#XB8n%3)1%q4HFLDv~R?Q6+MxDKu5v z>4G$!X3$KUMgBCK=FnW4NAu-aKnp2=7EvGtQ80zjVtV-hdp~;gf%|*w{pc~J(i3`0 z&*(Y5pfvrduB$(zmy}Mg=rz5e3^Iiqs7TnsbWiEGF0tM_pIGz5ni|cF=0*#nrP0c0ZL~4k8tshs zMhBy#c!SPH7o)4u&FC&qyx#AP%A@is+pN9G@}I^}hBvR^P+rNacr~x#wY-kQc)d_{ zBX8o(yhYqcIB(%lVK}_!vPo%F)&%RR&7*!)mF7r zom6MlMRipjR7ZG*w*fVKz2|ndphb&|g?O2Yp}%j>7x+fCus*9>;@K zH`QHv2^D(q1RlyhJdua-Bp$(&c?wTuU!KN(Je=q9be_R8#gX{G^(28DB)%;~+}lD9 z;L*I8m+(??D$9)_#!$mYoJ|s4rYm%nuF-Y6LCJKJZizY@h#EWSj=Ga1CP(F@oJEtp zbsybVblOI@)$K&3-|6plPf>0Q-BPy_tsT&@I!^REQS3c^ zUq29?+KEyNWzH!&bujvgR{I-2OB%Z){hsL3QAXuAW5)}dZL~RzYWMT&e9|U39LT=ojg>m4VzrK^W?S7m%o5r!9swNNQ-OuXPZ}54;FFe0& z^i|^~UpH;myhY1at=qJ1*SuZ~Baxv;1eznLBU(f`tK#0)v7> z7B5-4Z25}Nm8({-S-Vb!t>3V5)8;K(!?$gZ*s(Km*X})0d!u9a?LQD3cks~R_#;P; z9Y1jrPMtoJa5nMW`3n~<)=Np3bCN<%QpiaPIY}WWDdZ%DoTQMG6mpV6PEyE83fYr_ zj)c;0`zk2S6~rZjdEC;a!SKhHmB}$OV%jFVutfSPXhfWln@=vW7V@7ou>KnI^Lq5%tZ6`rrwkW{mk7 zDuEx*(&uw;6E5yT!|ZK(g9A8&FS(nE=4Ge=-Gt9!vL<(o=BD5ztegl7v80NVt9e4{ z478;ls*&C+Gc|+GLQx;^6+XvfA#AJ9>qq8D^A;FT7+hsd-jIT|u@!}~t@*im5xih0 z9FpIgc|@}puhL!_4b5P49~6ZMA?0q2(KYmpH{;Bu<_55p^?1mRw3c~#i8F{1&Oe4! z8f%V)rqDrVjuo~!3b9-2DYi|3ZHxLd(Vy?5{D2HCqSNg#O-jxPau#4LrnYw zD1s)0wRT22nS1Syfe|Fi^K=K%IfoWt%EZ8y!WoQ(Mt3 zqWqN-4T+z2kUZ~uFCk4PmAvHU+;i^FIp>~V=v$*Q=x7uC@Exm~ILBn1KZ`Z8b!BtNEJl9$Ug@47_Fh(s%+mfVHrvamz-wo9#zc@ji0+4M<7WH6v2 zKMy@^x3c0veh%M<{4@SJ|BBxgvX}}F*nsS(i?sMqT$NmsSDGQsM(@`mW$-eU@)AUY z!}3x2&**FXh}B)nb=!8^PW#!x>4X0=$mle5<2Y>B4om8WCSFI)_Iv2!G%B^T(8#BF zg*$kKVpJfHf$tg?VGV3Kdy1`Q9c(-6LDc&ddkyu{?;rtWK(#OxnSC*D<_X@xck&)& z_Y?R|p%?on|AhC0^FnlEK17OTR&0C@GHkNCvwirEh;!nCxF)WPe!N#i^k00ZE6FIV1J}(c*0}5A)l}XA>#FN9yC7WWKXKS?m-1d>}w!I6r)O2vJjxK1q z8$LLNAK??Et*jr2$xNbLNbbWsG{Y-yQ=KsIE;%M0ycKY_lyB}-0upLvzKNZtD)v5Y zRk%O_EcMYbc9Higfdc^C$TMLF@`UOjls< zKcW5Tyf)HNWQ$t%BAd^)(noxvXl6UfpLvr@s705tTLcd1C8?dBestB(YEXNBX}m6t zlYWZ$lt#TCLv;H$`z_sPa^@zYn?N*5Aj<58z3(D3>b1hpw!$CXh#=1@=ja4e&@0VX z7D?Tx>i!c;{m@BZ7GnkvR)$nu&Vo4>u zx{+E?@xO?uw=bh-4rF#@wq(}R-?8^Ts?7WB4R}NvJN)Po{t7SolxU)Th*P#hdk5gpXW$#R5GPjCd-Mr9j6z7%hWqU}rvZBY zAy&VI7u`9#UH9bY` zxM3bOvJ_t69jZZO4T-bR_cZ3BdUOQ8!M->=G>0Zrjr;}URBo)uRP(js4022c_&1Qf zN@yY504{PN#~>B3C#cF;2_7y47Ox7_En4VbP+L6FQnN{Zb@g%b-Vrjbb~>``Hbs^MXH*{6B5_ss#&yZ7EnQk+&b0&( ziBX8St^ySqyGB>z)-rYM$^cgW=>Jv*hE@hfRx+3BCx1n`8rD?(gOH}CSxZwC@GnAI zOx61>c)10?V!`78dpy{nhKo8ws?OqSSdVP(Oornj9G7xBf?BY{QBh7QhZCR^kY1>D zrC8x2W&yk~T$|!#9|xxNVl5Qb-CD@xKo@1B89PVO*}J#IA6F+#H-Yq<$EtQ^rSGda?h!60CNYdr%3OEJ z1Wh{`F*VR1!n)6=PoHj@h%JaW1&@oYc~wRE<}{zDb-7ghgZiiux=qAtXF~lRkNLoR z(g9k7iN38VIy6^lP029|%=E={9ycky4=DxTH!0g5QbxANHCXZqLh_*k-R>Rv&2>%8 z4|mq;Y~mxx9YgenX04&AC8~y#@nPLItQs>LqF0a5h9Nya7!@Ua7~&?i)b-ONLloo=i5#1GEIyA-{9?y5~N!#qBHl;JS%w5*MZ?_F|sn`0(&KHcC zkKrymDZsDf9r2=esb4&E3i%8wQDte4F9*oz=Qqw?-o<@8_+R}Uo=dy74sUU8?y^Iej-$wN(I5QMm zn%4#LNtO&j4x3~!a@!Tz;No58r7TpsMO5T--SZFnSGex@mk;`>4zOzg!|Yj}JWpO3 z28QZkKoz|M0hu0b^hh9!KQT6i&02UPM{b&9Aelad@!E_!)B> z*T8L;NQn-MTPHmenA;=wIPb~#oRT6d&JMZ5xmn)qR7e&~aXRca84?TU9lKqSU3EET zI_ez4k!CLh96~L%S`ER{{MF;x2ZN^eTKflE2f>-EKd-Qc<&CeYG5^5d^BeL-m8U?= zvBrZ{ta8R3a}X((_suuPe}+a=o8vRrq#wu^khDu#BG6-(Y~z>ykMC*?ZsNMad+%yj z+Ld;-dhJWvm1K#P&Dxf*B)^dD1s7rmznBEdO9h64+t3bUC)jBw3_luhVA?u#(oo`d zASAJ&6Pg4EaMNOF5~rEAGc?nt4NVB76-hHe#4Um{%}DND0S)bs%0B0wd(IurnS0MU z-zU0*T}7{ANzowyuaDt@*Uj+IqdElWkti8>6-tI4%;pDP+~$X#phF-y7sC@A%kZSr z?hr_4fRYK$V)GLmP06IwYV(s$N|rnQHm~1rV|cz(aCim5;bd96ou;i;vJ-uWD;Nv} zEEZx4{>WGly*{5PVxSXx+-_A>6dXbuF9@>irx}NXvSD72hvS^BjAKIhl%HS>QBE;N zR7X2~z6_T^_Mom8%3HKE zs}bq8vh8k)myei##oN}6I}X!z#~dMQ^&Q+BBekNrIREE^o+ayvq?1U(o+O?$#TP*m z#v`5x9s$Vp^y9B&W`WXssrN$n-}?5R%3Ld5>b=+QJTNb{jbRNV|_br`ET0}B|g|HY_3*E*Zi<{sD_bQ^FCsw%E@>_`h&@i#xJrvqr zGeYcgkA!yBI7p4xG|=Eq*DMA1)T|(EL+*z>Lp3os6Zp!i+8URebJBJPBg%d(1Yk@HS6E4hMN)?QRG_{JRw7b)cGAtK zu&KGTCuKE-jmwqDoJ6L%oaq(5eDrL}lN}!lwCkxmq5H>0~0|hw)os4sBTrY=n zSLm?m3zvQ2ws3D44_~oO!8NC7D?yzTfj9*#j2fGCMmi_K_0l#8I;Ei0CgD4!Q3*=A z${Kbib&x&BUS#ng8)qRq1)ne&W;m$Fb*P(B9eGand4X3>L{WwYg?wBz6ot|9(Vdo2 z3;fJ7XMvVs^*?bnq(aqU=l{cu}g(g$5TSn7eA~fLy zmtiyL!*ZrZGZh=iWp8EQ9 zN{fL{-Z*vcg?$HqAs2;>vp;?B^?k?QRRO`Rs$aO&ShR21S9;f+2hTSC_3(2SU7I#} zCZ7rq%`bgx(YeDXZU%mS()aF6pzk3I=H1YoUK=RZvD=olZv0Zq6M{ z#};D8jh3YV|B??*$1@sy%0fmYix8QI&sVf?W8%q39{)(T2LiI9Fp?xj zBB6LZ(b&i^b@7OVS2qS^+@ggPfMYy{la296ND0UiL#3-WdO-Rf65%c;H)~@YALk)I z1s*dPx_ZpX1-U1?Cbprf zF4wzR>E>>Pvt_JE%=Kjww%@;MG8X}nskuv&6q}OKdJ3&LhZLskdUiFcf3x~g!INYp z6f5^Yxf5=^kkwP)AdsY$=Yjb~=!sAl2za>{l6CbB#Q0BkJh=L;y``&rw;q{T*7eTJ z^dBF1=C@I~q&0@(KPYNl_b*@4-epv6+%Wvr#gBAMo^RRO*Y))9*mpm?Z}l@ByMFfC zcUB+TT)JlTH;?R?U;TC5(Y(m0?`p43-CNqZU~k9T2U8hDYp`_)pubmU3#|sfoA@UI zNn#5zMBpYv07L;|I3g;B-DCm~d`Ny##TdG(TNL0f_}_Oo=9}NYwX__54OIk(Ej8Fm z=L8OI6u>ABbK6dX3Ph*?(iq}KG-nv>`9=XzBJ?gM+?jv|A{tC{ z==PEj`n+y|hns(S;LxU(kDcAq-;$1$mVXTX@d*e6cv>Vu%F(KnC}tRN+Fa%|8CCA2}5kLoYO0|Ys8qt%*Opdnf>I8x&Kba(~754 z5Kr=MpVtcUCHH-)Ik08Vnf()sm%UJ0eti1o#qC$YQ4s%ANxk{@XQe{vb2F0wF2cW~ zOjPVQ#=JcqutHg>!X?U56)FxpArem3?x00N!FkNTJD_8`!4%L8FU4Q>QI`#${t^x7 z$DJ(ZYvoN0h`Br|zSTb%3K()A)f-qJfPq%$WrHnm+4Tr#TCu?pFwgqXS@ApWeB+4BW9^* zvz}Oe11j;D7Hi-IEuHjQ&AmWc1vK_!Jwcl^w8Fpe+x_BkzjyJPuJpF=KOFTP z7-_-9?aS{~Z5G8xzmztf?eBcu7OYZENa9G9y!qlc(4DQoes5W6`2(8Y9slOKT7a9l zuIRgOceT6HuCy!3vR1N?g=O<`Ix-miNoc(uLouPQpnyN20_rB^n-tT6`G#ZyF&RSb z4o&EX2_~J$jhhKHU?W3F49!4En!yc_*f42n#tBJ-Gjv9!{Iu@fwQ-xuqg`potM~TY zbM84;*91nSTw@WVGn6T%jTI!09adV{rnDtt3^uQ~i;o22lqTsOEd9#@WZTq1N zgXB6W;G-@ym0VJU(}N~0-!Qu5U}ne^Njd{6dZwupPXwiJ<0q7ql;%AT+T`_*lrE~K zyFfd)dC%J1pXM|!GS{nw7P^wQV?Uj$M~Xm4;gw={RhV3+h+&zToMNrT5RH9hjk(rf zqDDani47%i34EGLIuTl|aR7g9FCJdQ-7_SrXVEfZrv?ABTXt->mY}B;732MTaj+P< zdpI+EjXs22Wk?yC8_pe+@lr$<@QNM2qydik5`Sf{wU2ZSHqo0kL)PdrnoXw^@n}p8 ztiE9UT;s0a@tQM0EzST=u9rA*8+-M+8|}O79ni^liXF~l;-5sJR&DS#1Zu;})fK)K zf#qSLoR-^4#1eT9onxCNep~Jk-=pVj?}+cn1N4gRqIgkO6@RXu`c0DOV@&fW1v%`B zxv0wwZLTEYLj7?T*uZ#ize9^$IQ`%KHklj7G-SR_Q6rgQYPL^Rc=S=CDy1da<88c6 zReV-wE>V?&0y_25#@4pxOCK6{@K`+07n&9?9yxKnzdULzHI{Y1h(lTuUh01Fi^_$M z8~8ee91}#G&LokXfO^CX zXhN4c!iL#g_Atw`n*BI*Ksy;J-;5e_vbBIuCx$FZMk1<>pI#CzEoKUgYrp=>6F`dw z*}S${!_jlkn#?FBgq3gyA*j%ocKN#lJ;8U`v;IDRpVk);s)AKHRiRq#H|z`kPBxh% z*aEp^qOCMg%~tuVw5os*^+&a6fbkWeGI#m+2lwaf4|V2rh6FbWDWTlZl+cFIj!;|Z z!;la%>*DifO$$*)a)nF+Q! zrJNO%a!ye3td&ml2)e*H-j9KK3&@EsbyT2@xp z0GM(UphimE*zHE0oX;RY*8Y|QD3d}0ipjLudrAcH!pW2djE{kr-*_}g^ z%&T07x0^Z6b$c)SKh^}F7xwt}WYdUUCM;xoe37uMNcI#&btx``F1O-%Dg#C%s=LCT zn1^~ycs*m)rulruf-0-@M^>eC! z4(yDqcw)!eRa>(@WmeWbT>t2@2X-D_! zjF1-LEkui(4#jG5R-Otf&?hs$qg$_ccN;g1Lonec^V@q%{%s7jGN9S zu`ek4B*B?0mAYrS=V-r@UvlnqUv`Ra)#Hw+dG4KVY)2s55e2uZrf9qFbIM+)Q+C_E zW?s~RnFnpy@V-W`V-~xDG6t(hbUAE~*{R(mqCM#~$>;F;rsaBzyt*3Y9+*Aa zCQWhu&7C&*Cris)kSOB-tH zH*fmEre%X|^jhYt2bMIR0Cr`o@!l|jO`)YfZf$F6SskHwjoY_l#*KllpPjypT&zRH zCnFcLNgg?=KeWoRUT6{aX&qdL@T#-Z)8p(`PkMUQ^By^iD^X`En|)pM1EtT)pCIS) zb{2TQTM6c3(=s6(hY$smE;$^DMQFqXERw7cK^ObPVUZD25I=GV08FsPhuIjGMYn2_ z#i5*=$Mwf?Yz^f5``udf|9mn%(qz*K1aQNL9};CPTNvsZJqj!ws0 zj`tk{4toS=Lxv||N6bNEjtWQI!8pt(b{scD7QA+hQeb&O5>T2)Vm$CEx=eS{I0H;T z226CLD9kXO2KAV+Y*rbvr~~((y%3XEmW|Tvh}&IS$DC@u`7{{+MAb~VVGZ4pZCqt$Uq(iHcgL*oNweJ5Uk$T$cdbF3;di%cj zf8YOoB2$ElbyLtZ-4m!v_YAvS4X()A>hJJ(>JQtG>rdKGI=k~u_`AoQ4EH(T%(Jyh z?NYm?!_RiYI(E{$5jqTKL4lt8m=K+MEEErsP(L{Ut?X@C%&|w-x!PQ$%Y|Jo-W;G+ zB*0_gfE*x!UUERzoAoho+)KRlzrFO1ljrgWh1TF;+=z|N62~CZ>Kn{)O#I(&khWKe zSSk?|(|sVAOa#-g(NDT|vYh~}PXvRwsAzIzO16Dc-DeBDetJt9RYJ_Db3Es#%kSR$ zm>+LwOikaod&lPH9S5j8oe8UB$+GeH^5SWxO4Ca1HuZk>N$#Y&+t4jt zM19OfL$B#|=^DCedRsC@q=njgeS>M9)F|-|t~KX~?Q`*tgx^+3CyhR5yyB4}WyB|A(KC0M05{ z6!eNrjsP_&K?}S^IE|$>jcWpnn)#0}+Gc7wcIF2xe0T@vDFY8q-zLj;%&Tbzey+uJ zd3Cj2!`rcT;0`t^CzMUfGs@978P~o;+g~`aw+&Fd0p{h;Y!Otu3WelcrWEshDXS5B z7()0W?B>E8;d;~`p0Wo)exb*Sf0xN51icD*?2qYR zHlj*dqt|H+TKe-^8p~Xoqg<&`W9nfH8yKz#X$#$K7+~xX=}4Je27@KVp>#Hb@zMyT z(-|FhR6=_vGyJ2JmU#_Dm(6M`>Zm(wKquHLu<1NnCW}0WRh*4$;27*Sm?ESXR7ndb zQT|Duuu-NLKQ9Y>6keR?S-9FGYh`Y?n_!13n^Vi3j_Rb-o+<}40E|?U8hPMEV!aPf zhSrVQs$q#qrXC}2oxm5r#TS&nC=ZqU6qN;dBlz%=G~Nqk7t0}DB@k7Njl=AtJog$C zLveU63jG*L%Ift;vP~NE#3>+$I`a-+iuX_~5iG9;w=wj{a!}9lpLJQl;vYs>%!Dz4 zSTh?lN-BdzH(Sk)02Zrc(MYgB9Hf>oJjH^eSm-Gh_zCivf@$E= z?^{4c?7uPso6ZP41E7)zBY57B-S^zurw`^TiWcYI`xfV|Ib9!2VF%t8)jiwwe*VO1 z^EPeU;lA*F>bHsR7b})1<}@h?ny$=MUFUA2>8J+%TAnH7s(gHz&6iV_Q_VZ<(dooK zdqzRw9A5yL!uFY{psRqUaPesFVkU&}uQWlS&G4=5BOK7Dt}{ z=F=4)CzVsm8;bir*5Hru*kQcy1gs;s2QH@SLE?ZRJHNFV%c&mDXLBY^$xcUP6pfsv1t;i;t? z?q2@eyMN!eHZ^Is#o?G*h0*>YT=}`O_7As|?qhq2d*>FHB{=>5%Jp0K4pBzJ#$Dn1 zfsYzIvk$3824x{y7U2W1Q>9yMU~+_)VFy=(a;?V?-@$GyDh4+g&`i*kq9_;BwV)QV zl3B&ARyS+@$`~tn2q6MyG=jjY1dQECWkCo^nPq`S7LMc98reB!h9+&Nons;zA7L1t zh2C;WHt;IKu`EVvoz3P%y`)Lj=EHBm3b%n0^pZkZ$QN)}XcLIgPYMwWPY7-fa}MpY z<=JXaIiSCQnYO2D9$z^dRa(3p85!e1aN-xP9_J(50Zpk8|M64_=S&#Dcw!5lGEHW)EA zp0d>*G4|qs>@|gaAW|wAyxB80%Q5Rx=hP zMX-z_RA4ur`!+#v$Y$?-@6DaJ=iK{!-}z3H_J!uXDjWqfJFKjOpvMb8xN)_0nEBu~LI-!9Fy zc&KcjYErV8R9U(CZNtmp-hrUXGKCb3f`NdNVMBdNvLJd8 zE8GBzUce6=ZrRw~GH&9s8JiaENq>aOKmGp1`h|(aV~r0U)O&`HKAE}r;lWKEiyOv7 z=*ipFe!J=I&dx*2Y`?c?9a-X9;y$#}flm+AfbnPpTIu)Dis+z7 z6QWhnu@w(~chKbR&v9ScAys;y=P>tC{gZr>!Monzq8^63?{LKlkqf94k75x3;+XbGl7B5M^tYX{y zWqP~X*+sy<MA^#!kH@R^+;7DJi+q_h^mY8fPo`N0T^v?1`ZwM;4sTpT}(Ae;`Pm$_Je=RbiUDh zWfyXQam7Fzz%1+--0^b7AzeC+A#|IFOV+?pQm zfjm{M7~|pdRku`7T@oy0DYf?zM8K%)IvgeA9MGwA$2hH+ho5&xy1rSy79UydYx7|R z)ec{;kNU8gJ?vg6LRq-3xtD;g*S*W3k_m%4a}Te?!z;;_0X6*}UWXuY=d%-)<7uco zb2fcU?@6D)U%gp}H>Nj0PFn#Uzk-~I_8pH0U9q@w;JsZXrQYl&3xaV?clB9%o8G7E z5xqrUtzXq?n-0o}iN-NGhcs=!)~AtPrN=6%GjK<>$LWNj!)zT)B?*Cn9dCtbReW1f zx!!ZL4&o>oxJW*LIBadcJ8C8Wg%8gW%fw3GN^51_Q`U19llA7t+;QMyfF8Dku-aOC zbpeVNpaS!Yh(t1!pI$R$vS(PS)b*j?1cRLg2`bJ5?>hzaBYv z38A3wL>Dcd4fder(4w}V{p;_}`uNP$0f=rlocyoV$)oLVm>bBprPK)~6iTU(f=gX+ zA$d1C>{c+NfH8w8izUHgNh!cmNg@b0VKq1^*fz~HIpee&FFBysbC_J4c`}CY;9^L` z7XJ?wAw`J7Y#F)(iV&azYJadsgD;q=!V3Ddb;`To>VjJdeu}6uk#$uEg=6~SfSUIX z@G@{$%3f(x=enWMMw!?~Uo<-Ce%edfX5%&5Pp|9X1_%1OCeDrv1&2{^QEE()Pmmvy z-DJ0TNp_MR@-C5Yku&7BBva%=1h;|{Llvp!c^+Dgf&MPrOd8z-{ce7)nWRx)0EV1` zBy~(X36Y%X$_-^_e=s}43U7u*-aNSOfImN}WlbLPMld%DN2nOVKg-( zac?&VXLrx=@$eJ|12FWNxGceQN|}#`Q%gi-2_8!wQ7M<>6?CasC7;CW=pNB24~ian zUEGv`cDhZp%Xh@P@?(6K{z06R7jZwmATCMYlVY9RgtyX7VyoPS*<5oeUPYIS6>=^9 zE@jhj1Dz%sEye!%7>Rbl9l>A0OJRj)$rRk`aq}luP^sYh!MgVL8 zsaeG4ZAV9;3uWk7=1S(%%x9TDgYp!T{+o652e;O%FJS6LP@WRyD$s|nUl4eW!ef;&&=RX+lnR8#ZJc$GZtP!>n3 zdiA*iP{ExnMtTnmg&MEbtMKG#s<*1`kXg;!%xW*ODdF*P-Ux$E0whLULhHyDFjXD= z06$NRQ{*)NgcFBU@;IsGGx<+RJMSR-_;0WM-Q@WbpS_BwkXpTqt5 zBKr?E%WygSI$Ot{Wp7|Z)w(96d@A%PWRQ6wBirE&d}_ z44~xz6`{2!;;|fzLMFYl8v)zhGxOWuoc&{d_kQoapD#))!R{g0-HtV4KK5GY`wxNu z3ds+@EhXQ&JHclE3gEUIz->+xMlYFjw$fXLI3cGB!b|Oyw zKi8vXMdE|!qa!ZogI#{e_l?gz-!ll=_q`7!42+%XQyAO%7(oJ#W}gjw&x`mIEdRLi zwMAQ}Ejx4arTtHpESOZ(L3gXsOZzt*UF!DrpQlb)mBSZ3He-n-r1QF*c?k0ALwR6K z*EUBsM7N{u%1(8spQ(4P_19_5LbKfBYEfFl924PlLSZGMM1wg`_}3tA6~Yzl5|CI! zsNtaoZ6n+2ZVfeS+t}@nHuoO(u=$70zk zi%5pZ9Rg?`J4#IH%AKwk@`N2Rr#nF$#j{K&d5-6EbF+dmqI`co_6$bTlTk~)nO~V- zli!rzkGAltcnPk?o2*)E+uNI;G)vxo+PZVMAB5(6 zB)Vs$tu&kQfsr9IQPgKXlXR9j=dsHi%f#3C-ExOj(Wa6_*A5YZwWR>7+zI)(J9Z8SIfVae=ol*)3PRsiX@3n z(I@%U9Is2kl}d*~C<@Y|wva*6KE%O*d&`U=$pvV5E*$G%4lpN}vkb*-s4=i+#0|oT z`X1D?{va`?tF-r4>K-uOH;(E4481ue10`a2It^(`h8%#@N2Zm|s;b``C5ID+;dbBG zyU|9h`1eOmr%qO`UDj#+v1jG%1&fP6`Dj`3^hw!o+@QOszxT{5=ZB1G-fR5>kKbDn z?cYgG%bx$k$v+Wko0BFFT&KPQ^$){m&2h)vM*HSRP-1&OFfj8uvfDx7)s34XBsEv=7ShYW`%LMP$AJIY!8gGkd}yJ6VJev zcr)(62k;5Z;V&pNlyp&;D$M5tHwXOKZ+iU+e>oe=4Go8yaUF0Gu5x_Sok?J@@Pol_ zR6c9|L1d1pm}+Nln(H>K1uG$qV0v$*3a(|=l?B(JfHFfRjoLcIBOH0uu#q{letO88 z)FC{u!0yZ;kG(rh_ZtlSf_OsRn@7lHN%SH?vgAcsF`uPF$7wdDY2VWZULQBKUL|ND~{E@j0 z`)W=v{^~uc_Gd+UGLbW4@$%!(HU9kxjBR}lgK2RLYM4bUO=AQfr{eSszJ_n&H}fom zX(ERr2^Mj@-yfpZ*(8JuO@U!G97pTyDuS(>lxGk%L=&-@pok#X|N3B7X3jrIKvs&U zLVfiY!|g{^6Rr(Ti{i8~fRSDl^#R~rwx&|Qv8GX{`ugrX3U9RqW_dQeRS<17$FLmB zvn~KxK&HQFBK$;dBG1m_=epWlTixxx9qMk^5%s+9Gv+qqkVFyeE}P@!MTaK6Z{sdN zn{I|@ge${jO}HscXyJIcBYYxEg)yNaEf^1;2$Dg&5riHYVc{e^uWTx?V#fG5|Fk9mA~b=y9&;I3u$ zecV>DaL1g++Yt4E0qC5w;d~61I}wRF@B^T>v@Mt&8k;!5_23@jB6X3bZ3|LQZ^doI zHmaT8#c?EZFe5nI=2UWZm<=M88H#e5GBlBy2U#QuLc>UbN0hOqNtdUop~6zPQmKMK?>*k{{XXsAXW0{-t_;O?0l>}%o0Cc-Y?lE zJ7FasSPun@fXr{0d?=C-f^ZYR+aY^L+x@UYjU*@yZY)?iMhqbzKNRKg?7xH?;@A8) z!q+1GE`3ILSNs^A1LxQyevUrl`MuQ3^j_f=@lC3eepBcY|4Q-0DV-i6XyOiP3%x^l zQRFg*e}lua#MoRQM>FPwhaX`4qV_BA?96z=ou~x z&wXw7?r!#Rce7;IY!X5!dEJm;&|E7Z5FWuwV8N~FAi<0s$zrF}PMI<-FBxeqWQu|g zwIb4?omL=Z!=rVaf^GlNs#C_&l+r;`v^y{zim16a{m$LQ>ORi7_wJp$=X~Gq`+dJ3 zW?%yq&jkVs|L+35c9b~zhDOCyVWRPb1SYUB(QH2~AU*X31gMfIHfw6Rrm2d=SV~sP zWm%z`u20%U_!B`#1XEoQRgEdKBr_&Xg2Xe9&{U!F8^9M9aHFlJq;uLiy8!^fPxTbg z04CV zaEJX;fF{%xbd5@niAUHm<*;@MzsIEQ+H-hNI3Vt42b4kWC_XGGaU5pTaShAj9=2WB zE$&tn3wJPLswvu_&ZA4zwdywdjQSILNc|aokN#ctwb6EUA3dnPN&l$6O_@p*Nn?U6 zX;hF!1eq0)A`3!_fIET{Nz+nDEQi%W+8~LtqG$;C_Uy1^hr*WBrNHqCIqrjEJc|ev z5nLr*8W%m|-X z4(x6<#9l_{M}UBSYu~H2zOG^_P*Gr1q=HyFP7w?-!QPdW#JG*XlnDS&iUlGl6p5+~ znJADAz-v5S5HKXGXGj#DEs^LDV{!_S0*Mae&jnxK35CbU0B$#pt1-hVP0*7j(RuqS z2WN0jz=I_(I36n*L?6sC?*J6++?}%Vdk#rd53S1!L4ZV@F}xOM@q>7!^8x7>Ryb$L zyzyT-&jaEj&|}ZRt`*!jg4o2(A^#jkaBxy4=mZ)qmSiYLm8+u@sagwjQc3_xVu49E zT#!<50*o$HQ|NJ=5{jJ;thK)08$5I1v4R~YywouP0wB^1kqFfyCAdIpY;b$58Y)^6 z7s>+)RyYk+E4rn`ZLM4D)dY<;3bxQK^uqr<=-F9-lsf*)sn!VJWk&9HJwJrj2yNWB z=8aQ?4+yy*h#tcx5-H1*dR1vy{MJCLjTcJY_))x38o=L|wqlv2($g(w!+qeTjvNoP zYW((A!?c#M99u{F*(S1u?O{XY3{#TCU|%6A)=3)KGGeobNjKX~wyHnY?vR_z4-Ld4 z20mtSuD%7*0>T2P!x4cvD{0gCsPI*+3Bz};jaPjP8QJTuBilUH(``3PjiN0Qu?-2G zbU7uo4I3yZ5QzXH4Tjk*@gPE+>E6Zy?v*!uuLL2ZSj=(Mzy|>2zyNjP=S+#k4Rj^A0d1g;f?Q#?|xd&yI~FNBj)X6o;{;eT<&e7k=ouag2-T!L@I%;Z()%h zM305~yk=F}G|CyvdzkjEaXY!T&r-PSSQ*yM%V} z^xm;&nh7g{O>&Wp5qgxqDv{^tPbIPw?;_;8BCZtoz)~crWGYb*iSM7nQahsU&^Bh- zWtYVpA~_`fS|lk?QO>e`m8cgDKxj<%%AcpC1u(u-G=RArzREdx(sbp$UQi#xEjTR* zPvY-f#!t9cFPtYQh05_O__`bA(Js1=(=8Kecx2qx@fif+h2Y*}@rPeEuAzpdMTjSW zBt)NeA3t@9M{@=}if?!sdVs4HpusS2%m1+TX&I{<8Y(uR+ZAxuRtdr%peGF82+22w zh)G{QR!WX0n4E zk%puTlKwmEeS;)3%}s%szKmTz%gWeyO^3luS{pOt8IoC$gjJNX{Z4QChp~ea~ePfl$i5)LlWn+#VL82nRtCTk+dGlJenc7 z`Yh)HK#Wjkl*~px$DvaT7ONRdl~5jurn&2qBoOi3d9}@M11DB>mxQ6&fcXNQ50_@Q z;`I~t@4R)k&?O|Q-48W`2@4PB4xj5excB^$?u}g!;jhpBFw?er-jew(hDQE5>%d_4 z>0!6<%=RS}ZKk|n!SP*d_H zf`U+4P1>Bc!~+Qu?2&rZo=8tDTk$cIT4{%`Bh;FhPrH0wq4|kH_PnC%WdKJMha?;q zSvk)|NYngCji%-Jz%)F~s3Ss+zkutY0tV1l&gRL^QoQqXmlmD5*OnRiNs=jYrvv4c z&*9wtt8J}M>Qnn7eX;%uF_%T0QqutlT`*uE2v}`61XieIULj;VvH64JZ@8{Avi3DQ zXf1jw_rq-)*6$EcJ2wa2G4~Vqru)~m*%!!+SC$VPI(F)%7kRa*&v%7_m90bZz>p2zw?9h;bVdMhgxNA_J^QU2K=wXLpza`^Cz00>D>F=rf=;TSl@qCI{Sr@PX_5fPNo z3m{5_+rwMKN5XVij_{5ory$`)HjLwpXECVUX43TVT1PXTYAs_rVHrMvf=$fT?o^)1 z!E?+V7f-<(e(VgqnzF~a z?(#kdvgE^y`tb5T2a;7#1&K6}b8kEj!Y+xY;vQfNgdtvTN9!=g2`XY>00eLiaBPtL z5}Ea%oygyOz6)u87(;$G=TJL47q7FaZEGG*rxE&k;_%Va2d@Ga;`#UT=eNJG1bzFN z9ZgM7VBRpH0R9GD+8{=px%D)vq05zWwTK~YcW=Q@vjI&Mk{Ny_-^x>bwUSWVRZ<;6v?KWfQBrFs z291jbX<$si;A~jIZKGrtQP?w})F~LMrn2ertaY6*p-i$p=^Pv|9QHKK#X_sthXP65 zaiBOjmlgCROpFn=!W?Kg^yIcDqD_ky)_wS4{>A_uZQcFc>dJSOhE>b1PMx71bZbAq zitcbHhy+^UJo0quo>J29mAY$pOMSI;IjSHls5vM}CMgFskxkTkxlL=US`%9XTeVrf zquvSl7f4BCL3Q%pWm2=Tth)K$Ti#qy+z&n5ASPPj+sOpC3Fd7>c`la63n zp-_J%0S^nb#2&Ru*6HphjptBVLM zjPQZATd~FUxV$BIXM5dBG{KOq~$WG)O&2Gi-@* zPi5+WIcSpI<}H)_!bB#aMGf7hEqHfON4IpOTfs~r@jboq^zs~*d~h~VymI*;#_`M; z*=2VIf-^vII#z5Tg^ zWbLtab63Ri?L1g1>r5OxTI zaD$;(j$mjCx|l;;AwGd`W??2`8J43(l7pVxEEoP7{$ zuE%598J7XgYVyDQ#$M~H=8m)WJeP0l>(m#KRrlj3YdY_%)hgupJbxjW1Cx{QAKM_y zw`is+wUfGyS#=*EuN~s@5dXm1=jtg*%}_XZ+pXCtj#8)qYYQ9M6XFH&vhcq6u_&&l zIw(@&OreGS2LBYx3=7xjF?x!=%`z*v75qkaJN*OtReFFq%pT?r^I{q8XXA97sbOol z8a^Q{qn9xv%-Vt|@FF7$6ia&;nuS~u9uLonlqh=W5%N1uh)M7bWgOxjl}Jw%^%1BH z9Jaif?-iv3&W@!_^q9aDiYsVcgu)+G{~mt3@-CmAVF_yb@{kZo5%D$*+AMUdUQh~n zx&@^M|D3uHS?EEuF8?xmKL7jt?On{-sR{H{{``5(4CE+=G0LqxyW1rean zo{U|IeG>B#u|%vD9$biBi?J~$RFcZTb)Wl?;UY8_D#h(^NaP}JSEM;bRqa_NB~e?1 zl9H9EUv<{ib*N}76vznK;>e*{(b5vQx3vUyl%Nv0_p7RC)W(zK5JA}Pa3y50b?U)y z8(y`YMmW-NRN5)qnZGcVus^V`*_3RT*?l%e*yZ*dd)lULtNO3$8F5&k`goxSq$gmG zfmS=wlf`C+k`$MgGGjpcF6To&d*is>qIe+kZ@#NPrj6^4-@7}XeZOqq`RudL5aTl# zgGq3U9pZ%5mxj0rG==SBx@pzgN^3T4`6C_a)Tl&aq@9A<_nje4I&~*_&riNP_Pa<{<_Ruhpfxw%YdC=rJ0>ZaJ%M)sByy z7RID($!ZrFf#<=3lPK&VOv)zE9K7VKD4XNMf*sda6oos?EubmPA@?x1S*iaa?_6Un zxcA^aRBaXs2%OGjCkxjn*M2(+1Ze4bujyo6fL!$2u4VPz7qbC6eEQO=J>B2Oe7ymD z`AI-3LW=7*)?7!Ewp*@SZu&BL-9pMfi;pEU&PG?GC*$oW2bcj{zc9vrK>pS8H}(Tz z(lW_h7oF#9?~s3B-n9K*uyooEGu<{yGEX6|;u0yeRY_X47Js{+^xK2PJ+UhnUUOk& zLDktdXDeipHZP5^q@yNRTn1Rc%Me@(!$o)L_l6_0r*EQo_U%uOXKx)r1%3PW_4e-D z*GK9vAm&K+@~1bmZ+6cOzcf5Nbb5Fg~xv|jBh8p z;4k^|Q#qU+>uyxRMmn!8z|Gm81EJAZ+{gq_5gA!1@Vz!B^V)IEr)c>VEl zL}qV~Z#h~ATkLtUb;olD9@~8gwzhs}_V3x*>`eBw;nEwj*O5SJejCe~C zB*N~;MWA^%E`p1YQ@o%-R<*2CS8K6*U+ z1nGHb_t!kj>+ggSu~#>np)B~~kRI7KpCgkYU)jBRIWR(nPsl*wlK8To?z zu1w2LB8({W1dwDG8bT!UNvUy^mx~u2cQy13b_Qm^fMP&@C-2W4h7O{3MBP|Bl32fW z%NyMN%itsg&91%^H5dsE;htW#x4I>>`Ju0^*icS~`}bBS{=H=7`Rq-=7=w;>0>)DE zcg6%GF(F&ADyg9Xc|hqe?k#1lN?IZ1Uy0-P%fXLApNTU%QzABqyTo3;Up}Xg3)Yn( zqp&)>Ti+QzC?8Y~=+76jmEqM)ny(S-9O>YLx>YYM4p$0^U_wuX5`|WVvq)^vD;5j7 zu7|9Jx>5EmVZZV{_jgJs=nYoQTl4>NExFBJw`AT_ZWGB zc))}H0b#Df7OXEiT0|BZ-u!rxR)+ae1>LDHL$NYcUWUpR1!HiyDo~J^*Cum@TXM?G zilEHV{bRV~w?S_pdvx5G=g?>eUV#$bAaZ8HNH7R7$b-WA(qKBc31!rss7;+g98yVI z3+iOVB?@FjYo-yMj_~yw($X#~q(S(>!DQjLslz``=yUJjEEOEf&HC8f)zL+Tczty= zP?%f$G;?kE;lo}LE!ETdfcO*rE&Y9+3F?AK(;6|K)`$w6+eX#JDVRq_S?&RItrx}d zY~+Lb6DWoZRFCKu)P<%HMZmeQM=gjp?{sMDVoF(JO;elQ=uC0Ue$n? zsz#zRt{TxLFcg)*0Pl6E0kv6uQl-@f%>ey!XsBMB)5v-79ntBgoSI*Y;^lO7Uf-`p zbH&JgnKA7U(E(Re)2i)Y-3sU4HdtOxIU+DX9X|Pmm=qKti9cQxl2D<4y}>65{4j#& zK@nU<9y87*Kfd>Pg&?0wUYfbHe z<9{B3E(*+DCy!aqfGYmcC@CNcP>3sWEVtL#GY+fIO?WAfn^0w!f>fDQke6buoK^7R zaytlhNF7nB7MLbfN*zP=MK{8tF-o`@E9OnRz_aCCIYE@8W?%`p!-#mPuqrpWQ_7%n zL7`fdF6GC{yULVeArz-lpu`kf@oD>q7VK2*NG0&Z3gC%xLYbRbmZ@5I8=Ta1Q5TBVd`0bQm1cX+zyC?Uwp16wCOSDzZwd zC2OTg(rRW}iRL{7=T;PsWn4(x_^qDwQC{#CBRK5k*aC|D=kD0znO`tSUvK zSjcsZ8n64^SwsJ{>zVtQ@jm99bI(0rU9h4p-*3 z(xyl%MQh5K8dwpnM@%i+fMw1(Mg6%QFT!nUkHQb}rYv!E2T9;HVc zRYo<#E1z^|O*cYlGNv-a6wIn7RV<>0jHn1(R-7bQlbSLTqRCoI^6I0;X3|Z&)gIn! zoFGH&ggRsli4)ccImJfQQ^qMVVqGWK*){c=aa~-qZj;+=Mx8Nkiy7-axzFa+1wL=w z7xPw1om%?PF{;~htPvYyYUzeM6LMxfxJTqnlMWnhm-2Xb5_{9ZW|?9gux60=v5b}X zoiGkeN6t(QO`M~G3`x4Iiln1TKXjR&xNI^tHnr4uQ4 zhOX(Ht14qsAC^F&5RvwFdZ`yhp>Ht2OJa!mQDWlh5CyywF^GDuOhZ*Ut5ik%7ON^3 z7ptO+m1Pl-GX0&)RhqxU{XuxxZcA+USE4RR*}Pp3$DM#k=btbgPXV8JVcb)|2VOwi zHyuk}nMK=I${o&bjhk|I>%k`A?jkZ5Nqq(70dynf3RvA7_5@ z_7bwSH2bFFhxPaxaD$b)^qJ%J*quRtFp5o}vQw2Z!-?$2abEtcf$}2aUInYGCb=Ev zy^t&|K)iIiYgO0o;r^Z5qZ?cI?~USu^3r=>(COm-N9ygHo^KCG^y{&H`UuhYL*GQ; zDg(@!OU_!qofCi!2VKz5VL{Nm*)6)QJ+Ox!fpXRGV z?BB%-j0U)#CC^(g%c2csVc=(Qt3u8oIgW(??~1{~ioqUw?m@*M%d}$hxPK1A#o+Pz zqP#NKaVL3PTHxZpX0W{@dl)RMd>ZNa!0{TDIq(sY!Cr7(a+#Fpz;a=SZaC;tMKJ*g zvtaryJUy<@4UlXrwBzVx zY0c00=aP+%(oXuB`XOl{zi=Xn#8B!~N{QC;D0CCj(CORZqloI+Nw1xWJ8>Gvu@i0x zHpJuJm=Ao89nSd#@!nLv7yB^`)%|jmI{8qjluvC+q!@ z0T`QQ4UajQ6PJHltPb3bW*_am@Z@v-$@(W=IQr|Bjk)UCS&z=R@B>d_4VG22iyoJkQC3smY5B;#Gl8?>`Z8}6|h1MR>#WJIN?NM^%&vW7$KR| zz7$OzO#f2y;#L6eQ6{H+{9kHhNCqSV`Oq}3#pA8(kSRQ{GQhtUip9aY8Y(NTNCmy# zyQS6C<9nY#ZjNlM1zla!Ti8;cwoMhH8wQb{{c&I9@vp#`OV2Zx$B>@c>g=<>J$Q0= zU8ZH@*Eaui>$>W@%?HlCGP%BglZv=?QO*u2KPMsbeW#sK(=aXFW}y(RHma>qXtiCi z+Co+vEf}=fY6#H=+HBB_;wV(f2Q$JEROEw6+{i|qx(s(X<#}&1gQ1o}o|rySi~mp+ z0TK;M-ENo2pms?bLoNz;ZpH;j0)elfEz3(LebIIchbF8uyM}+$c^HCg*Pq+m@~b`T zzWVjCJwKuxlozANHf=54%j~L5buBFse5vnfOSF+Rpy)Vx37&;Dq{;CrbVuNPfTjay z(4mYe*n6obNfjEHra7`&x_oi4wUs>lgug!ggiqjk@*lRVKDLSTjKA-DXJ2f`KF5iD z=kv$ePW(X}ViMc26I}Zs2xTw`ALW}6rgbBNu_TC%!CG8Un;;|-Hb7z>6IHi$T_-J+ zrXfwWrDENOwpF0DgTdOtq>QkSEKo)Jr;4-ZJsZbFadN)%-TVCB_x(K|_j^7;{%Z_@ z;T}TA7GA8V!l31puw&SyLv2t%^7dcKb!hfzJ_7rIYX1rT89@3JJ3i~X;v>js_U(lW z)+g4qg)y!zdonxNUI4Z9h-(JhkZOAdZ^B+ zH>sIaxoj+OIR;$D6^S88j>zOi`Lg^-W_VeVNw=Jpi43ypQl8i9k~Q@n$}@8g@M=`N zWC8Cq;4M*jg1fyq>mBlvcF>mGD1H_|Fd^O|ND<=;(DBx*?5@f)ggygyWu=0&H(^iH zUAR@(i_5Un<_s2#y(ZznB|P?kk0 zM$d}TTov=`gEUx{locYSgU-4FW(}%4Z!7rZAz(CsPwsmjd5Fi;?kQYR7=x)I<}rlm z`aQ*^&?r$kScuh%ZUWY_x1on}KN+1*ztOn|!)~|1012p+^KRLlaWig%9ul#4$6~9x z1zC)c4g8H<9xx-=JMX|n#t*3D!%781GA=yi8h71uF`ZEN4WqgD^DcBf#lO1#;|P&f z73I%>qD5zZ1u9?!bBe_p-R9XV#M9Ltd3-LgF2!E3;X>JRID9p%x)~y8mL^TNpa#=g_{By7j6ioN5J=l zX@T&9EMx^nFplCnbqAqR{(992-UMEFMP0|HLIqq3cwVKFm|b{-Yp?6Ri*d1yGK5r&HhxA78{IR`l_;W-K4kftTVOFa^KU%Dp|xFbR0uT&F1{4{Zg zD0623Z?n3h?FHt7fEQ6@+%07#(k^vM_a$aX8kfihX|F^izKQxkDup_vu52MvD@baD zTndk65uX*Y$h)bfxRC#acDJyDa&i^V)16P<5sU;$XH~*+#|XwwzPc+2@_P}40TsbM z43X#NNAZz&+Jf|Q-V>l)R^?t}t2J*R16r-rAq~<+NQSfn<;gNe_gK#*^+}|`kIm!; zA)RE1jKd>)`To{|o`kLaD*at!O+QoH+ zN!Lxy%u)$E10uFEM#T>3KF~RdD%uRjV<305Ti<)>rT6IZ`p!&dCq3BnFOTJK=6~;m zlts_x4zg*@734+%98kXQ_czOHaGPUoV4H56v|a9UoU-=^-jGJnHTiacKVs@Pk%WYk zxVel}`NQs-K#SDk$hx%>!sSMzU62F3$t2nwZjYZB%w>9O@shLHjmC>6u?n8sqat!f zU1QMAdCB2nE5}8(W0*w@IXt2_n4(6LI7+$|kG(VE%DCDgWxdWwM4QpJYZ%cE zG^*GH9WIcEBQ~LZpA}byXa3k2{l>Awr!QdJf0j1%e!J%vt+{`fUosl@zwkvSJo`Gk zt2^?`>s;=*51&ZkiZRUK8ZG`-b?!{tgT}T!_`7dj-wKgxoSUT4jhfJhN{BOv#AZm8 zu|L%OG9IHE32O-<0BLNaFBM#9S@cS(mXh04t<>nC22hC=Yb-p6g8wL@h8~8lC zA%Y|D`&xvHklCDz-OLLn*ixV!<>WLf=vJyFq2tbACu}xY_4{iRvoQdk6r(jgIl(Jw(;6#hx^lS9zFP* zeZL(G9oTbVW9{kYPi?mLzJpGdRLGDQ%X1sqI^a5r6x^Wn9}B-(_v0ATSJ^N1)iAYn zU6y?kqZc&G>^57(7P}p|6Z=a`nZNR);d?F2k7|Dsx#MSIH5P11TbG9u^@!&~NBN@( zc5`TRx+l%_gsz0Hq?zlXX?{AvTu*=Qn@upX&lMxqP&~ATXY`3RiTw$to(rY zEf1HA4USQA?rrBkWCUl$fKRdVZjs&HfPG{5DzZYz`^(KSYns0dU2igj+M#eTDE?{! zCrskqSbC171!9=r_2U zp}vR5T587J%}ufGt5>Y5m+|i8wza!sGG!2XcwiJ3AYrAB}(T z_sP0&{l46^FV@eVbgfz6T+^`BegFT2S8H$+*BQMJt+bL>+SN+3EX9^3%d%w44{XVj z4IkVZkPbZRUk&&Lm(S0|tU=(-!kE*rvgT(4iPiJDCX(UcpRD zCe92LCS%%kT4ze*nsz|zek-}2cKV|$t#s$E9(%uY?m6e1QQNUNc2FwcJa7NiE63eS zo2pBSym>ojYhs!5O`C)sl!A~%S92@VoU}xcb2i6-}`>*@5Yn+MUE%m z#-pe*3h#;03T5+nOv%!PBjKRi%ixLe(}G= zVBwWxm1Bw6=#&fxO(}r@QYn0Kk|}mYrrG6#;zYtzZm3aPO*`k^?7n$@jbImU*IfJQ z>Vbkw)=*Ynh10a*#B)J$PNcNfAkx9Bx8E6fd+{d)f;-3d+kMaP{di47i_br+ATQs( z?r3aQ`^s`>!Ly;f$OliMnySgilXsbKm=VOIEa*zBuua-f;q1jHG$*vZJX0Zt)4~o~ zAFPL+oxdfwm-aG!`aZ*{z`X$b!`uzQw?cGf=JwFfgLH*?g>|KahSQdYR@i7*tZ-B~ zXrpcJ6*HjfV^#AAZ#B!)01 zf4_`Z58seGuU?fqZw%wrSGwfi_jco)!$+{^Sg(9f)*SyTAI^`RWb)y{p%7^W_6w^2pI6^4(*{aL$pV*x&U;riDZkTqP}e zi#NK9xW&ib-BK-|!MD;Pp6oIkLiE4zo{1hyi?)V)ai69S(Eg%Oy&?2wczcMx7Veq( zc{VL~uF51~$13ydR$4*JfeX~1?JtZJ&=tWR+LL6$Cwb~{+6o&9i{%R7ey=|-Vx(?G z=x+nCkYj$S)rSC|pGaJJ^=1e+Nvw+$2hiRJ`@%G zr%hb*ZxaVF{|Cj(UGlvi1;xWSr@KeKmvJQb^u`ZHmY;2IJzjJ)qj7fA8|xaXUSUSA z$b0_-zO`3=+$Dc;^ss!lJ4FG1SHc(GwDrN|x37Qq%}u$rbGGl>x1(OkxFe)p!+;iR zkOf_ro~;nE*OV_tO!R&3lIey>*KjSmR*o*zHF2-%=oZ~hu2V~1s~sc<&M>z$%2q?S z2%?xOkitjkMbd?==u?~y+f7NO(ecFi1c>`YU}7Qwy9y)^4n^*jumpySlbH#{QzLYF71r$|DX6zEJA?$MIgc>MDRG@@H`zdK*{16EQyotPg4*vkzRezYueGm~8 zwv5H%z>h!x?g9_(z_Y-*`*1-1OsPGi`jQ+^{(}a3(=4PJW*C?qKCOPBCTfS44ljfI zu(R3|ZpHHg&nxjGNk;f#W$n=6lm)FpIGIPk{+sH{M{vM5N+1iDG9Mu`+AA$XW=>!* z(F%-;vI3)_EU(rPEw9#_IbLlP4ZPYU8U#ko^DP2n5d?-2Sat@LV2Kee8890v#d?v5 z5zcJpshU9ouQL;loloqR?kVF}Vyogp(PWT?R!^8vUNMB9_M!kZ4*b*srHCky1Sz~~ z;G`Zv2lvdC=Mnq<-|fd%c}F!KN{n_6@0b5f)}O}&@0Qoe@_9KSx8PkEG6$Lb1wxvG zz*!zv_)w~8uq?Nn6KI>I!%B)RGc1yYGOX5Q;5bn*@^II@3tF0Sr;nft{T9s*(^kt4`<84@ zozA+==~ick+vi-(Z{XKw{3vs)N>4MLP!ocz8AgKv>$0>iOPbl5nc-BqY#Gi>tICnX zc+~teg2Ql!t8*1mXHZYW73k~W|=B1&nMD3Oq2LMUBDO;K9M z-f{moyN0Se`;M7iY2Npr-xsYEmZqpovkNsKlA>fl z^iT0=q_7|=Mw1bp?${g+2f*4pMUQiTd;Z`{O^dAE))gy#YUt3fpM^cp2&&Zc^Ve@y zF*hwxRZ*xfT~qpgDO*~g zd*h{%;M+kaI6U!%8FqW)LE^}-C=EIYR~c>gRW`flPHmQbbLC<9(DW8HvqFBeV9cy& zK8xWQn$i3Cq*}3M3fe6_qEQu^*0Z&;zCPB0-z;H-Nw!EyqVRydXQgD0CGz*%RI-ja zz35oy-m_=-t~=J6I^NPVIM~y2{OHP}#N5Rz+UM2wT4UYqRZWf6(fm5Lb^CWO4Gmp- zbjQlozu3S3`08s<=2bra@VdSQy9XCF&R^^+p_OnZ(#2Z72epNp>@kZSPQtj{x+HWx zC`4UqyQ{`&IvHou?NHQVX2?_t#{=nNWT{J__Xgj^vJB&N4me(LoO7_6qYb01PorfD zg9ytKy|9%~xuDt2oR+Dt@6mbWemr5w(7uto=pJ6R24DaPJZU|VLAn6lunR=kWj$q$ z;y4bXHHs)wh@zZ7gNde)W2PqXAo2melV_p8rN^1!iJPViH%Xxd%X^Y=N$erdT&Tv1 zJ0141#261ua;~qAhX<{zZ724pnui%39nRU;)llh4a z>isANIl5kvvUvOI;P0tNE` z2^L8WNfyG=dOr3&r_5(=0C1_bL0G+{5B(or#OHb*5OHt~340HW$+`g05*^5j%v6 zZg4nVZnwh`a!5wdbn9_<5GGLd-SzocFGuVrC~EONcPW1{eWCm~+wSII0(m9J@1Z!n%P4jZg#fbmtBQUrAM<`{l3z&p~|U+e|Vno4D7($HY<@ei3; z$7U;r^dx4-3f*AvW6Ksb7gkR??bCQ1sT{vWX1h5Cg$etDLXSUCmqb#74asLWC3w*q zgsnJu>ngmgxBE})r~RCy2HgRd1cFOZLBJIMo>}NoLoQdf8gXV@h!KWhBorb2-#qo^W`hZ zfK~srh!UALi)m68_*VPcOJ&1Y@9_kR*E>{5kXwQE9C(@wq#8^Oql|2UV+G%KhoUEQ zR0RaN1TUhC z^H>J?_OHfA$FH5Z#Clnd#@-1;_b)^z64NYVSXL0-96udT%yL^9Fl2$>DpEy@@g+_6 zRSc_?eK1>!&=aL-p4dtQ#|eJLTjN!4^B?|axA2$I>GUo5;kvmf+OX$>ATlZqW(|lS z@d~z9_AK`n$8c0G1sedssCJ&iPA5tcWk7}(6?$g%I>((bPanWnzC)o}<>@!W2Fg0QenNAvBb2v0jD5h1)@0t=X zR*EB$JWn|Z1PCdRNdXiL!}O=CJF3wQwK&xiTxuI)bgo9=p1R}%5)sW2t0_J&%ZLy7 zgv}+Q%vD`34|i71Y)wRq%LBR|kV`dbMO|CGu{K&Z+pGKKQuZR_IodOCUQ=0heTg@( zxT4qEIMI~(xAjq9)BHqbojJ9zVkyi)pOiAUnRn285mHM|m~n3qyO0k_kO^v&CwKkf^)r@#t?#r-~cyMsY=ASdGi0Spm8_+z7 z;t>v_d3lf2LhTL3RYIe4X@cB&2HsJA{#bFLuT2QFZ)`GjLJ3JJLj(pd!}l- zOPt~M>CO+FQos=^%b)qJWoSEt8DXy5c^x2&O~)PQf2pqW;3lp!{*FC#pR3a=OY-X8 z-~-8)jRjtVZLqLHC^0t2f*Wwbg#acLC`TY^!1<$vrlF9Aqn)(%q?BZef#ASE07gK$ zzcWKh6J|m)rJ44RWZHBDCLP?N!_f=LeNVDsy3)LBccgva`@Y}tm32%Qb28>UNw%Fz z*pbJuk5JTS0j`!PmVKU$252D8H9)j%9|>2;{T9J1%OjOo-G^#Po)=0o!=8E~DAU3d z4e7mf;`rrDCr(_tk!^0CKfk#-%PbqY`rFf|um0v&8&q|}26Z{j%QOJ&f7m~R7`Uut z?l~T~kOuK4-seUxlea?feWPNa>TOOpPuHtMApvQk;xrAmhHW-`G#rW8!x~R?(qO<% zidOJP&8(kAES;G`R@+NvXifl|g_v5pBnW;xwBHU#BL~TUC(IFl1VzY=v!Os3hDXtY zGx6V_BHJVtHcod+_0-g;Kv`BDFS)vL%AzgfB`Z>*OrVCzc}D7q*O<PeA@e0h&E4=vi#;)AWk&`!j7N(XLc0PB#u4Uq$i(O;)YGyohbI(5u#loFe|F$qC-@8R!NAJXK?h-SLoKiEG2R~HS z>1rV(2~tcGlA1L2=6b19({65;dRqEhhAQ{ZGVxX>QIkqtAgIjy4g}=e3@S6ioI} z`8e^x8DAh(>Z{`AUY=I!6|GxLl}Vq>Mu-6<-C0``SXoVgb%bHs=)-Prs*U2TU8naY z&7xo2C}OeOqmXqEeJl`Yptq+*co2j&bwQA@B=#n7!W+o0%pT0*tQ>U2&6&L!)JNYn zkoi7&;Zf9~7+b{yzGQ3A=;`boeazS-FVw;OIK^X?&Ph2?nRQ2;EO1OA)Oqf&O(~)hht$>T_jvw#roY{SPXyJ=2#;EWhU>Om6-9h8fk!LXwSrX=EuxR-~c`l zhP<*PVV_|~P88KIw!f=8&tKGYNA)N5mvnfi{w45TJ?4?d=t6GeE@qeh4Kp7_F=Nz> z6{f@95x`yME=Q*e&u8XqR0qbDe!anffYWC(8lf(r4LV$cv(o2hf^J`>-^o;j*$`(I ztrf<@hGdXrzoAh_e?PE7-bv2bBVRFiwh&v3EV&AuIza9$C9-eWty5b^O%O3mdj%+F|nUh!usO9hIfyzS^#s!=Gu3Ttste-UtG?-OjI`pRp50c!fBmaR9{)| zuMaHHE)5ct4e}i>sME%@$S8U+U@TOlkZ|aT#bK7hM$8GL==Bl%n-&_nkjIQUz!G6d z?22d)0>L66!5cCLfoKtt=#i%6d2UkOlH4CJ`_z)mE!>h-8lw_ds!*l=&Yq+^@|X?N zrDT?>LggB0K>sa{RTNQA!Q**lrMT6@L!^*dJJlCO;C|oHHz zzz6~n{sKA#H0Y3GMFCuk4`PfxI{irSlV7@J`Dv;W^LgT1>E~%ndw<(4wItApHz6A( zM^CqBrwzPay!Cl!@zc)9_uX5lD83DQ(M`&R-Ecdzn3)b((5Tqi@4yzc03noSFo%(c zBQS~HI?u9^Tb<5`gat{$Aqa-gs2KZA*LX3s=Oq786cDzz+qcojE`_K?Y;WT5rHBxnmAFg5t)wE#io{ zwlYSJ|s)Bj_<>SLR_uJ}Fo-uLeNu<=Kn*e@i;PMkQwfQ?D8-KFKNEY#&g z&9ni5&4RV#qopfzfooIMb3y1??aWX6npHQ>uv~-G(}A(w>b@9vqTL zlJlfCaNecD(3pLrAW5=3YJ3>jFqOdOt2TIyG5eyM6E^>D#uIg5g|1Z4c}ife!m*M$B^1aS#sdti7)zgUl__%ph+*>ah>~0l;3HWtJTL+0S*o}b zm4W~Zy5Rj=K@yt~ap10N2H->H&tX~1YF0+ex?0S|XjEtX+?^h}7JACXa$Z^W?*aDS za8B-YDVfEAUBrEwuOR1uNJ|q*SnSL$VsmE(DR6^gOK&|2;ae(m!Ge8 zf@5YUw_JN2bRA3-v2P*e@A5i5tk^YA;=9xUNvFC>s07B^dO@en08s$E(r3!Uz&|a& z3teS{x~|K&rhJw=7`UG>`9l50T>YM5?tb!1ncMhqTgT(VWH>; z)+ru>hXg~RB07QTOgh|cD(pI?%Jn7WGOmUmP2fp>nKKV^F3N4Ur-RqKMYhK{FXMs1 z&@d(*HGyQGd7Jcoix`)mt3dK>^(b>{nFIzx@an!lOP2lC>Pob;)Zt2%!<}7#@ z&XuQ?yGBRsw*7>NELdm>^z#8brYaP;ku^;rI41^eg`1*PxoNgWoa(e(vadQAR~jk} zNzvuN*^OX&YAWix`%=SDKimbDJh7P$jGmPW!9zJEaZ_R^d z#bl-+`2+>maoR!JNdgjuPBJ#n7@KzyHoyWh$*!TMU1xP5l(;(%ny?xl#OFYBFH?_M8|D!h@_)wTqa zp+`bHLM#*t5UT~KRugFP`)G8sqSsG$vtZqv8h@TZeOthaQ0iL{>!TUl-x&Ak6ZE9c zbSn~v_=m@3?g~!w5FI5$L8da;C27hHeBtvXPalE?4w5}f8N`q#Yh4M&>rmz52vcsU zjdrThNW9hO%{a=ZGg^y@#}k@VpErno$=~U16{m;4x~BZE@||D2ec+YPH+^8Uou#Mf z;?lm-{$Cz^Y|bl3w;#BD`>iwk&%?8@{?7-N&wt}q`NXaAI`-)&<=f?pTfPM~pMm=m zsaJX{SH*q&0n&`UDFaW~EuW7cnnrhdUK_uwoh_WQV#+QT%hPUimZz6;y%|Kv?VAzk zt6a5pG(^bdt$s?OkqEa2rUzyPSRfumq!JGcCXz-#gwu(bJ-)HS6FU`qKgMFV$Jc?O z+;$|qw9%mohsWpS@J>Unu`wP6NfX@G_zolo#EUq|h}67|kq&2UYOjuo$<;B`;Eabc zu5t)E!;x`0vP3GN!<;AOV3=_^1cRND&^P%6i9#|KZLHstgIqZ3NrRnUny#c-B%Mm{ zNV9Ywed^exsN2epilWj`p-@D$D4;4D#2S@oAupxDMD-|KaWpR)qndX_@=EHDlz$qL zzZ%JQ;a=TKIy?MhLO0CDgf4bRp$a8Xl}D1KsP*8V`q^8{&dhn_#FKw7zyHJXZ&n|l z(|zd4WxroNuL(-s#`KyY}bj&YlgKn=iw- zmuBPfl@+g@e&)I7X2FxsZ|cc@|2wPR+q-Yq8~d<;E5op#ucjL@^3kJJ;?PGo**c;1 z3bA$~wUx})ApuiU44+ZX*TDV{Kg6C%V82G3nc=%Lj}fX6F6TL#C@H7;aGFM(S(N;U ztz<7MXAv!fq-c**4dJh=@wmX14PLA1gRrgpJ-B$*ye8zQX4OwrB4WgNnu1B7mHfe7 z6LZx)JED?Y%#8p7ms-SA%V4wdBJVmm{^IKztoTW~HiKlsLkL>5|Xvz7hpw|zIVw&B}fD-ZN<*jhDZPk$U?tEilC{CL(j zM*L7gb$k%l%q;Qv!7o20YOV#dE<#-Q_>sNWk8H%1a{bd)adBjFUwS*V_j}T(!vF7- zqb}phhn2G+!Ni!<}{^abU_pVn_JM%JMxV2zm=^jFzRIP2tQhHa_{ z?pY5ugK8oIsWK3=ud55Rp=(>U%MdgEaa|8Z2&WG;C_MUiRFImSHz+UAY z)LtIsa<3EphA1 z_Ud|%2HK;%2NUrqQa^dq-Gd$dQKW*FYtO1Gv7P4~EMj!86mfKzKmofklH01v96R@d zRa(QLv<58pk?g+Z4ImI!AD1>h14-QGd&O6XzMn?|JXe=Zj3*5FSgG(*d`{}B6faIGv69SGf)<`K?`WEvk*oAZElKSt+ok7De%t#iS9>7CK&yL zR-!;xex$S%v;rNhv<#YTt3b3;HWp0?{s6QNZ0~u`iE#j_tL3}1@9ufu=Y8JyeV)&k zr7P%dY}1U_V}v!EF^D3)2ObNZiX)u6YMju!DAIJ@n2i-D#kkTbEI~JBV`8HGX5=LN zj`OKOaSB4@RM=a1HdlBNwzL=a!$MfWZ_BslpCD(*xgX?zlYf=0z?re3>ijN$8LRyF zjViy5`2z7Fpo;`z>UNc=WC)fW>5Kv)>N_MkffBcm*)rBNMDK!)KM z4f^3YYDSM+%6nWl+!zd37v;KiY70LjT7vV85QOHT-R$z+EhgGV@$=$!t{EAm399rT z3+TwAdKj(;)~rGesdKD#yzF3q%OB^@^Eg|bJn^xOW`7{D&jEjN0PB+jE*t#E2DYk* zFf~%O81b`;t#f$T)HQjm%yct=jRCf4IxE>l-E6K_Kw}hzmb+%rmQZ4{P#q5H zYke>KhJEZazI{Hz`Xb@TiU=VQbI=vUbrkf6Lb~WkgtTxhbs-8;$`#8#n`zEwq%+w} z#v^s*PtTOjM!_YGc-$9ox?M5Pg-Gtt))|%|C7Z^DdV2_HLD~PK6eD3Z91R!2cco#*uSy4n+yD3`?kZi7-60*||8k z0L98dj^{i=NzB-pIHnCBiS6lNTk-| z^(pnL$F6{`fRb^$7;nAFE<#qkDHf4^DMnS>F|S_3a*)M}fH#hsK(;%GlPYz=VJBg`f^#Ic+AYgcs` zP=xjRcEvYe@f-07cMpzT%4g^~6`TCmsP4%?>5$8E>u_NQJVy^O!OFs~=~37VU1Ma& z7(7#WV=VvNSmAASVJDdl``M>)=S|UTNgG2#c3dYKZfTBjb1T*vvtjIEOrLJ`-W1$zi0XLK;# z%rfR5`rIC^CqM$4HXNK%8w^g-s)HtHpkd0axV9+x)aaosWbZ5*?doa@j~+@x`c87R zDX2x8#L<&jcJHX8?36%&h2=x!6+NDt2lIwEEZwn`EIp8001JlgbD%f}=6sQBgvQ|w zvv$lPvkv6q5FhStxY#G2ImeZaURGawGT6WeFp7Qe#%rH1En8yQZV>8 z5V&HuOV{zgnC2*>7!X_2zNK8R9SJIs5Mxm@wbm+zKx#!%6s97{B$ymDCw|2{eC2b~ zqt9XQhV{SSv+HFhtYRJSE0vx(n{=Bzcp=Tw_EpE4_Vom zHEShSGL--9Fg6F)2d&{)=tx#!qK_G^O)rh4co17_I0}MZQ~`zd!cL} zjiPmN1g(E+M73l+QoM{&ZP2Zd6W5Dmy|`T@BBII9j6e#NV?pc7XuZaWM9F$v@#8Wh zTcC*5fs`28GARgXc^BV*x5Dd=;z#Ip_$}b6!&T@xuY2kfJa)a+7&u?)IE~_x;&uMI z(ZbB}8KmR(>UJXe;h-P<0z+rd|M2XU?2=`>5jcq>uG6as1O(C_CZLr~9@kF?P*43h zM!)x(mlVC=6{=`Y-iLeIiIxq9W!t!itI={Au2{)?%S%3|r?^-5_IOz@brvd{nAAqH z+{OrOFL?`efc;?r-z0Az?z027VxKc~Cw!t_Q;RA~ktV0Is;<;0R9qc*jp(WmqDwo* zDuLGfxe!)~PCa;$zsZvg{2~4n&;F0?>W^*Wy5sM?dv|A_?`)sX@#X9U+X=BDE)6tx zO(3lgu`~@`LI91CsTP5@OQSMSASzq;gOs(9wA%oc5IT@rwWEOz3Tt3EQGYOLzcmIL zYd5yFs2K%T<|4H&RBL?M_njS8t@g+H&i38A@Avz@pC8|DIFT^Fjenl!2o^Xb5iW+2 z?NXz&!4T3+NzfC`?Y4+#m|*pRUN@Gsq~uL7;^n^t>cJH7tA=8NAM^nR2bwp z!~fUm4t|GleH+5N&?Q9H!ZU`*NSf(WUtfFCC=@F5C{rxhZ&AA`N z4fH6ETNj6iL4`h|r^qOO5>=wLrf-wuA^&5JNBy+R@fAP8C;^THn{Fg|rHI5yDZ#BI z0_-PUKuU|p9d;9UFo;^PVFZsv?}7jl9i@?#sbnV4R6AP=BAeA}VZdOdZBuol0L)z? z>;3`!_0HPn=jKHc!gl;XM@>}E)kkL2Q@YaI=V_hOu(Mwj?uoO?X!K1o!v6?rA2JoR z1tS8}qCsEy4om&A_X8**bmQ2 z)=jv14}FXnFwVM=j(Sa9H2E#y&I zGAbrH&!iJ)@^9xuuW*wUIWl}2`Mkb}kMqIxnEhw*X7*;jYr%Y!#kQW7wnmk`eF0R()T3GJ!WM|>vREP?lhISKkaYzb1^Nc5tJj(n6-h) z2#2{{(xgWc*ZG2mM-IzGPK8=V9ah)PKGp|U*9PSzeA1CDSNmJp)_xO#}bXO$lUKsvPp2i!w z_mJT@G>%_JcFo)Kh2qDF%Xx1R`lSdP3IPKbCjfQ0QHyfjPve+1{ktFHS-0phTyMR_ z4#@d=YX!-|{NX`MOmCOct9(ltQUK#F50ad)wZCw>lFkm5%i+UgZo{j-iVveG>cL+^ z8`p(4nHmv$QyDT&#!e%l^ zDMs`3g`@Rh;>fML3z_D zC3)T+WA6j`!yM;e^JYUXoD}0Pf?A!ga%mgq3aJMmVR$V}~HITwN?z7sU=i(-{qow4%eQ9GCL%= zFe_Xx2av1ikSM>1h%xMNNsAmaGT|`f8JQ?2H&xOK!_MUYBxFkn%PL(Vsw^jvlA$5% z>JT|k-naPv*ZZfYiLd{4(7PBQ?e*vv*$P^Mz> zicJjJK22>@IXF&Sx^#)W#s#L{|8y^>PyHLjz6kDnJ#?FfV(6F|eU{%Rk-BPJsp@{C z!WZxxnlFGnUR6h)z<>|?a(K#2=wTHvSJ$fB)LrTgby^iv6?tO*I;M|Co!jFG=(-V! z9~Ut*y<Uo(|&noi`exf@5YwOydPFZiSYpV~FfeAcleRIOvS~;t; z@7kfUjR7z0*sAHPbOb6j3)Q3ln2UHp7Y_;t#Umo$CJu^Eg}7c0>p}2gVkp1`LakDp z`c-a3aHNCj>edh!=iu*Q(;cFIXjzzEevox$61Zu)Pg3v?JaamWX;<#7CTIO;JHYnGH1!YBY6C1y-T zCXvl&@)*kKYl4p^r26!xY^iHa=WIHgpBtK6MNzhEr~CGV8=%hA8BhQ|DvP55J*|sS zYA>p-L8&BDLp`8FdBu1-#@UK(>!g6cjO&_`r{?WGGiv>@aNRoh!p#qeG?}%Vu>XDN`@A&GKiq*+#9~T0vLZsJ*}R6uLUYBs!_R z7nnr5 zyLzowmL)l|7i3uvTaqno87~C_&D6zHf*rSYttMbn9(7X>i*>rv%c#qz#a? zX`9JRNewv0G<5otBvVp4Dy7p0%qXOthCn(lB?(&hyDP~&XPR1;u69?eU47?#=R4== zy627L(YhTRS!~?I5sAwfiP31}NRj&wM@G0)5)oWZhPYi#j--Hv51}Va_0A?X#NZz0 zFhiIR3CtUL4l-l2KSabZcAzjyfda_ES`W}!QggF;y`d@p>49>dF$mDv6>qzt_D7w3 zIt+c_aT{qDL}WtQuaiIW13dQ#wlClI>Vx~fxaQPvUjAu({=njges7r4KJec2m&0R| zYXq)M2N#PG`9Qb@-+l8u5<=$e_31{|zrQVjQuMeq+C7u%01y z2avIjGS$F=%iE;-d0ueXeGMjmNQ~O;4n+{K0za*%#>hMR&gu4?D*T~YoAbMlpCj~sk$;-wcsBUg|(M{iZuSJ?@s}#?Qm1+_F(U)Vn0O=0n2^Cj%)F7tt|L}=kEyyE zsw-1n_2V{gdI7CI6ig6>7)Dgm8q`q`KbxIf2G+tNuHa4i!v*D0&i6_G7|$r z(o!(HFRNDG2&3P~m`u`A6YQ8U6Svt+&=lE+Oyrp(W)2fXuD-}rOeZo+A1TIEIBbSBw(UHcNPkwF7aBsWs z1#*_)1r0x}%Qtt@nG2g+;Oas2sw%KPx13?QQ-MDQm|gWaNY&cw4`&tzmj@pTGC`09 zt0Ra?7!!JjDYrwlSTl|>YsrlZfIv}#(OMK53GSo8Ed}@caQI1bm=Llk^y9S<+%9f_ zn}s`u`^*cMhEPwr6r;T~d(%U)s*>{tH{t^)0wmxjh#r9Fpq^%8*wfJ7ULA|jP28OJ zYNj#L>B*5T<(K$@eH*1vTRPoleAAKd+p}|TqRqd)Q)V_FSTXk4V7)S@sipOE!shlR z+Xvdep7Hm`eH4qiiP@SuEVwE9{4uM@LL6`%Beo24_c!`bh6!qaZi!{W~AytGrO~VP8>E91fx4F@%ipaMA+K5)}zP zK@K1TVrfjU3K>>T^scSMgnaK+NS)9@vAj-5p}YZVu4jgtUlYodqtoSDv31iS0#Rd? zAVK%lIO~qY`PhjViABVlISZ7%(TT1IPX7-E<14jhWezf{4&pEn`hn+lLbs(2Cmr3( zfY9-@fBii9rf&XNGm=k!_TtU_-qbP6Zy8L1j@AAuRx%1;@7 z#b&4r1Ri&~+)k(K26lFv!^r~-W(#(?>jHi!=v1BGLiAov1)zsKV( zNs@0^mK|0rZ?_R%mojq&!xoDfImM40b$-7f6u>zbWw*!U^T}ggB&kxL#7K*RcLPoY z;Ocv~-Ui%IewsoDFb!4K>5A0`iRl5mp<51pT-P4D)ZEfOm4A5Ap{=0$ZP0yI_l|d> z=gKx@aav4!A|57tJ6I8IKi>AEwQI-UxE&hHp6}s5Xo+X{;K+pw6pgu6G-4=;I#D;? zbsTjA8cP5TE>egW63o59{@`j|fAZbk`_mbBI-NzJe(#b@wttB2p zpit?y?tE9KqEp!nEw(4s-31n^tJKz-n>Vj@xHDy~D3)rak`;)8oPm(hk1h*HYG)R- z?V$8)iS$s7V?p3>OWd4HAZyZQ6MgBnk5c)ruGZE<3a5&l+4lC%&Us@UDA$)Gxm7(k zi=IL+B0)M0EBJKJUe%@VuIP#t zL8Kj87HO2)2ot1SkwnnQp6VIpyP1k?$CmTgsg2L~PS+yrb=r8e*fk?x z$*~=fSs5Bx;pw4eXxI<=lzFr~jxTAhPe0Yp9lO9bUejK=cJ9J4NHq`6yl;4uYk^eL ztf!iD_!B&cnpG!8(PVUcl=)lqa+GY3;;3VCrvE4nMoqK92uPBJ@3$>9i-1nY8pY7+z1N+(7 zJn#o3PJ;mxNTK1;d@P?ps)Pk9HzX<@Y*7R0sVA8jbQKG`-}rsE#YVEd+xdSoZtDK-#MJ2=?omt z%w_06W+XG75i%>EWan;oEFPMBP2(PlxDNN|E$&f)d(@agFdE@lBkXM)X&i498pT#- z{CLrL^boV%hf#ZmPmsyt1o;uUW?L!C`4U^nMaq#Y?RNFy9@Wk z4t|GC#d-4I=)VeksS)XpP$L470Jn`S4HqeSZ!3A9fm1L<0v90S$`$@`X$WnMlE2UO zHG`8P;SsJ3?87&~p(wtPE?k*XWPa{!nj} z_AC7wWof!@misF*^qvFuqEN<0k%4kaBsFZHE4NqTI-k=<2;0Z|a} z7)f^yR+vGT-Eq<>*=$ayD|8I$DOj!Qi9PK_QtDDhA8<0+p*%#5P$ZT+`1i2AH2tY- zQ&}vClr;ge7gQr7@JjGkH`|aVa2QmZ8UxEFL18lv1ofaFJeZ&FJl{W=pU=O4;YdDJ zzhP|OYp;Ik*`wn3uMQ1eogaSZ={~3h2Y5k$D?k3T?a#k=X7Y#cVn_?KHbwlp?RTie zBBl$j7Kg!SreG^sG7mPS1w2fdc-*E;P7;8R=o5k<^rBUG5?YCX*(luVS@nXe&7pu0>4APM@C^HjvnKDxkZ&j*Si0UgQpLUuP;}2Q$LBZKrux`@wjhH{^IEjd@FC6O z4v9%hI$^F8I+?il`7@oKT;VTQ*cqCva$Ky4w=f?2ctzAM;u|X>Y{ELy`l3(Q>`wI74Xc9{j z#P=7#&wC^yJPS?O09j95(-ISwq1<1+4Cmr+7wQgdZ`}SQj14YDI_L{(3G34I<&p7c z!^3+2w)yo-0Z)~OBa4tP6bcI%^Zn8^*vMVXmF+@p1R#sKIDxsG<7lWW=JI>^yK2fP za@>S*xojm5*LLFCTAugK)>>%5wUP5Q#WJp_nG~Y#8$9EYV#ayCPhhW|~hrdCY?pW?I&ZGeO|w;AY!6stNf1QZ?)TOAPNbII8Z@&;x^@w-ET`e?At_< zNQz`gX{kq&P)Sh10E47)!yNt2MYUmy4YgT>P8WOZKv{tlI;&V3ZlNgFIIM^tHEO!a z&ol&7KZ4dNsH3;?KLUN_i~TLTw$Rt4v-4a2Bc1)j*z2RliQY$k#8&3jL6S^f0kFoqgrT=G2WzQ7Ub8D8PcNT38JZ1bmgfLQ*ZcoMt zVH9(PX>J@U;deCET=Lvj@;n1y!+Ob>A&|}Z>dapGpiF%-3f9B&F`43lWCuG3D;{N; za!GyOS!STBs3vsVqMC>-tDrtqEO+g#Xwk?m{tn}?59dr-pwzIpZ?2^Rtz1?^PhpL| zE&UlSp0X^+uemxa6X-~EJW5TJR$>nlgFu()qii!f-$}gfuXvoBi?IsvIJ@aU0@4XH zK@%ugKIYAAshDN9M=`T4{BFBhX2~0Ugv3k@d@9VSpQ!Yh3aSugG1iv2wYreyx2@!N z2B~w1`@I&w8K>vs5J$fkF0o!z_Zh!EpYc1h12M>uf!$lFV~Gen$|?7@wQxuLC%@&I z;w=v>veIhJ#Q>OI7SS|DRN)?ai|gH-^_;M(%*8IWy5yjlRr0EZ7sM&VxSgovkEY9~ zAa^M~kKa2DQR1OtQ*roJGgO&TO@yD?>U8Aj+oooLUZQb{ zh?HKhb!a`BpalXUF)baIsFZ`pOxX^^W;fF0Fk>uu?1JFsqEbeS9;7l!GapKsmE9VuKVCTQeJxBt~u) zx4}$)hxkUmD}NXCSH@b_f5CrLeE-u==hwab`Z^gydOTLu!cXa&(kY^o81k|1 z4dT74gIYyqsv2Cf(_U56V+Xl<%OP}eCHl4_u$qO45aUCyIj(bAUb(B9R~X~KXut{vAt(B?FW|Kvn{uIcfY zPFut}dML%FOfIR5${K^J+}Cdh@dL^bt5eK&d}hh$ZJbFLvY3Za-Z+|67T|0u1*o^R z3RE5~0aPQ&WNot9kCSP0!Y?#gL2rrCvFq;I%G#~L{jY2vTkCdCOhD)t3(p^HJYbB8 z$y@ndM^csHzpiZBxv}8{+`RRtGx=}N@4Nh!lPiW}y@+R=6~!rDZ7s!W^ZuXjs)23d zJj362f6kqM&-U4I5})tv#6|>UL!5*_Xw0N$P)5U45!@Avlocqn{FpJ36)|8PDGj6X zC@GK%no?llrw|&*PurEO(==9TBNG%@3QAf<{A@&FDhhPq%iiw{A!@rNI)AcHci;EE z&-*^l^Fp@;ViNWVVPQm|1yYv+ev34Z<*~>n_3D;KZqS!>ohm>hG28f@vYc5tv@2V3 z@MDZ!d&bx0XJ8972U-Jk4J_ROIzV7k%@&K#r#n4fH5C;2{VL}m-}17-_u(O;HOeL>rSvGb6;@Fq zP*$E`?Whzc{vTq)iDdaedhmPk8a0p53yiEY zK)&HQKx~SR*cbRUm|Dii@+cgJY1e=VAqQgKDbYa8?t~A)5)Gg*@kPZ%1_@7Y2NrvV zqu?F!hwsP*7L#FG!B)~9Io5H&Wfb*T0W;5K_MS4j_f=d83Ixw#>Wq9&reuSlKj$4I zyN~u;r0Y=pp$_%Iet9riU|TNEwU&Qtx1|1*3u^QCIyX;$=os$-Hy49KKGyZjRMa{0 z)hV-?VPl24F(WeD%$v+7zy>g#)YOwRVZM1*=XyV=!$qCD6A$0_YGy{m5hp(3JmaKd zz^RlIRQuCY-xa6P6Zu9@)QczJAE5~`2W}Q_3)DM8t3YiOaFu`s@XdAlON24LIWy^f z`y9RKZ8%3M=wn2@EmA|`h)6YvDUsSJVv$&Q#UB;nP$B(&;^?8^R75kOFPh+7`=Jk6 zRM<`zAd1b((7w?YrMe7^(#>MFi`s@bsA}M#LR3*PI4R;F^sP2AS!qSP%zpUI{R%SA zRRhKY?0IBD*(eVkh|P1l*I8=q>$2;pdZs?B&bY-|FV;(2+$MvS7Y%NwHCN1)xSWEp zr^-W}^YnQrkB4_nq-onkp3loO+dK;S$?OQ7;6R>ioWju@n7WuEN934XBNHpqEOUx{ zTc*sRW`wQC2cDZoUDR)omo(yFBB?W|SQcIbmp;VV%fiXTAnCk>!-iA^hBc)6^Qi(G z8P!BGs!iG@f+p=#hV3{`ixBwBRe$1-u0B(H3ck;D5<6 zJpaxJ`p;d=-PPc4`@MUajQok4#`b}Ndys+}W2PL>#4MvxP#hB}JIS-%?vC2+NZ=7| z_51u`KkX;+No=UfyU@GQODo<6Z_3;39rCi?PW)`lgL8Pr?x_+M3L6Dl5gLS)&@2oI ztU&Gxu8`H@vqUVkg=9d545SGg0qK;(n!c6*{KTSgA^ZRfd_opfi9wo$L zJ8iA4HoW4&acp^?y>I#Sy*+<3Te}bLK4${Pe;PWug?R$GQ2?!tjF^mC5s-quZ42I`u z%vfc>h8YFfsu<6=4G)qsEea1paA_E$bhs;uDvB~R%Tbck?hXK{hJaith_z_4y97H4 z?8O9jj_&w(*__JaTdY~Kt{=E`cle9TTkPrn4KLKZ@~Z_k8<^l)ZP(0%cA?gpUtWF| zCvINB(Q~u3_?sR3TMiy+MGxcL4jtu!ZvAC!{Brw?o~3z99J)-mDqteYSb!542m_ z-P4yFuN+?;N*&vqOzz*ea#JJw;mxYo=CAKs{H69u9i|U<nL|_3q)_ds?~( zgFw9WDZtf-;Jb08KL(pdgU(%+F6UpI7k%s{BmRjvKYN+DH2a#5Wz1MaBrr<@kTEu8 zyHXzP@eqtpxeVaqba!O5MtgY7^ST8ynT(DB0V{rEVP%A6;cB~CetJ*$plI!z#aKXfj<)2;%F&cB~S|nk`u{E z?L4}^dfM_GUDvO+4Sl@xOwY}xLrWJ`{*X%bPIX_CBYRL z)Y(~(1uM!$+hU1 z@ROMeAl#;NJW61w0DwQ>ht5XoWcS!&XJ=_6Piuew=4%=;-k$Y3lsv@<9fLhnKn@q^y4eKY3I$TD{0yhw22+gns=lW7UYL&0g zH{_#zKCd%qm@B0uYL(O{4N0^lF{&pXv<;KeN&t0|C4G$qQv|vK#tzJ#jWADQQUns8 zNMJ*TN5yCf6qk$OV1OWDJdKu?;Ed345;d)2X65R&leVwf+rL8l`i^#eNc-0t>nUe{ ze1;lip19{~e(o244&t+i_b+(+{`w1A#{_LFuJz-J{&dr?A8dXBPguTh`VmBp3_eIR z8%9*n9Rqk1C-V_|9DRg2ia}Hkk33n^qr|%o*sc*bio$c!!%!$R2pxvY!KCi5W>VTq z?d{r*jt=5_Iw3K3V6y)bUai4RTvvGS-CeC@$(9x&31eep3)}dCU&0o)ge{M)VhVl) zVxTQp5OASj0;Gfxf}QZ3Wa17F+XN3KX`8m04k=4Riz$;1;Et!`&H!l}9#crCKPVk= znc+vq1Cn>ubMM_cTvB+2YLw9Kx3A_h8g5 zE+(Cz4NLf*a27iJFJbudO!MS=_!Azq%X8R+J3Qa@;3`klgPm1rmixf%{>aN|X{j7S zc6*!Shyy!Pu@j*rBx>CE4)-I-JlD=`=lE?fl0Jd<$h8qNq&w46(&lh>^u&(riye;H zspYBoTq-JudwuJSmc|*yNdya=;VR(}nNdaF_a9^Jd%_k#oLR`_j$|ETQGERA&eC-qHSyhnBdqi|RIa z0p5kl2i74#s+Mbnp)l*W+&U=I?Qn;du$XE6jt_fNJ(=m>ZeM3@3dE#nWgup$unIOQ zDhf7BMfgT=!GfAV3)kvu#jWoyTb-K#ML@d0yLff6y{6Xca?05O)4aDJfKHtoaQ`vJ|r^toxJlG`vhwW+e<=ehfYcAq}h`sex;iZ;V zDf%l*1=#~*S;go01Q$R>oPdfV&Lfed5j;Cm9>I~@p-|05bm0P5o4)qry>!+Ix2P1x z$La*RH%$EF@z?NFtbYBtHQLqmfU6I;kU{4@`D2q#y$Z8XeYhUxR`NtjB>dP3KXf>C z=Tv%q0aEP%a~AgH2p^O9c}h5We%AHx4Gi=w%Qra z&N;h2>;IPa2UPQB&6<@pe9&23=|&S)Us<$vS>~(_UoKrbL%j5-%V?qY`^-q!_U7jH zP2s1`Q)lbG zOY2vT@ZGy&YrDF~jt-X3%R5QrhqUGVCNV_h-PP5AgxBZEF8~6AuAyTehg9g`xknPh>&NUmeV;f^-yE+@{1cxWO(Bhxl$#Ij@|m zTpQcLBXmK-un zo8boo07rfSge0Boys*DL+7th0Pqcmig--TKOsAi4=DgzL1E0SC{-*=Si|3Ub8zhf| z$3Xi@t%Khv4pZ$0Fs5?_Rp6{eA}~J$sevPrj<4GZz=-L3W9^p7RV6VV!b3r7#C_Qf$&RA`8$uLzQ_q1`Bymn45H;&O-|HfUU zIg%13Z(LcJR4N^Va-abQ>v&p?UeW_eIhA66ZW@N3h}K+}9E*nj-uvd=pEf&$YocwY zd)>+Q_K(&VSa`fr`$o^tKU&}U<6plQoKSy(JO5I z>1N}&fQ*ow2ZHD{x`wV#Uck?^1KL5n2TSTR_3%s3`p;+`fOiMlEvyhKAs-D9CpsYN zUSrY3(Dnh&Q zB`pbQ#<{A>e_;)IW0wyR8?}{{aZuH z-1*Lw#SW`GXEU%zR8@Rl*A$Sav+FLo>Uzobw;K8>&SjeBWM@t*WtuEwPaiW)u9Rkn zd(>{eQ32KQ>qH*xj(~2F>CW-sUIh=r zmz9Ygh55yo=<7s2z?V$^4i6A{;ecTu)+IweN2VIoEyPFAk?1kJFm_QjGVufSsQtnL z&;-HIT@(X}+4AV#ig!pvUWKSKkkWNARTM4a(;)TAut;~=pYJmC(Va{s*-X^p7?RUL4&ZJ4vP2RWqg(1*iqssxtWX2OPRb;-in4Ml zE;_#{ODHbCpKcR4#wZG%S^m18 zrpy#S8MkDeTfl4eEp$sK7ppjcksk#}fnu0dKCNWkPotNxYM%Vu=qR+LNodbIkKw0h z3iHJ~tPH_Xvkv(wR+yi<9oe5l@np6V8g&!xC8#oci9QCW-f>KH^d4n&9onPx#>0K+g^%@H4&$>)94J+($m zike+S@2Rw}>J%{e`l600EO-HB-F*{kBM3#0MKHCHSY*ye{2>+2s*7RIIw3z!t6c@W z4Wi%@=!!gOg}7+d(M%8@^$v-*Qr-0Qm5tMPt8mxk#?}|tz{kH%i44|wfYe78^plya z;hX6QAn? zkgbA>bXTag?xU>*>lUz!qb{>;cij%P1Uju_yU>SicOCcPt^~=SJvZSIFwVHs=Fk2A z`#9%2-#z!-|3BAfjQRV>SG#+7H`2FNDAPSW7y%oEfI&>LXVoM)SDFi}K?^#F0|S^L z2~yx`mbvNQ1?YiKo96kPB;IJ#2(R*aD?c26osB2cR6P;24~MIy{G+fphR%I1d-#9k>LS z;TrrA{sbSw4d{YT;TH73*YF+Ofq&AskviPqTj(p+q#jcY;r@y`Jlapc3_-MGir9}F zkNxJceOQ!O#HJB!3D(tPia)%^mE*gIoZmmy$M-h7_m6?68flFV2j}p>z$yE%49XKL z3ehmM*?oX~TVwn9kA(`GP+|ApZKTwW7{m9GpVRKYF%m+~M+hUVKXKn~pNInj)d1Wa zwuyeDB>3H{W}5~wXu%-Cf3n!kT%lt$lMuW62y;c)g;{$%fT)eH1O`A!u*tl~yvJAe zm(p`iq`OCSoiC?jfeeY{-{@b)m%CzIF;ox7+W5`hF;SaqrfVj@xxW;VM(L4IBDzl1 z`j;~f%>3bPDCg8{Ka9h-HW0m38Xg8}6_|_(2{M&P6doou=o3svjfUA&H5x_mH zLy%@$w`FBpt*m1phWVW}J8K(lqWm<}JkQbWFciNfL%OI820c(VVh>Z1TBV^(r*ZpT zS6=M2B8g_gSUZbWHs*KLp6bf?q(PKoNi(I`T;f2AjjL+cZ%wAGgm!6`pS(9JQh)}nZl%i%JDMhUNsD%hU z6oIVwY7A+{2~|-?k4ELKTZir>>Dr%t5wZq_1qt?1%d?gL-= zqpPpZUsIz`Nw2G0GM4TEA9D05e1zokkR(P!h+8S1D_S<_V?(G^DkCx?l}Tlohl<2R zOhh6vCZHOPmS_pyF(pk%FcUMOcb|1&4=&o!u$-ujLT_4xh9Mck1&NJJP87b*uYP{f zi**^oX9hBP&ND$m6UhjilPY`_PombJ&S9d2PKQHqkQj%9#EO;)jpCGfL}3zo^A@bm zO}$(%+|rYY^An#C8cF8(*~!B91`?6|+NRV^4cTN$qVUb!LDKrFC+>Na*JeiLyZs z8niEyh*{#<88jG?09uq0qLqv?&s~i=oA`6#<>RL+oYXWi+)Q6io^#!nNBU3@Wrw&n zjAv3^uuwR5*jb4LJ|+4|EGyhMxtd4Oz&F}V3_%gs0V-@rrQG1=)J8BenbNFJ(2BhK z#f)p2kiaM>ZYJRi_T;4RofbU7AnSz>(Lq^c)GR@%T3=b3Ipr_&? zq|r)g$Z-n>ngY%xWEPO*#+6%NJ-%vI!L$kWR_mG6?9fT7bv0+Uq#T%`HgYR+W}i{1 zRfZ3WLLzL%uUfY@80OBKT3laWxFY{aKH&7$?Prq>(aReyB~P7#tWwC}(9AZa%qu*J}%tK{<&$ich9N38H7WcPoH=>79A0s4%@)*$~I1{*H-^rW>zd5{gQe5WtiKo{$ShJ)%UrZ?ZS}EIcXUE~LybUhwN~L>#p`G|b0`-;c0cfaq!o3>p`?Q7Q^3!cn4E)BGm9m?3b zmRfMT;fVV-|2qFJ#(NCf5JN1v1pt~BvLyJWU?vz^$yQ6qd>x)48i9#NO0pyKbwroD z#iZL}Lj4*cll|DEzsRG%m_ZzP$}%y23SpV?iV%fGv0KroxT3hK_(<^&MWBLfWnwJh z2m*N=0WOk@=Q=o!i#Y1REjF2Sxh7LCa&y0r>mH8SS{UzM%AG;wcu2R5;|PC`0sbHdvl*_H1iVdVGw+fBVBJ?QrYtbBt@xag=y_TK14E4L zL~(&pu1gR3uTH01?7DX+6fsRFQU^Q`9>oPDDiL?{-TlodQHcJf6%rc;euEFXjJHUM)aToOgV`Z};|&yW`%k zy%&3MaKZt1uy-Kwl(mHf73yPBM8{J!#`;JUEZ~D0WAMQ=j!GNt!|6zqC~9K0MiF70 z_-c)vv^pgep_9&NiFL+YH65B{)I0m%-2=qfW_qx9yL-R=?cVSIegEI@i-zGSvepYwJc2#%9M$L52bS-c$aMe0%U9{6>w+qjit}R((NA^C4)8ueC zT~5O8@cIaE8pNUPl*W5K6{P~~Oo}>`x>`A;??TO;)Q}Z%Lmt@WwRuB6mFuq4>0Oh9 za{AoDxy;%i3ic6RotO8n@!s>wy!K-IU5CR|3!Hs~zZNL_G+n5dSFHgf>N7D#@BBzm zX}BsDjmM(Hu_$9G3D{zwTU0tF9fNZ57;N!je-wliwn%AYhb-S8_3zkpxgdz5L=?%h z#tb)^6Qn6YW*`oQ#=2ASNH_vG{^WwPym(s8yvm{%v=`h*cfEVzV#l^$zjB?_TumJ5 zJJQiVaOk~1UtL~RwOrV!I~mVC_wu@yS4*qdt*w7N)A@1ZgO#-E;n8>c20IRa`pNOt zjg57$HZ%yHWrIG_4i!m*8MK9;dx$;g>GX7_-)3)v4|^PHN2<+M?y1h+$I4mkLkl31 z+AY_t+l_baD&GPcSuI}gH8v%ff>Z4ItY*KvyA*H6yD^Ddi76~d%H+MhN|Y~JH8foR zSv(@?HXH%HN@K$@J%|_A3uBImMvY{#!H{g#kN`$>G7CCEYoie~H&GIyahB!2MOOB2 z-QD90pZWt@G$&lQtmgIaU0pSYEk+f4LcXF2d2DV9jedww1)7H3C(iF*GV7ItEkASmhV=7)$DMDXSYHZ;E-nlC+7jed(h+qz&fY0<;%5 zlc$8-4qmUv&GDP$srXHt1}tOW$)#^)z$740Z(;-5A>k?$qFauo?x!+0UbT8GWslF+ z!jo2^?YNb^C}uq2%FzgHeIi+-RqGCQG_C76w7zCz^W3@3&E&<7bxns4!>LN~7&e&I z@REH@Wc>Mh;5Mg&&t#ASRjC)j!-eVATphgMraLYA-cZ~ZDPxB8x$!{V6Zy(3M7e>Z?QKJb- zjjAP$5TVv040!c8{;9z46E&(xYIJKvBNwaCfJUxw^2=*R`3Hc1o5XKS75R0~;O`yf zAAma~`MqwD-}4Oqic$VS;BWla=O5!AByRrC=U)Q)pA&1GldSQlP-Btb<5l8u1s3ox zCT3H$BLDOx-ZjD>fOP@Z z>eKXCuUDjj@yOMSF}CLC=4N{r0fWy~oz3PSC}azRh1lzBw<4`I%^I|l*0XpgQ2;%) zJ{Hw|2@SPg=%~UL;{s8ANg!&lmWaI;_G9&aonTLXJr~f$hT}tk6B{pz%A^M33q$9S zS}Y`KFQE?^yc}zkC2h+9tJ|=!q@gLY;g^^9Zu`zl)kh|OcS;$PRhqb-`2BHIK7@6( ziNUm!O;>N;_!t&a$M9>j6Th|PZvVkrU6X2|hcmsTQRJX@ls$;%pG(Xxu3!J)pZ5}< zZR-9i-Zg6{^h~jG^a|)~IYbds@KakSpn1-DdDVexZeDnWb4A{=z%p({_-ltMrD&bI z)k;n>huxC`95=&U?w%efL`I4rI0bWj&7R7J?tEO>zN$?$M3 z(VxA3S=RK4^w#)MG?jjP>0zb&8^BbBM zIk%ZgCOuf_TNR!g-T(g2AGRVIxsL69^unM1R(I?dTD)n`i39KM`rstYvwh$lIpVzc zC+G35k$De&h5klg5gc}&JPi05Bl8|Dk?>Z#B?a)-F+BL34EVbtaT>wre#Hlrw35cD zCX7v~Btn!v^SBwA%|=S0ps-eJR4CO-wMJo4ShVal4bpVsH~DOaXJ#?A3|Ys#&R~`a zGVRQHh9VJ(j1bYy29`AjjpvP|@hpCmu)$o47ZwHrdX5VOqV;RX9SdcFf1y&*7`$2G zob(NZ=8P~G_LyOMm^pI>xIX+LINaCPhJ3gj`P$kN1M!~3fN(@bx-Y}4`{8B0CBB)8 zT)G53hyiWp!*6vG=Xg_C7BZAmWd=&FuqtYd%Z(IbgaPT$TSCkon{5$>t_{f-V+U<8 znn(*J)5CD&ZM57$s4Yr$mWpS+q2ns_7$!l)Z4)lGz*1w6yWNfJ-1pu1o*UWrS)69v zgq_N1??WFlTMjvZ10o+J8}#6B?c>|^LBTx)e=Hul4a(G%^wX1)qhttncKMz7Ff zT38rC3!>@&uwAaPQCwFXzjx-&?Ck7%XU5~**@ySxwRe{=G3(fiAJoc@5)$#oybOkJ za0;j;1n@d(OB)a_;aR|jQW6?KI4=n#1U7+SoP4m!-D4Y=4o*N}^exGG%z@Qt`O719pW3g$&W zsYrC)QUyxWf*GW;D1rU~?ZchJ)EbZjjuafKpSO11#yugNsH^Yv?$Nil&fdcH{`YxG zxIc#6Dj_!(xzU?O@k*H2UPU6rCUU%luz~u~06ffKR7B_N?h>&io)XWCtR#lTF_9HT z;-Zx3H|Yl|adxqV4liugR~dh5)h*UulV z&t_Vob?QnkH!$u@_F+==ct8QabW(Chu+O}MeY<-y)d1rav3%>;K40mH|gPaZpHpl~+VysSR1hyS9WADJ)YzA84kq32Lfg8hy z4?Euk=4Cu$T#R^YMAGKPxRu*Wc-sDwlFRAgSHoo6of7*M+0CJ^_}v`mj>`fT{N4^P zUg*VAl?DX{D|*T|Z3M zBb&+A*0O4eTAHwFRy&F&YI3bgss1A-fB46%FW-Oi=#IskpNdD4GaTeBPMFt^9^L)m z!Ig9CLqql_XKrA>g_Ze@xr+NO*9$8%jjjy7hueYPs=KiZC2=>;JiBy7&)DIMvMdOO z9x&{(+i){O&k1^7e}^*h4qeZ-HqmN42>!i>#E}C#jjCB>3)x5hM#xm# z3bK@Mw7*2w@jtZx4my=lGb2TeWF>q6b`Z9OZDaq$5|##DQkF>ZEW>MTf=}2R*(Lm1 z_C@}E_9FW!>$LMC#|pfiAj}dH=fon86M3Gq3qst+7Xk9Hyj>&$M=);_kZ2b~8(}$0 zI^NI^OyK1=GM^{@Za~DXTj~!N!Y9RxpS~r$^2eXa`$#)iLQ?bo`xh5 z5kr8j(=E>&G*>Y$Yj+n?&&2n@kzJR;kO@KtPlr(r90N_2TBDwNL{oH}=(4khb9~%k zcz+Xl8pbVpyCq79s*G^e_huXBZbp zBEgDaUyuz_I0?z48M;Y8``|}a;I4z|^k^jzNK((WUKJW|Nu{Syk(r6&Q)JqJX$L-m z)Ebq^9I-Z`M)lkzc&ZXOXfGfdhV}@E12MoS9c!o z7`X{qwVU%uBY7G{&|yP5W5>Lg3u<0>FcIV&6gtX0wnC_=Fvct!Rzz3`P+&Y@0Z0Ik z1#qA~8l}lA6hNY#QKlt26lK1Sg4N+CF353Z0z4Ev1TK{>$zjIe1aVLZs{#N^QYeOm z(>VtQ|F@EyuI4zy0*wj!uq=pKT$PGe>sVX<%=25zz?r%Ie}3&uI`Qt#26OX&pYGW3fSHjty|04H#4$Mk1Udizm_T;<3Br zEsG5n=f_W+I{iT~3kLfqoocQ479Hf`U&nbmU{Gn$iXVAQ{A&~OujAl&{E~nbKQt-+ z8=(1*EzM7VMDuQ=fa#~}kD_t6%P6z-JDuh`)m+8aSlVBft0ZEL1~!+e@_iT?>ci1< z#%_~;Tm7p#-@h8i*}uF()}U{dPnvxN%wD!;-}udzxHj$(M>wB6de-XknYoKrbaO^+)BNEKVD4~c!E@_o-p&BLP=J970|bCS z;1Q?|*j}N0PZdV#{-${q&oJkcgXRLbUNyg9rhJ5N-oI~_d^Gw6bp!X0xzT9#T`Yss7MHDP*WcSy}UqcOD=FQOh{EV zG3iLI4&e|T9$<^ZabKZlSz0@#o!8iAtxY=wTr;F`TCP7iQ<^Wbr85UI+19yTHB07p zeQ(jq6<5H)`e?rOkQ5|5d`qzk3VL}O?oiO7yg!`D-hz~M42Kzakq2rF&YsqBb2{aC z`WsW=8Sd@s;u6us9PbadzWj^Wfde~sU|(M!^TIjrrmA@0#?;2W-F4^g4qSWB+&4f~ za|ASBX3>0Yj^=U4IL!y9paM`qV3KMMf@+pnG`}K0J~*x#Z_Mt7@!m_4kBQ$t5r3j)>50^eul;{~t7dESHP|su^iYE|e&{jruT8|i{&4;wuN6Nq zN%cp}MO+!Ez7!oZQpY4LNJ1&ov9ndPT33Ye~?5lVU`wE3`t0Q9?V?Z!R6 zGhZ&lQ$mMc``OL_o-%L5R~>tsqW&w-u9uE|gQu{rk=wmTH?Dc(0;`Xh=3mUw*xnh07#ph;7eB1C|$8PbX%*{W_@%UT2?7|;k>yRJaBw$ePNZCX+1HQlN# z*_6?BDE7{MP6B}q&C+}C-uLc1&-a|~ob!FARy9*-)98IXJr!9LI-NsR0QoVJrKV1x zyB?ACj)TgVbA;%MoH}SOlHMV=AqP%5up{Vn()2LWHsl<3lINV0PBP)dR;PKc1DWxp z8Jk0k(jDlIGh{t#ce{X4*r5+P+;Db%DZC+VE6 zv|66!<|zb zR;g_>l{_(P-(&%9hOucLrhyrgQD8+nwB_7i)ZeO!8n~k5$yECg(o)i(#ToD};wAnu zp7imj`78XV`~=S};G=vmKMXfGr88qzqGee1vl4CPI2CAKnG8{805PIL!4a&abbzt} zp9pM#j5?P|4^<_{fIk z6-tS<(@*QFgFcUa*iQ8Jke%2OC_-170FQX=lD*H)L|O#8VX)W;Szn>t3RWHg<9_se z^kv#IO5kJYl(dvZkFH`_i6JN$gex1C>V>dW1Ba*57w&TiyqFlcV^iBgjwN^2j7J2fy6;c!>_+#=SCZm~%` zA`Xe8qJkIu;PSbc5;-wO-bNt`^4Xst%ueZE1Q{Q11O86PyE&TP1$hT{A@dHCIg16} zVVZ}J^{KBEKa=q>JhQ$!jSmK`cr<&7#NftxH8qraSAk^vug&=XqqKbnIZKR2SifkV z{dKAH?2v5#2Q%yQXYCi4noO|XIS+qV0bpN1HDTm60jwZSh&W4IJk_w39wXr7Dz?Hh zYjOZ|I7%tEpN zOF8*IV0T$Qe2K_f73PS5RjU%FXJMw4n-8o|Udq)gutK5ry2>Aez66cze5Fuc_K9n- zgpxj0xtiDNK?uEJq*EKs45_ zpZ8+#e%}v8{#GIa&3u~nEZ}nqe#%lkZm?AIQ$cXiRK!pnf`|Onc!WICxsGft7VoP7Q<6zv3ULRuhiO+R}5Hv zZDcAx`FH!t)=fEhP4cD*V|DV2oNfNq{?}_4ukP8=Ke+z&?>D^Iv;8Rk`Ng37VtD!G z#O3!(uI_9UH(qSXy4cW@zsL~yTV0uJ-9I)Xf?895WcRWSC<|H9K}o+{wN~}Gu9as+ z^=6i^vD8;*vn@Wj{!1#MT!7;;t%J~2;7yci9@HzD!AvzbsE`aspCW3+MujnpMh5y& zR*W2yGwLD?(3Rx&23=*BH_s02d&^ zhrCtDSZtuaFyM!GpGgih?7rDEp8NxLe*GKlQIGYVdas)plLOtiTtD56rGI{dA4(>Y zV=HiJ_nsu^1`f5Qt|?yRK8B3cqJ@wQ0`zNSNKHx(y}_rnHX7=(nG7Ah)a5lUXfZTr zH|Mo1*sR*3`NpcriNQh>2mp;bs>bTLN^4T7v|5l(G2A2NWDqvN{W$~Y=q3Po?Ot!e z%@SPFZln+MCdzSndx2J^&eUphZ7MZ_W#%Z4`FK%`EF3B80A>_-!cfwBI?8ZaT(aS) z4clV)`njkFd*Zn=jZ*7;x!e66kT-E0BPS)5hmEq&u?)LX1bzwG2_7AfOh-ClMDaH@ z4QQ-}ax5Px6b!-BajL?mBh}TRsc}f_Q1Df*!WG%ae?VnPq!TKH-JnnkqUiS;?byoz zMgffGY?Bg>87c;}Oz_!@7!##of{&sXPhO66uRm;hgBfC;9y;^XK>yAY(Vi2p9DM6~ z+lCEo`jFcltf}-aAvXxFwH>$Y2z;AVklVxVtxt4qi*6Jv`?v1zZ{Pc2-HOKKUU#)v z>Gu0+%t|3+;quY$8q5HfbXs+ov|tAqVzj$-_;4IQ<(HZBElG=Kv#A{uZ*yo%}(07TXHrvDjrm`;uJ(~(FgFpufTlpOlReK-ix zf&~-TIDO0Al_g)Ys_zDdD?*{c0U)q{F6c_X3fie&+x6tYOD`SW*z;!J%kNy@06#wDaWARy_?CzYGX14# z$5OW|p#N@D?UT7TUTA8o@$_yxv@hwPnA+J)G4)LUzU{s5--{{F9Ht6U6?F1C{LBSp zN&Qv|0zUW>I2G~GO|*J0XSu2IKa^K(Y*XhIe$RW~`+aR+Cw5}TPJEs3V8Bje69QRt zQCav>M^Q?;z}$qECUmF`o(hD1C|L($bea-0{xGd2)w+&#OfVP_2pyA_PFuGsle(nv zFGbl#w?zmogO0_{&U+mwbkelhv3+wL<=*E!&w0*s%3G^j7q3ff_H~rESGO`&w_0Uxh z^{9z+vECY}nP|lC&UUSWRTD9O#R%#nwsS2v3*>|_X?{e>X6HE8L{>G91H`xwU z&#Qx-FTK_OnR=EwCdAeAvDve_xo=q^9C_mj&*A5vd1p^9_Fsh~lK4H{n52>{#{J_{ zJ0`ko=sI6(ptWpWd55n(&|cP2uC4X02|TC}B-!AU`emFG5c1wYzPeK>YYG!tcTs*y zpwo9-+)N0_%o{?^ODp(1ov7lTu%tH#!HGJ@6B>GPqDW4JG|t&CIcNWp>BfQYj|hj>Sc3V~x4-f7cRF8sbN|4J-){NJ0!z=O8j+-T zUVm|C?yaHX6HvLidTxDvPumN;BK4ddoHfG7`%Lvgl3kixD1OH z?d_>LxIeRH_lsTO16AAc|5xX>(lzsc!<4lCe66@#Tq_E~$o!05DPOY;Fb2(Q)I%aX z6lv~lETRo+6tB)qj8M#n*TCjVV|QW7!61wYvOck#q>Gm|SWdZWQbqY<$)hV$P1uAea!n48%bnv}E8P{yHAgOW9gfw?j(*${3wDCw3DG_$T?}1LC zejQuGvj77E+z>zzTm~;;I@1u3rEyp^;U^EnF`nbHv2?RJW8%w+6A%?DqNxTyf5Bl` zeC=m&;^ti9ruboQ;wC;gg6n9>W4MdR$ebHGE)W@=SZ!=dO11drWP7zXm6U9J!{4sh zk4J0pJA6}&fKkh8wdJHye3pEbJ|pyq*9EY4&DJA$2}r;I2pH2UZ8f4oLLE@4dXZKVMz@`{aOHZ^ zgDE&0yp_((rZa);G*<|gG>y&IjNR7ED{Atwj0=R*dk0?`JGeB!Kg_W)xfwSJ*lS$J`1 zw1BnDU8f&sBSP|@Uvf~17eCF7-p*xivvUrl1x!D?@zeNyJI@^qhGGB8r;QTJKg^n16fz&(b64O$G^&Fgb0<)sjHTA^-kj)>p7MaDX0Shm-^Qe$Q)O zMfRv(zo*1o;`bNtb;}>ID;f>+`)#zknpba)>|9EFlzCzCmo3fYa z>baj}kABvf-$O#%P&cI{N^aSyAF5aBq&TTg8XtMDgg&8vGSon1C+#-2dv}I@gy!v+ zi)KgX9ceSK}h9_&49x0vy#u>9auFo> zYGEKeXG=@5!J1kFl}8x|Y?ViO#i^9Xw39fB5FD&UC`oKfq#dCSGcC5#(y;@hlt@i9 zD)KPdyZ+~F2xK~AX7A(QdrtPA?|lFNeLweD)iIttc=2Vt1|Ixep22jmF@@F}ajlBo z%e?A%MDUKY53sVuYqR1t6qy(BXPKhN9fgoR3~OK(%!IXgm!Ep%$kFpXr{C%B7?~r$ zy$M;606#oqZ?XSozit2h=0GFlb)N;Fef88?`#;kLGLWa!=`w`mvvWZl}_j#^nT9xCnrI*%_ z^2J!u>H&A9jjT$xMYv7^$fy209o4bni2a(~C-)9dm7W}VfvD!D;! zQMQ-ul{>UP?IK_@Fm)ZQr)$_+c{AAu`>1M?92(PB(iZlJhWSrOSfYOHITUHk;z-?e zx#cGKl*&vapvc^vJZc#m=_Y!KUZ#w8qwpFVrA_$5mnA0kf0eT*+kN zaVsoCL3@O6%EGuM+bvyJ!x`FgvDLWPVlO6Iu=^{kM;*Wc_G9~_)awGS)5Ft78F))z zQ!RdB3C7O}H`8miX-qYmqy^Fsr3=!>?1KD>p?}kO#(3V?EA5pJNoVBG*lng~OV}Pc zm@J2N!>{Xxfeu-c!VbglaA45R;A!>)j;ic%a1?c2F444Bww`T60WwgMbV|9RQq+$f zues0)4LO1{+V?Wa$ZwD*n06dm;N{K-@T7DzwFWlW z57YOCKZI@e^Bmwr>Nc-x18|(9jJd>m1O|1SFXOEnPv%nd4Ryr-`ZfCo*)2X4Ib2>GDSoQ=80^vYq zzzXaRvSYZuCV`UU%YCko{)R(E<4>zCI83({rbt1u+U!jmyw^Sb~F4! z-EUvR6)ndVX+kMqwZ3s!=1O@{{v#^o1>Z$f%1@m}i%`kU$~Nsq<$$Jgt>hkSC6zy? zig%=s3txv<9+f>VdhH<@C2yR(akN|oTm?O>0CiAe8CQjkZFMXod-v+yIHAiFh5s*c z%g5wx2CNhE_Gs79GjE+fd$jAWu5GnHyQ^z&;Eb!MdhGtj0p!9t6rfhsO=~$zz$ClU zXW#*nYdNtxvW%cneC3)udN#%%F(;9k178}OqkBQ+bM*0Z$b;#>vcp_CVX~OB6TXIA z3t9#x#l?QVMWOhvYG%eu$Hn-{%y_arGag7$Q7~v>p&B=Sm)*)12xZP0{r~xQ#^>fL z3XTts8~-e>yJ<|xgJkEK(a{Vo3yx;vMz`YIC&cI?J{pGBjj4WU0x^W@hwfE)W{PG7U-`}-yQ~T<KS$gfl9*$7>;bY4sI=I`5o*m`i?+T_+Fm|Y%R>BB6F z&b-&k0^(p`gc$2^gWJ;GHLN?`X+;=dC1+7X_Zy620i{f%Q6Okfh^C`qr`_qx)-?c$n%dDMof zgGTa-k87`J8L_s2S#Q>F8MQVVR#O>o2o9;oEGtivBzH1qU2Pp&MjyIHdpVSzos#eN z{vIOsO1qy$Q-40Ow4#De9RApD~{R>^#_-ZB-JkwbH(Tt++eS9FvB6N#Pg z<=g7^z#TOimdQxn=+2f#qj9ViJ@krw&c0DLV=g@YC;Qs0 z3Et}3+0E~qfa~^Jx%W5c?HRvJ%rAAs?0@gMWV43Cib;y=_90jWuk!VYjAGMBfNZh? zYPOkOqt$t4YE2&H=h-K-KlMrqUskS9bt&L>8W1H`xVYvO0%@F_FimbOe1*j|?PjM* zzhe%W^dBa;k|E|(*>7jj8B;9~Ab2u5!y=>Ve+Ef5IN11zrusu0Dr{Go=5#FhloQYeBQ5Q+mh zZ5iG^>WnfVRV-~OoiR`mh=C}X@JInmcdy^y-USJNbSAUAciFwW@8k1gbsKni1UhF8 z|5qAs6jF85XY=TJtAkI~)uq_erew-!Cfbf~m@ofl`;KpW;Xo$Q35VT)FPf@0Jgsa$ ziwoJg?91#nb}!4aq?MAIn;?FTj!^LOpguf7B^jbF&_%M}%_-uLI+34=-0dQ>1xK(5 zK2fG_8*2fNLMuLv&k8JyeGn#QunX`)b~)Q3yvnu-JMbQ1AAVo>7`rxL6rdlWyMXM3 zQhF3u%}!>Q&`ta?_P8L@M%B0kZNw_zP&y(ZumEzA6&RTUa*Qyd$}l1emKyksV*p7& zw!cBsSrN0ez(DBXcv<3jh%y|F8S?w{3K9&%*%GQi+CljT99WFVc4^^+oCMz#C2fyZ z#K3ZTa_sm*fDTtfEEAIfxvv@lY^q5oqL48u+d_FVMjNcfTI7d)mix zj0i6zn7It4@W6edpo$C<1qLxZphbb0rcfw^1)gwU61Wdu@`9v@z<-RWIJcqdp=75- zhLRy)Jw=!!Y!ztXLGtUlkNiCUkNu)3PLv}SPV!K$v4j&?<>l)W_Iz zr^BWf%=`YNreVl$nN!+2C)gtmwr!gIqxN>xbGNH?(YS~}8^ue;qvx?B$>5h;fW#G)p!e9XRz$80i*5jrue zvkX{eD|pFhJjPuN?4GF9;~JqALjLi%W?%S-=%e+?$EGIcy}o4zdU)-NXOQ&K@R4t? zPBv|>`0&!QUn2dw^+OYlEe?nC%jWJ`gj{<{_Rjm+ySLb?+On~(uTCs~a#3{J*#&X4!qJofO)anr{p>mF;oeQr03eYk^hULF3~ znkSn^#J6>9IpDmZjd^JF7%g%0&DT-L){7RHTLs|KORX|Itb_C5#mr)E1+#+N#erUs z=DTDO5>Z4Zuq3={IH3D~lu;TiNK&(5=q31s_=cBh*EHO(Asq2$DcO4ure1W-i@Y_e zjm>CAzHix=z{p9v;AR`5q`*v;D+)uEEy(}u%ms6ifA+=AZ(W)N?&`~}ml;J=_jqU6Lf=oJNXer6vN z=iy{1ZVqt^98(-y9T<`Ksklhq2ZI`t$|YJ_p!k7#^ZEw*QiB&+Im#H%tRR6N0qepE z0do;8qToMdx0|UH>5w-gM(|gLDz736MXXh5ll4KGvTj?a&_-Y{4Si#dFbmMP7LU8h zl)<2PLU#hxQbTkFk&~x5(e`Ays!z^!1~0iHt z=|VVR9^O8PBd!1nWI-6XRNx+nHk-Fn%@9Lt;AHj?Eip+&#N1>!*9YT#6laGDD(V4l zg0YtTxDNSeEG|L*X%|jfmyh>=LYUWIY<--k=lu6g;qjMV!Y=dr(UTk9)-Ox8`-`;k>-E@c})gcB*?- z+NHYHrRph_QPq$m5|TQly%Oz`+|p9%l*GWK_2T+cuxS;s=2TxbIhsB3SaY9;8~~y< zZn#WBOo%;H?$vQ-Uo#7vO-r~$&&|}%IVFuNu-RO zbLW#AbLQUo^!6N>Sig1QckQ+F7oqQ2AIxj4{nhU0P{qoW^{2M4t<&evqtU%>XaewT z`ZFNcXYR|QYfn&=-%uc2GBUytF7bV7bPQo;8{zlzs1N*Hni_mY%>+`cKJbjq=HwZ| z=I~4h3Q~6F#Z(~3Fa}2XLo)A!-_c=z2i%V+&4)w-A>WYu?HStlN3x&)>EQikQCWfe zqeJfB0LpufOT+Ie&C~!nZe+Fw#ha;Hc?T!%)d16vrEhY_?98?D;6%Qj$NnSfEBj>! z37J<6U3Mn?jBivqV3rF6J);ycAmCsz1u@I1mXnZ)MjfK_L*-=I(I~?aR7)t)Er!H$ zuv15H`~Je9In3Qnyp($&W!7}3U?t*I5?0?%UNP`k6+mjysGYrZ4k0PVJJ#X(*4^vf*0s>TL#yXE{pKg; zPUa&rrOnWl?R+(^MA2*)A3+Nwco4PL&9wB?N71S^}$()-sAlD4NDZn^v0Wx~+}Ek1u<_bCQBI z+wpy;d^&&c^SQAliE|=t2ximPh_qW4K1AeXEe}g%sWlS4d2>|D+L&;t3`7nUOff2( zcTRNHOcxHmxT{}5_f(nZ#!d6ebLcTN=WA4zFt6xuZurH3OfMNbGx)26E3VxB64ec( zrRcYxpKW;RxyyZk>HLXN=08xGKB|Ty7;_Bpn z%rWH=i^}YdND)>evNxj0iXsOhcHXWRmj+q_9|ryvU|Itx5GV*m*-5xza(53@6zG1x zHy4%0QVFQh7y~V1P>;5lWVw9vAjT z>~<&bvFl34+v3HP7qx=)_ZIl06f3bhOOwD2yDk;zx-$ubY!G)*rTHrR3W^E<*aQgF z!_bA`35mna|Brt9JstHHwEMM>fBwqwAVj^%96=Rm4~n8-_v4Fu`ppaU=C+YT2mi7V zZ_ho?p31$0zYW2zZtCoS^wm<7Z9T-QQCp4lBf`skk8p%PqOdjrHOo7Mg97~FMcbb0-91G;7n_zJ`020BIjH7zSI2_f zI_AAe-Z@Wr2hW@2o#H9pDFX!tyi@i~2f%)6;tS>`7l-`|t^JqLT(msDUvpCo?DyWq zQ@x;8qJWl2Ei&u^i@Au%@TdSnHFRE2h(jXY1KLwWkpv#Xcn{!%IbCOx3~9YC%0W_H zMFzJu!$+w^rv5syfI&GtomRSi%uJ&SJQr1%kE8wUsatcH(>EJQzru@s$LiNIt6vYp z{Teur6Y}@aAmxSlxw!;G~eJSjPFWX4J|ZM6TRX}4WKAXNp?2%@ehvlY zDl2PYxvIu3vl1PYkw|~NeeCwyv90ZO$iErKA$j$=bI34Y9+g1v&~hVs#lw- zRX6#X;}80l#_h$Lb`lL3f(pV}^+jVba_6p$E0vY;c(mBZRC8hek>+0go&8^hxgBLqm{`?Pd`WXVxdLc3O>Cy0QdNGFszr8IblI8A5VEpF^~uL9fZ z@x@(2AmA22)7uK8j>$ReAPw%Spmc;hy31V(+hN{X^mBbu)>O$v)&La|8AGlyxNaq4 zN6W=#Tdo(%JmL=O40Jq4`ko1f%Ayh9lu8U&Psv5pXg%bzbXz^bI35u=Cw7dM_;d$)e4RmT&mmGizHnkS^#2 zZXgURP+u8BBagVGKR{^Uyb**2k2y}mDwoFhaxL6`{2KRHe3=tD8Yjpog2?A)EYdjM zp3Rd-^ntcCPVt<=^Bjk1o~E#k=V_WVUJnwKuT5?9zvMn7o$%dYZm{Ep zu0UZSVGc=C6-`ssKzNJNrC=op75O#>7eyxfS|cRlLM_ZMQ(jPp6`E2yl#R+&g=tlg zQW#K~peSktDOqr&wbc<6()DmMJQSwG1g)|uah>`f<7EOH#dXH<_ukyI$IR^E^{yB1 z40u@^*RkdG5rYepwwTy7fpSB5Mq)Rbe#{oc$PyQ);xvg93G@_gt2`~8by^?`e!QlJV{68fuB zTGeAUpdtVz`QH+d(2Ne8|6)yTeX9Nw*%J6Nu;CD{AYV&D%2$myZv5eJgP04H9QP%pElnMX*K@G6y7V96Mt&#tPOBX+)9o-Hb z7PhZJ2^zYQ$*@P5P{ZObjYip4x@c2 z9m?3nZn1jPXJ}ar@x(<5GeqS$R+b&E@*z#FR;xk7V3uen z;KIPt*?R|LBn}-F`T(F8c}}Dy zxgMcg6|*C8H?^8($QLY=B-s~^BZeU|A!1A~*1=zaPDip5+Z3!QE+5wA@HUE#qY^Q` zgeN>TqcMlaQq^!T;i{(kDMU{KDxvoiY^d!Nr~{1$jq*HHUWVf3Mvz6p0E$yaQw{St?Sm0tQ+_VJOhsgZ65>A`hBg#dbV%(SZD5jVV(Z` z*$r>tiRnhN^}r$P^bmv2w5MQ#Jp~;=S^I4!o?ymUL?oWXT`-G0FU6fP6g))NshYYR z1|AqeRMZPl0M5*%O;jBY{Ju8u@DAlCI-QiE;9cwB-Hh$bCYw1O;vw-Pu~%dp*ako0 z}UugrYw7d#!b zQuBeTqv*6*-k|N2+ugggUH(h*C3mmZ>$m)JHWLbEhx6rpf2~~WZ*jM%(xkvN5Qf0? z;I<$M(#BM1;j&;bd!e{oB%(-lYoV}LxFHOJu@G1kFOE)&l4#V&7P*-0BA*nE260Zp zn;A>54coawLKK4uB@hGIVFFaSM>)z(i5sMv; zzk2pB)?DkzZR>*`e5ro#uC9*|^tgTSmT(g)6+k*VYOeYg+sw5HEv{x|W2hz4I%-p_ zgWW0alsnWz>_P5U*6oNUgo2?+I5H|2%jas8H6gK&>l1FfZ+lr^d^zbPHwdGUX=E!L zcY*@BMLghjc9BO4KpB`fw5=M^G=EN_Q^H76B^_Xy7D^rsmSk9(jSLN@8tux^eYSau z8W9+N=d#g3N&3KLI#n4xmLx!ZaKM)=^=Z_A@a;JNP6XHC3Ah+9-EIBxV(;K7?T*#U zOgwY+`0-DFy!RI{J-e}jziX|vcHFT#Pqg5Y)9HQW%3bRohW&i>c|WZZ>yQ^zDTY2X zSKm`{GuP&B4Yx-387KMk?0Kn|mFBsZh)bk(?pMRFMtMn=++jKFuHtKX{<8FYnYd!u zC31W{{~F)MzsvuW=XhNZ1A-uOq7aL#7%#&6sI3cR#r;I!1MquAh{3H4B7Gk)G*yR~ zp%}VRVlXR!QNAQxj3jh#iT9NEg7=1(^ET_SPknd$?Y)B8N>x?a6x~N_*w~k$pA@BN ztW_Z>CX85PDg{$!XmrLH!w+0Nc5HcBMMV-E2mFo?(rcJxN%iJe+J0xfckJ8i7k<*! zeC;Y(ZuQ_ni0 zuOV8^dU)>OuA)(3M)sOjXTz9d!b;fBEE}^d-cWGR-{b#S`PhFxOMKctC2K)!_L$l6 z1qBT;At6;tPbyFPD4PXT=pUm27pMWwGqk4) z7Zt83B)LYm%N$=0Mr7VN^)8rOwZ9QKI9Z%@wlLM0EN+~XN|(~r1KS2umb6ij7D9lU zlu~{IARzx{y4qu#y3Y9d&VBhl?AVT-Yviukg52yo z*8w$-&*S>q_dDl&zu))!`Me}nU4>`$$n1*T=?~e*5C5x9rQm!W$OA%dq6(GyC5=_1e!) zzR#)*s(tv%K zn2bU+>e2DqFcCxSqil~NWyg3vKXwhP{k$SQWH6e-uN0?#>48ZP+`?^4Gt~9=nGW!r zGXI#G`pkPQSGs$%vBDrTOHP@=+A_2JxbM;65M6ueH*1%yUpF#5^*rRA-?6D@@A)r& zvi{|feZ2A7-p-vld2g)TdW810ENpF@B|daDQ{P`3oU)`CST zuZ60;&mU$zi)BioI zhf~?uTO~Ls<3T8^O!7o1OYTiVGMZbEN*ZQqz%)yFVJB`hb7MJpRWL*e>#~%PbzUkf z&%Kc#N)*Dn$$GIl|~3{ACdb ztTSd|{jEXh=jb^(I%-_3yNn6+AQC15LC=nHhB3=W7uT7!uiDoS^=;{@EP3Lkj#&53 zxn;Grpx4$V8(vvc(6OPpq_S&E-y!?@uHq-^;VM6Sjr|dn+>FK#^qAwqvbVRlQW&rn>OL z2$CphL1C1>Yx(__o|p3b z-+C5immlq@Z(hiFW)N9*6*7TL&RT^)v!oymOKr4W`hWk?8_Y(uFP)f{ zeT;p5OwD662p%{M0sCwFJNDPSF|~#sd2oXso9aX^aMmdNmDbYdaLGFP8zd1pImmOw zrxM-*@Ql$KEWRd~H5u;ZDY8d|3|U2j6qM*%;m4spIeWru*V9)$uU;>ckw#d<57QFjEqk;w@C zJ8L58LbR4h;YGt}a1*)4o1vrkk-I81@oZ+vYcuNnt#g({r$>huFo@1_DiZNiL zu!brUrx6AZSyP;|YhpZ%c?;-rKDoyxd1qae<3_oomXZ;@pvW?t=1~YxbdQq4$s8cU z@HaS@1Ts||iK1f4c$%2`q7qA`Krn?8Z^()WRt!NXc=*zm+z{t{ z@gvX$xD0sq-}cnxe}mg=OSXRCO4YL|Vs)fKi1opK<>U>O@0f8iQ<-MMHWVj0BS?t<$cI z-12_IS{BN;q8Q*#*QQ}M0WTH0D(Q#+C%jr< zqqwf1MJQARNclO0T9~h)RZy#xPpTFbqL!uwOCfxu7}FNHF3FC2-`m9yp{kO1{GPSz zz4zRE&ppTZ!nmD#xA4xGd*8lW{%>(GAhkqWic(`z&o?LT$+!JtliX;u2q}LmFI6Cr zNZ76W#!~B{D5L2wpYpA9pe1=U3X&@1i^C$w7k6b%+|)oZ4r;L&(xU2f&tXl)>Y!-` zn<{`W(n%0BTADqQeYYU3>RTXTs{266=g(H5{Mqyu_4W42+js2W*1nqVC;F?k_~n1}<8gI$)#rBZI(v3s*L&pBjvdD?ZrFMO zFwTL#n!_-j&8oW*SoR$2{+Zp9Kn1epg06>Viz4WEL859~r25|LPasjF6OJbzcai@! z1wg6E$4a^iDqcF=eW0Orb0f^aR%|T!{OeOawm zKzG*&RYf@x0@jN5!`M1m`+z%=ee}VGuN1@#G(BBE04ktb$-W<; zk4DSe@W|ZxQ)`phu;iv*hSI83iKbGE`na#y~lx$W8#o zMRP7P3lgp>Fc=gdqsH)1& z!V_}%DJFO#=D=ifj}||Mh8zFYUul&#*>{Bwh(|@sPPk+t6Ox(@2}-8u7L-TTb9JIa zd8|T3`Ty~$+4$6I?dka9rMHueIB1O8Q}r9J;U)-kJiI1hZrSIL{{AG`Y%K{Yf^GOC z=H&utvE?du;zAzJ^y2FR4$!JfYsnVa2t=mQcY|GE21S-VrdSgqZU)`)P+i8?X|V3* zDCa@`A`AWoy5&a6wPXq7TeiLXvRs>NO;W{SmSv5vZela*c#Ft#9O^v!X7@n)uzdh7 z{OXCTcAkRTPkMgOf(^gq#;2FmkDK};u+Dafc^5v;n(EN)FmU06U2k5y zmOcbWzWMc4yH0T%X#3ObOW#|#>*w9pU4Ue9?PXBJa2^QP{l!94Ww^*n7evd0_N&r z##@0@X>DWKVl&E2RiVc$Lw*fCc2kumzKlzxMRQ+XqT2W8H}LfM2kq@p!>vPig&zY7UP$m4J;)7O)9nu>lu#f9LKGf6 zm6(Na=y65x{jQfF;LUuI8I=>`RlSB#FA zp^Ww>F<=?|)JlYn(Hp?hjb1!z;opu8J(7FvJKR54EL^r?(V`X51K<1of9xA}|K0~3 z*uUFu=H|V-|4$tU4qSd4#K~9C&nEK-5p>xqh-2w`kC&L_wqh1a^U zOH(8#C&PZibiRi$?!veqV_cOh%Z900d9j454QZqcU~3x1z=0mo9wr$|;H&g_E2CZp zSNesd{taW5EE%>|7}%J$jmVkaib_~)36L6mK?bzA!?f>(XE!AD9=qq#jEO5dezIpWfeu{i~yxhb`aHHKhVgH==Bi~v7e#5$= zIp=uw;w`C&CuS(i5x!>FH3NGRAJFPYRmXNO-6@G~m$WY?K?_O{2iH+EBD4>iIh5*hfa)HW4BXNlQo3VQH$bUw;2Ej|hlWii z$arGrBOP>bo|n(ipGo%GpShRL+g*SIE%y3Bdl2Xj&z*1ISC_mzcaelk@Ne4NKZx61 zI3MSvafy9BZdt3>0ES}$6^%KT8O*_SK$su$XW?E)??YE$tu19e{VBtE^CzsM38bZ9 zVu9InJl)aoiTCa4_#pcaQxV;Xp`rWYGT;yc<)ginPp?=(NlkDZC;B{9F=I-M*qur)xb7&UEzE0d(Y4R zeoma&u}y5_p9CDRo!9|JiX95sI=T(ARf4TiCWIz;eKW?-&|DqLv*uW(cIE}h zfOxtAGU%H#=*z3BQA_2$w9Y7{$Mijiw=a99E4*l)^dj$yHk>)jzL!4y?cPIDUQhn* zaMhdUrC(%!p4hu~$>+YrvEaS&nCR1kWOu=5uA{P(R(YJBs)RF9b=Cd4`>xv(6qAHz z6BShSJhDYGiGHC8dTh0N5|$^)esY9JE>a*&Bi&d@NCsa-Yp=)ju}h|Mejf4_#Y6bJ zrKhV+wD*{`c<-}?FGagBql>Qe4VAWmy|16s@1bGnpgtP7_~NEh|I#l|)3?6y)UVId zi~34bkL`4~zP)hhsiVK^Te6x|(*LTQqxsVH|E>VHsL=keDi2}zNBXe2sDCCCSM4A4 zcT1GNrQd>=46rAFPQp}Si;3PhQB&S*P=n9C55BMGUH!|v#iw4~G;skKQ_@afP>0zM zk!I1;X%rVm2iT5+orI;dv>93^DI~=?M^a;5nEF7hc6BFx;pR;ulcR)~pM%vFOmy=} zf>sq)+E{>n?D|iwYz~+rOCpa1R!5FI2c56lZ#e%@b*1LE&HhH@UW74dyP8o8>H$?& zny3EZeg<*|lfKOTk8pn7AZ8#Q#wbDAhaZiOJW96Ka_q#+^&V zEFB^)oV`+Sf3+L{vxhME+0%Arw}7t-odU)*bMx4^okBnkTp zBqQ~bRcxrgtu3+`R`%s`_8~Te2QnM&3(SvP6pKbS3es1@3uh>h3b1e>9bkdL7d|gs z=_##QxBlf_{tdc+tbC>E{t^Zp4Ydk%Dz%Nb;Q&nM_!fC!SzckGh{dOWaf{(ChlJW| z<8@_BsJbAD%V;L8zZS}+WB67R-Dy0piTh_^R^8yAf-D!pRVErs-%2isW@bF~B>VtW zA{pTMH1M<&4fEvVgT%ou_c@*9A|NyYOgGLxgt|rwN(Oosb`{-EozvOvqQv!07b7Ty zu1MIxYfDRN8mB2DAma=!7+&*nMu7sA5i2|1%HoYpO^va1Z9HF9s>}n@|vb^7;I@ESsd2bDSdx^E2IIo_n^Lm2;{)Xwq z;EBM2sN{g*{w&J3{)MwN2I|sy_Y_#Unv%e*rOABY(zKFItVW>_bZGMh+Qv2a)+2eV1_d_D1gDzEH-z zjA4(1h|T7zcv+_6-n7yI3=Djt8MHt|)7P=y$v+YosV9rbwjuBdf`WZjYu4v$;KE(d z%!OQQ)?A3haj@C5=JSYi2;XZ!ZO6Ky-40Lf2(iqrVls*1Dv2wPC_TY+kOhOO#X^5j zbhL3;nJkSbVXm7e!UNLWI;SelS#GMh<4I84bg*enMViws6^+H0zdIw~#aZVr-3)DNo5kDhWMkaYt#SSZvXM!g;krS|xeqIQ9s&TVdV^ zetQyJx`j$h*`J84-PP`jm~%qzV7=0+ci!QAl<%;5WsSjU3QiMt`v2v$e8=GQwaEyWYZaPO^8aJJ+JmF2&*<-Q_da&-y?b}}?jyE5mKZ__63HgnfU((BC0a+M zS`9w7104)OD-wpOwCG?vgONc5JLOfW?dWJxT9RxCdB`KEMJT2%LJE{>#aa@WiD(*P zN7$R5-`x;&#y>if+1%aPd-waD^PTgZ&$HCSJzeZ0fb@RKH&?7{7Fmk#bh0z3W+=TZ zdp5m{6vJtwNW+JE|Kj=M7dH^fne-xm-BTkREZ4~jIvGf304{QG&JAj?4c394-ef%bq47NVJm zoQJWvV8i8x_<#97;uUw@hb?Xccngzk>Uytni4U9nA+|_**m#<)F&(`5=Hn(Lh=?za5-@ZeCFL{Rk7b?GKnLq=dn~v<$bud0*zV|WqEy#q z@!@>sDTOJW?9U{Ey$0Dko%%5b_OM=#LNpV8#Tt&IzQzEXb z!~mjLC>jb9;dog*AXW#ZusktQ3hk~noom+gM&1-b3^$3_yy;Z z&ri2Y988r|$mjh`)neKdE$K^|w`n!L8gq@>XnHx<{2^W(tI(=qb>@%FXY@^` zR|WIzWV@^g1<2T<-c0FL+Io#?8dFpiWVY;zLc;7f*=aTJd=wHaS?eMyHUYO+g9I+!D-vI@oIi&dyB zE|tFG^kw%*j3+Ml@Wdc={Bu10QDAP8AgN6SW=gk7hoxRaQVbdldT5{vzo)S7jH-I} z0XZ+)f&vr5dfRLTz*+*K0Q)Nm0igs?v9bd$EbjhUEZQL*zuE{TQY2h}Vx&i%{sV75 zzr%j{gU_hikevk^7zgT?$LbmLPt?SjFhSa4;{aDc^nQ>v z?XI%!w3x*^*ePrX@PN*gwZTihsc0TX*i!Noz#79i9PDI0#J0}5NY4~~ffFYhfH&TV zaw^g!O()4=JBkK~mz5U6O_QL27p;9&&2uhU@+#*vJIWtiwPtdvbK`Ft*ZjU}>aP0- zN$%W|(1Ar}?NUty9$`pcucz7o1Nv14K$(gw4L}5}(P)4=svttra0PVWBDydVmg=1T zpT1lRqz@d-UaVu+t=-_e{FY?JpXk})PRo%#xbBTu6JAOc*4WhJ346+o`|Nuni|vOZ zn~hEOu={M*e|Q^zPP9L(gK>d_K_v4Zk}-m`($I+%6B?DKFjPJ z?x8)|p_a{So~+-#z{Q;Qj`rHP7RL8~eV-M7xzDoAY_7O-ic`;Lfa*P9Szo z>8tu~o!!dkadwhZ+QnMGUPQ-R{SZ+n=94K5)f&2@9l>ClriyW zGIyzw@+aM1xNzQ<=0Cjfz=FcX&+pG}`-S7Y{halW{LJPpnf%l7C(iF}JLhIKOeenH z(*^IpJ7rEa{>D!lXL-Ld?3cZ0rWO)HLq))f&2|F6j#fyM!Vk<4niSO#tc`Y5+KyZBx<=;3W*L~ zm8ghoMXpG5V9`;rN_Cgxt~_&E&8gFAqc=dT**4&mL>22$MHH?!o)fBtspik~Pw{`( zUt=!{t>lk~Uf}JacS1glv;7%G3GM@W1}enR69~4dY5<1P(dL&Y$V`3%X*iEWVS15B zKwua|jET8kK41+sh#kX4vCa{=8Pl%KIQ%;ooL(p6+&b8M^mp$#pE$qj>zU62uI8NjulRfG|K;yr+~nEoc02Ih z3MBmGd#OO9K|My;xM=W3lMb7dUE##*RrZa#CeKN(Eud*$FBJxEIYQ4WcP#3O?Zlzo0P3j?f$a7FVsDB>SlWL7R&p$74Z}{G*98sU~Jgsu8I^Y^a z22^#s4jO_M74{yv1|)W&{&z{v_heAt|6)mU{_qp{oAX(_rH3dbY>J3z$0v`%l-sYgv$n~fpFkY#Ztt(b=2 zG!3vupsSi&kpcR;XP?(V7Bv}PR~PxvHho@iy|zswnpSIW2F~Tm83bijVYEuX3#erj z9VsjX;atXLvn~`Bv?U)`=7JXXMW{}hE03#U5~!L5o=C_H_Ms4|ikv+E1J-+ukgv^A2qx zd$JyFXuwNyYyWm>cp2S(VvVRHG02``B`AV+*!PvvY4S9EHk~Wa)!&x))A!_K^sjOs z>t~vWF{wJ0{)ugoNJcmmN{d4|;jm9r;H6bnwJy>J8ln}rz{g(!BRWE%jEo>)S{F3y zbVs(TDoPO4P+M&TM?e6zrH5mY{lL`Y%D8$ZtQ5C0Z~c>u6*=cVbN=m|nQ`EO zj@Gxj)Za9aJ!7VB+QVlSh_DG}R)hV^lDt9heMsz47*G(GaVEQ z>1oq6iVp(XxRZDTOBJ^*0~mEIF2I}db}V5`-J-i5*gOLO{bTsoqd?MP^MnQ9)~=kF zStbaQIk&zDdwCz+gV3ER6Z zh=aDO$AUpGU$Qo+0~EVJ^k&d1@iwnF&ClV40-PuzBNPqI4^f=P`6~dlkq%8Nt4xli zz{zrpYxKzlK7jSRlmMre7ikknfr3=0Ur2%FI1TJkQVUefoqS6Rd|gZr4Nn)U54v}6 z)%OTpd{gy(gLV2=)ff3+)pzCX_>->%Hh1GN9z&F-2GD%}a&8EhllauN3~p{5`mH^2 z6hPbqg7@nE%Oc7r11j>f1y*_Y#0i+_EybTtS_{L_xmZ zK0s&!@^38Qe#9393slI*g2Oi6>EH46JFUSm_GbrcoX^fW{Z6MB2MLzx%w=O`1)I8* z@x2yYvvB!IoPmGmJmWY+?f6-|94~eHr#^GPZ^kb+9B^(dt@`DoQ2(UFf7p5GLnhkL z=FzY|s>y(jS~@Z_LvY(1*FvBKq=1{NUXLfxEer`)Lvh>lBiAVxak(-rK2Ij;we>M> zw+F6v5TbifCf|}2e=Ku9IgY}x5+H&rt8Rf_WwLc(R>}q5Maz@IE{Sp$v@j>aJ#P}{ zEn!#k7Cl%{HvZxIAXuT`Rh;sBr+@9pgxc!bUw!DGwh#|nXCn(gK05L~QI0=9GEld2 zPHs|t(mtV;WORQEk)S^<{10dx5dyOpl6AqG1oQ8{sSwJz7v%FT)NY@1(YeMY)Ys>d zKX=8I$p0HR`b}|#Eh5}c-HJQ0jYw3Uu6|3*=sk1g@kC6F7Le6=P{f?vafX7=1RK-5 zk5X`y$aMhbm5}p7Aqm+C*eqz6+eTm@7|8`c!$p@M#!lz^T(^VM5~CooF+nU&&f991gy%~?l(tC}WbIgRE89g&z|vkbJS!!Tq*V49D#>bmC;^d<M{@d(@b$#z{LW$I<-!{Hhhji3Iu%a4#S=#Ap&RHbQLylx?RHjM6PPu?aSE zSLfE}(p+2BVz~&I0!SghxES5z^j0|SN0V#|BMaABd#xUe+SURKdX(s~)%2_wvQi)@ zwonv;rtnj6w(%T7 zb6Q9qhbDg@mM6Xp=ksodvr~CIl4FN5VmWq75Po^}SkBE4@Y_j#MSKZ%s}Ovp2~($| z?RLzg<6`Y0?brG`{iyztF3po?YwPJNl*MVM^pX2>`G)MuqvNFt`jE7n?vf7cXGO33^&Uj|W-r1R*-JP8^%Z_*LT`w53 zV9(mTEMH!6d73muEov=8MG2%0j%k!oQG`_~A`wAA6%r?HfVOJ-h!leXv$hF_(iYLi zAyGjtio`>uF{)&6qQp@ZJlk_;mfEJuzwVD2+k3C?J?DJqJKu++`?o#LjDX+!Z;%!b z22(HZ0|U@t_t|$?9i2JpAgR}>XhiAcxIsl1@t_+?+AVw z_64Z~qbKFpCas^k`gY-z{q89w(|~Eix(0$8>fjWz;Hyr#J@pi}9!{B9&sJ}+|HL2U zld$@jv-%a3ht&r4;tm}n-4NkgFyYTQ8(Q2QU!St$@WhS?bU`WG5t+IJ@GyDDAvB2l z(MFoU9r1(l58~W2aeO>}K2DlRb9^i5i1R4kfE!3N=5zVWRE6A`o2sO}I7)8sX2csN{hP(pBrq-nq zQ@gK`R_&HXG&Ishkt8B|JYJ9>r*!CGP^#ydvpOSr*sn6I%=I7v3xW)aBu9Nn zR7E0EP#L0F>185T1`(cOT~G^T9C@FF3T=s4-42s1O>mo z7b%b)kB2MLAU&s12`(w&*yw`c3WOjyS~J%}h;ZC>AwA56AYI5f;cAX%ht|j7JqnRQ zMCD8ufWxS9E-xn7-FfTR_VD;wo{T>~qsqC=9M<|wy06HV8L1GSTb`T)6aFV~zo()4 zKBS>I>Z0;|eg%J-zb5mdjHf|0sTyG9e=vYi00#oN2>Pd=1{5=6k^vK6G4m!dX?fBz z8My{wsY#b)O}Z>=npoAeBJBT4xqt0+ImmsF+V8064^RRMTk9&wg6?Of#4ct5wL1z? z?`UyUb$iPsJHWJL5;BpTT15V7`|gE59C|zWs~ewSPy6@+dl=uDC?Wpr;^D~c>H9v+ z6^~yhmB~k{2Or{dl#qs=S}cLxy@=_i*^glRZhu7Ia&1WnH0 z#CZ%|e;>pwjZC*NHOt{qKi|T=p!2{do^lnX-R|DEY6ir@xEwy*YPfG5c`MGisngEqhfocTqgD-Tcp!!wW4Jkn zW3(b=#b_)6k8s3_VU5k?jC-MMracR>@6Hbc&o!XwXcqb#t!xV7qM}eyoxCBqUf&k{ zp8lHrYH%!A>?v-Nmdh{5{8j0WM2ZS7L(b)IoeYMp6hn}biREJ?#ynLlR>I9>0P>F} za3T@WVBk?;KZK%SX9pmy$H8iJfk0zMq??u?w1=e;V=clM!Rs&r0(~RS));IQas^ep zd;rpm`HtF11{uuRg7&Jab z;cF9!>ScgB<@Iue>wAbNk>N@Fzu_rUAPE;ylOl2vWoE-k1A+)AT|Z&p1T3ZWKqb5L z|EfHgIU2MooACw{h}h?7IY$q!%8zny@>y8O|T8*Q|72~GC8?-;9;2Xh*!cx55t3I4TF=A>UX)|;S6(U z^5RD{Wamd;qB$pUX+Z}%x-aDD$S~7=VW#`SO!tM+gy4hf)B_vt2R00&6zZcfusBi( zOG-pZD=U?z;FEz}-1C8-ac2UT0wrY(+QqF91ThTRQ^8Oz-;d^_q&3{Krt z7p2Ry(WvBynKsZZirP8g4;jD?lMm^n>!ioyhY^}Ptq7(-z(8F^X%r^cyLH{qAg+=3 zQKiF-Bg{fMmI?5^NF6CKBUmcrqTHQt?HG`)`Poo#uq<#~yuPlUtHo16jh{Vo`|OSJ ze_;NxZ+>TI4Yh~n&Z_9P@$Ly!b4%{q*X(ZlYoA{G@Hdz2d-fZ{gByw8uAYkORlt+4 zL*5h=Lr188uZ)Z2ko>vK?e*a?A2V4OY3#m=_oz6dwyJGvUgcFHy0s&u14-IE*9C?@ItmYXKY+OT_#Dz#Q^(3WU6B|lO{&v2rj^1wOdL@ zCge^bHI7D}G&J;3(Ibui`uGK0xqZ_DBeeEMe|gtlG?9x>@&29bh3ncMhiWE859nJ5 zOxejd0Qyciim(&M^6#N1C?%*oDhDVrVOX}BZDyBw(-d0GqvjR(fj1f0O$K(8;oPK& za(F~a;h~pVrm5;bavec4Fh|Qo1#eY{l`j-dD$^sD;K!mmRPs;% zus-JhLKjG1eiX$Z{ShVAoH~%=x>7hrCB;fnEo7xqhNqMPS3(J_BrxS*U{9nr=&9N$1o2fizBcsM&M} zh}$$xS6S(FV0snng8%ScEwELcb^QCz`<#28y^r2!xTo#yg9ANW?rAS&m-LXj7K4L< z%rUi*=!7{RP@H3CL0J>pGEvY(LR{1>Zi5xWq%HKe<1vv%!ZJrdVU-y+SLmj>*;FKo z+*AMGxot&aOxk-M{d)8N{{P?idz{Z;ErTx5{(Q)dT0b( z7P>3oBx=y!Zp?&-IT%)QLw67)AOz8m*^?#uq-?6>(8c2@syNlPQ*O?pB8_jPrPe@M$2BmT7oHQX_*4_);45%xl0cJoN z2<(?wk%==)q!pN{B~6xfYlpShqAe>)LtH!UYKUYwL>xFme9}1SC(U1i3mHNU#JB9V zPuY}i@38mUv`w%VFdY91Il;fq&-zzazPHn{?bMsjRflqxtJDSHoFb&VD<}omBwVZf zF!u(^!6a^!Zj`V0knlisLV@ss&lWz711@od@IWwV(iF$krjbFL!ANx^yqF-= zq*eN^P}hoI488EhLqm}i4%J4sc^^!8Q{Jcyjm13uu}9LpgmslmJa7bm0wx8s@TZ2i zt=;@4PT-y1qn>wj1b+og^(Jp>$)nA|jxD=Sc(*q7e0|NniXSEh7$Oyg7Eb?zc^lL= z2~ssWEGk%?NjMp3^hhdYgiQiqt;t=`>}XB+Y7=g1iWo)e$kAjn4ihC@90wP}g~9&4 zIwXqW<9@aw*01P_8`$$K#j;6*09&Vi=c)?@K?IO|1SB9L;vt7YA(CU%IkW&6croy6 z&m0GLS6mO|9>T!zq8$^s&(Z*CuZ4OlENg({sWTVP$)n--v*9iRSifvhp}uoZ1VTpS z&$#M4-c(xy8xeNFGu#tmo zC*b}CANTuCBNQUI*9986ST0f{sGUH+;^CREu`6NibH0mu20agPHtwnz1=B$a1w*po z;;JHb)c+UX_xqW{|DQ_cc;?}m?~nQ!BRad7to2pfUpq4M{WswIBV!0pA30W2XRip4v2aAu^th`BKm{=CFXI?ZgQPHabhETaqNG=-iztCY@Vq*V!(oO%2m@a92#JKR zqd4FN(9!Mts+-^<#*eerHrv93u@M$g&IE9orTbar{DHUsE!puIrJflhVoA$3Rv8>vx|a8 ztx>mv75_QOC1GU-R$gIuA{G7CO{gr#DFKR>SWaQY04>S9ATqox(O_PuT#*q&3?nKW zN1l?r9O8Ld;8lv18JUqdiQ@yTqKG0-k5iLCW0S7NB1Ke0kU^T~BncooIV^A-L#`VH zL7k~A)@H}ci=%c-C!a9JSQ#`kA>K zP1E|BGisq9+RvPU-PRg>L%tzjov-Gr;l!@!%N{zE9ULT|eO`(E>Ol6TgXH1hOWA>$ z&f&w*4+-@`=PKJq7?6cUK_E{WlHf^#-C+jyg-=q~q0J2S8gjvZTz3_o6#%ES0Fep< z_O78<0evSCXP4u*VV^m>tu2>>eHCndGF~oB0=2+Tl@A_&FYL@-fNr366Xs<$@M$S7hba~%N)Lx?Y;GR_F8WiVQ&pgu-32msUc>jVvYq4Vg*t3E9Q83;yICFX@M8n zaZ)k$+K`C(A}JW=3a@Dv+!@PN3YIEknJE~0ZTKa}OSWDv{hxxN-6pgdnr+s0c{g`u zC!lH!6|z6+&0e~k?FA+{grm4b??wiCz>NYs2b^ov-zjQ|jCGw3xK$CbX3}wbJ)&t2 zNg$G<7;z*i5J1{-I)^xV9t>mNPP+^|4aLC`1hTf^9!?ebG7Ham-Fzz;V4e$yBDi#a z`+XbNTc0xTnU|ly&$X=E`{f^Q$uG;dHg>hPE&^S87Dw4booOqDPkB;UGBg5d$MjT{jU6(*9me6~)nn_hsp<#od4D~fh)K2^v=BiGVIH>>(XA(FeibMQXp5bjh zWbt-1X7ThjF^&r8D5L=@H*tCfJgqImxUx2%ufcX@k^z0P(o_M1sqK4zchcPVS4eu= zc4;}p8sBo-8DKa%z<_4a_^ef}TG>ptg~#LAFte#HyEuHrwl?hSw&iZ|IqaG|;hDNJ z^X>QNCanJP39Gb;ogd7XhkHgwj70ZDx&QfZBwqf`@D8ks)|%m?^1iRXdHKixezi0) zS+pi5p|71lFOY+*#u(%zqV-?_r}25F488@g0V9uq^yJ}l{E`djl_ezjC%yMuV-LvJ*EichzIAop##Sha{d+hg(c76Z5Ha0fNXL>)1hSs+uu znu*Ic%Qnfj%W|LFc_L!*V|XHy3FILXdmXutS&epQ1#Mu# zFjv|jlQF26z2s-;Byy2SnBbD&p_^PpUdT5wEp%~f%cOvU@K0BHw*^0*^e>PEic#I1 z&RemVx69_+tga?WHp;f5S!H?-7*)Pb&Y=QHLIAzwEMWRBKsC_Bc?#9iqO$xCP|P#~ zbBk-Knx+MfmNc0CK3P;2&1G|ujyLePd<@>APv{4*Jf6c8OO7`jYC^guE7cXo0_pYKiX$aOste0qJ7In~*Zcxqx^SrX9Es*n|GjG(pdMva+#-U>TbWX5%*%AOv$@Z~crjWfn>a(QhLkp2+jKKF{M9v`ZCzE_E7ih%GH(PEniH3YGcDFV*LWfvT=W0X<;ifg zNaBPe{Ui}~6?&3TlM=1SU*eh&iJ#9S27X*KEtB%s7f)C!1yog~DBqFUAdt;aRyyE3 z8%}x$MFCxS9KG(`55j#3D4~*g{k9)NRXGFY_3e6u=Ofoh97W07P&(2iekGG}zz0Ein#M6BZy8J^;oo zSU#X%gZEiJpFx8}9B?{dZnY+5XfBwNpN&xP#`&a z?FcRyuQ)!F$AxW3OihUz&;n=kPY%!`yY< zfJ$o5jmcOL2$Vw~AjDr0MaWOkOSZ%a0<)E#?pGYKLnoKT5Z$8S&=5Txj;0bPX+bJx zvTa77onh{F4#s-Zd%yDf?o`)AC-dRV=f7!w@9>2axOim!$gO*jQ<%kRGVQvKOf)l( z*oU9h!!a7u&um%rSZ|UGtev~7Xty6nkf>#K~xT*K$GMf zK~?4aBDGi){DMD7I4%;VRt8q>4brH>1`Q3B@*%)1=s2`kqYgZ3eVpS-9|N91WXmPc ztkbWYOozPwHM;IPP<#2{^T)S*u#RK@`PN(QKR7$R?$psk@7T)c@14W(*LF4sC|JJ$ z-)^}YD2@I&4?^p9T~KI`x?K;qTLSe_2WL6$rkmm1hMRGP7~AIu@5$g?Jf1l1#%}7h z60&`&6$(Xk-De~s5rewzBmA7pm2?|Y1pKZ?qecQ&TZW3Bv_aY@4MWo91yC10VqKN= zq%KL>4D}Qu2NO;UiX6QF4CurYY6Y{DA6R+n$cGy2mVs%2&aoQhzT%|*;~+WVrt~kD z=u(Ama_djIaw=U}Z)(9*MK)u5UOF^zbkoGng3w=lLG30kSMP(_NRO5B)V@2u=gjvn zUOafJaSj(>s~tYDW8{2z3*|;H?j-A7zeOGBC-acU_wA?=wBGRHt3JF>!mJ`e(}_!7 zOAwH0A}De%B8B{i@+ysu;=1GS?c3SeYmS|G!%5U8C~1+>CJi5w2DMF-V89y!A+1scRjMFTBdS!2P^DIC8@FFt zDy6~c|IM1CA1bx7H6HJ!{lEY3ZT)=SQAx0r+y&15|EDd zH{#C)qE8IRXFfX{?bH@7O3n&ZHRn@T#q7Bk;Td|8&yPTk2usvPB=>EvbsFD$zFR!gUS1zej zy(b4@ba_2l&W2gu7CH+F3jasxA4dp~;W;N)n}gTHUil|$v0j$SW4^iOab znPlEa0d!om*>jRtMb_u71}jCeUD4cbMYGyeMUgHOGg#yv6r?*sZmN84AB8x^h-D#R zwQ1a|J}mgK&&MMak}0<(X*-X3s&;fX%GoMZF1jB_9*~T>J?;e;pcgRh5%rPjs`P2; z*!s@Yk`7V&h`y*v_1TTQv1fB+CR1cc&fa^Vu;E)C(H}QFws>*-FFqdrPL{LzBNOQt zJuQPtn|s&p)u*=Xr?b8c+&;}*0!NzE8m%%;INKeC#sNof;~UnGtSryt8kw9!f`BMp z&4dNe3W%3wGgT)cz-FOivivkfq=&Cz`B>IbN8dPgU>b9l*eJpZsWw4_BvjmibaC1i zsm3a@1UM{`)8?JYj#x6VqN`l!Z+j#LNe624_=eP(vyTbemDd>piW*7$(Vo1_lB4xIp46>)?D>9Tp8=b|9X-;N= zV!}MeHe`iY>$8YrP&A05bw9#X^=Jih!RnFAN+X{`23MxzrDzeUjytH>{`U!CFk&#k zkTT3A!MdPSDCA0gqA4}9hEBR>X;8zD7rzVh;KPe27vJj3=I|KIirw{DDUbe&(_}Ar zn*x~JJ3m0aZav5mGv$)spLJt5#Hd{mpm@UE#p4;13B07J$+C>J_OhBqu(-AGVJHMz zTb#RQ!!{U!ZmXICafB)A(DU4?wqCH>(R*`H z3`ekh&;R)BP^q|Ps8kv#i5~M zaqTc5=jSMguN%Us0j-{AHH)OOtck`pJFl8d;P!oxX-(%r##oz8fG@3CU|~VZAccNy zeIu}rHu&No-ntT`>dFT{G!Yf<)C7Dz9_R=UHupN0wZ@jME|xdp?~ktPD2Ga=lDj1- z2cwYLMquf4WI5Tz{2e`v4xqni@*#34H%n%7#zWr2>t?-AuQNsA}dpIzxtVQ|p;*ru3I-D|Nc7Dp%;2t_4t zIF!lxqMOWBGr2$1kqV`n!|AC!F?V%tiu$sdq|a?|dP9L=DCY2XlT4;5I=U)j?Fn_J zBF&3e70IC}4u{itvMK8J_?KskzQk1%SsCt3`;&=4OC@j7x<}$o#f-5e@=mK1@du(Y zNtAp|Eybqf$dGEb+`q2XpK1=Y>}#_=&a6u|6SAO*s+Kdf`iZO0b$e+;v@lGJc>)=qoWd4ZK z=x3VMthque(}0~GD$nMa>hW-p86KKdt&jpMX*t9pui8!{0mf;Nsp{67ks zD4-+=e**+e3&VtPl(XACHIg~!#W;!*G-W159iXc_4blF*k0{* zH}!>wv!zJu^2~52qWKjz&TbXIro7e2D9f;0LG~c;Q|)1q7u0a9 zMk;44mcaX@LPI$$ra}))^SYG;L|BBR5j(cq8EGVZB77=L!eL*cM)GqElL9wce*T(- zPe@p*VG(3kPi+e{(v0hjrAM=5mEe@0Q%$?omdZmMhl2u+j$>J8rB1(u=`JJVPSX;n zN_u@!yKTPkquXn6T4VO2hcRV}L^NuZ5*|v2>e%V0ASB&(%WITm~pI(3WjhO>a z@yk6hU0LJ}CzmU%(*MN~n6AUF=14hV#kBPc>zHMsXN z0^h_pVJcgvOj$oBXgi=C zl+q0-P@%F(7267IT5Gqd$`i;ch2v5p5OEQYO*eKJLp1%s!0m(3uQhT9qv64OYR%t?^~akJhpxHmZ98ZeG@A- zbZ44y@U^#(2uB898e6$$!}c(5T`ouB4qhpLl=WDZIRxs#y#b$jqRW*+Xd zq8^-{Ms}FJ3{F9|vQ`(QIeHdP$wVKH$~yH74j8(pfwKZ^N%Rvu3!=qP0p6`Cku0hs zLwQ9D>3%eCiRslHBaM_<$X`QKib-h@W#~hriaF+27>n%pH^jJj3i{CJ&><9u`xNLw z-$60p7i`C_s@L1#dIPD4-`$tjYT>bcQwOQyy#68)3pZPEONl&-yySSHo#WcC5D~@5 zam1o-BA!pBShlx_{f8@Ihn=I*n`h_dR3T2#i4cN>Fe}Xou-bbl%cSg@v9pS>u`CI* zbGg~<>anwjgpF*uLp`P3tNg+AL2VA?$klwRI=yY3Dd#Olra;N`API`arxKg5N7w!( zz6I9zg{B0c<#dStHc79uxU_b=B$(_jgVxj-a@$>6hMA8^!BMHz-`83BJiV&3+iYra zh&^3GlRco<2TX2%+LL9v>cx0ld!3`}UbF1~?@qi}!a?mjnk3xGUqOWIR@)jPkDt@w z4t5Th1nvgk)xPtu*L6`G#Oys+dQW*$7bou_A2?k*TD%a@+XcCmiq~qB!&KUCIPkNu z1n8pU4QBbe4ogKcc%i*L(CP>O8!U{3arg>(0vh-rXta$yl1Cos^K0{FbK`)Ctb@U- zi5L-IElHGkPz1~Y9vF$Vgo=dE2LdhdalW+`F-=7hy3nW?>Sg-fD10kHi-pFL@{Jk=-_E?B2T)k|ly4A0I~WZO^?tEyFSRdrs& zxk?t6u&+g(+f>g;RV)-nw}cO_hN(VXmyBE9Z!YR}Zwtz*U+O~`$bT!VkTB5Pno zB;pH-Eh-}dI8Xvcgvj8OC}L3*oF(#kpvL}!#bnZ7B0G=;e#pkW*DL&jd;vl&0cCqo zxWbNbxYi?a~sph+&km5GHKQb3fOs0vi46T=~!Y){d7!0wAv!(_C`<<$DXHxsp7(H<%v zD4#m>@=x-6H~XIG#PQf4M^B!}l%Fa;inBPSe`Z9PuVGOBgKr$e(Ldnj2mI!4Jn7OI z=R3=P|MT_N4LZ%EcPJB(=`8P1k?BG`XgNMVjnaUO-7TjmG7dOMu&~H_ zc%eUpLlo#B04)Nx6lf9I0ce}eS^}V*gedhH`r-_Iai&B#v83l~ zMdHrOa=iL$;?-Xhhs%oj`7}<`o6>2m30;Er-H+O7yw_??Q6VD?2_z(V?e-vL3g`8j zC{s9KO5cBD3Ol1FuiUI80cj*jr496o8sg06`sonRlcV=dEJ#vZy`@4UNsVQgFh~Jj~)2zk8=B099;k0gE%<;?fzxXZ1Sr|et!K8 zyEv!8ZP@V|-Z|>;$CF%L{XZC!!O>}6*kU*su47)Mqn+op+XaV9c2sEW0m{STAVwpG z?Em;VKls56z}3?OWxreXnR!6&c7ndc4Cn}_LRE1C3QJ{bS_b_z3x4 z-BU;JA`k33G1@vX+=VUoPfe1)-rRAcTmS^d0STIUsuc$WBtQV8HXN+8 z=zfOc=$8slc+MmLki{C_V3N~bobMe$E^_VvmDq!+0q^gA>5HY5-Ttkjpam6^<$OYzIRz>AF%~RH`dVA<7C-)rZu#LopnOood`=!542ox39FV9Ce-i zC3z(p@n=iL-~mgM z9i5K6H6P9km$%+@&9~p=Kjas}cf!UY=Mme>wqwy5VJ3RUd0tm@axN>DDF?2%7ab4a zfQO?AWNHsc9EbElJ)_qn4+Y~UZ8C?lILnDBfvy3c0{9FElR0IwUTlcqLFD-xYKjutMt8@8szA-01?C2e) zD1~?^7LI(}5%tF{Z7nW$a8Nq>Tu55J+n1Y6?mxfxz)Bf3cBITl&_NM2BRfxPaM6l$ z*7L!dlW^R(^;oYb4J@s*kqBul5oA9{`-RdVCJ(K?#}i$F;yREp0SN-_Lf8CJy5?^- zgZS`fP#OVOn``^^rO$kH?>2MdF^b3L$LhRM0nG%cyo7GcJzguWWGAzX+tumH+w(#` zcGEK-xEc8{vLM_M3`6cCj+Y(BVl$mHu`}-T`kI?_+3|63YM-GgXoCS6gGR<^#6DU% zuOjFi&KbIJ5?^Zsr=cNegTZJt>r_F*oSZL2s~DnH3_;fRARm;`41!LAoO|Hw8fWPC z>B%IksujdaEZL`2>)=l|CQn-Rjf)a7s*|_e0Vm&rb#k!j<@4o*GPBCi&y{fLU2+Jv zxkd8&#j)&EmdUR5sX(H?wA9(m^6m>*jhW6tfsJ5=V|Df7xyg{i2_hk&`;^Z0PNriKfAzEd_1 z4S7DTj2VB%jKStImB#9%Sx+0EZUW&Iig}haBG*6B(6a`U<~J)Pg%~xZz#Sqejefl< zr{+@&Ddt=PCsciiR3E~WzzC{7qGY#haC;t>W=%5|sToA0p0%NtT_@DCm~JXphuYds zU$J{x1@g)BZe>?LLH4ce<|jx&%}*cbU^Nk;gG*=|4$51eDih}i76zDeGL}^;y_8D# zR5#PDQt2VPFMB;t5uClGbFQaH{m_O3wDQORZD4yyh&~$Mvu5kc#@lGlGPfQ;yzzF^ z{&59!*jb&vKchKIF2K&}??~BcE&o7sl<9}-yRg$@FdVe-hFvd<5NOsCfdfVwbT3HW zzb9+ae^5~K{%12koB98kNzi8PF?>tsKwW48J&%8M1-0M*^IRY-C2IHY&UK}v&Gc;d zN?ncXAvnt}u!_^6vk`{Zi`-#yQ0sD;ZrHKCMuso?WX>e{z-HzgZuRW+E9Xn0u;lZZ z4)&Qy1)NMIXV9xiOGXffI><0Y#973VZ^@={S(aIoB+I4I+^+FHj_iPWyU3`rkbDD; z!V}^4=nZ9j5XMWy0IP`L+;4kv?^SXNmC4Dukz8)%JrYEty(9?F9Zx3pd`t9j zl}sWRe4)#%PJ%DqVYx~|$Pd0~jHD#L-xQTun-r}P{$f=&+odY~4e-mWH^_I;B;ld9 zCh{g~A>W-v=<_w4nt>c!tecnqDT;LwY*DP2XtF`DSxRsyWxy!w5P6 zu1tpQcALZMWexUZNMLo_5$vCzB>yjmp=GtyI1ykZ(K7wp01~LB0qHB=}A=icq$Oc`7zVPD`K22}Y*t zFb1+(tkzfL?qYSRakZ>!jY@7w1c8B|#KsGQrXEyD;gK?7VI~XrU5zuo04e}?vDv8# zbXt=`W3h?eR*QqvG-c2x9r%?vzK}f#NA_#mH|JW7AzPrB_Ox5W6tSzL=o<#a!Az`+ zbtnFiOz?XWu@Il?3hx$U&}|HGJ_elkgO{bzzpfy?N*UMg|C>_QHhHp?C)41`(=*^i z3IGN(R{=l^8NMWIWM2?=o@7jJP5LNopU)<=#ZwKZi7Ql%;534&06}${4j8uqJVdE! zutwwbDb&2!OQ|`5TBNNlLa7NrEe!$)zLQF&)9X=N>ja~F_Ww)qb&~Hx6$4PySV9Wa$dIf@FbxW9FzBw5??GWt%ch~E zM3G3+f7!40*ru*Ce$GAD_xce(6UTYj3C>M&jfuIzj+2-;vB51igb+d~S%xk!FabK! zENFwV2cQ;Gwoa^?fGVv9LgO)pXhk(Bic05Jtv4o_(UGP511~VS(v&J?V{|Q)T=v~- z=b?^j(>DIY_Vwet-}%nZ-|zc==bW05D-z355>Y6r0!l(zNF$uFyCWyv9kO({f^>(Wkq<%}|K$80gal`u!XO-0Wd;Rcu*KzS zkr@mDgH99$24gX&^D7sz{b39OU%*mHPWUI~{!2LpjrSIV))$$^=g3NLo)UM3V0nX^ zWtEq=wu*{pMID$2UakKz^L$RtLCm2=IbO{LY{5oDsc~s}?R=Zg9Q8N^Eh(7AXuqsB zrrWoptdM02IKnblG?aFpp<1J^Fxs4jMw@NUQ?ngb8_OAW=3@^poL1H=7mkN1n0MRi zGH9%heAY7E(c2W|{%}gSAE`3Gl~d-q(8KQkr}8SY`)`EyzY$qQT&I@Uhj*?KWVNP~ zwYLiX+`>}}l>(V%Wjs872o6aLbsW2s^lSmL! z^J??WoY`rujNxna3-{KmK9tXrQin8-Ds%oSiXcJ@shmIdJ7I*>fv?5r7ozt{RYxFx zA^4A}_8}c|h7F8Hi&R>oMikMih%k~erALA=I2|;N$P;pAPMH(HjwNGBJS=U)2gn~k zx6&Wsvr*~h7vrfYtYfemGinXdX@rpk#7oKX5=uM*aTHAO9K#17*f2z;%W-*B>Xd`d zh{vMRuwGzxGZX_`TSNi8q>_kWN}NWPMKy^CGCeh(K_H6ZG8L;KL`$o~CTpEq%TQQN zYqbcoDuguzXa8{uw4+%F22l}2PycC7D*H32Ov5+W*an`pRmPHIW6AXc0|U~yN_XLd z4=!BTx%1m-24X$pKtBnK)Owwo(dvjE>x6`ygTxiUok%B?9Qe!}p<$A5sZ(bBy3~a#SzhTa zM>vn72+J~r!4L=Nl*<`b4tQl_$X8`77GwGQjpR4?K9k?G=)2GuMA4!0u%4w=T8vno zhN2NAS8qBEsZJ*ZCC~opMCWoWbw$++qtQ>_iYgu4g>FD38s%Sr7Khp;LRzkX;VuxGOiH)GeMc0gftA98uFxU+&xk_;8V*14ivE!KQ28s|Y5hs_ z$@0^j`Y=7H9xOaua)LgiK2vz2L~S1`&6HU)1w$6?kS3EyGSm>t_v`#O+}ItpwB)rI zFXEeF@2yH)8Flzk3-*__IE!lw{C0m)S;jF`iic2!P zbt0q)dbM6&=WWol*`u8e4tL68!SW5&@-Dz8FB93L9&>K*$^HJ`#=tXm1E==d;W2P( zzqhxkackYPzj)T}C>`0+xpMpVl`FTCv(LT0-(j~q22Stu_0A9U*6lm9-wuZ7e!jP^ zHxT&x@vPr=WCEc_YNUD_SkZtY6e9=ZdoHR&jpzv!Lrc*L)Q#4m%~%RQIAwgpNbN8_ zZ+yu}zEh1mt2R_oT$QgXQboF(w=`3;n*+^@n@RVAEeojG3jzxkFCeR$dYY)}ruwEu zO=MN1Cqh+6>LZIHB-w-C+l+s^9$${*RqJ}zQQfPztfo%5&%3D&ZhYSTp8F5(Pu%pk z-22>z+{EXOxI5is!@{D4E>BmVh(lt#xK<>h$gf)N!h$R0YIhNrkk=l?QS9}xr9@EM zXDrBWV_#@@h%$!CL!nT6hz^x3E?u%r zFt*{gW%Hiw@Ge>=BtRaag~fzv7`_Q&e`=fQYSuWMGnz*F#niBvN{Yk%DW539jsEmD zFpHuHJ(UOs({O?7h+>nS6X~nTsT-idqI{&n=nD&%C2HRT%w4@sR#VV zoF6nq1XRb>4)#K&FS~~!Rmy2Uf8V`Vh-fSsoW~a?t0`pSB5&}FwpNl zT*q-%pVyZCs4{UCW|PmWM)6S`nRr{egdKz8jZ)}_jlolbn|bX_L3js3@(k|3&GrZ?^Ev%t*)O-9RwU;p}u=IkvRKWA|ai_ zk^8&iFx@CA-tf-vdapmgdg<@dCy!)j_1N>V=VQ;up8wP74DFUWsaht6Y$y^oZ8Bnm zK@VoV9zzVn5a~x2(iGMp*2Ge^EM_m_s(rBDj86p3zG67?!e$mel{b0Ig4t>wo@V(7 zTi;-V1Ff~d2Ip6*wq~<$Q((!G`91#l+^vnl3VWkn+T;2DvLml%uF&)}kF@RfoLqY7pOlw- zY*W`A$ItQc`*Hog_Pu`GYsU}b>lg8jV-tgK2oRdgU7RXwLNRp;f(n{IyiqYmY1Xo$ zNgdL(hpIiQ{WEFWUkpR%glfw)rfK}sO`Wv;wM81+n1t16VviPx_d7SxQpz;VmhSJK zbMHB}zMtRsch33l&;Gf7=Wp+&UYvgOM}PW16xG7sXhk<}*bkegEINTsYl6$j(py)8 z9$wZ>>7Qet8=o1U8*l0VRmH8vDqpP~IefT7+=_W&-m}0h%+JousLi>iXKt=pt4~eQ zrnOr0RI4?u7VC7VLuM7Pf)$fZ#yG~)$n&n4J(<2rYG?^1$wXVRT4SBwY8#%#HhV?r z&AYIR_DVfjjfOsmQaEW_^CX-s+J3Kd#kI zDRo?*zDgEQ1)U;?+M}bDL$sx!L880z;J=BAS-k(>`gmww;yCYBasjrD5;W3jQ-@q= z$L#hPeKp(HH$Pi<%;1^1=8=V@X8 z#NR6T=?GNiy9G!k_|iGxA?@XyaG`TSRHuaCEBhTAlGN(*U8#`cA-L${oCHH8n1qfy z&t#?Z%uClG`X%Ni$F=j)hc}LEOog6+a6NS+T7a@Qu_?4)}dSbAr=Dd zVOiKK88)~75I+jAc~T8G1kp|3E)J2z<}_+^v!yn4@DpD3$Uv-~_>R%oSa!#|a@rPP z!?{o}t2OEwY+}S{+GX|oGmI9yjC%Y{!EQ>|C-;gYPwX78?dvPWW#QPBQ^jbcT+{^m z&bo(6h3BJlCY_53U&xGpDrY)vG>1ZOu&%ooqPwPMcx%5t6?=M8I>#2D*!b1%r;OG@ z|A^#r37p=d7d+wmguWOZ^W}|#eD|w`%jJkYHZT?m?`u^f*#Z~;`|gY<9Fn&@JFzjm zt2~gv+k^l!Sjm<*_I!CFjL!#h_Uw`E8`+&RyIu$?em(1j3UU@5AWf|YMbR6IE#Vw; zYMyZ(b-p4HwnLhVNAxMiob2=QR?%dYMXQk*@CunjsJE(^jaC^U!#g~N{5^QdZSZwS zvCXm}+#y>PHV3n#n9(ShtoVo46|2UILO8TchLJtjT`V*f2MRezg~knD^{@vy0f#xD1cyJ;oc#8|{k4I)N|fJupz^Kb z6Jy7e*K$*FVe3-|&z{x%;4g_hoHCBHJ4fZ|1D{EiFnhT2qksGDZ`Z9|3*4zGo4Ao&>VZ}a~_s6!#ydx;c*G)L$xBKLjS{fLL8&Len4(X&e509CDG zOt#yRRk3+w>s9hH(j!9hZBeV$cgT?9up`_=J*1gL7a8M5r>J9H6k05)A!|1Q~CQNRQ||_4djo3>;lN&ugcGnNyH&DnZ7J8S+M0N z>Hz9gYlIAuW^z1de}z>h~H0If=U=`EzjCYkjDHx7vVQeu#ko;|Sm#l>rGc#gosn53Hw+gsA+s#v@u=0y{l& zo_Zr5hqZ30Ef`U7g+yUHu&Owd{jx=|_+<-B?Z$35x=Kz1R2>Y9#$+8e4CD04qAm|i zbgOxsf8e2fK9Zpx%1{p_At}H^@py8D450}5tYRwKi}-l)<)Ws8w|%Lx=(zo;fd+u0 zB=OL_NUIUlrE*#IlGIo%(Dv;vEOb)Naqpf)2LMD`t^g&b)yh!ZELO1MK(+FMzbHYy zfvzg<$G8o*EOv|U_nvSv$T@5yirZ&m23#(e)!g*jwtw7m`hy|6#jrCLu($-fE#i2Z z^EiAy&ZIZnig#{5&UfIm4{#i>0bwsH;`}m_d;e}HGoXBLO%dVdA!AX%X$m-5fI|S7Q38~3fD#S_%pEeVFyaZznnk0)W!*w7_d#3U{>Xpr z!7w{ONk=F}ARVEkBauLVKf3~$12BXW%U*B6G-_ebu0E(gAcybvrP(967*+;9V5EA6y8gCdiCXU4kJY##__Ib@| zo8fo%Kil8u2nXI)OeTx$^4pv;3$3=xCo42c85&m=Hkp!#X*LYgY#1JnZ>QO?oo2%z z&4$#jjDr*8U72*8WhJ=v$2M1#TdAJ)q@rmgb~ z!|yq-ZHzhg@xk98V0^GS24hU^0|tkLmk|O9X&{iMDT_lsx^y9*pmn3^(l*_)w91xt zTh%UIl&$+yP3n&{gvQV$jn-CMr%viL^+&7zh_p<~CNWi7SMej@J&4>$&gyVI~U-H~bcDuk5SjE3@>`%kIutxC2ROggPMk*U|#Y7U&$Pw$;9WP`2law zK zyw1Px@vh$8{l~`r+XLagj?YT-lfNnyBX7)K966uvaod~OS;NVrFQ0kk(^pfkJx~#f z^WUw?+rVmYt|^X6Nr@~R;!h_T0{3Tar2^y+iWnQ$C;TC1{Mt~;{VmLQFd*!SZ3EC^k`-# zI=3M95}`BtujSOois-e%sT22Bh<|=nqXwP4pwmsz37nezi1jUYwPej3&t8zx1)C3QM>Ki*$z}_2O4WX8f({Z4;t%mPd7tj zT@PAz)9y=MU2>KVTn+};`jTLw%wu6tjsupsW!Q4mqO({O%1l<3Qo}UeOV-j-R;IAZ zDpg@7v#P*CciFeAhwVhAdkaq6i%R$Q1_rso!7kLAF}XBLn=YkNFwZJ0Wp-+(gzODw zX=tKKmc!FD35#6%6gn)7A1awldg7>OG7e8yI&U=E4gjFPjz(uBZP`P6Ud4JreKHE( z%Vo5Eq_E$i_a;)%dmVOM19jC^5-x%+1N;t~u=aon)u2Hzkc{yCV9}j(hJ4}b=4&;+ zRq$>Z#ji($|OfH2k>hz@ec7#fg)0 zExHT31Z+kRa(kvo1XA4xRmh5L{j&DAwLHAh>NI(+5$h?Fp%N3_1W-OKaI>4Z?riR( z2`KCvp}9}gMe&N{)vBFHUMG^**%|9X^16_`wMbrKa}$!cxk-&7c@F@2D(#*~Bpe28 z2Ht>*S7u3lLp2al4#>PL6F;&IO#%XWAFwvCYaF(U4M-9fky#%PN!#@wh(ENJGb=~T!E|%AO+N| z=;`p(bIaX6gK)t+qEQ6%Ud#b+nNiJm430`3K>^J2QJ?1wfC*`cX)gg`$@_ME-G#?u zN=4GTRSD1k{D)U>C)d5+c3|t9Q@gos&u$s>+3evzj~$+CC~8rO98@z%&;aXE$JGh_QRRkbDH_e6ldgzB`K+xZ(NDU}h7gK8%K#&mx z89|U`A%q}=5ClJhAVuv6Ley>(5CkiLV1sT~$|P1QsghLk4&4SRVx%TQ3o_T)g$T;* zDuliZWp=p&0SW880F1b0RRC7r5+qd+h%rlRCQBHA10PloACuJDTm#`yX2^F4cCE{S zs7pf~6J#cz^{W@SpcJgp!o%sfZ)))Mb7y%=S%sMD?@d(}m4mack9*laADX_xpDfzE z7S0`-*BNMD9C?o1)S8!#?3?&wDJNo6(&;ERr5hqVEi@oeBmy=d0UMA34g?yIPG`Ud zM6dxlL@m9+ue zUC~b9BvYWLYgr+He^YA!MUwumAYU!4!5v$3WBLUB2MLlexymehcd1$ZgB~0tEX&nz z)AfXrFgeZ)HNExZBsigH2NG75k$IF8HdOcp4HgW*b)ls<81>WRLFff1u1)it$50~^;= zkFMkY;xBi^hk9N1`6tG2k8@$8Ez(aacu`~$||h+Qe%dElW1U~@`AB9X=twMNNDVKd)$>t{) zGrl$?rCobjdSKm4XF6F^IPt80^27cM`+v9TH+N39J*jL?Hy;`rxG?T+_(3eK#MT{t z%{CtWR%ca192KHmm<|~3fI>0S#)b0=*+8KY??{0EK=?%9{YGoKx=a}7GGT)822qxk zNF+mW|@vQW}ZLO0Xd=rad0pG<}q$arJ?&+?eK$rJqUj>2y3xcQR9Z zkP8NlFDjgJoeCrd@)^PTmdIx_7!+CbL=;vAC0jAJrnuBK+D1I^#xb&vlTKOx7N5y@ zP^4B!E7YhUOFMR#40f2&!bFs}f@)H00>Z5z(P>LV^t9!~d#5dJ@3j^50<+J2C70%* z@X#bvG#e?`N^v3b(EY(v6;0HV1qBc075oqBWgpwbea7+o-J5;q^SgcLvlGX5Vnduj z9KR%?q>Bp-2CTd(g8(uw9Zgx)mT9FBUJ8`9^aa|YwcViW7VSk_5Ss=GNlc)06;j5k zNo}VMl}*|Z0@OvzCT)~yWtctBosAuELeT!PVmp%W`Fy|M=Vb+X=lL4{15=x9b0W=Q zXXW-qHT$d7bYyOdVXCLCQ^KC;^SK?afTKC+vAO1kxjMVDByyGP4(_kw=;&JKa{788}xB%+D}-LtzhpXBpI zD-*YP_K*2Y-MBJgo7XzL&KkPl+j@uBc9JZxcTy+Iv%hz%6VebLGsMT5=WPStrn^I7 z|jWLbu{rFzL*XyM-}h0b)=>HoxJOHmV|2XUSxsEAse;OQr+2 ztbppt;)p2jW?A6!U2QtFk_Z>)gYcILCj7rnQld^q%##rcy@u1E;EPS$H0%TxxY_-L zh`eCZKyidaPy$-hU88en2GwDwFMQp7A-3378OOO6hc}- zq!rXG>IYmBShN=GSwkscQ7>53i57LDMW>EqQJA3xn4W8;E{!*gjx}m?8MEdupCGJ} z&3?wsm^Ym6Bs&XERsY+&?}cQ%WybuLsK5J{^m#d)>X;g=mbec--tgO8UxEJL0@3=H zm#z8XGd0Us)~;VMZ{Dn{&FQC~*a!~IlLsXZqY}C@e7B~ALVZ+T3CkEI##aEWYCx+R z49+}%7x1^1=dW2-)GRBKm`Fs?EV)nwCyL-i%UX2}j;rQ!mMtM&YFnN2-IPn+OIDR~ zEwwP;Hil$5AM@Qn?|YbUDw$iy?qOSC#|cp%oTSuSpQb|=ThgdH-F3`N`4zT@=i3dP z209`SGQ%=cRTT&Z!D(~SLLeiV;b8D( z>^SUhFMjahXal_1@P@m+5jMtP6#-{*TwqGX4wDS;G)FLwL(ITZZWkMj!xe`x**&>k zxp#Yh{*&IVtAo$PNPPP5mK=JkHTPWZNwSbM8{b%*&YkZX+1dN|mk*HokH~|&s?AMg zvzrsI$8!Jp!@1uJ9Qo|(-pjx)mfN7QYot;{=w||EThfvRfIa{yF%`^yxyQq{tDP#H z5(ngAaoEJF*;}8b1&=qGOeW&-6moPgPOMF=OMElICK3T-%t#xf)=1-!zApE*MMwns zhJkMYkRsmz4lU&d3zM2L1ITnkfs_Z>a=sUvWWCbh)*33+r$bsO2N@TPwnB*7Uo z&uhy4<>H<{YZuE#HpbF$r>fLDY12w}grhwkRhAX~Zc(+n#hhi<_ZdXd@E+3z|5~_R z6h&554{{b{nOtBlIB940)V+Jl@$hF9` z^*X>DUAVL(f8320&741B5Li=F0*S%wS2R$u8?Vy8-uBq)72dkq=9iYw+Wytnrxq?= zoO^xO)g5@)JlovJ3A?(|^IEpH$L%@yrJa|w>qe^^a^DTPCndRmNl$&{M5(`L#M7n; zB3*T-y{J+zO)|Ta$n6A?g^G)5JzJ7h1_@8mf?#@q;m5DDKWfeg@{V@Z;hP3&Jezb*LURgaU?e*lZFS z!U1dT%HB}OkNM!BMH2!DXlxyhH>hs-QL0{Qm1vIy{!q{og3abbO9`p=39vX!5N8o?By`wf^b$L(}^dn)Mm%FaqUWf|}e zTZXM{Wnl{5K{74Xr~xS^(Ncpmn!>=b7`P~jBHvozTLVauFP>a0;ec}@Ur#CD6BHGy zW%c3Li1{-bZT0?E|9n3a^@n7+7Ge8BAsfQ>jXV6V;P4xrX!ez3UkE4CzwdyeAUo;r z+-FKPd2URfbX4`5j*W32f?6td2xg#hM4)M!Kt9hDlz?ySkYAI9vSFux&^5A+ z-cdgB+#IrRW zcfzx~=`*>Rv#RR^A!2NvLOPTg4eejq+Y~3^iqOOLok_Yn@Mg#S6lqz1__e=6rz$)n zJo6E)Q)%z{v!I-p+LsmvJw(?H_Q-)WAyzkWYcAU4o_CT3&O2rm+#;g5$-LW)Qzz4#=H&O7Rd_)U>Q1o)lefWpGZV*3@dnEf7v!@#q+eZ$ zcvEvzDyh{cyO}Kq)@)qR@o2}X=&GmEUw(D#PXjf{mN^TE<-y-9SQf8)?n|xFMUTI= zWa>i;8i{4@z-Fv0UkOz93r$h&J+~he^;1U&d-x-+L7s8q$tpl`x79rX>iW!jsTRv7 z`))gJ*Gd&&|G-jxjF4A)i1AX?tzQiYE@-c;C5!c&*8&M!vbmu1Q0>SJT%A+X+=Tl#U&|qFHjVsAXSbE4{57Lt=haa!5EAQGELj3 z=7EZ;FKHw9Ev;nrp`@jv#{JIB*kE(32@mTTVcFLA`~UvuJH*lNK5j~u(=er9>HM|j z<6MP)2R(&FO|d!Hc)*d4Gv^%G;SYpVT64HmI>naNd_L8jUA}ffbg50a4;?;_Q0gjp zpdl7y_Rzbg-EO;Lgd+;!2++qb*=f3%&zCcEbOjZcuT6LLs73f08ZU=bRK&$%J^DVK zMhcxrVY;GuIVo98Qtu|OCl``*GU;qKQN6Bi5@;2E4at=Tt&xOZ;GuJHN>yi^noWdd z6NgX0c$dgnrB8!o?4XyQ+-}EuiEd=XaCR*AuMj9M>I~q!08lFkC)8pw2XF3v5HqJ! zfSQb_yI3}nkU2IMPwEGb&p1yiK*JPKf7b2nkU3~jbw$<=u5$RmWMg#n?Wu3y`R_mP z{HMEca^Qu*zh1iVuUz~2wol&w!>^0sB1K7sv22BN90>VvS}tURpN#K&@9onsf9v<% zzdXD1(23U$K6UIQc1~;``C@y2CMCx_oA~;u7+{kxN`lvYvh{^$fT~FmsJ=(2>W%y{ z{R7lbwl2@|Ev*yQg@0E;cg(Z!$92>UvJo~{NT(w;lWeU3WTz2wMXmr^k)S=#^WIsy zq&W~YV24Q4*>pM=BSfk#P0GqE$6{=+A`D8Vu$;^YM|XEri4HcBMYj*m>s6 zq0OU16tlVKm1Am4w1v~aAho}@!cp=bfRKtNvcb(ecPAArHJ^Elk3LuF9f@a;_&s)S zr#^glkc)rG6LeaFFYD7^nKn!xW(R$v(_qW+WJlZZnad#EEzRK$sTj{YhflEa#d9QhDM2jH(|th2QLJj=p5;nyU@M|q0p zOM)mi`}zh|g1Kp6Zmx>k#Leb#o`{z7+5BhAkiZ#|KqHZ6 z0-wfBlEAxpbFRr7MDf-%WK)5!7fDNO!jFhvh~p~Ai@ol6JQf==LYQ^e8Aw7lnhi!)E1+O=5R7(uUVj)qiRx0%#lDVppx$0`QRB^RBI5Z>-4mL=& zkVv&r=>Mt~@~|42hquhSxFB-ZAc1*MS~gxn^e@by?42e->E2K!txL&A8!RZa(olLn zF6p}wcP6E9&QE~iTp+_0Hym5@udN%2696nS0SQ#>`_vCI{;T5 z!(!E20mV60zY4{o*2&v9rY7&)UaxPRi}*HG*)cr6ySvdmqHX)$t9yrj_7-OGPMrGN z`121?_9bcXrQI=R2%~04_}S4pTe`95sNpJ^J+Qcp%sV5S2Nns`gMOm!3yuolT+J9cxbkqKPgL$#E8T& z;m0zTVeM6A*_ONtV<$r|BAYJIO`=8)YPA<+DeAK&n&{(n8+P0~RWtmYt6tFu%bAnC zcbHw~G}-*^zqI#sYK`jNGiSasuvs3VF*8su@7jmQThXl}M~1h*-fnI+2Dufd+B^0| zBN$7#G4gXh=^e`SKb2`=)Z@uNyZ^GSC+ypE)J!v(7)^znnQ7O=-A{{9W>9~)M|vX@*xo_hixEH{AW z)s?f0&FeI~P#OJE^C`L!%Gm-n5j_=slc!SzVv0a?0z{4&ahIe=Cz-G^vh4AcTKV}r zmDd$X;Dj?&B8oT&(wS9ungH;M;f&uZTV;>oiy!-mFMhuxLwq6JdXd98a8`XO28#F5 zS+9=k;bb;q64M|=KH7**CX9_ZrBj$+X(gt_PC_Tu&~IlfR)ykZohWI|K-$X zw`?gle4V)h^FnNh_u3;#rGw_w>P~HU{%h?Wr>FXixo^WMEbR*Qzw*w0?{AWaMnCUn zO2{sTkp713q`v5Opz1WJ-CPMC%_CvD2x$NM5QL- z2UEleiei+$iWTZrCLm=wRFi5^Dk>>1S1W`=Aw}uBZeOrdb^t!v z709IuOV640RX~9Uc35n)@SSsh-}f~dIA@kpE9Ca+(NrdrN-?tRV;UP7rU}lu?X=Gd zNT$zMGfK^2-tv{1Ja|+S`~s{sA^eOI=3s1)8X$>J78O zQwylCgn@r4KpqSS#)R|X7<^Zb2;|y}eOrsyi+`)CeJ1~%u59X!H9NuO>OTQZC8z4)0S?QUDA@x=JN}U^t$T$ zmF>mip*L1O1!hi|<;Cq>lCywr?+ar*~p>)Jqp;1}(kJ9>)K)~P_Mn7-o zt}3W79NG7(F(F(lsR){ervzLK3W80bu%I*+UQjV-tC*}1O{o=D7MIz?9mcBRaDtUL zHHqm|74{Q3#Fe9h$>Q6^v&BCjeAky1+&*u^qUAr?btqBZmTzy&9X#0Iwdu)S`$!w< zG+$~MxpJHEBP8?FRqmkA^XA5_FK=GZJU=!+Div?cTQs=p!VfIhnN)e zYfE$lypk&QN&_iANCpW@M(GwyU;=?7DUx#I+A=Y>I!eE1xi5ljT6c`ZM(L(g282=f zSvy*}05SnF#UwQl$r6&PDgx{o%PpD=Q;{5{ts^475nV=U>2f8#AOOL`Mt)=hdR`%K z6d(=Zmq54zP(c;!GEg9tbIz2t(*EJ;hn*Q)M>)jP%e#see->62oJ=EaB`6u^Kl1>4m(1W z^dzs+Q@rvcul#98Fso--`*<=XUS%>(G31p3?y=!yb8{1l<)CzyFXP&)f+(i%#z}k%e{sZLTuCAR((p;8DK$3M;{^HHQyS`qA>rOjK@l>92Q!4^t&USo z6A_M*)a2s0^m#jE=Kzkb5*+_N3yygE_e|zqRL&hwZhAbALr(U!-tm3xE02y({uoT< z>*hy;XenFM%Z{xukqq-Wa8&Xts?w_rWcZnL@!5k=gZv=R@-|pGNjj1t87MD=4PnZ)E69?oKRMeq22cHcvQ%#VZM-yHw{RAx(5cKGZjdC4lH zF>*6TR>r#Yy*iyyIz&j^bEH!zZky~r}2AtTb$YL zh|86hN|qL6BIHJdM3CW;WRgRM*Z2)w?O6=REIWI@?I`FY@SXe>wwYXi z2;}*>5gx#RY5`vA5hZ1^0`K5uPqHt``qi*%mLqDS zF{J$^OOT;1s&2no?Vr|vh>(;7yL?I%)l?NIITWrn@i|ggZ&p=BvuEkEkT*PZ%Sly@ zo`XSTrrQZ*1r|5lV}O+?)9}DOWHf1{>w3vdbLJh_x+yj4Y}j#`pU9+7k?3E_uuO-KD2uIJGyq|L4aB`ilSBzj;wSthYe3n3^Iqi$6>?Np_dx6PT*XR4|`fUd841no2cn zbD2G|vas1#c3k<5FnKa(=`sjzgzm6>vZiSD0Xyv-@JWuoXATrPx!3u<1IEw;ai(L)p@Mj_? z+5X(7!5^*eT>sI5$Ocs?MrOe$H{A`(O`G&^Hzmm>d0KI}Ao5x7_yO|bomK35-lZjX ze5+$;`vNJZv~RQ0omuSXbGWU9@C-$DUuDEFSvgpGIX%MOcqcDSFht zlMoYUzB$9h-~vF-n4NdPI9J5G;_Mf3BISc26N}uC9LDDjD^#8~{VsUXB$5@#T){gm zNmH$A!+b#{x=IXnP-Rtg25{yBA}cn4)UwxmAGO6PwRtZWu+)ed0L4#7EvLtfMlq1$ zKR`Z5TWrmBT>e{ka=7(5(bh0G+jlhs&j55U^z6<}>ODv89^7{ZACscnjGv_aEWz0p zh(KiZoz$uNnw@VQ-rK)n%aPYB*4Ks-uS~8q5jbD4{Q2kJ`?~ncFMGQ-MWkFO(!BTu z_YZy<<7DcYHqv^AaoqiCNQ#&kYhVe3W>6I*vr+}oq1W9&@p+Ut3BMr%avEP;K{a@^ z=4kDS;E9?OwN3}iJ4fl#Aq#AGjQ$7`%u>rsEiG$OG(bd?+Bj88)AUf)Dpg1? zAcRzv%s(YaZLrh#W)BQFsbqURyDNKs@B7~8eZQx`{=kxE${=j}Q%nKztgs(k5ly!m z_(;|{slXVk9!f}(Vz$0$*h6}~NX48MON{}x+@z5{-AEg8j2atbr`ZBXN{^7+Dp)FR zj$9A=SOAl`d$ZXv+)a|)By5lCILc04&1NUBn8Q<=1ydgs2jmGh`(aU7wUT`eT8pCq zcQ7ZFF$u~Q*Aw$sCg93^YX=<^qR|Bv9TH3{RQlML32P-^bh<1-&QxD!Nr2xMg^7%35Gn|F4K%vm} zqI^Q;#FbA$7ZkFkxTu+TlQ&_RMPj4-P;ffEAG%o~8p=d8qG+C=?=)I2w#lueeR*h$xDjXoZjiNc8#viK2kf zqh#ao2?C0a*HN2SC!|i#05D%m^kymi(+sHtMrvt8Q1o<*;ZyXMmX5B5&U{X%dS}8W z=$(3JM@L~CL|aU&0hxKohoM{+6lz7ojgy67ywY=>o&5k$)D32E3O8NHR9i=B>v>yS ziytZhwZ9=Jg6>&tg^N80EOlA;F7Yi;8pRFZ2&S81=8&LOX!M$znt`fT%s0WjOtp&t zGlx@SX%oBw8@NGu&6f6aQ!jicoojOXHXRSddUIKI;X;mUs!kNz^K|{x{qNnkw)Kv- zba3Epdj6Y+FW6kiXKGg2lXCS}dH23&d56(l;}%$V+o5H3^L*)hlb(p;lkE9xe_7gj zuxDszX8E#A?-K5K=C-ywwV z9breT^(05$H$;m9jl(N`NncNCScO^ijb!ErGMV`x?;6A7aKyv&y%{x{O2wnm+SAY` zacC1S>oYVKM>iyz}=#1`l;^+34`AZkr^Ojcw@rOm~8z+I=5Rqa7l z`4U(w3likjQQ=e?Uao%N9og-h8>))0Te{Tgnf`VE zOG$L@rAkBP|Av)ECFnVrafv)W$TNoH?2!Ti3BGxYDB3L+KhB{Y3M>%@b4Vb-M(kK+ zyIlK@r#H1I zJheD`@0CvkC;W%mTiWzp+yx{rdCSODCBWDP6qiSj&GpOr4*z!TfOc4WM?0(iGj>Uv zWAW4N(te3^0B2SkcGU<*byW=}%tRT*wS7MrXnZvk3gYev2Ekn?PeEbOUE79&K>`h1 zH=2k>iRf?u^YlTdlZVTQXgFfJNM46$sSz)korPsEsSplLDJC$m$8cF^krBo99lEH1 zBPRW{-;5yXDqfOh3H%oJO|hQ<4oH1lx(RlG9ON!MF*VEO``kzWxUtZk-}_9%%MWR}#jW%53w_(>7L@0Hc=#B0N~vy8$MaA} z4(rNRvoj!Wl6>6|Bn9{_;txL-#j6^roUR(G2KB1q9d^iaeS?HJ(AL_SZII_Zm^H=c8}N@g8|_nRE<0g z4N9D`+Xa>)Q8tf+!PyyRfT|`UE~|u>ddFFo1X$y+)3A%WbBwBprKvKMrmlppVDI!) z;uX*c-@9(!XXGj{{iMfCQ~@`atg5~lN2#=5M)nAhsGA$T-dn0c6_wFt>DSwBp;bQaX00-K0ZZca7Lp>O_Q`(IvZlgEu$7LG)Hj; zW%eunU5N|FT?R15g{IwwIB^;s?iFs%Z8)4d?3v!-#8FT;juT>I`wW*S4C_vCWnG-h z9Rw$1xWLLFUM9SM@N!;sKAwcz$Yk}Bqax}!(}{zI_vI#w*)25LgGJ~GPkLMX;mb?` z02gp3%C#&QPFzKgfQ6)(*K9?n-_#7;Xa?TO^8Z+`w%Df5JN_Mij_ug7ea`XydThs+ z*oo~EpJO|5LVOY@4hfJ#fWoqbTYy3aBtY8*5SIce-DrWe6AZ`@>|qnq9@eA<6G*46 z?KC8|Y0_@3_JAhPc!|oxq_In!{l62Z)4FMz&=f^>a-2N;{=ci547N(!-)Azq_w5|$ z8%!<>GCA8eDc9fj&9en59ZH>4Otv10tjuNh4D??cw>GH zLopNdBbc*t`jBvznL&0Ev77z%i?U(KbYhz2$Ub8@`q3Ff>qo7!UO+Cj#CaCIClHB{ zs?Ey&la*U{mMBILsECZHx&j~WKNa-m>N0d^I2$r~4)+DmatH|i zKs(5aLQgSYr9>QRKpFI7iHRn961x+J63UFVX#J@L3uFyhKruqJrFI1@NT0_i+G=^6 zw!;FweZob#d}%6O!aKpB4TOn$fRoi|^ftST3?!G!Zbv48Cjsbmi+l;Er+vOS93n00 zk?9wv&rAy@rOBj^L&QndNP-rRP?J7MjC)Q-8I(6)FE3Nl1sI_sPVo03^3>K`KO|2a zfEs8iWBgB_&tzqXA_N7L*^o%Ao)jg(zlxAmr6#t|dusXE*0Do{O}(oI2E1LSK)9E$ zvA8ZCJ$SPGs>c=QoP$=KpE7UAs~GN7mZkpMvtgtzv9iT&rD#?kJT$N)5nMC4e)pxb zW>Yv{|&O$H}(RE_}a;>27DZ-3vI%__;l z*(our<4@y?c>Fp~@qEY}HAQC@ss6r_)r9;!iBbprr6VYkiFwOtfy{t=^3%!GBZ>`|u=wh+Gh*vv-hT;psH^ zu8mxR^Kjy?G>}@xzG#k)X4YCKNy+JEw`I9(mB;@qZiL! z`t(ZnMx!T~Bz>=f7o^;r+?y{gOeinocTpbwNV2+l2(hp&o9oVPXntm`y6E^*y@D+* zd@5C&>%_Dj*bjxT|2@BdnG5K)S#lVpV4cVrl7`KOQG?Q8h+s)eix{hB@HVszS4+Bx z1l}Hzw0bde7jJ<(RpazjHp|OKBAKxnBh>CM;o!6{5C{>*dnoS&AuZrUQjTm3lJ4Ln z2uNC=2TUR2V4soZ2*^Tf1`J_)k+cghB1JGvWtUj0Qr7yI&npnI8~H0uh#Qg3U2fFM z%hsSPRGXO%yPAz29nsZf~M0BaV*VdTAw zhY^kJcqqQ@@M>Xu;YKy2=qY^$aB}ld(;vh6JJ2Xxg zJT_4d0DK7(M@^Fo+Q5z*6RimO;&7E8nm> zQL=vjf6@$;N3u-o=PREl^R)T@CL}1}P{D24=Mz-<&%IZAudKY-`#j3}+b3`Io$mj7 z-wEIcQ|?nNp;dW_&}g90h8ij< zBpMr2d^|3eaDFP0NZrGE#N#typHHTpoT!r1BHJOVkTJjo6oCM8lT?N@fdCjr2K)xH zf-o(Xh9zMd6Nxy_CmTgE4u}ekC2W~WCZSJRBD@O)4a403ltniA3w z?dn90M$YvNvJgU8t&SPogcyojB7~iO1m|=vDVHoolKT$kU-$rxY*EqqIYNgawi&oV z2;^A$2q6IwfYbn4<6ecVape~U9+Yn`|B7^g&o6%MrFg_6&}$;0@;j&RJrUZz*SdSn zyLYxw>rVC^aGA`ZUmn<7-nwn1@7Sh&eN;%PWAqkV_s4c_&E&Deqp$xgcKrIPue?-r z)|gYamS}YC&c9zB>sVJDFAm7-a^cI02K*H1{=t6P#v0r*@We*(U~zQ&)}VB=r| z247+>*aVEPV*)lNwjs2pUc8WGOEy(Y6Vzo=8%0^yXqBdA(UeW9mNn9(?Z>ui2`t26 z9Ysyns9mZ=n>6jmr2U#SMM2G$EKAiG_MU444oM)PWa}hAT;GF_&pAH#d7tyXNQd6L zh}iji6Rd@Y7{4{4(ehey>TBUf&A^2gFRWUV!;y(39Ou8qUx&Om0(+{%sc~dhgv-Q& zR0#zsE<7c~VAD8FLkVgUv@Prz_E+q?tdwIZmZgxA6s8JNm?}tNiXkH5pg*UlI5_7? zVM>CCJCqeqszO;B9~wC;SgOt*v%Fwp<}9;!va@U<3x*%$p-PHWT--rPQ%Rx995|7h z`pT(cNR1Y2)w%f9)LZ-B>;DO>1Z4%yXL9(p$#hbH+vGI< zCK|#~v>ks7rEyfS_Vu~C?M)ottu%P0wqSYqueOhE5}QrqqFgy#A*g&%v7mrd8pz?- zg)*Hk98QvbEPn^KT7zXM10hrkt4oq4W|BRrR8KhAZBTmU6^zcVljw966;31r9sb(q zleTr_uvcgd1Q;k}q;1ksbPysO?VPbuHkZv+EaF*Zx_T#E+iO?P`hyOeBjZLpvaPDsFgDp0;8C-LHZ1}42&{+XZEIt zx#b zASIAn>`Mwwzm%uthG?MMuQD-X6X(91?j7SBw=x=qX=|t8Q0v{_*p~{mdiOMI%Qjgo z)s5Arqb*Hb=RkPwcGFN-ZP;sbYw0H1+qEgw5Vcn~d1V8=ebq_p;TvOnwcffK^F+Iy zs^|OCCp%k04t+!2mNT!mHy#`v-L@_GgXdmPy`*(myN>kGf?j+7VE^WZMx{=AZgV}Y zQ&)vN8RYI9dcTx&UG~0kNBa zs3&hRI$lN+A$Uy`X-p6r;}Jq*gwWUvG=_o3IMB#+cCr|=DizzJQoRJ2P2mbui!)Hf zTKxn#BgA$BfV042B4kC0NT8=DAeS?CNX3wcVH_}xP;0K@1;?mk#&O*tMUECn%5lwc z%OP`Et-PnD#pm^Ua@ara^YPI8Jmg_KZ=3=xrvNfBa{}f13c!#;IOQAD)d5?gs6 z&_ihA03#yk2VfFe0$>-T!1j1MX8?^gFx%luz$JaANM0J-Z}=c{978+wp}Lf0R9&?z#Spxto_R z{Y)BJ1`9^D=oG%JkchVW5_RSx+B1Jopz9k-ghi}00ap4V9JrJ44%ms@PBb=?f87)G z?zW7;b@Ca(?&33`h@zJV5{e2 zf=bQDVxY0cmPcspq)W20$fgP+o7g+hvwI5Hq9g!ByBqkVP;TOr$yhoKdEP4%v6wSV z*fKUY@v92Xx+u7Vgv)(Jy@kMSpfqaB@kM#9=rQ6a01?_A4>@t3#And+4&?bA9*)W9 zNp?U^sG{B0O>HoQf_$iuE0WTdAP$(y6(p;`m)9z}4^^6S#Sx*9Ts#(742hL zwxVoQuU-e!owjSr6q8dU{sTOxGX>fW;gD8fNoG%FTHvp3W z${d6O$@~}}u9DW3*l={ghT0Mv)}*O|5W&g<&G0obDi-_iixG(P0FH;AT#fO;5t6@? z^c^65m{74=S_e7mo|znt&(w|i_g8V_e3^7uZZEpALtr0D2A5}iq7?zlp;fFny<|lc z1eOb8%#nOB8nr(*AACX!nu9^ddTQ{YBl%Hj;3EkuWP_h01Ll+KYry=-3J6IGd1BFk zx0d@)s3{0=ZPr>SM#F3L(6(hBQa!1MR@Kfrnq|%6`0R3krzhq{#rS`FmFO23xLGZ5 z1;bN>We25SIV>NJ!_ORXPajZgh#4e-4L~yZ1;;87a%dgeI=E0sitgL-%zZ(IK1Fuv z40`gO^Yf@zc9=RX-zG6g?x3aiU!eUD^b{jK!_^JSe+jF(x461<@*K4P{cKhTb3|c| zw-pUA$G;Zm{G0p}X#ewbvLojdBN79SE$xWnF0|Q__87F|#rD^r{YPj=#kL^6|9fcn zi|rO@UsLL#-S;%#j*L8ioH~t$VPEbRW}5rB*uMS0-lvV88$CCAZuH#fxzTf@=SI)< z?ukC6OwX7*0$k}6-7v{Lo<`ya-7JhQQlP9%@SmPNmDMgC+)CU%i%+g^ltF!d_J7V%E z?~9T@nJseolJ)y<9DQ@k@rnxh z#lo1a;;`JZfwiTRe3S^Z4fOj1iKM@6Al@EG;6DTsiGV+m$e&u8_5X#0jh-7lH+nv% zCxyOB)k&tMW5|F;1^PlIRimXe+NAbfE!O7n{tI@FrC6m>9WKWQkN^WJz$bOcjxM5B23A8^v+O@tN7X z-TQsJ=k@)t@!j6pcjsem?!bHgfvIl|!4x@A3mLFWt|nE3Nl6^v5lWH*c1fTPq+k?< z1d3!!q>U;y4d5UflVVqGM55F(X%tmae}Gg-X^VwZC59GmuW#0N8nuzipT%d*tj9Aq z?|t5P-kZg>YYsm>3>N1{aTp_#1mC@8c8L4L zqdv32*Myrmh9xX(a=3|`EwU6j_WSmiJTE<8cC6@?1xJI9=g4#H0m}i0!99ZgYDqkj zijYVoR?8DxWr#6U7Mo4cNTeDD-QJP>xav+NC2zt@5?<9i=pFYORA`9)uO()S;`O3( z)$LWvv+-CeMq;Wt@-ykolu#8 zs*B6%OjfR{O4I5AA1IOOsnaZ3(c1Q={;eq8zBqx>=?uhK^th{*)Kn*-PL_r^76%JO zmgU@qJPLwv_?qgVoz2?PtI=Ov|jDJHlp?XdIUG( z2Y$IDzQfQ*{`mL4-roJUXZG&e^DMsh?yeUeml{@RgW6;G2!056zklJ~XNHo8X*FDz zzivEbXn+`0pik9$pSPe;ITrnc??eBGr5{EA;=dlc<1_6SUk<(Pf4lUZsBtUlWIHWe z9i35Q8`;Qiw6r-kmKz;D?4k56@feQ9Dr$MwHbR~}6Xp!ioh`PSf-w&Typ}U7y`Fy0 zB@ff$+3XqcOnVH-gFPN3Q|5B^aK%6csZd>oN`-25C>4=}uvr)sn1B!$I)q8#reG9= zMJR}*%@UE|E6+Bh6sfI}pOLdP0vX^hXY?3kGikZ%zXNb4UV(M|IFp7S`Ahk8`ll35 zARNJ(YAEz`A;>nb%4VCIo13!PRn1HoLa=njlfGRiZoJ&{{l1l7{pX2KjvsXFg$NWJ zYj16B|KTfb(Bfwx0yT}{p*;i3o9+zv_w4ICap?WzOEjar2xs7=aTG<-)X*&!8%Ofj zhj^D_(E9?#Hj=-s224q^0I#!sy{L6T=YkilN9@O)$A#Cduh}idVTYNcT}W4 zU1q7LGqNnB^gQN5o{|nq`Xv!k?|d}ivAPC`8xH{Ex`)QRp2kDkMeWr?DX|2XTVtQy z2-tD?k-8A+GmcWcZ6*7(Tz1=WgQZf5ynU&x+SB+61hB09t>~ z5J6$|+jGcB0Sh{4)e8?lv5(l_u`_lrXH(*KyxRI;G1197pOCO5g#oHxV9gdEC|c!h zR$dJf53b@F1m`>tp-#bzBu>{2!^`=)rgrV<+y#W0=8e{c;7X$r@-D zRzc$qDY%0?L3#)?MkWdLn5djxA*$OC4Tz7>C4{J+Vt5qj;G($FLFWc2D)O*eILTm! zjxwsd7#fpVfht3BmG~8O4aakGPNrvnR$vqr&BF8j;sjF~4qiN+N4TEtKZ)?2U$FhT z?0sZE2K#f_&mBPcZU<}D%D7VSp!FPL@>hoZWePKrzoObeaENrwZI0Vjvy(b^852B0 zl%aW(tWGeg3tdAP<9IrkOHZXyDxI0VfPk1vaZoEet=)hP&A145)D}a`uj$Ors;hbs zoLKxV1Ktb081zsi%k(}F{z3}O_`F>u6R1*o!I>=dc{ITUVdT%@*kwNYQ26(t7*FP zxVgg8r1n=niE+uoO@Wj(`sjDpZXkxyZuVP7d(gvs3|mYXM;A74^(^TEYM+3z_kj;0 z`mx$6sFsi-2x5;52V8O2q>JfwjkzwnZn_LEwQ;%PQtKO_0cp6XG+b&Rq_`{=uA#^N zhMn}-2cR3X8|-whozAtZi8^SCL(sT=(12|0PU?GMNOAV*zME-AU@R6_L40D~S3S-U z=`4LWkmrIv0d?RDF0<5U!<@$_U5ha;j<%YXiq^7kV%Es~G|gTxSOvS;&f!KQ#w#E2 z*ef7vIj?bAoA^JBTJHDv9JRZTLJrT}_fg9g-+RUiLz&b46e+VOMY2Q|;e)wYIDS zth{ptvg#ggDOmZQ>R4^WAK`ys(oUWtgqk@Ni7D36{50agfM8tVM#%Pm5nt`GOwV|ilvjA{kBTJs_}(wy zJ>T)~_nq&2KP751T@|req?|FLvL^B%XG2Ytvw8^zyH6JNdW!<@TIjp22cce#F&7z@ zQDPl%xJqGq%r1ZdC}T#sQ^LpGl)y42f<@Mk+yP@moWzzxQkH)8&_J=cW<%j3X_Pj= zBSevaTQu-67P{Mi)3E3QEcz)H&wCUTe{|W72ItD3H@Mf(Q@Wow<^}$9z~Z?HBVB;T zl!G$mfrhWZ)4lchKEAqvFKHlKU`JbzrZeyGGY>s;1M|>hyh{&Or?}5>CBGMyVSFBy zg1`_#ap({ZvO#@N2$r!13rp9y*qC7O+sq#r(#;Gp*WpA^)Agwd^ z{A5GYm-q0mOBB6U1U@(r4BHEu10XDDzC3c9x7q8JCCe1Qdz&ZO)$j9shi|KLx`gs_ zQ)R0^zzX!-y8<|d0Y@IY&m#nV*Q8E_a~4387z!IRKWyzC^I%tTFLpcu#0Vfp05L)l zBY+s8h!Khyp%W2`7@>#}IuX$jBiKVE(oJaV$qhljF-@)$mIPR=XI*R^%dm9}<{3K^ zfMp?~_@gozQ)uIHt|}no5me1-6&>u{n8GVySv@>V(L1T8^XK!2p-<^N2YLo_zg265nwAwB zp^B$Lk!ZlezRo+FB}1S@dvVa(ct^jVK;ac!+&G`itw z!Xsco@WI`9!jA29WnO)mY`3$l7a5HPL2V*K5leEoD?IG}kPxynck;1-6I1;vnZ9c27sO01*-RZczkgE|H ziVx33yf*UY)YSWH*Ph+{gF_o%*tFq|!7b{fSK7F$K{}OekghUO_WE!#IXriH&w;+( zCmy*Hxqoc*=e5a9Ge{&)Nl?n9(UrKkl56?tt;GJuW*zK}sCP00|))~3fVAPkIngoLpVW;GBxxJa1I&(%)s%vCPz!wF4 zUC0Y0AxsOT7pR!TA1Xpqx*peO-2UD&T$X9l`fH;gH|=UoBaAX2a!x3QCbpODhlKBn zT5hIpW>c1%pa8HVe4V0OAyNpe3Hj=BO!@r3UF0jSV0yF`JE9vWfWX zTw^FTXn9|2ga=Y7V9CnsA}vrj%6vGCqrgl=rl&&GUSufPqOoSTmFsw&Hu`D;_{Oha z+`siT=UY%DcD$`#o3w1(6KhgjV^#C;ODk6o0-LTPn+$3|ow#4A zS>$xM~QF8e)DBhfnt-X-ZoPOFP+oP)R!Wx@1z{L zE2`yAx(cOpT_@?3dZRd+S-P~l5vLm=yYL<*F12Uk{)5t(M5N_O2I>|i6n{+;B(u59 zk#W{>8CJ^-7GGrXbvDnE1Ut==UKX=jW(3mJxH?nj@6}^{CO~^NNQ}U))sJC6MF-2x zf!Qqlb0BWXro>nZ#MYw|BA&?2hGLQ>mwhNF;6?8LN(P&^C93@veY|%(cpd)t(rqPbtk$?-+O|v}(6&SqlBNe#U&eX|V(rpmtv!zzXrCbvH1mH|Oc3_|h!~scc>@v6VALX>V;~>`>%+kq zANKy}SL$cDoyLORZ!0^h`oD@u7$T|uyP<%sh48JeasLH9x9yAx=`d};#!E_M`gs=m zusk)9_R}`8`~ry}%l#6r|MBdMx!4CA% z+#o`zavagp18E4yB<#uakd$>OghSAFg8%K;*$K71;D7trQ}`bT|L&sy=#%~Dey^r; zpX3h{2Ro=XB5K(HmOTYa?hLiu{;isx`*YFa(|nGB&o7IXS2->cYvKhiwaohjywg{!+_E8B1V6w zsO4let#%dBKSnL;I#4g)0*jp;e3w42gy*e==XdBFe}p;yReYmao1+8f=qXxGXchvN z%A#ev##bA>wZ0hnEzR;N_>iJcQnLiWCsFhnp$yLH_@nC2bZxMsE-ONk!+*kGV6utq zCxmXP@j#tyypX?vbg)^x5>#07suDGsu8PigMj`RbCF>gB}TQZL}jd<%2-{g%#3oUgpau?fn`bri>x2H zvvEg26zd1`2Ng-z00x-?6P2BXLi{ihJj^)T^6$ju7Sij zwPlLqib$dG(#myOV=U4raa^oQRa>e4k*!EoDmATAwJ)g*DoUO90r$yLld6%dmO840 zAEG)hk*%nzADno5?wvccGc3g@dB{U8%XsWF-}&yj=ljl?j}7=XvOgC=y9QS+{1q)$ z>bCmRJwmrfLAPhPZf8_hQ*~wh8(mFL|E8<$2(LvCIQ3t?TzC02`$P}?Io#NR|A!lU z^v08J?9q4O#zJ56Jb39zH-@gkA8#osaIKMdkOy{<<`8_wdgeXL9(uuZ-$QT}^3v3@ zX)M1BH|E4oZZJS*5r~XJ{@F#Nzb;mH4L2*PM<0Ni5qiAfS@-;bq)-AfR4eD{TcBy* z+XU7470j@a=TV0rFDMyh1fnL)DDt6<%H{PwD++#j)~iQttR;FM{wc`3WM0KcjaF4d zvOD}AJ7JP&QWAJAtYGQ?_0_7FRC_Yg&go>mlyp3U31{U$C-E3cB<;;ltR=g+IO zfiGndUtMmhVZMQ&2HfC7lLkTlph%fFX3xrV@VwRSW?qy=e@FikNZ07s;d%cWWkp=% zV6i|rR~+OZgG%#BgA^E4GEi7Akh#KUp;Vv+)C0xLb8sMuc3^p03Bq#|3({a1hqn^T z@4)IRJqphQtb?LqZ8$qTHLMKpl9QuuqZN!^RA7Rm=qgR}qXydxIh0J)2AG4FQRX#T z!E1>ggXeCh!Dq$MT%PTMkE23E6?|Uy{0g4Ktd^qsRyU9GtyO(e!Q&O>d+^-Pk`xUc z8zN|EVs~WZeeuq(I$goWRDjCrC~63S1SA`RYu+I_b57?Ss_@*d;AN^K3OA052S6T@ z5-!+-K5uN-*XQiMR^d6z(lnsWX)D^Mc3&%LRY=pctoDX>oj+*xW+O$cMq1pilkT|s zdx|CKnXwCFSH>tBo992qMmWlu;)No~7V*vE{URwUH%bdEJh@W|XBQW_rgl2RX{8FD zJ6M#?#TVj4g+G?#m*Yw>j^h>7&+f$CRKYV$rNN0S6Yo#lolqve2<`2Zac-+J`fO$N z_3quv9Bj8$#vPY34#TN`abo4f%@Y)zc(&NjJ~!3vRCCT&&ClSujfLoC6)$sx)%_7C zQz+|p>bc`m&r@t4T|bD?!LNLNo{QV+>0G6rw3w-abBtj}k~o5)@Z8ExQ`_-hdF z1)BRfEcTa+W#g||_-F$?6!=~sYye?`qh+tL@%v5uiV140k`V9reSCt3=0gO9aHs|( zhP7IZYU|{=>?ta;3#Cp<-}|R@nP=g72&QNfi_sE?DVmH6wYO<-S`rhD6kCsxx!7i` z6r(ZM7~O%XIYnDp0|_?b#_h=EcVKpvj>B_-=@g~4bT&PeR?@rWHCuW26|*$8N>cp5 zjqyTGOJS5s27+uW!Sc-s95=%y`V>6pSc;AgmIetLEJRhd8+wc7str}JGbd||HNjGp zZD0*B(%QCRR=!o?6K-avPxQg;KnaWznO*WSZm*HsK@KVt)^wvh>U7!^?Gfr(ml^Tab^>1Ny*C{Tg|Ry zZ)PdV_Ec9}4m1t7|GGH)v~;YCa(7?OV3g@DZ{sFzzlqE5l(tGQIcsj?340q)%qIvm zO`=suEgC~!*ETM43bjs~_lh;?BR`efI4ld6kHl3Df>i~dOcPBsp0=)$IoOU$8r7`E zv$pa7#qzZBoVAUoaB3^D{0^+H(jSU#96ThUC9;XBgp$}LCr8~zD;T|~ESWpUfY>>} zLC`>6)tG~qQRX#T!E1^BSWL$RUCv{a&$YC&T~R7mX{dtJ%bt&|jl8|v&82*E!YkZd zUQt%WmqCo8n6Wz|<-Qj_;pSoXzfgE02?CHj#CUV>4nh+`Ic`R#HliFM-tP6lZ}Q9}*o_0-*Skr#7#O&-Y)^|;Ej%kcv+{y`vs-vBOsXuN z%Fbu+W@$Fr$KUOCEGSm}U0KKRdytjCs~VdI=`l(MG2&kSuJNS2<2WSqE@v)hNQU|R zxlB^Ln<<}l){%GA%Ioxok(H5~BNUAc$KwuffJ_gqOipj$nZv1 zB$%HBI&n|ua_43z?F31WtyLV!&a-BpXanokR+A}066ZnkX4h2R78N+P#Vw7lmKKLw zdRDkwO7>;9%=DC_z@I${;m?CI>TT)bEv?wz6E8xS9amBiH6x=stvS-{Yp}6ERSBWg zL8;JBU9xxbX>UZjI8V>8M$I$WORB%RwQ6ny(v27+p^1EfKExW2o4%J zYcS)Cao2cYc#Ial8sUzu-2$0B?}}P|N4}pHt`Wlv`m#=r>2vyBonF`1b)xB0`n*o{ z<^hhBD);QH{G!;(WgPzqxOA}){;R&JlTrN`KvJDWT622KjnaSCIF4>JlDEB;(Krr> z@0kEr)A&jnr<K z;fvB)qnyKQ<$#*KYSq{q;mFwQsz#=$5Y$FNx8u&c)K%d=j6fDG{OPaHv; z`1|-U1oggmWhv% zvPW#LF8*e`z~|d!Big)$wnjU>OiW^q-Y41Lve>t3V&uhL?9F|Rqfg8DR*U_ot@d8eR{n+ z`!DOQR@-78A8m1(k~Wr$UNUPkQdGz1S4`@@UWAd+uG|^L^(#_ufIfh>^Dm z>XYBvLNXbR-is*)F(vIp(n?N6qSg)w%@(Bl<0{;{?c5)iygV*5){M*i@8W{IKwN8V z3EqLSk@l5A88*aY*dYkYKn4!VcwkTuh{?BttJwd<73|~?(m!2lQ+0D~BTMff)Zf@&ece)c(wus0tB1271?IB59@aAytZ#1dda5il4D zb^{V(3CWW#l)?usC|BkRH^DPkP%9Mx#AfI!&>LhJ7+K;%K1Cskz70i zArm)#!3$S8#Np`L)S$(A7=mD z0B!{V!#4_*dlVFafqG&7gF@j-L4hw|;!5Fwis=9v`q@lJIowZSM%d|T=GEW7^v+Vh$lOHD< ziWQ&A^f6|Z@Dging`zx!kM!swud^kVWG|A>pO+c_BKg$MNm2A5Xk3se4@Xq1chpK( zW1)eRyY*kgw=xHPTqkhod%m>E)iRZ+xDSMGO3q}TB%elmU3k|7xhOXdbCZ8wzVaqGEY%@ZCtC> z#y5?7YwOmp*DFI>r7~0*>Kmz%I#KKM>LnS;>(@!61~~2BQn9=$nemy%s^0Nh-=>7G zEm}7G5g$)UKA+r6MkDf;nn95=hls9f<0=lnQS}2JwW9hf3t%f1Xe;jnNbG?YG;jxX z)fXB!=I>yFE60_>VdWCS6OKok?TB&%I*ZLY%*x^{oP9MznH}zfDN3^*_n}gOzW%=c zrI9q-8!GpNL+%69@EAPhp8jBmx%d-26fU!wyI(#>d-=A`XmQl}aI_dLv~vP`&N=h$ z=FW-7pR5!;xpID&6iW#=>yr}|W#Drt_4$6KGBLS*UPu*A^~TD2dv@cVt%c3wPdg1{ zqeEO+wI<@$!V&TrD?TycRea7dbaH0+K*Ij*zi@)x8Jqdt z=tgi-+l$}*Le5&1+&BD#m#~sQac(oO)2oRgB-=Y>MKRTYrmBIp0hA3`0WzQs3*lhU zOeM8cDw#}0vqH3{B2{20${ZZf1_uWQ_(7|$&&+pf`Fv--v%}Yu>>+yw;d~qH;7z!M z38WAh&h}Yc59reN!jx_!mCVM1VKEAxw_?V?V29S9#iNR>hz!MvqF{IwN*Ee+HLVK5 zgC+2={6puS1nMg^uuKB=<(YT&QLir!FVg`ex0QeBo0;Ce<%#cEN_;q&ZYDikW?uhj z<1syCta1JVaxlK*yf?G|@V4&kn*9^0Z;X_ShSV{F!lR~W7OjzQwomMp-WV&;&Jg+)tr?Tf6=dAdGbg{YdX^dKd1g=W(}=jb-XOhh0lMU4?){ZJ6?Ivy!Da?S??1HKR@M~e^WT*V zefjS0v$U5@^u#(Roogt!uh%>B*kg4lh5YvyOW{lQhIN}-r65(d$MR_52s68ILfjJi z+4YePpmcgiQ|a-^9pA%BC!Td~!)<3Zks)5T`>=e|31B4Ap5W72z!i*KTBgW| zGGCv+XDRvbUvx<1f9tmM_XrL4=^hFJA(~+k8;{*k7I7Ch( zh+NJf{ERx~IpHCFo}`C_yoP5$mWUpVs*}=tyq!<_LpV0;=kj4W2?Y z%X{Dvyl^oV;3#yzF3iwhp zYD-&cIrw0C(N~=_XM_2@nSQLSzU#anFWQ9^LnL(FY_h0@;y{>37EG~f0*@w<1s=26IH4!_xVzb5nzAUx zYXODAL}91Ovou95lH~!igk@xfn^c8cR5cH~xvmy7ps$-i)`~)0WC%|DmZAW{BievFSR!=@YCW*^*wRKHu2$iGSHPkINMaB5gs<+xxEnS7j^H1PPn{gVK0uiPrVBK1jBl4Qdtn3b55JOkyM zvEZ3peyF=F%jNnC{rRFjJQBrcR(kRJ-og=HPN4-xZ{STq*i`7kx*Zdy-nf0p`MsE# zEZnZb=yfx#JG6#+XwpivjYs#fZV!OWOYmDNYr`<)i>7_=EAB7$e)w~?j$MKh*anGp zp6`ybJ5ir+!_zlk=l2IZBP&r4gUoj`jt_izBf}wp#{qn@>_}o*5^Hdi5e)*4h@Xif zH6$Vnl!wN?zCN#$WFb>{vljb>7hHIARq;x4hzSr0q(aeHLt{u>$>y_5Yzfr8QDue8 zPf0yD_Z4;sD`*FsKX39~Ghi>r6l80}`%x2>%y!2*7?D*)R?|gHiY%u+Ot?-ENQ;W7 zA{ZG&jq)j61T+ZdtFQow_p?=qqZ6t?Kx*k57uXv3v6wDc!nNV51j(cB9gc-xBBB+v zjG#kAL?LRrVi|^`D`8#n)##urAO-~@ItunTunbL;gE}z;dALSA>ShZ4C$hmN6zat0 z;Zt87d{35nFpH5Jx71<69S0wK7C}D;68qyV0SjCDxq|(|w?3EfmVzd^&#iX+;5Yq- zIjErDFw(jf)-|85nTQ$Eissi$ge%J;9{tDmgXil)-&te|*7*AT+Y_|Ud?uY&PVo&Dq z@nYel=osM0i+@?E{rVc#%X-)@_!qkk7DE~wSimMh$IrZxeuGIuL3o{wfxi?cF_CjI z(7~OagLk>DF&_-0BkQKmqr*9*2RUF>Bwg0ih7>lWpaFw~G!0*hY-EdD{QxJVeVNc8 zA9NbBfcWRUIH6Z%VOqz+!$cc6b)U zcZlX_H5%2tzL^Y%jd(OvsY-&1&Q+nr5Ww?6fX|6QHf!f=YjINW_L;}tmFJ5e&ILXS zFwQF2!$t-0_=k%zHp@psN}}xClKDnAi@<2noIbjxdwmYmQjExsTq9Fiwv#07KngX{o+G75M@g z(P5Y7)U7t2JUhmLQaxCoC|iB|UD&068PVSVv+(Exv%kmKoKcOAt$@uwkrQy7bHS)6 zm17M;q`~!b@j3d4r8@=}-XGS~N-Gf1O#yVCVtB^O=4*#WMBYPHH@G1dXKmIANagGt zHD^rOaAYkXRNXHN0^GMN{J?}Ua|_R6d)Ysi)ea1hZK&fSsYi&CHbRI%77bjIHcIc3 z65^1hZd1Grd}RBk;?_LdG6QzdwKi)eC@=V9Djf<$ra^QqXKn}sUq}Bo(-H>6jD)Ka~q_M z?Buq$F8zpI(dh@ldpmbuo5?Ot{KZfI4y_0Gu#<(^B|Tlw9TLv4?D3@=K7bdhJ6`_! z`fJn9JiPL6Z?nmN=sAFFW(`~xCyG-@gp9;o5QzFx#IaI#ETt}sJromS{3rx%YXDDy zRb~xXRJBwq$y4_JppwMPtD^otOmdLPpB*FuVMVTRs?wn$2EkMje+&sUHi#3Sc=}`Z z*`|jip^r|QvUc-$c6l9iLiD>U*+sULPHbAfqN!d;UfH?l=u41zq;<~r3`{<-l^uJq zg(nqiKV&lwqFWKJ<3*nw)2ieJ3 z=YzjKx~4rslQ;hnTk!a=_I`7|aFHE&>mn@N_c7#7ojr5v{BM@8+O%xfzh7Fq@yR6w znasmV?7&JCnM`r55CHm)D*OG^ z8HMiWyPn#@{vOEqveHZ`E$yM>Nt|Z)lM4S)I*OQdED6v$qEHOi<^MF{f(c#b56xrd+oot9qWA1~ z{iVlf2bydI)$o_=2vCJ{O_bzMC*papHmq9qfEUj)@g7a*alb(Ee^`hC^k@Y|iR0`wiRicw=hlyHbsgx-hg({pSrPP& zUq$%z3-BSHu}>$4Py_a(BD!cq7+?5-VCo~R#`d;Gs06zulW;%1x91=cyt_Uu#Yq_d zXWwCB4ZP!~Lb1B<2X_XAJqA2u!P?NqkU*_aStt{tJ~5(D{~_AoCX#N_RkXTHvN_q6 zq$86+tt99|GD#2pm-4EOZR;w-=i`3ZzSs97_O-8_IM+$+xV7uv#JO3Twls%yl&ad) ztQ%wNV zO^VtdV;d52c+a(ytoy-)f82ZSJ;zt)dEV!J&im35(@`t7EL%p+Ml*qgsL%tfA;dyV zR=iM%_Sw7bL7UnY`rTK-!b~~?Sdfo}OAeg2fReUx|Ki}jGPFMl*GIQla^V@;g97#^ z;q2(_K>jOS=5GNsH)IJM&KGG{sR5co&?t`>cpEvgw2M3<1`_EfJ~J@7bN2&>X8zK+ z-fr&5rs6JV=8M_h{I>ot4?J~YqWZ$zyKeTLOx$U#^K@1?j|_0=-!Z18^{6MP_?G&< zN`9tJtFtP-7_0=}3R24+wvXBLy8Ta^{M5$J*)Q2-hk|9aErgwr8zL^0TAabC9(Uq> zaVp2-$TZBfNiAyf35%gd9A)cV?{E}5QS3&~MM<a&8zsboFRK4XZ2Veeo^(P-5e|Uegq3{4dxpLJHgm>sPYDb;ueU?WSj!3d? zM7*<^iy3mZJvT-_YHO7H|aT$LeM#0tS6L*bnb4^CC5s_#|b z-q`h>t&iRRpIcY)RxBRs8a=sd;J_1oo2ME#OCuAnq0m*eh zavhMo3P|pNRgfkh1GLmTy8;bL3=`S_2;_XZ+}nHIzrs4mmqGy`0?2p|X*&3Who(nQ z4;*`a*M*U}fgf|_$Er{Icqw@HucstKPkJFAC?Hl0zz0uvCgC3BfK3>P{H^3qNkIkn zKLs)jLmxno!I`yvA{g{ReM*$nz*>|@g(fDUmJC#=Jpm0T+$N#*Q6W+;NSCX6@vcag zjHM3%YfZ(t;7|BCdvF~q-aB+<1fK-3GXVPQ3qy0&NkBXT$T?~gP{;i!E9iAU&K#o1 zAx2<;IXdEB0>DF%gH#j|`|6)yht;Awyp$%dSkX@Sb%nTZK70+^YGuLlB%gPkA* zam?^=a?jnz_kA5Y>5xA0gJ<2~EnHgG%bai-c{{rCNUcG?d^`kAL zgMgcEpGE>sQsMs%naF{Fd)Fct4EWprM3|P|=3A|$SR^jz@Z%7Z=Vpek_~H0)|H2TQ zNq?;FA!R=jI$pSpg7u6G^NjOzY&HJ^EBP0;>vF8e>=Rk}E3Qm6s3?5ToBKcK9ahE_ za#OjZ5TqDNS^5W)YNa6}-tg=K;00yhDe2k$ZsB8f=mEMtb@TT`%QEQo8g zvsi=W88l6aP8~`Tlm^1VfD+;>;6$kZMb!h`MbaA6*v3vzV@@kv6wT8$M<NikBgU6eX89)5?Xfr(lphw zI9*$0)3cIHWpG!OBug?m>Ln?bQ!K?)%}b?lJIWeamZhOAwqS{%CqU{6ppO6F3aB2^ zz??PA97B(LvP0V1cw$0z*Oq5_zQ~a^FJB}OG8VHv%-}x`#)EhqpTobwkTw4K3#Eup zB}?}FCZ?-|jisAR^4u@3_x?>d8HO(>-6p%B+`vK@I{w02d zN9AVJjvFqcG*8W3(Mz>7W+SMjLR(qUf|AqQ>{%>RfD3q*Zef>NmfG0J5-G275FJKD zN4S9^wS~tv3m>prOeY&L6760#Vy2k4#Y?eFyQim|6me-P<$y1Lo^2u|A!$JtH4$3pF4$ z2ki1TwqCS>MA~cI1KXqf?(3F=Mz3Nfm37V0j!3NG-tH~M&bX8LYJRfF3l$0p_(2t{`J?+snOIpw5E}cHY+-2xDWWYcOJ)1Rnt)J?uq3;< zuw9p2-*fI{+NO(i*%TDY%#fb*UFM;0Y-vzOTH7;wZ}kaiscDJmOcqK`8=q{_EXqRsC8OkBnZg0)lvw zi4|C|oQU)1SOec5I{tj`!Qt*wC^!@xem*}ja4g$1G_0Jg^ampWH5mL%I;8s|{9Z3n z2hW3wv-pd!J$usVa>`Si0MeY@jW!UK3VL$p;KG z$|bD9=~;>q%~GODG{gTk2(nf)T}ji!W&I7$cRa-Obj7*0<3ihU-W8;HJju0vUS=|% z@!_N`i-rdwP0G_UL9#Bd%eUlBnU?t=BUMS3^)6lx1HA0PGZp%$CLN(IdX9qr>5TYw zlWtH&r+nc(bt%d9pXB=2_vpVZVy@|zc3bFUH8A(E2zU*+o$`rlc%m41bL^_u8{%2W zYakwj*A35_(#4-OcwW`i#GPnQDU;Fz2U#TH4OYY9u-`Ww3n&ZSn%Z?JZ>V8Y3*_`K zq@sEvk@70OKwV_e3E+7&1R4Cw|7`{@Q#UDV(y{Y8)44T-!M|A+Qi^n4&+1G1vQD3$ z)ThO-b^VsEm^#+4NT=Gb&d1Vd>CYgO^b=+B+y5nz*!irNDJZoS>JOaapoiz+$YjC=S&nd_i zJUzc9eMrxM?c1&``O(fS>SIa53K$jebfJI{Bj(_V!NtMWpgh=iJSRNwhxK1vYt(S9 zae};uKG^v!dilI89pwoE@$v8T;e^dEGk)}FGRYouAWI`nJkh+_+-N#Y*=$ZUr<;q- z<>pFLY3^}8JT*68b3*{uYyVSmyy|?P_6s&^E}PP2V6*f)d<6Wh^5@x+>=Cl&JYc>f zM_zb=VRI5swi$I*=-c_ZJR|J@LcN`j_dnc3J+DK<`8U(5)k=lo)**ZdUaa;ZG;DEG zu7Yt~pjG7psndR8H%cx66IrN#{vx>$P1=2;;$f{t(ESj@BIr+I>0ANT4hhQv*Al7^ zp};Ei2frWjgMyW(J=cyT*NLQpm*`RG94f(+`NjNFemM^VYMTY}B?yCHt-sYz`Z;}~ zkoF6s9dD}>Z^gMo{{S_SAUGZhc|6=K4FAknp0>TF($@y*dk8YMpD0gguPn6pDHZ_YimW(UTq$lBDaR`I3h`OI zu)?vl%`6x)Ws6ypR?DImm&7jev%`HtsbyyilzI>?3xYkHZ~4s=&wB1$I$v#J-@d11r-- zX%UD49lg6+d`=Kk=KrtygSJ*?lR80q zBEyl=Vq@b-X*12zi|JN+Bdw%6c+UV0`pEIe`bZUDZ`XWP-0xw3da85KL5`EDM>jLT(u7BGI*#*lZu zhpK!w-(bCl5eP7BFt2KBhG{Gq5;IO1GsdFPGR_&dj4r;lffU5N-cKx-ALVw3p9+@g z12n>w;3*biXC%15pyCQ#2?4Hzf?1d;Y!u`ISAq3#`UsW;(%HR8>iBpr2S{TaX{>`Z zW{%B_ZH&odk0ZJFQ-0mKUj@BMuY)>a4%6;#xE;absT$`X88bup$4sV`IhVPWQ8MoJ zo(-DImpsZOtg)Ae z_3gSRRImC8%L$ZC765B}vxc>rStB*^2zc?BU1MnzKEg@6CPL!d=N#`b^A=x2tvSw? z^Ch_~lMY+MScbY%FJoUi-XqEiJ?*I{xT*kGp9V$bph$E1M31Yjm~9qD3O5UqR=}>f zq=IPMd$silYnA^nU-hwVoMrrd-#cHNw9Z}HG*pgP&m+H+f_SxMf5K`80 zosGyjo@gOWPw4n@A&ycr1n&9A^YM6lJ9USIT^KMV=401md~CJRuJMA6@`JljetX`s zG!0OSO_XA-IA6S8lvzYOS88t&QwajG3 zleq(JT^6B!;aRBMm$6@X7F~wCJV|$noXY7O$8(}3S%hGV7EO!gR@N{qyGKBBNtR}1 zt(wJ8TUfQmt?L#HfOl!xvLM+cpXOWeamXk6CVby)ulr86pY~1ryga8?^(sMCsk&HQ zuJTo4j|w97FZM6@b8J!oO|c)tZb`CSY;w$%$JXUp9tYe!+a0_wwr(bFL=FwX{J+!! ztdM`w-Ks{=bI778f)5AA0t5y8gKYi>C^f}^9vBLY1bFsgG4PK7KLrN~uqz*1!!)-7 z^J#eD68|T#=f^I$z6RX7hqjAROmL^{_aL`$7_E-owIlq`?>ENRz7HAoveW0p-RxDj z&uvUCvO=xwkMbuP{YBg<9Th;`v3BL8%-FIN;Q4O$*w3T2j zgzF*ODKxyzXS9a8<2HJa)I%60pgpyoTxS2O(qj zxKTUX+HTA>mT15YnHa_>tc7dgv2Z;+?eaw%Z_Cg;+nZ8 zMIA0%1+;g<9tVp-Z8j3r7B{_$L_Q=3ZZ04S7N+d&QQB!psf83lsT3h#W0L*a+174I z$?HinmYhf~B(K6pPqI0#S*mX>^2#K??KZL}Lmq5Ms5oPDlv%OEu(^ud6)_IWSe9ju zqc{wl+!%q)fN0@tn1olisAH>s*b>Z9?)^2G1^oWa@1ovWd{}|T@gd!%C=5oIF_q`# zcjW6pqCB!2o?&y75Z2fQ6UDa6o+y{`*U(pIh-#0|?FKuk)EO|ST33lrRV9h8H@>je z_>&?g8Vz+D8goKb8`6jdy@P1~#VdWo%qzo=b5ch?%Ip7sw}UEs#q+(U_xtcy_<59d zs*I{o{Za_aZk0jL*X*u8rc5b|ikEeM2*S~nx%o)K51UANT<}~*183a@q?yS^}#HEs;&oL@hCv5EAynWIBLbgGd`+Z^?Uh0^*DlRX)fMu&DCWjKy3)q;Zq# zpWfR7)>eTa7ugjD{ZGx&2;bojcgF=hxqX=ML}3X#e27$wJm0^iJ?zkiFnkvgZYxk&?Jo zz)eQFAt}g#gF@Ptdef02?=iizWF!yW{jaa*`>^Avk0;A2!#g3=o7#1L+H(#WGaQ*~ zT%-3@EVY+%1eK+-UgpFy7RzcmTdtKy%j4zca!a{c&*rA1H7?>FA#I~McIf2ufR>|C zfGFgY`iQ{a$Ee57 zRB5>cpG#1Y9MLOStYj;+Qmc$srYb_ENtcgq2_7<54)OcgX2|`@-9`q5K{Ntg+G1UL zw{^c^QE$7US<@B~E!EPk(-uE(Va5b|ENlCAXx=8ZOp|tW7$yy=@QB2WQ;uh9CdWJi z<1ghft)s_QS?l1+GrZQ)0-AsAYCa>R(LmgVz>eETj?l4DcZA2irW zcfj^n&rRisn5*T+bMrYqXHVSJnw^OGid(X6yW(ni0c;y)d%#F)G*wS=bB(vDFBJ#; zr*Bxy)CrhzdMlpIaglT*q0q(@AuNt&!BCtVJC%r^*S%eQ%h-lUgnMG2hd{J|hqBSvtJE1rd!%iPo{>Ytx$L1~=kMq-c(8v*x?2Q3(jAYPMxoy??CSJ)?I}d}#Nc~>VNc%Q z)e(=yBHi$hEQAqCGxhtG5Wf_}N1 zwh<|!W1axK^B?A`H@1zljKA-_zH^*7IlGP%JC1X{ zq`5o)sn35dwv#sVJ9jus)+O%fO1G}-S}07kt5Z~sp^e2KMpyAA`7mvj*yJLLkcLFk ze`^OHS|ON_D0BHzZGf6+5+Gn(3Lhq>(Uj-Cvz??JLZDHhICsADz0Y&c?|Giz`+Fj= zri&D4FFHRe{Mi-Hy1T`f9{0sB&>=ySHbSU_xAKP_Ym`Kge}(F znA&(({jEOX_o4ewlLYh8>NF~exdiw)LzP5=X|(=W3?wi~Qh&dZWO7$eVlhdRCzG}0 za*}T}Ad?JxOig*$JXvT7S1hzphQ)2FeINfWyQe991=l9-F2iKCD{oqPslY~UGBXIDg;2^pTUBaSNmTJ+!a-gsluO1)F3S~pPM()9$$}_{pC() zK8CEdUw}=t-i80sb4=;2>(+!;e`-+PwEn5J-I>VMpX%#T*7#(ZvAdf-Q{)99gED4j zeoY6mSt~QSM2_Z&muuo}I&y}$>8!OJqCvPN9rE@gTF_-^Io=kh8&xAtJG%@qJ`?A}xD=;xLgP42IE8NA z3Vk=A!lARrSWs{tnvX-uw6dfSWi^TQ-m{Xqy3?<#oD}MT%E_5AzC$;L2hFn4Xiw0n zYRei|)@HOz8WFXSR?=$PqQ+~MgC=U~%15?8@LvauF^jXfitSZ&ADf?ErOA}h-%q(T zO{R@BjckI0zYh+Mc0*6+(=+M$v`tKx;Y&4LOE0H|^x96oJJyA0)4I-8_!8P?qVdXw zkqlTTT$c4u*y}g4m4TsbB>?}9p)3V9&S$5xGuca7TRB^WQ!Trk<+BYJw;}Yu^@1=6 zl|i9{{}LKRCum2f&*?JSNPt8MX%#`1P$yEw01hBvO(I<+o6mafEv*;H5bfm^DobL} z=TZzUi2Xqv?A83(4<9M;6S5!mB8lv$PM=$IKjS8DPm5jrv87Z{{^pg`?}qo>ybk(g z&z=qNA4TpB!*!vO8oquLM9GysuB#s~WfH}*sY4nvL{+@O zwFBXuk8a%k;Y0oI)~^`5?>mAlMC>hqNE$8BJ~_k?aR!`GCu!|T5FU~-q-$6U#W0C6 zK>A&74+A9BVNjI7?Ls^eOGg+izK8~V9QG-i!YMJ0ff7bB0Hq_>x2x~TzGwPueId8Y z#{`@MrODwlh<99M_@u9X;JW#C>UsksfXGB>7;ssO5(DWnXuRR!Us*^o#in-J1^G6} zQbPv(@F}pR)Ap9*_da&u^jDu=xw-PoCV+UZ_Gs(3KFl@|{O!3nzhlhd!FzYT@?z2yHSkG@S^En2(RaJu}x2I|J5;JtWj=`4UmSe1z= zAim@|<>8Kb@KFy2JU3I1gX<=Kci7FjUH|WzYdJq@qXi=pNz} zJkHKe#sRHfpFulIom{8WsweG^da`N=Kw#S6gz0e$r{O5}>DSl~4+36mYpM>~YF!Pu z)2VD`$oRAlgkrMoJpP3_|NLPnrsrS(ZuUU*i+^hrP|JaP`kx=2f)YC9IdSmwk6;(? zkbC+fPkv(+R{wD$?muL(U7GQdmwz2*yiJV#xWC(ewsJq(PV*wg90s!PFlN%Tz|h2z zPN!1zR2**a&CF(M8KP&(nM!6JzVfvU&Sy%Q=}Z-_7BjFh$Jvx)O_OY>towqFe+zuY z>%NYHuLtOexC4xinZCwm$Est*IX33^(^DInuZh_St~61ZSeRIvu;nL86Vq@}ov6X3 zeZt)B)_JLS1B*zvyx`|n?m=5=N=$>fL<~>Guo{a6gD|`94bO&aVWNjC;rZ}#*j5YU ze7F>@!p+4nA8rJJP2JG24t2<4NYt(W6k-^oS#b=kkC-ux%#Kt?h;w8l5MVw=XGgix zXk~O^bZOLW1lW$49xkrRs&oTiGk;$ji35jODlY%vhQ z1l}OZ#E3Ztn3ClG<}IvT+U<>8!W^OrF*I=+tITej*lA3w_^P_3!e0Fss;DaX#3~I8 z7@|6*POFRRvdT-UuFj~lFgVrVhFwKXH_@THHI_LOGG++Af&KPH*^^~b+j2}y{dCMGaS7OR#AB6 zDBzN6R&)YC4!Yk*-Grm#)8iEY#FiTWoZ3%KMgHHcFejr`?t#f@51WiQj3P>E{rvQA zpR$-)_#-@(yp5T+VZ!B2rpeFdt9jzc=PhO?+}^@$p;jPzp#f6l#RE_ed zB&}78>u+XfjWK_ML|#gerQeJh&-}ih{q6TROW>^75@*iCri1*f!Lh-^gCsaO=sGi; zH9R&f<%UOxPYoA_eci*k;axB}JUk22lHo@=GglN};>_K!T{MZaNgPQg!I@!mZA_ch zNQXA6ozyW$hqko?vQkt1!s#k?LIvz`?d@eWe zNLK`xt0)~xH>F3@K9oL^mQXsE&Zpt^ny0PlbY~}3OGC@m6UKxw-7;;=q^_%9$LG{i zV$xuhdeX#_$@be)R9QT~Ijfp9qp|UsE*{2>PX1rC8ZMy7#90#~GiT;aVq%r0^y8wc zvUPnUZdAM77>=;`cUlR@hg5t?y{g_(fnWQ!-R|d$_*!K{a5A`|w25CV)F{-=YOij9 zNDzp82}Fk2_FbmRBV0yVq*ay6)$GvJ(3K&AhN44Ys8^{vG?dFxivc*4Ik@RWb|QPZ z=Cb^U71P<7f%j{#Ti5KbYQKJd&Z;5~$Khbf5jY%y!vP$Qi^CB(oCO>X&N>)5IVbNB z2U`M%C2&{*hb3@W3pgx%$+~LYv556p9J@J;g+8*{tM0%{2mygZ8;d1<^SS9rI69216Gxbbz6|FmwS!Ux12=A_7K4z=#MK zkp&nLd?|7@awkF}kA%TWgEwyN-rKm^dmDj94rts48k}@jFDFhztRk!_>xxB?h2dwi z_(vMItezhFim}hwYyPtKS1W#PoY*+Aai;E_@bt>*jWgzT+_TQ# z?(n@(BDMjEz1W&X9tdk{_?lIl`Zj9|=iNPeUsejws^UD6R;5ihEpOd@c`10mShsG- zakCQL?C5=YDO=rDNYyti?s-S=%S;h_1uWZ5O?#Nb?vVadlEJ0y?$XPiCe>INU-^BN zMH;M>)j}`+ycc)(Lgl=7uD2J=w39tB4LnC(7phaMQ}I+!>Z8<`DL+aD&7gHG^-0Qq zK!0t+fv!1q-ki4ru=@=Y7fj48^(U^SIwP*7mi1X+w;N3{>rBCHRg;*lXn+~qJlO19 zWk`J@yS+jy;ZH(pvnuTYyOkE(ZJYOxwH}Svl4rS^rai=QcSwH)LaP~}5q3nUrSh2A zz$2{yM05nBk?xU;BhYbvPs>L}nBg)uIUvQ%d0?_wpj|1dt{sREd^|wNK+p+pJvQ*k zfdAm8F_`p}-U<}&k}=AHSiRScbj3l4T%bdEshc<3C4&hgMW z44vbla~L{DpnD=~7U--NOWFh0ELo37$Jx2)&_f)0NAV`Gt6}Vt>cLw&?=y{oYsPdll>U=clYP|^ZiHqr}_*1C6mQBX?cG?__o0a z^@z$c87Tl{vRr;>Y1QUh^Oi}78MK4h-AL|iRmlZcH> z*BTh$#&|S78b1>Eg(U3@|O2kSLD?|*6ST5rC zL@c|PemEK)4Ic^nLNK5(+#j9|2lC-v;i)hQyXl8T`eBiN_#x?UdnWRKpmNq@U!V`Y zD=Mc)V_|&Vb1IKbtvu3YRm;?<5h>(VAbB z9xT0GO7eBv(%KH} zz{g55=-qK5;RHJ)7!0W>u|F}DxRUU(E|5q(Z5OD30c?Lm!vzg%Zd2DpQ`fwvuCb=B zc}-noOn8gRgVkxxZagjFJ#qwvg(G;gW+TWaZnW6*ZwS`2ngUv2lu;f|I1>Y*SMOuDC$jP>5*b zrH!;=k_?UqgZ}VEG7QUCk}_0HUPXS~um^Q~+PyOT>HnCo))*(QD}3)@$!D^;r~RoU$WL_$JRHRYw1LX}n_ zeTV`HF-fTS5urBK2Go)$twKT{QfVcNs7+}>V%;-i?}qee5~ONZ9^X52Ki|3EIp24V zrz~cI4IC1McN-s6VM4eV5^r6HFS#tLR2Jzp#ss@CHV_cV4=MQ~h%kIa<=RdLs za}(KBd(6{ry%pnUd4y)i>;|T2j^XrmW_9xysC<&amg1=cmh#bXm&^ybTm-WF|uj_$qrI!aKE?*(||7Y0md z$r3Fd9ENnDN~*maee(4!KJ4$$@sYtryANe)9}uEpR#U8lS0|kXl|ro}sF+umsTWiT z^r035mbiVYNXE=s+ob*9@J?Dg>#;q8if0gMen8d1RCf<0X$n<#CS6I_(i7?T(sn*A zrL*Z}=?gGuraRIWW}&4b*_rV+UjP5%-JmL+A5BnFvG6LDO06-V@RVB{5ij05GW2)N4Ft`aV-dL*Torf4huPqaybZr5q?A%agTU5nNN_c4-1xk5gtF(9*X5qun58b~h-ChH>W^lx$w54o|>v zsn|gV>&+`vb-0YAI;`HSk}fr@GESDkt~8Ik_%Q!dp74AuAc~#+byB2G$``Sl6pJ~i z*57~86EtG6Tpj$EqESbk3{j`t$?KBNbQ8T!#;KeZLjhlicSorljYp}|ZA7E4cqNB( zxtJ8k@s}ZiI>{F)C+8d(IRuC7APxuEdJWmIXc~7uQ#GwxtWDXZA}$t+I|iTQrNAF8JG+$ZNPoqQ(jZ8g2k_?!Zn5AMhbg7SS#{N;O%<8 zWDOt%w4#*&c_;y_DYFk#)nb1hfBEQ7POj5-4UdW5huFRl$1M%@1%18j z;ssj{>^u0qtzR$wFe9Y`?%U$W&&I8a!5Z6F&c>6yh}Sd^A^8kqnt!71{)9J78LHt5 zh|5upXzj!(eDalSc`k820C*=5m~7RMFrCCGnMqcXwWN(tO38`jx#Y#9J!zi7LsrQFzfidIzW~m+ zu({iIn4CaGEYL*I0L0Du!}?yG1awU=>Eu{nz3=Tl!uoI*;k{U7p|kx14S4&FjOYy* z;~FN&k3IH?)ElKy5H;#_d5x$nNdS{Z z?$oL&OWokV3I+=r*YXXwR2Q(B*t6cDBRAqC-sT)eVm* z;wovlKVO@R zX5j}o@aNxdyX$~(^U1R%Pbeey@ag!vjYr;u5NQ5>X3DmmDWE}&sKCo`SOK-mYj6SV zB+#Q=Jp~L7nAbqiaGLJqhMuJ;EtVMQ2tL2x zECG4H-*n5J2e(u^6ga*tk{7Qfle(^J}@y>l=E1{o@*uzGk<$_osrX&4Kml6 zn3$Tk(9HdVX5QEaAu|gtXF$J#3O05cKe-6gMUaz!rQM5YUx{LVp|tS7v{!#@8&@5F z@1E^*5<5P}XWyM;`_5=POKg6%`~7V*B|SlEV-?z7Y$aFYzii#vt(TU{k9~5dvw83bYsKc=7c^ zLf%o-_aQFg9v}H3s;~j!A^E6$Lgw^bS--`?vdk5XMQ|WeinJmNk<$@(WW(((j-iip zrk<|;ep8_e_yN~VWHUo(WiqPD1c^)hbxY{#=&W@FwDhzkI(q-r4G;VA%<_EaB-gTy zGw~e753GC8_$vau&F@~HnuG%C$?ZJ(2537pez z;Mx=#MFmvB-)8~TFZDmuPx?HAR$tJe8H)nX#Eg>3W{8r@qk>d03M5GiHnaI3^nKwl zwb}lMsnb(;?Sfu3MQyuSMir@IRN&bPE3J?x*|1wjx?}d4U!nnB*Gu}6eqDDD5xqxQ zT}Q(}Sr+p#AAe}Ucf|LeZ{6p5!*|^$1bm>;zVHh9>@N&?^aJ`9E2VO=$kKIMWaVTQVzADUIS{U;zg`jzs0Poy{4 z&$*xMiEmx$T1?{(=3_BiSD-lxAO+())?Pln``}Fe=)_Oi=uUhfAFog*>?_jJro2E>*x& z`Ck_>8VrJ=>iM;MdkPTz>>UVR#B4o{8q7}w&=C$`(nT=qYi^~}ESc)!xX%}%N2b@O z1&(2-gmEwoleq3gF&YzGcg1lUaEvli#sD09s(P1`>bGTO>y!Y-n z_NW4Pa(R|##rtTU={9^p9hT1rs!*9#tM|-^`bS^{bZQ*Y{2rt@hY`Hiif(jn8^3p^ zI2W8`-BEbz;^t77JKe5hay}}1viHKE&NlOl=5}ZbwExMX-^|2ko`5Dp1GuB@>#Lq6 z@@teq2U)Vuu*!5xKc12HNkT+bO_Vj=1NyLT>qL+G)6o_37?aBCGpe8>83*KLS&-9b z0V4t!KTz`3xf?@`U;`@KRjD0pXr)@Eytrs*ME<^63*LA0Q>(&GI8Kj$z||!^OKbl= z@-;1nNi1fBp4xgW_jDp*rw$BEPVPCR*wr6>W8S^5{r;e29C+#HIc=xGlo!lY?%l_W z-#V3}(cP1gIDez*&gVQ!;MSsO8&kuoKS;g(xZywUf67lLWZW0l!b0Fzux5#fNF$HE zCLk%Mcwohs+VB>w8{l{5=J2BJCbz8`C2PTyA-X=aR3T(*+vo5pVdXD>?R@)>oj+fF z92WUv=by03nTOu89=RWXx^uHU`O^M+9JI#SZPx{1+{2ul+rTbxA+=Yq#aZkNQe;8i ze2b};B}w2$Y~60z3-*$|Y`<*3XM63QGwJ4D=S@imX8S~UHnQi|J1Bh?ENg{@hld9T z88)~U95qfD%f?N^Wk9^`q;8Bxa0Z_cc+L&K3O<$m61D`xmb7l*lJtj487G5De4_I+ zydNHv5E440E(^acMnKWF;OVod430OJq#-V4c1WQiuWyi&>_k3~vS1ikpF}MSnNcmF zC`=rpN+ijQL^8oST@^zVC9p~oNtR?FO6y6S3?oxA4fBlY>N8E`^GQ|IC!rEflM-c= zhn0OHO0Dcf0_JiVZ4J+A7-^DL)|fV{wY5u{I6yQ^ux*AXm>Xjrl#VDgfOTBLq@Q3P zuZ> z6%<*_D%CNXtw*}<8aN|ThcdM)e!Fwn98OJtzWHcD*uVDWSxiQsJghf0C8!5%ztWr% z;}IcTh#Wn*<J87jyBQW}zr`36L^ z#mPc^@Io&Weh8v4=SFb|A&n1u*Lne6#M&XqNg_0SSG3kB;MwGvtyWbcVSuy)ZDR4< zSF3i?yHa|3R~pyu0@y44xx|CIS!wCv&UYMCuSBePF6{Y7Gtt}uZLRrVxHU4dDWg7q zu<^;$fNOl*N)Lfjt!G>oy5fEWg-`-5vip2eI!lB6YXF3TiGx(rL|JBV)^Y&pNC*JP z14`V>kSOvq5}6kql!zC^C2?6i2eQ9;Og&k+{N^eyU4}hc?KzFxHYo(87J=4doU^^1 z$Wor`93Ef!(y`&uh%rBZKn-T{DK%{!u!BSXuw=OhT-M~MUpzT6nxpscW+VOMw%0TG zAHu6OHj3*C-#d4n`|!+qAG0s7XT7%9X4kW3cfISa4IW$;LL3uXpajF>wsLu-I6M+7 z2&%4|NU4H}(g$jz{Bhb!g@3d~w3J4;jf^EbETxjMqGA*NM-A`?r3jCE?yMnpO4VK6 zJ9F>MJ(_dwx!?C4>QM|lTHt>N*qcLFjUR>V7wRYK8B(vv9Cq++ilSy)xi)eyffG03 z;4!Ep7e_)MI$?eQjKQzFu*6#@jo4W08=j#@?mYC35`tnj*aJeEmREt*XevKzoqS@En7~z569s%O<{O5ppL9}4JJLCPQmjQNEyqeeW zvNn!4faO~G0?!=cafPT!+X>jTga=v-irzUPBIYj^3;5H@$iE}!EYP&>98S;-He zAo*RsEULjlKHzUjWJ&$eMvNMjM#e=N6S|HPEz|>-2Rv{%H7EV{wi;j7DPOQnfOk;X zF_JCJ2ZQ{0;6i{2@P_JiIK+U4g4jlaTmxOvVXw)8s?imlk#xef)FDoG*Sk}0;wSE9 zY7ng;i1-ORu;N#OK=*udVbYbE+*hI{iC>{<5DZjk0t70URy9*4D!l#5wb^~8k_FxY zr9v6Q0`tl0!#P-XyaH)~tg{K!(9lekh{po&<)Q@8%Mu^n42Y0?o|Z1aXwB7oe6F+E zXe(}Adhl}ih0VF**Sq?2YjVj^ua6P44SrkF&)yeRZTi!& z*UO4KsOm0G$?`VY=}bI7;<_%QqZL#N)BT_^04{%`a&gKX!iou;rFaR}qLxW0N)${@L}`asEsa9ov|>V>IXHBYY|Xbs@0-j~MfVx95FE%DA+ z-S|s;@pd{SpU@%RZhlDLqHoVVJ~8{?-lCh@pthKgAI{IcUnA%HedV&RKQGt3KR5sI z;ry-DbGPQ1162chW_Z|L{RaK>F$q;e)!~Ue7#2rxT;AsU<2eBvE z7-Xh=IOI$Cm?#z{RQkw#$lgy-yfG>%XT9Q#nk{<6Ih>B!;9qWj(-MyMDViyr5 zK5BSft*wUO%(muwV~PW+4_l+*_ry_Li^I}5U7CTV@j@HYM7F0`C$q4W<(P;Os7)m3 z(nJOo@g}W^l_G90eo(wyB*iDV0J3i329+e$QiTFUTDhYZ=pK6eM063O^m^KWBAXI}-udZnIk6oBkfk#vv7vKR5;d$KEH(z?+ zm#nW((#9UEUXx(?k6`(E_6l$%SSC=b8kkzfmSv0waT$-}3C!aEvJ8Uq`Lk!)=Ci zHzh1f^-@YAb|Sf$|M?xOIcVXplya!-rDOxuT*2axgq21Bb|rMJnA{3fYj=LYz8zetqYL zq4s*NmJi6PBYdVg?DPcH#0%?&xKYU&Je$j{F*d3%rd;ZJcbnYdiaCDyi=`!Vx48qK zL)(bT_aXF1N7C<+c$xed^>iSJ#~FynYwUhNuH#0SvoTIqkdYyXP^rj9Q-4-=GNNGP z469CUX!^;2I4|?qDDEqc|Bl(6-PyHg$K&1EoxNtg?BP8;ws(ANY{IW#+z2o+r>qKt z5iJ2y0Y-=tg)40mB@t?=Qc(q@5|t!EMCt(!7)urW(WHkkK?GS*T9XQ)sA}aZs?_V)?lOcL6!+Qcfb>bdYYORF>ni2}-1LghiOwXGJ_g z7`zOp?1_6!57ntB#$wFvv*2AiQw67iM4w1hDne|7amy_*f%_@gehPSta8x)WTonZ2 z3%JBRo~Z#6xUPfC<^ztxCck@IpMAT|khXls$GMW5?MbAEJOBAUL#TW7iTx){gQED7SONhb1v3WbQ*vU zbSx%XYSQhl&7@qfxfwOUof;#12^@l?>%z}NSAn24CJS+axTzp55O>TbZV9t?iVasywH*~uP17aiH2YX3Xs=HJMF#mrsHrLIsYx5MabB(QQxihXqE&exD*UCtZ zxa}cqd|ypWyl~|6_Lyah>A#^G^t6eOTJD~K=WT@U8eComgf`rb&cl4pTK#leuMN+O z7smoxysu;XGku{}hMcGq^mN*J9H?0Vs)?gCDx&w;(?%wfh|3BzD_@h*)ZRp!LLpT| z(67Iyu2G3kHPm*Mswj@*iDEX@+8SBZ=*5C3u9?~rjcVa=fXaX<@xYS6;{h7j9KmwL zjF8BpTv`uGj%+rqJA9HM4NFuC>Mr7I5O6*j^*2I`$iWuQ&dkDerj_Ahln-h+WOnjn zCI~l1XGh^KWFVYpuPJ4&)aj7Vel|P$CC@tA6A4wJ7*j>XSX0DAM(GiOJ2Gyn!KrrL zqh&-*DJjC~&whOG9y_yv_{r2r<+G6w-gx8n z6_>DstiqJ^&i}SDKR-bq$A75==H_3xe3=}ad-MJWH2o$%T=^dV=JES~r;W$A&Iie# zw|@BH`SWY$JIRe|wK`Jy89G<3V9ogrsNgRk|ASfwRn$q+yj(FTf~c2-nbV<2o1BoL<{LQ|)9qHseRrzQnMDt^UQ zJzdu@FZNm)n>A_LH*x(YRC}?uhv(qf0f%s-eg(N*g)W88p?9E5ty$<&?s}K1RuQWn z5j&k7P}kprBBwcu!Y?5IJ(nmNTB&*&&VO~Q>QwcpaL2Z~T(cr0b*sk)AJU4y(RIx6 z9$5XVX60C4x9WeyAv}~7f1|TtTV1Wcv0AsXIv>&sS(VMgW6qbsYPx2HPoR^igCz;- zWxb@>+g%jc@A8=Ruw2pVVc|6VlNBotSc}>?WOa?={HVRwU}cwJIQ_8Jjrv+GXb=tl zl30_~V;90*mQ6>J*BZ9=TF0ytmHg2MW&@W(oo^OSr_`UaJJH$10(=e16mjr-d64@L{{PoX%t#hESDAolXQ#)G(%%9)6z5@c@6l1hSvp> zpQKwa)YC=+*&`&rt7CnVZet!*%)<8iwC--KB%xd-6*@M2dfTR<&aM3|`qIt) zr}nJ;`jhN=b8RZ#v2NRuBb7fK#5)d>b04MKi_4390!x=!8#Zsu_2R(x{?&K7I+B{P zywsnZzg2kxzrz0z>~5m6n%t%PP!eTO9uKi{i_s`s%|S`FVp(XhFD0fDzfaKZi35q5 z1bsh-|Dj?@-K7#>X}`};3`Z`_@);yWC+S+|jTjN8MXg9g3mLqg!L7DTMkq*O+%4M z+IHE9Mv+gF#7Syh@G>ua?JZA}<@E}1gGoLHpP1!CMc=hr4I7#(EnF-#ULHO;K|FZ# zfUZ3K4ktNY=Fk#u&s#J^u@qd0>K8(4F2t0xArC7Ye1%Ml;12-(I~VYuf1m zY{}j4UaowUSsYGz(hZiO`@_bWv%~#*o7G-;W@y=K->&?XM;E8?quGPEHV>@teD;T> z*S?i72g`-dN1FC#2ZFD>e(G$ce<8S#=OdVq-9V24>ay8tsxn6k^kd`&w%WmD4M-(O zf@%YcL@=Kq(#&nhVq7#uDo)V?qO>%@kbz-u*E5eHyG$2x1$`Q|WQAxcFzWSDSL>K>UZ2$02=Z$RF*vjoIllgSc-=11z*#2xHCukN$P#b!dX&IE= zn?07L*<`ffZ&LGOpGZUsJ*UK?JGG~@7lBg{^-)6oelKeGUNbP12(_tklI~^=-mIL7 zXGrE>q*rZh6UiB#nO*O$*N(kToG+8aiSq>w#7;5}-g6eFO5zX7<(wnUeWbob2(G$A zM-p_LXvJM~)$t`&!apc#g{tHSEp1hakAUD*wT%!$C$%Y5I?}xw!^>2XA zi2g2b=D~0Be_S;_F0GYod{F;gApP3|T&~&5jf>`i|FQN$|H`KEO|@0IldrydD6@TY zCKYt;%I({D=2;rPzx(>$x6fkZtBG${e>(Tpj`t>aJ^5fg9gt5&i*MtbXphhflr^d@ zMFzbK;#iUAT-dd!VpSywx}vM5*&m%>Jz&DkKEU4$D1EU`xX)FtJ8upa62njuZ)|?! z7!-a|B-eh6Zx#P6tb5R1MzI98SyL&iH=tDyMvg*V*<*~nU0ySLpcnE z^HRO`IsObCvU$OiY{=u*HJw!j=t+H1C-3R_1$|nd)j0>>QctKqRHZjnY^quH6;=9* ziX|R$q}o;HhkwfCoJ{&;jATP@m8CkHtA-7nrla^YCVTNgOa^fZPhzPPbS}aM1|t$C zNZfP7V5ESS5P2Wr9GXFMi0_srD}L|ZpJ?Quc0?m7ZBlz(lj0h#)4DXGYkoKE zjk6Q1wr?x-ut+Ct16Y<|L;?lLx5DkCz4egYB*n(7$mLy3y+C29( zINK{$ileJG%zmx_DiPOnw0)7+I^KcOn`%gX0EPR^Tg5qi3T<_K#>eVxpQ&%8I_ug( zE23o?`h-_hK|f!FR@!1dBDT5_MiA(K);mlI3-`dIx{<VxQ^X~I~AXD81&;7t}~VW z(woXzlvtJswo3A0#lpz4LLmm7L#(=v4l%cf&JHaOks-)-K(NN+T)0AITU0e+vDdL^ zlq`;yEskR}KJN2zi#cvFCoJX`b0qiQ7LTF3_@{Cw86-dB7Re8a*Vq1uT9_9jpGqK< zW@Ie(8EnW9PWd=jy?E^-`94l43aUbl%!5afI;tVfGYV6_{L2c4d-nmPUjquiQo0A~ z>IV7;&!6y~J96Zl_k=q6;)|1ta{SDh%-jUIbpj<;NK+qQ&gJ&)V>}%Zb64aEG51M%ZpT%U8<`m?jDXWU zX11l>?(hLNmBtbe8x4%V^q9WaJ{muEGdRH88{+ACiok$`zYpQ;T+U3QWxlL!8kF=R%n*V>Hp7VgmJFBw3E3)$6AyyO3SVKFrD} zJF+p($OJQLsDC0n5uK1GI4s+rI4aJSuw|n%@i^F;WC0Skq82f%7=Jvp2>1VGup;81 z6H+;3^#*$x$#B!*Of*CM8D2@5XJ~bB_w?lF55yhp_tdsB_Cb6P??Jz~NYY~01C-a7 z8k-?we8i0ONF1?PB4&~ci3=t{&YU5qPCE5-PHj4M!l}1%tPyCCa5|P=NH3*j0~!pP zh4ihoGLxQ5ucRgMm&0*^z}iOBPVl687AkP}*uVTdUr3oXv5F_oDjvZqb}y6LNw~@W z&fLjFZ$Hb$aEv49a2EkVGL~FOE+u6H8Vs6+UlzU`RR`l20+@ zOCAageo?{T7SgSx(2p;YlsHdxA5F2o0a{F9cZ$;&PK3>9B5F=2rcK3Wu;?&YbpEI4 zFj#aLED8oMbJ&86+_=3hX~7YTaFST4mA;U^!1Sd2w&;sgNG0btqy%n|@o05C6@E2cDSo;PoqcTL%E zhRu`El+6kNc{~0@)I8-)*^eKoS+ue&OJs~2^}|WLFjg2NY%DkSa173gk6F!F=Ko=k z>CgcC_p+FW=B2%HUM;`;3KexKBWmUzvS^mIv^sAMP4HG7wCDH?niW1Ee)DhzJSBAA zxe?Yes_Z8*SlL0ovTgit!H=#LKe@7P8&Dgogk_0a4PaRgEX#pqm0(#MmQ{jfaafiE z%UTBui+f6(PisG_JVTXPTqs^fVO9rekZ)~ zdu>tgb#`R&qtQcwjYpr0Gx-n3OKW%B-|+hG2k)$X`t#FxC*FVP+|`}t5&9qQ%Rjh^ z>WbrMckk}L#D+ZcizE~YjY$Xu6Ci}55nf7@+B$>;lJHA~QiLH?K{GPa8G~i2L_=DB z6ChBE)oOw*KhiNIXdk5oK_fcy(4p3$p->>EQ!7-PU)%4wyZd}RV9@^fr*Gyn=ia;b z$GPX8bMAdU91^`suV{y0_axeKfReDifw76XNqVNPMtD*tiYY=B(Fsa~me8Ut+~@Nc z2Q`zT*x1&Y{dfw-wOD`i#YM;Fro`pMsTAjpgW)}K5itW`d0$kNFN$p&6%#`d0xkPB z8WfT3J#|tVCd5eNrR7GjQH~@}?n3RzBgskLcGv<2jWgoe7-mLZY~I*02?G=2y{0sP zcF4Fr=e57TGU@j#ibh06dTWb|pS@$Aa&qWr!o0PJcmElo}J$uOb&?U^`k zQ-bdlo@wM>;%BihCMqV^tEFhFrm0j|QaHB|&3|kzEW`tZFM_f17H9htspl8&dMf{& zInnu7JV_qn->$RygIOL3{5rO~ySL9vo_O?)06YSi6Z(s3l9#%>`_sMlJRv{hS;J{k z$2&Aqi}nUB6;%`iip;?@Q$I?xl)un@__i2K(gxF4#cnD`|Hn|Tf?ThTxBAe(0_*}~ zz+{jPW`pSt(?9{n90QG*V-C+FcOQ+>W(YV~$jm zx1fEy(MW4iuE+P8+*e8-UqRo&_bimx>lKz|){%)eLb(s^30Qv}>kOHW^{Ygc)rInK z%>8YAUj|ecf0DCrlKaL!f_sAgQm5;~HZ2GRI`O_Pf_CtBh;HH3T}2grQyU}C zkM|q}?o!+78?Z}1?@K>teagV^-p9V$fG+0KC=XeU&~u{RO!cUb2KkaIQbYqS(Jtc* zn&}6|Ci)rLNgW0LL22qolx(EYIM{Cn=ARB8#GHqvKg?$xtdAgvh;x*Tx#ogOtbNS2 z6Wa#$dvLBZ(6^W40e1ZnSOgo?gGX6Ete?#`$GIcO`(HxeGg#+d25SzHVDI+1(qkC^ z2MM3fs6&opdGAbe*<&DPVR&CBhf!n z`YU{feUtrzeM3JgeRUe^Ztp?HLah@s4`KXlkOYPqyXiiMVd%^Dna4iM@#4<`iW?QEdsP%+BKklO#~EOZ?Z1xq#Vu0mxe;rrr*J<2o*!~@ zh#y_$bK$<^O4nb*CHoBLT}T}=331m7+Q4atKYo>H(~eth#un=ZbFuZh(QGwf-&ttzLgoQ7mLvWuX&&Z%lkZiIL#+XE2YX_^ zmEuMEzUZJe&^=oFmEA6;Q8DL4u?%IjBd7ECTeLOu`&97>Efbk2zX-XFZZ%9=X8e}N zSnaayto@DK^jWkSewQttp`Yt}X$GGa??WAH9p|%0%qM%Er0pibhdXGi=*FJ?*yB+t zw@H8EvHPuV-k*6F4b(O4kNW@~qi?4a#~z!cE&S3(8>J7!7CfhMQoc7xe;@sSN>6wq zX{#p#`RNKJo5&?{t-UneZpAtUU)D9Kr=#Qb^ppGKc`;7*`2!UYSs#EjTlSZ#b<_lQs;BV|_fxg9$!b*^s7N^n z8XR7xd!*b8N~uUxD>a}52vJQtAV)%80s+tf4uZdmvGf$?J_Na+{}(XoYsg)Y`2IY2 z6@2J^3x(IZUVA9wyww_7*GJQMM$JM_&${}X?7xF@#pB4sIaVv9Eu%=r7(kh(hceX; zv{ztUSY01Ro5d3JyNNzGLpeb?(uOv^&^@~60h#ax_#i~4uta=~mCu*j{vNDzE;$$0=ku8OJT?$3H=6VR3B=BEa1WKPkh+R9N*hx`~MqHPf* zZlj(vC@;mglb{{!6ocq-=UthEdZ9hG?*(VRG&9!RC(j<=vkGiO`7Ho1>p2X$ z0rCp^@4>j4kkx2g37Ly}2`EDS9n>cP73Dj@MF2f}@r>!s#`qmz8NWxa^FQ>zD{t`s znV2y%Qxmc@=g?U*Khf|bHBeG?X)K*7 z3IaO(%uGzlPf{`xWz75*I0#~dW}s#)K@kzt1CB{^jua4)qi#5p{oYsJj=daXw$ppg zb^ib7eZKDNy6^jW?*IS%wE44vr~S8v&HoKOZQm00o^?7<^BuF`o^PKY{l>99@n=mP zu7j%%D{H@_rgXH{(bTfmn%h!8);+ED_8DtEX{XPosr??W@p3WowKu3Oqb#u8ZPt4XaPJ=H>B5pxEfAU>^pF8^Ad;0%v+wOTA8mdd}>wt#Z4XyW}ZTq_8o_4AQKhke)+t($wwms_g z*N?rs^-OE>%?7)?dr*+4UJf&Ai){I7v%x-(zt1<@H$u1ufx)&X=SL^bk>@~U-FMg1 zymJTEF0kBhPPf(FX}7x5{uHEJ&K#cO?%sX1ktU5=`d<|Gy7L}wM~4&Ev9Hx(Tto3} zAGenJ+*%)^nbr0vd~sb}K_Acpq=Jy|ea$x{duKQ1=Cyq1HojPUgSBqluNJ)DlkdDR z%l95_7uqhm`wRXdOlxp}N|RcoNjJ%Hz4Xvf5HC5y+c`se7=4;Dwkh8}k8}ppz(J|m z5y@qc)Vxe;;UzuhFS$}zw4_F8Nq;NaPizIZrPi$fWD7v8(Z*eB+gxh5U25M>a$6?3 zAC{g@lsd5XGY-v~{QSE}P~tkvB^dVZbs+iIx?d%Vc} zp6uECqSSYy)Q?-rlN+Qzw)CgI89+@m;25|gy);Q0NKG^dZiC@FWP>ymn}&f`7E9j1 z2U~rJosrZ!BiZLwYN1i+G@5Tfzc$hsY#a;UacDN4y-1?EKQ{Ln#7&;W`#7x z6%c;`d!?y7r@~<>x=iZ{sJEtlB?a<*88{xmD-eEx+|NPOZ9($^+5}Zf)2Y3tM*yO9 zI(7xqA3PVZZZLibp+AIn2d+;OS&DuU=y>AWB)D1 z@xEylV2w?1{}_8W6R%sE0C;Xe!>yYEak>p&+ZIYY(0vD5>}2g-^u@y^0qqiqmqhp^ z;>RTRPePL<_DMpc-DtWSjd!ztGHH^Grpc_8%)DfDOTp(U#7+wFkaAAigPnVbpHyNk z75h@LZSMfUTA!dv8n&gORT}M2**_hd)3G(3_CEZ*kGR~AUp`~a1FZKsx$!ykGl;27 zVl0z$=ODTq!p6hI&KDT!WCYv{cH5LpJ`*jswJ94)bz|{~Y$s$pyswadPGO zWWbo?%*|y^E^FrE&s;RmLyJ7@$YV?%WAd=&ByoHa{wIl#e00fY-YM2TH43Z&tX;qv zQs51U;{r4+fY)ixj?ab6eEK8MfF z1pxf^SA1Q}{J-s&&ZBV&+`l1D|L!DRV2=yL?ghsE0}lU$cPSi7;a$o;rR?)9>wb#{ zml%JEd*Kpsbs3#6v&LoeuZ(;y!$)PzFQcyve&viUXKXq8m&2i)d@P4oIqO&8n+i0l zV2=vyt-!7d^7{($c7-$W3OZfk{J8>;O3txLG_S;em5i+<=PQZ%tK`sCG`@-rSJAkN z9I3+JRdA^yZ>sR;HTJ)TZ?3_un*M5hRgJCH*j|m!)o{9woj2*PA+KuqHmhNu8girt zJ~i;EfzK^s?-pm!E#Ch_yxvB$@0{*_d)|S|9nQE~Y_DZr?EyYpTY&|DcheH^ZYpFN zb(U$ILFJzdZp!?k1@HuO!4Xg`)5IN&1D3x(!4aXsXagIB|SsAA$pa%#5>%mtt z&b~4a-;rtR0p5^#WVlSTNnjl~460;Y+JO;Zp-l7FWFGAeX3Mnj1KVXDbCz*s9oHow z9^}jXvKhE2)3R9R@ur|J2nKNgE|1@mX$7}d<7J*`!*$pVOaxJYeOt5dlkEZPwt-vQ z$sihJf$K8uIso3Eg6C80)7}*f0@&3ao7%(I4Zd#hb%U=PeBF)#xVppD9j@-^>W)?& zu-`H7NgjE^iaTmqp{Hs zo&2!RkGX#6JO;mwf%8~6{|=qU5hvr}Ivzj2&OZK)0P*Zk{Q9G}Kk@62pZtkef8zM} zX!u4Fz)urcdjkJWB=#p_{~zE#iFkXHxSEU}QzB&o@Nd958Lmz<4I2WzWrB#Upe{1O z>=S}Lp~P-zkj#w5GBdH~kMIv8=EL9~W_kY_pyMp!eHJk?doLi*=CIZrd@vVn=MfY0 z7&jlhMT{)iAoDiFn+;HM$F?zhq`x4@FX>)*&mVP4> z0j~)7Mi6Jqux&Y-EobfubX&>%RlKj_JXnq9k!T(X-$?9ypB!If!Dc{vEqvFa?^@Pc zi;tsNKZ>0DfOBFUas6SUOf+#6jlIzqWIm#AJ=(-zOAI>1z-a?HxDkJB+%FSLjK#wL zPxQsXJC0cSGqJmg9R3*nHxmb2*ken!%vP{%kIZ(~-;NF2$%h^Icn7}P35T6<+l3!@ zq0KJZ@$4B-o+t2M0=`LLtpt3XfbXaeOd|6V=}*EJN&J`0Ig(6&3hVE|H>sR4sl;0< z`=pYGpAe&I*qw$J>BQ7Nbo~r%4vFt&d| zejh=PBiQ#PxtGO%S)4~%`0X#~ag_hEM*;rJfzL74JIUm^1f;Zn#MQb-&X5ku$TOetlG$;o2YD8}|;@~fD> z^W^4v{9FQ;61bPJcL}jjLT;4&m*u(v_p!X=0RD479I_@!4Vi>w@|J{ThA_oUB|FKG z47ntgtjWxpWU7<(avbLzoWmj8TC3LEWm}VRba_k2yW@DN^s-)5;%K%{8`t$cp8xaQ z_wWAxzTfYCKmWgeE7h#Tp;AsOWwVlAhiH4q9y#n>IxH85^?igdN9>Cup1oteqxQu6 z{CnTC5ApjDfA838ALIOqd7n80j`842**;E_6Y_I{?kDV-6Yigsjgy|8)Za;2JxPm` z^r>>*RN+&FPZd5@_*BXCDc+y57f(6YPdAMewIWr^kCg3+RAVU2gg=1KIkjOJ_?+`W zq?*Iwxk$C@z!)fmeUZ*;1{0wewnwU6J<_)(M5<$K9d*v}`J8r;3lG3Eup^S!ajM%I zhQJJ10bAkgNawbM!7vTVU^ASERL@%V2EtS*f%Wi3r1P3Uf2fR9e=^|Kz}SXuA~iC< zv2~i99qA&^y^B&aJv4tg(j|i;UAii~?jv1xAIyo=rV~^|YS#$NYj-?S`~XjMeuB-F0| zuIJ&6u5ZL^h?+xqH?#rZG_)(wD3|BC?&Z3d>)y?345PsmM}WTP7XV-9<2|3R1=cU<4Eij< zqX3TrwF=ZKkmmxm3bsI1qy=g%ke>y3FQCDKjUX$9_Eq6^K*vJaD8#GqSfrxHpl*@A zi+EE+zoL&LIp0&U9*b#HjBl|uit$~D@4_BHmB?HP{Y&&wqK^{$vQ%zL`BN%Sr93XB=MsBy2~C#TA4_Fp>1cQa zXugymWppm1Um5+%=vT(~GFe|HFUvZB^J3X7upgGm)A9uJvYeL7dA(d7m)jRl`6uf_xr5q~=RJdqsb*(DPLq ztfc))>;F|Re|L8LLnc@0ah2z<>-Tlqua?Wzy!z+ek=D?D&1-(e_2Ae$d`!sE)!DiXo?2LO;7T@IE7B#oJEjPssN`}nla*nKqGFL(QK-OuCw@>4;R3O!Y*Um=GT=2y6X z!2JX6ACSWXcpR{24mevYX;$gIQ7LPcvQo*XgK8eMj}AJ|4&r~v+(Y)sA(=R2&BJ&c zrt{(QNJor$$JlrAdXHc4;c?Xb_tpN8_aD*YUv&F~ZlCr6`TWe-&yGeq#`Dj;FFvQ` z7xev-2ghaNEBbxq`YZfT=9qvf9Sfem1hRCr4JNE4&feIrZTNcoOzSR<{-mf?1$W-P4hs z+a1FD`+~$eQ8MtPMO4YBtwHb6lF^ z(wuHBtkGf$Y>Dg=<1U#A+aqh)4Cvc(Wn`D?_0kcbek=7`so%={R!1WH-UE@fZVGyC zjn`$?yDS%I)TRYktBrbX@o%esThH3^r0sLSr*?d5*9nG!wc9-d`fcA5@M_Py4%X~2 z96Y<+{mbV>)=|BV^uI!lPIaLVOoK&{U8&}kcf%KvbvCavZ99JySr=L9f_InoKWuxcIk@b>^UVQBJb!5Hi z;5$ur4Nlj1)<=y#_kle1#kDVA`|7>#4EP|jerojN-4Ai^Z|t>la-Dn*knI6u0jB}- zG(g@5$nHRW55#34jz5y|LHzo$``63T^*G(2?;G(P!q1x$;4<`3WIxeYuAJSxJhEZD zxWyj1r5HRPPS@dh4aeR0pKSQ?$bQ-gK8mlFJ&v{3*olD4SbdFCcbq(qGk=_Q#u+=_-XCut zj_23y_U{BePMi&Tm}sBf!RI?@bB9b#!gZ3|O_u%1G@mRBcXf#Do;{IGk(GP%7*cjPNd;bCRXUW8aG=9)tnJwcF(dr@G=UC^re3{!A^!~8* zALad{xIb!7<>@<*cX{gM$z~p3^Q@VN?_<_@tRJZPnELb7ny1$9`1ORmKB3nqW&bIC zJVnoZd$xcc3)C-kzfd2AG$^7=5#B{=7wMx|-D24;#(N>J7UJ!DQntvLMaD0-|4Pg$ zdbZZsPFXt|8zrti)8Nc?%~+Gu z;mmcdXjyaSnd`G+?zdN*xvpLPzpPiyZ(LUuziFK`acl=U#p6;w?gBMQWsmK|iQ`BJ zxsDT=)^TM|f{KvPo%im{T={)W-iIesgjjbCtYHTg5}P8iL_%W4h6?cq@CUF0Hf-Q` z&OPtFv7II=G$X(H&AsRQ{O-9ge_+pqFRSj{O~Es&H}_M)vlo7Q;h%!%)c5E9O_}k( zA76PQ_?$X_*5_M46FjB9-uj5~4A}j-rM}wwBjYczolgXl9WQ^CYyNk^ zRP(EEvUo&22JAV>P zc79Lz;za!~PSpS6L|zvs@|u~DpP7)Kndr+*)t8PMtD&;0r;G~lt<}f)>!<{9ZP7eM9^;o-RE`le_C3pBh%^-JCQ1DnH+1o`1bzR)FwWwYFW@t zUfqI5gzp3B^bteBS_iO~<1bUkc!nH9f<3F^I+6^2HKdGq^70N9($FA%vY4nP_Ch;` zJq2RRV8v_3Y>_e;Ao`dsI_wlIJz!r{^+G)4oMFJa1@9+pg}y1Klw)v`%aCnTL;**Y zvp3oy`H;VT{3UzS>|ru0$My^CC;WTFwg=+fifqcZyzgo~V%vpOB)~6UnbUFwY+A00 z!?(8`$V$nTrd~BHNx3f>S2SXMij>$9i&o_!VEtq9>LgRz^VMvs(1Rpd^Q%o=om4lK zOdQLX{Hy6|&Ww#Xy61DEIyrfr3+=^hud$KA&yhrHr2YYOS_|*1nuYAU&#PX4gdHb6 zB$)`k_Z&&_>|^g(s_iW_XW4MCJUcYkFp&HmcP(O>A)hnP#)LI}CX?)THM2DKpGjw8 zj)u7D`vNSepWb{&$-NxK3lQ%{H5A{Al_(_9LwD9);FK`S-hY! z70X8TB(!q6ZGC<+o>hg+j-GJ;dG)GJJXOq2SZOB4S%0DMi@4n7DeR-}N@o(W{Jaib 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%0AI%1_GIkj_(skCPRnN0+VD_ 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%0A6j6F&AyO*>15RC{$EBL;%(pKOEV$|im$H4 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 DGphXP diff --git a/mods/certify/download_certificate.php b/mods/certify/download_certificate.php deleted file mode 100644 index 96dcc41a5..000000000 --- a/mods/certify/download_certificate.php +++ /dev/null @@ -1,124 +0,0 @@ - iconv("UTF-8", "ISO-8859-1//IGNORE", $row['coursetitle']), - 'full_name' => iconv("UTF-8", "ISO-8859-1//IGNORE", implode(' ',array($row['first_name'],$row['second_name'],$row['last_name']))), - 'test_name' => iconv("UTF-8", "ISO-8859-1//IGNORE", $row['certifytitle']), - // 'score' => iconv("UTF-8", "ISO-8859-1//IGNORE", 'Bestått'), - 'issued_date' => iconv("UTF-8", "ISO-8859-1//IGNORE", date('F j, Y')) - ); - - $fdfparams = ''; - foreach ($params as $key => $value) { - $fdfparams .= '<>'; - } - - //$filename = tempnam('', 'atutor_certify'); - $filename = $filebase.'fdf'; - - $handle = fopen($filename,'wb'); - fwrite($handle,"%FDF-1.2 -%\xE2\xE3\xCF\xD3 -1 0 obj -<< -/FDF << /Fields [ ".$fdfparams."] -/F (http://www.helsekompetanse.no/test.pdf) /ID [ <".md5(time())."> -] >> ->> -endobj -trailer -<< -/Root 1 0 R - ->> -%%EOF"); - fclose($handle); - - // Flatten with PDF - - $output = array(); - $return_var = 0; - -// $exec = '/opt/local/bin/pdftk '.$template.' fill_form '.$filename.' output '.$filebase.'pdf flatten'; - $exec = '/usr/bin/pdftk '.$template.' fill_form '.$filename.' output '.$filebase.'pdf flatten'; - exec($exec, $output, $return_var); - - //unlink($filename); -} - -if (file_exists($filebase.'pdf')) { - - // Send PDF - header('Content-Description: File Transfer'); - header('Content-Type: application/pdf'); - header('Content-Disposition: attachment; filename="'.basename($filebase.'pdf').'"'); // TODO: Fix better filename - header('Content-Transfer-Encoding: binary'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Pragma: public'); - header('Content-Length: ' . filesize($filebase.'pdf')); - //ob_clean(); - //flush(); - readfile($filebase.'pdf'); - -} else { - echo "PDFTK failed - not installed or wrong path?"; - exit; -} -?> diff --git a/mods/certify/download_certificate.php.bak b/mods/certify/download_certificate.php.bak deleted file mode 100644 index a5029f21a..000000000 --- a/mods/certify/download_certificate.php.bak +++ /dev/null @@ -1,125 +0,0 @@ - iconv("UTF-8", "ISO-8859-1//IGNORE", $row['coursetitle']), - 'full_name' => iconv("UTF-8", "ISO-8859-1//IGNORE", implode(' ',array($row['first_name'],$row['second_name'],$row['last_name']))), - 'email' => $row['email'], - 'test_name' => iconv("UTF-8", "ISO-8859-1//IGNORE", $row['certifytitle']), - // 'score' => iconv("UTF-8", "ISO-8859-1//IGNORE", 'Bestått'), - 'issued_date' => iconv("UTF-8", "ISO-8859-1//IGNORE", date('F j, Y')) - ); - - $fdfparams = ''; - foreach ($params as $key => $value) { - $fdfparams .= '<>'; - } - - //$filename = tempnam('', 'atutor_certify'); - $filename = $filebase.'fdf'; - - $handle = fopen($filename,'wb'); - fwrite($handle,"%FDF-1.2 -%\xE2\xE3\xCF\xD3 -1 0 obj -<< -/FDF << /Fields [ ".$fdfparams."] -/F (http://www.helsekompetanse.no/test.pdf) /ID [ <".md5(time())."> -] >> ->> -endobj -trailer -<< -/Root 1 0 R - ->> -%%EOF"); - fclose($handle); - - // Flatten with PDF - - $output = array(); - $return_var = 0; - -// $exec = '/opt/local/bin/pdftk '.$template.' fill_form '.$filename.' output '.$filebase.'pdf flatten'; - $exec = '/usr/bin/pdftk '.$template.' fill_form '.$filename.' output '.$filebase.'pdf flatten'; - exec($exec, $output, $return_var); - - //unlink($filename); -} - -if (file_exists($filebase.'pdf')) { - - // Send PDF - header('Content-Description: File Transfer'); - header('Content-Type: application/pdf'); - header('Content-Disposition: attachment; filename="'.basename($filebase.'pdf').'"'); // TODO: Fix better filename - header('Content-Transfer-Encoding: binary'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Pragma: public'); - header('Content-Length: ' . filesize($filebase.'pdf')); - //ob_clean(); - //flush(); - readfile($filebase.'pdf'); - -} else { - echo "PDFTK failed - not installed or wrong path?"; - exit; -} -?> diff --git a/mods/certify/index.php b/mods/certify/index.php deleted file mode 100644 index bb97ed8eb..000000000 --- a/mods/certify/index.php +++ /dev/null @@ -1,92 +0,0 @@ -
    '.$dout.'
    -->'; - - -?> - - - - - - - - - - - &$certificate) { ?> - - - - - - - - - - - - - - - - - - - - - - -
    -
    - -
    -
    -
    -
    % -
    -
    -
    - -
    -
    - -
    - 100% - - " border="0" /> - - -
    - - \ No newline at end of file diff --git a/mods/certify/index_instructor.php b/mods/certify/index_instructor.php deleted file mode 100644 index 3719b8928..000000000 --- a/mods/certify/index_instructor.php +++ /dev/null @@ -1,100 +0,0 @@ -addError('NO_ITEM_SELECTED'); -} - -// Fetch all tests for course -$sql = "SELECT certify_id, title, description FROM ".TABLE_PREFIX."certify WHERE course_id=".$_SESSION['course_id']; -$result = mysql_query($sql, $db) or die(mysql_error()); - -$certificates = array(); - -while( $row = mysql_fetch_assoc($result) ) { - $certificates[] = $row; -} - -// if there are no certificates, print meldingen under, else ikke -//$msg->printInfos('CERTIFY_NO_CERTIFICATES'); - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     
    - - - - -
    -
    - - - \ No newline at end of file diff --git a/mods/certify/module.php b/mods/certify/module.php deleted file mode 100644 index f30687a49..000000000 --- a/mods/certify/module.php +++ /dev/null @@ -1,95 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_CERTIFY', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -// XXX: Not needed -//$this->_stacks['certify'] = array('title_var'=>'certify', 'file'=>$path.'side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('certify', array('title_var' => 'certify', 'file' => './side_menu.inc.php'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_group_tool = $_student_tool = $path.'index.php'; - -/******* - * add the admin pages when needed. - */ -// XXX: Not needed -/* -if (admin_authenticate(AT_ADMIN_PRIV_HELLO_WORLD, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array($path.'index_admin.php'); - $this->_pages[$path.'index_admin.php']['title_var'] = 'Certify'; - $this->_pages[$path.'index_admin.php']['parent'] = AT_NAV_ADMIN; -} -*/ -/******* - * instructor Manage section: - */ - -// top page, under manage -$this->_pages[$path.'index_instructor.php']['title_var'] = 'Certify'; -$this->_pages[$path.'index_instructor.php']['parent'] = 'tools/index.php'; - -// children of top page -$this->_pages[$path.'index_instructor.php']['children'] = array($path.'certify_certificate.php', - ); - -// sub pages with navigation -$this->_pages[$path.'certify_certificate.php']['title_var'] = 'certify_add_certificate'; -$this->_pages[$path.'certify_certificate.php']['parent'] = $path.'index_instructor.php'; -$this->_pages[$path.'certify_tests.php']['title_var'] = 'certify_tests'; -$this->_pages[$path.'certify_tests.php']['parent'] = $path.'index_instructor.php'; -$this->_pages[$path.'certify_student_status.php']['title_var'] = 'certify_student_status'; -$this->_pages[$path.'certify_student_status.php']['parent'] = $path.'index_instructor.php'; -$this->_pages[$path.'certify_delete.php']['title_var'] = 'certify_delete'; -$this->_pages[$path.'certify_delete.php']['parent'] = $path.'index_instructor.php'; - -// ** possible alternative: ** -// $this->pages['./index_instructor.php']['title_var'] = 'certify'; -// $this->pages['./index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages[$path.'index.php']['title_var'] = 'certify_certificates'; -$this->_pages[$path.'index.php']['img'] = $path.'certify.gif'; -$this->_pages[$path.'download_certificate.php']['title_var'] = 'download_certificate'; -$this->_pages[$path.'download_certificate.php']['img'] = $path.'certify.gif'; -$this->_pages[$path.'download_certificate.php']['parent'] = $path.'index.php'; - - -/* public pages */ -// XXX: Not needed -//$this->_pages[AT_NAV_PUBLIC] = array($path.'index_public.php'); -//$this->_pages[$path.'index_public.php']['title_var'] = 'certify'; -//$this->_pages[$path.'index_public.php']['parent'] = AT_NAV_PUBLIC; - -/* my start page pages */ -// XXX: Not needed -//$this->_pages[AT_NAV_START] = array($path.'index_mystart.php'); -//$this->_pages[$path.'index_mystart.php']['title_var'] = 'certify'; -//$this->_pages[$path.'index_mystart.php']['parent'] = AT_NAV_START; - -//function certify_get_group_url($group_id) { -// return $path.'index.php'; -//} -?> \ No newline at end of file diff --git a/mods/certify/module.sql b/mods/certify/module.sql deleted file mode 100644 index a470e13cb..000000000 --- a/mods/certify/module.sql +++ /dev/null @@ -1,35 +0,0 @@ -# sql file for hello world module - - - -CREATE TABLE certify ( - certify_id mediumint(8) unsigned NOT NULL auto_increment, - course_id mediumint(8) unsigned NOT NULL, - title varchar(60) NOT NULL, - description varchar(600) NOT NULL, - PRIMARY KEY (certify_id) -) ; - - -CREATE TABLE certify_tests ( - certify_id mediumint(8) unsigned NOT NULL, - test_id mediumint(8) unsigned NOT NULL, - PRIMARY KEY (certify_id, test_id) -) ; - - -INSERT INTO `language_text` VALUES -('en', '_module','Certify','Certify',NOW(),''), -('en', '_module','certify_certificates','Certificates',NOW(),''), -('en', '_module','certify_certificate','Add new certificate',NOW(),''), -('en', '_module','certify_file','Certificate template',NOW(),''), -('en', '_module','certify_tests','Tests in this certificate',NOW(),''), -('en', '_module','certify_title','Certificate name',NOW(),''), -('en', '_module','certify_description','Description',NOW(),''), -('en', '_module','certify_status','Status',NOW(),''), -('en', '_module','certify_download_certificate','Download certificate',NOW(),''), -('en', '_module','certify_add_new','Add new certificate',NOW(),''), -('en', '_module','certify_add_certificate','Add new certificate',NOW(),''), -('en', '_module','certify_student_status','Student status',NOW(),''), -('en', '_module','certify_edit_tests','Edit tests',NOW(),''), -('en', '_msgs', 'AT_INFOS_CERTIFY_NO_CERTIFICATES', 'There are no certificates yet, let us
    add one!', NOW(), ''); \ No newline at end of file diff --git a/mods/certify/module.xml b/mods/certify/module.xml deleted file mode 100644 index 56cc2190f..000000000 --- a/mods/certify/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Certify - With Certify an instructor can create containers which one or more tests can be placed into. The module will keep track of a students progress on the test(s) and when the student have reached the pass score / pass percent of a given test, or collection of tests, the student will be able to download a pdf certificate. - - - Norwegian Centre for Telemedicine - helsekompetanse@telemed.no - - - http://atutor.no - BSD - - 0.3 - 2010-10-25 - stable - - - diff --git a/mods/certify/module_delete.php b/mods/certify/module_delete.php deleted file mode 100644 index adbc8de3f..000000000 --- a/mods/certify/module_delete.php +++ /dev/null @@ -1,32 +0,0 @@ - \ No newline at end of file diff --git a/mods/certify/module_install.php b/mods/certify/module_install.php deleted file mode 100644 index a72a17d43..000000000 --- a/mods/certify/module_install.php +++ /dev/null @@ -1,71 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/certify/module_uninstall.php b/mods/certify/module_uninstall.php deleted file mode 100644 index 68a95c3cb..000000000 --- a/mods/certify/module_uninstall.php +++ /dev/null @@ -1,44 +0,0 @@ -addError(array('MODULE_UNINSTALL', '
  • '.$directory.' can not be removed. Please manually remove it.
  • ')); -} - -/****** - * the following code checks if there are any errors (generated previously) - * then uses the SqlUtility to run reverted database queries of module.sql, - * ie. "create table" statement in module.sql is run as drop according table. - */ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/certify/test.pdf b/mods/certify/test.pdf deleted file mode 100644 index 0776f9e7ba2bcf9887601b241308bfaa793f6fb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 526128 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%0DMi@4n7DeR-}N@o(W{Jaib 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%0AI%1_GIkj_(skCPRnN0+VD_ ziKzIR4MuR05>oLf_$$idzmTkYGseS~3~0$T(;^BoEimC0DD}HU-Mt8<2`b!GBA^*5 zjAImpo;Zt{%Tv} zz>>!H9l0xeG7I~k*fVR^+5s4YmdQhn7f0UgfY--P)?d8Xl$=cE@nG&rvVeM13{>!n zme?JHTY|d-s5`hNfZD|F0BQ-e1kt>}A`vw?=J`>rW0r`5ev_FHsnq2n_DLR_N`}z~ zS{Nai!o1Y#>IoIWB9KBVX;ojbwuZdW+Z#E!pP@G+C%VyzI#bYn?oNvNpm^5qp728K zfUZcDlTrp%pmFn4op4Wx7~R7X=#Q5^f`P(mMW+*Q|6u(A&#?Tjk7{M8xr(c znAjXZEuX@*0*q&w;T#){Pn+r;^6C8%+Am<rT*TpJ-nMc z4I8k5kbdeE@sk}YZIpAzM0 zs?jp<@bZ=Zt!KygrwRy#(qc%Ixw%hs;yIOu=^H}&ZU-J)uI+nxp1t*y-1o?1+!d<$ z$FM%Ss^gI27wuqxGbQ*MXO;H?6(I~a&9TK$v zM?aWb)dj|p2Y;$8^d@0kQrL-wv@@ZHuQQUUNaSsjTTg94s1PEU1@)9jM@4n5ICS1~ z-c#rfZfIH9A6ZpVQ{!}AlrNr9`qs7Px(^iAv=PVd9h+h^8cTlaNp!8+{ouE+XILy( zz)fU2nG6a+47#+HMW%=~T3Dp2#nD(iE&yb+0@-FvAcKU+e0wdW%FZ4#gLI*vV_dF*b{QIdNj07*`^?cb{~^qh*H?#aVdoP($jDTD5A?W<5*E7 zBC?hR7~zcL7IRlT%9?JV&`!6q{Ugq5XW7pFN90i5w-&OyDwL)c|W!N`G$tbQiZPEL9I#{3U6&u_Wu~#@3Rxk##ixY z^u0{rhnmTVEk+spjii8z%mvM4K!$sQV7gbZk!Ksa?5kv@=C#=?`Cl6~+BRxdd!_LZ zKwraJ?jHF!-Bkk{#c_q_z1iK_^Zl*8XCH^1^Bu;=&*9kdox#8+-V{{QQmDaDH-HO) zAWG^27fMu8Y6uFDRtOV7f;34XsA-A<;lCK93Q#D&x+e+PCxWcINH-n>XLLgyrYS(JrES>;uLP9^stt^z2^h5TFe8MkiD8xFb@RWYx68 z9AXI-014B%!xZ2fvd5ueQyb`8vZr9=7BsT;a2if$>vN-w?ppHUTHc2hwp-)qD&a*g z1%&jWpXx5?bwXOK**WX;hRV^d$UAY5oVYH`Z&1gKdU5*mZ-egP^u{247Jh1E{O+`=&EL|5u zQFuXtQg-OH1o{1wEM=;8U!1Jq^ckN%` zdoYPTxu1@NaG%+^Q}iJ7moolzywooCN1!_b5xd`G$%ySXk`b8vjD%>Z7oU}S*_`g{ z>SvDL+PvO#q&Fe;#t%!qeUz3B=8n>W>Z*n+oLL1`oJiST($~^L+Ncs<>Ao(Gsu!t! z41_IqV;~d=mqtnlDoRKRyCd#_N^4}nK%CouP8e%KHDQc|B4J!AK=s0PHyqMVy0M+F z@ZpaXSmc8x?!{hg(=jh7q<%cAMofh?T{tu)lPmyvxxg-|JH3OX&NJ z0}`*3aMw2E>*ND%YQzPuP-O=s_P&t=*nRMI7d6odcdk;uX=$mB_gu7T2^-M?N!>?& z9O_Bi*>aFKwcfZ)P7W9M0J}=6PAwW46e~1XG!m?f7Do%^2L@WM?y$+-H^dm_DHdUmvpRUo{&B3h*^OgM##W4vjUPI;YJBb3 zWV70=H&x7x%^ccPHBbMcZ`Q!pSnJR^RpyM^DM_4MGChQ~C5ejBu~9=4RZrE{CI#~j zX2pR@Z(X9gY<*x`00RLYFDpot8AgGqEaSm4R%(=DX$St?j)lYAU2PAx1O4sNM4&)s zgP0HHKH!o0y&QlB;x`>|VqcAIO70~yM?#lVFeLo>fUFl1E;zKz`9)^a%rQ1i3b&ow zahA){A>o|E*hu)#A(`O|CYZAC(Ox$@aJg+q2Wpy+UZ9mp?OH#nT8l`%T7gumg`^^F zu+*ZJNEMegXwbf^p%xmR9PtPbla-Q*_kM}TJFhyAs8wd1Hr3hEX>`ibkZ`}{A(|T5 zgZo)ar96UJVY0|MmL*bRJX+ER{6ip^<3jS7*3@Y36#w`;Ctv@&;$ z3I;y7#rLnC(;hhx|JVN2mmb_7H)G=~9S2`+-Y|hz;dsy1mwx)*?m5px7}ySQzqDk8$H^2282Hg+ftg;ZNQ$2-kKh!bouSV#6 z4k`Oz?tzP}dIA9sPBpD4i{b3+uS@L8;H=J^b^UFxT<0uvRvA`{L5Q8!6w(@KP|epV||hNZrzJ1rT)ND_6u76EBDhCLR;VOxz>(n7CbRH*tg5VB$)#(!@n# zk%@ElxdCj_oAQzJd)%A_-Zy1zJYEW!kAemI`$GOu0~A1H7J$!hc_?0kyuqhD9WIYJC|~*XgrV1L)|(3_8IPEm&q2<>eDqmQk;*FV8}Mac7h8F*OoRrdM46XI zZmkD(i)akdpdGf$RzbbTG|=R?1he)4)WCYcV{iqq5f%Z0Sb!E=peYO7mP>Oju+>I& zy}C_R)RZT+HfQOCtIig?Lz}Cbj?h%5E0sxgrKn#3*$2_Os572RL)(LTemZk7&3~0n zXRrM(+b^A#h^U&(Jf*H9Z0us2?G}2EuB~DaU>apn6Pin`Qq+JVbVYUPE=^yBv~6@j z+ehf~8K-BO!d1pm&|@7GT~mY$G)^j!>wXICe77>c;MWq`|C1;QHTnjtC`etMZfo>B z8PW4(#1Jc1cZ2e?hbjE7k{L0o^lCh0FPFTYjJ%l)$n zH>Uo}dilpjaa?hH-t6A(`Sxz__I~d9e(c%i&W_hVfV%?@4tt4#K!W)Z92BRuS{i7J zp(L0_O`{U9k{Buy2oQt=qP81}qNpvwHq<6*Q_%uy)si-9{70jxZA3|w%1P5kLY&2b^-6XV(%rEstMohYG*b z15zYitJT$!WH64^U?>oX`Gn*UT{~#opMV5b`c+p9FM6G%sy-6aIA1JO;&hi-c_|v7 zQOS!*wLIpMBoXC?SX);YoRx@)$@2QqKjqvbIXNX~>r!7P4NMtqpOnPg+J z4QUUbd$JnAtHLU{JsJ2xIUXPk?n0T>?+fB3z*6^IzqKOHB`YiDrji&2@Zw2enhy#| zE^xAA@!WZK`f7M=J$}w-BV#|Q?%m$?`lcO6^0}UP@a4!R4xWj8y8$eH=g;k|ddgC} zX6D0Rda%pyZFY72{i{p9c6mNLxnfIK^(>#i3zqJCc+I(u7)!oPmeCqRA+8uEr0{Wn zAdC9+W8EIi3Ya*4L^wn41}I#oPY}yHr~q?uZYK94s@8Vv5Ik`D5mWhHL)ABGqu6VgoPL zxQNFi%P1YKrG9%b5D14$^{5gGMIupzMU(=FmQgnYK5T!eiwydr4u*T!{z$(^MA++z zz8Nha=L7>-R1%fc~Mue7anUo$z|P3SRYM$>n7 zNpe{QNpOdW%jygR9@5Uvlw6TXWzy#6LQ3@eQ~nB>MNAI2_0M{H_Z)h(C6cLWTYUL4 ztQ#C0?GC8~J~{_0|nPpSqmC-`#93F0N)`WmMs zSuEDLAUH(Pw#QyVP_d$);~11>j|cX6iNoo1%Uiv6QN-!E&}(s0VzXIHk8P!b)k>+3 zhnaE>zQ-}MG6a}d^3;BstbWE8P3qZBWVMM^n@zKYXH>@IYy493q=J1nzZDL$-yj^y ze~bO{C!nK`zS9Ta$$!6ZOzX?$TAi+p{*z!SJ>KgN%(@gbhe;CJP}289byQ3*iVh zuG2svFceD>2_XoL8Z2sn`y>Z}Now1+rKaPcVhTbA&wol+8gmPhk#PnmHsYi23-8~7 z-@QVwmmUxfjN|uqVY}A^_6@cTKH6eynTEkdgTb9S2WBYNt}z)8S2c;?4u;>3Dg1{0 zY@J17WfH)r$ZwPdk+JFMn-nV*(gAI${~Euig>Qi*3cnTJHCVw#Vx*d6$r926PwQeg z9O3AI4JgMA(WAPHu^B-)oULJ~cYEKUJ;Vtr3DX{3L@b*x07ppGnjzZLzi{E4pX1|l zd|XAAQPWw>TiM-p+U^}lF$zY4=PfO36RVOBB<3a3 z$(f00B9!ze9?UIO$?Aq?6_zc=+Wq%pZEl&Sl1#;H6>9InT74zfB38FbN^LkX>Gt1Vk)|R`dtj zbbp=D#^4KBoC^4T){64vTpz=eIhk}NhAqK*mq(Vn^wMeTGh-+7>yLNt>V5v;uHKhc zEm{!QYRYpBWwrF)84?A^VGZhd!-wdDHeeCMSzXV3ro(zy%W?X|gM z-Hr8ijW;`tdl!c<9NApE@aW48^>qy|-Fd4}D2yT3whA@KwKEK^9RVHMiK@HkV{(s7 ziR=Tqh=RYEZ96gqiTH2ON4Vo+ge{4qET{ii0}n&{$y*5g9zg z%nCEnwoS`SGx`hAh&IYjQzY77>Y^u<_Bar(DY%Nq*QUldh`ef?$hRPo-`7t;Vx5hQ zCh1BfZ8Uw+cv{k3a=KUgM54XYYZ8@^=%h0Sx_gT!hJTr9SJ(udIJ+v{4L#0NPWqU0 zr<3YVaN_!I80&Kunc2ov!wXCV7#3>G^%YK`1?@BlIH!SND9x_ARGvuJ3n0KF%!n{$ z#9V3NuNXpGi>!Oo|>aubX=T8$A!gF z<Sl%;i&L02nY(+CpQJ_?E*{@JVW-bJ!cpsR%^>!;GhLy^GfbgwOJPRaPD#9Wy6Fv*z zmwn4Bwbtn@G{JLdp+fgTfH`|-0D1xtFeebW<)AU1xQNA5d=j%u`xy#WVz(e8>c~m- zAm7BWTfv1Z^MG?za_>bOZ`os*HOzd6N zNMj=sPzuTC;-Eptm}>b~=|RhRVkOIUpT!Djj+}Q5-7-&fZZ5SzkE74Fnn4{_{4!YFw>cq&(LX7Vi+^&F!hk8 zU^5Y_dUrW>2&Sgz1rQkZ|}SJo^vh|lHzQh z2E$>pB=}Wm71x84M3;UJe4_(9Yw5f`uI2M_ID!^Q=JJ_jl1eNo>Z*4|@w1z*Ucd0c z6=B%`)(Us2zaoE$yeUG<_s8xScXxetdK+-#%~kT;RF%?N1)%M}gRUMO{1H?KRmj=b1ucZq8eW zJkT4uIbR(z*_1l$A+9>?#c(iNRmMscALT%OF2Yekgn$q8dGmFsz^I zbSH2FB7OnZo338Febjy%)ueNADiXWb*WKIF+lfiRa6POucGagy5e+X?7WgY2&cxx?sNllQ3rw$(@$7{-hlMv8jXU06W^@O2*4Hl&y=Ev76vbH?`C zVz`wh%Yjz0+0vr?Ox)^BWAYl#;?_a$SBu|nAIpu6!dm7xjpxRw>%OLX$y@xCs-}{H zh{dia_C`874;*}^RWU+eiv@kHKRwlL?no@$V)-8LcL$vTH>^|(RNF(SHV#7AW<(^w zea;T;%{~#}7>P+?v&v)suh3WE%}AFwp2Y_c6T<1S9H`;3JZ@CmV zdvCbs&NZIZ*<`J~Rp=z^k%sK3!!X?d{ta7Q36V0K9)L3>kj1hq++mY8{44G zffYH86*H&}qtarPG3I62%#*N!m1U|V-xSP{6{~riu?8siTC)@X8lu3=46BtH4~EPZ zW{eL}=mlf!Evr@R2!sB}lGB5>Su0`r@|hwC-%c_y4qALPgHpP)xyI34qotCpmC32F zK}@BFCctOx!L&0yc<|swyr?ilu0L8s8g`u6Np9wUi}e$QJNe(g0lq>@fqxCYD(I3i zzudaf`l9uM^^Wd>(f1~gmQ8<* z^uGek2<4K26{h%LFaCWB44Kd0hShaM9WK~$S6^SB@ZO_)ocH06AAQ965Mg?MIb@Lw zI!(@)IY*9iwUvaRa3mxO#N!URkX%_At163Gt63@7SRJ@aMR1=f5oXW?0pnxC$8rIx zz+V+{hXvA%!X*JS&WeZ`bUYIT-NA+fN_sQWd)&(DeFQdtChop1KzeK0Y0zO<0hgcMyEtT5HteR&m_?ZEzP6-{rJJa@)x?kyX8l} z+5PnX!YSN*==Iup?dhGb^cAk)!-eO_kzR7d6I}GI!nMmIh4Y8X9d9(&&bxc!mH1cSjDp|s>+PpMk5WJ?4K5`RL%4aYKVqZ zWl*7((dShL7;2b4SgvAKpPFc5%=TG0+b81;HcI7EaiBVgc8*Fr(09#nLevJ6$vw$# zOGAzg^ySSx(YxCBbge{92dBp$w=84YHy#Qf+crr$ijlAev%G+WRus|Lij*vBt$}L1%*U|k-vP(^;!Z+Pu~ zw`vdB-bcDW#B=Xsf@F8hOyf-hX)d-N%((Yo#;ZNHsrw55&hOsqYy0|j{fHmej_rit z*bZ^PIDW*z7fJ^m3j;w3*|1Qxk_AdfL(97zDl3p}Y=kJN9ol$k-C$cQ@n}&<*+5lk z+32KB)2N1u+CRcptqtm`C=w!ec7E3mq^zsvD=u#DSGfT2te zAAJ+PJFs-)!0OxOKbHGo*Tti2zA<}m`G>-A`MSli?);O(P-+sYmVUh1I zuh;6&NkY(|Mi+-V`PKGrzQ_JaNS6*mRPS;UhsVl^m_xrPdi++2Sd)PM0{po$CSU1z% ze2$A?BtF$d8wl|U;N?5NRq;#X%rD^}3#Y<-ZX&~7rMpkDyG}reH}HK#g3#*`9%k^> zA*;%gk&{s)KEgf9b#r?;kt2y>vPC)l?2;9$Rd=my)JfDJ>LgCjb9y2G5vW0UgKop( z}1s46iH-CojV%xDa&BlZ$@p$B?)Txl{bY}-aJ)}MR$7}Zu)5nM(g6Cy(q+kKdFdZUB`k3mJLGkCrsPhsrM=cTJ4g99(o~0^{ zGBsKnD~{MoB{^FeELDx>k^P+P!;!;E1rrFpMbhg)?$1b9sV+uZE3Q;Tg&>AqUR|^R zA*JDK3m43Hy%;#S@5P_A%{soK9`?|i+3c#n)JEei^AZo)Hm%?K=*lITr`u=j!1%)S z8r_HS#mQDxuGiZf^|lVHwMKwQ3!c4*VF(ym6oRTL;Ek;HZSv8A4}2`X8jQ~y0PAr_ zG!)TCXMRY$QC|e2#M?9#$#%cRpp7BDmf!I4ItGgZGRb<#Bt#;2Py zyfecC&QQE<(W=FrCYMEDvwTUuEmLqGj6S!${|Ad6>RNep;J_ev!kVwCU7DVgr|><< z#~bE0<=h)qKCvvl%2Bg!Vev=@6 zZ2Yv537;W)L=6*gA`u&-R-4Qz7QzALo8pp*7xbdvqlh2tk$q<+-i%~aZIUTR0fI_G zDJY!M;kkqf3__4J;6vRhFl<=!4gr1>35Jg0oCD(*5zWc==vssH<_cnUcAN+ z!NPO#&K^eL@jNmYi*lTixHLMVv03vkETx5fWlEJQd;#stU0JgGo8!;f-m3CyW-ulP zqtkeWUA5N@N#O2R!dJ0ugzxyp-E*zgT4~qC<}uDa{IJHk{=JNI$5tZevO3e9F|Ou* zEtU98w)4FplCV9o!1`2$gwM3s@4)e|;qlWd9v-3qsG%AeLJ*=+Ij-d7oU)2^lYNRo zQM#3_3Q9}Da0zhK$#E2c&>#u;71{2w_++~xd=V3u$s|!J2To__+J>gcaY`3qAaUWRdHgFASMq$k_x8)rH8BD zg+pb6U;6XA=ayD5;D*c3!{MDhJ^laqlAIse1vkp>jYmKSV)+hcI(#qFvq*-tLGtxP zJ5*^NsnFc+lC^ZU=Nn9}ImujuY!`UL?A)9ddxtE048joott#305Z}Uc{2_zF_T52$ z!e8)nyZx}%zsXOvmH&|E_l*3+fa^G>*&a+{X{6@P&9mbPP!)S03!jnFtm8&xx}ME!L_l=tSJ z?Vi?fiflbTnjf*Tc8@D;KjTx0&riXDXynIAc*WS}-d=3MQ;mt?GQEuc8yp26obx~Wn6S3I2L^Zb^c=cX!S%*eU*o>KtxcSK0Br2v_~Ff{FlBN{ zb&9nD;#e!Gnn+Y-nMp-DTTNMNO(@Tas>#27Hkqd~v6z2lG#WZ|I$?uD)JrC-EyQy~ zrm$7^GmR||P2Sctw#?KfyHjRjk!eTVn9zKic8Uo_-1tm2GT|s6v!6K0`dL*HvLeZA zIx%1AZR{UaqAfob$2M0+364mi@JiRGlFax{Ew1`gr%rL}N=2F}T}3f*<<0TKeB#w| z?$z?Y504XcBu`HMQ@9|y(UHV7NAh=SfwiRR9Ezye1!i85k=3S1W<@NP`Ef-xJ{3D2 zqcIEViN}jwDSXNT^fmuN#?K^QuRMi}U{bxP5HBYn;b`iKQ%KyiH0WsXo-=r5zitfg zY0~bwG5IdKr^s1UK3{zCc@%v*p!4G?6_zUOEAefZip=OzXmI@0@EVF;N!@bDiAt&b{ZI-|zf>ZLXr50y_nfUHRR@i1;8xZZ1ZW zVel7Aehas5lgqE%*51^FS5|%P^g2HAJUlU5c;|xGZ?!k2yW!Uik_!CNhSDG5|6sPODV0J&HiPX zr+8+*KU(Yb!2ZbWJL~{qy|Qpq+yl4?kp_CuKDfzPUq6@>xKlN`CSj<}Swg*&z%fhkL9>f~zvH*Oixt;yW|$%tM=CM>?NA3|jMWLrKe z3-W<*y>8-D^=bsOZeqO7ou01ZMm>yy5xqAKm@=FcqHL zur$Bx%H`i*djHBrXoSK?k|{nX4Z}2Sur<~q2(*O=VFw9`6Z8l4c~bO#H_-cW77{vQ z!HD=P$vk$9Po}#d(w?%{XshYQSCS?MZfca@bN0ad1Z2ux3tbu+sI14Q=vCzLtEOa$Z(}sX7l%DP2 z46;xmm+zNU$HZ)o4~1dikV=T5UXgS|4zFuLmhOB8Loi2vw|Iv$M={5T>{;l49rxd# zU`buoU9~Ph43iiC=#+$(RPwWQ~2|mL%`i-N8XdI~hGPv+rr`KVS?!*8D z3)4djtZ{ad{9m->P$NRarG0tqnzg=<2?q)X3#!UnbHW5+k^!lRjTPX!<34&XPW+%7 z%b+55X1mudYHwxv*UPXnnv2eW#X-l%2M*UQuiCP4x=@A~=9yl}^jXv}-o3r>)+&G< z1-ogPD=xIuGe)8@Q*y9iz^ovy`uaq&CZRQAu{94CS_@!lG%PMwiZ8Hmu=v!j!cq~9 zYT;xo5OuJ{B#My)TL**rg6orPVVcLo;@_OY2vQg?ILRdXx6O%*k3m)Cj4bxzf*W>f}J%SVpSBI;@f)sJq#Au}sABGx@ z(Xb~NBPs0Th46E%-Ot5ITNOw`Js4o%l;RDsHn34p`X(0Vg5}id({%dRz2Dt>VE^-% zj;$KZkI=;@UTaygZtYV)dpUoF{xttB_Tq8&VzBmWJMvdAUeCXEBH};S*|Os1nX`X> zswJ-<2i(1y-z?tbm~Jd#^bqg>V3g7T%*Q09s%r+L55r!QlsA^9Y&)QQp{-NZHlr3%-%wez+NUy= zWpjlw9QwZUp^uaIVL-UaCvSI&DXzmQIMbOjXO-A2Z(+`pkaHo|8qFn*uo1Kd?5EVt z_TUZO_b}r_uxr#=3;TPD`wKhiHj+k7;heAXoKDnQHRHrtcxSXKWI0i}D0K~1vy(b$ zFUpHlYAeovehSV@KJxM?(2bO(8*Ff71B?uSgVE#-oLgiCnv@Mts%x6cydKl1xV&Lq z^F&pp9vfIe35*R4i#&1(tVARk{$0cVjVe?L`M$kKmzK`V|{R8`pcx!TU?++7eL*LkTx56u6P`EbRW;Z(9i7f>1su6(-tM~Yh`q;2<%Ex+q z)TgNgs8;hds0t#wbm?i^kF=_Y2vtSqjsr`9Tv#jx60G7XmEyl+h+kOz$M$keD^Z0h z>%6OWA)Mz3GL7N^E8^Rm$-wV(caSXccUY3#OieQLszP6yp}wK9dsq%CvU0ZTIIeit zQOZ^Rf)Oe~i;SrrOA@pBGqwyZF4>wNztVR{x>G;`9TaC7JmYDo>T6KdVkb(J-XNqF z>NzOBEizGf0b)fV%MSCfj?$DSF9DZEc)z!nwDorAcN_axo521p4(MVFXA6Hv5)@Gw z`*&+cGzOIUwsu|nToW`n;R_>NA{RCCvoK(9aO7<$A?a^$r}{D46{calmL9Oej%?w5 z4&3l83RB!i%s6VvtW*If{Oou=V;^m zKcK^qqt31nV3tIq?DHs%3Y&qL1Qsvjl@5$u4!n}&xi%JK$w!bY@f(4eh-x3U*C244 znBwtsB$G+;_|tH|b3AuPsqP`jT@NZSVXJ;CVOIpK1Spq7T)8C5lnX{b1Mm70&;AI$ zYx3g&!C3l6a4N`xfO9Jdo%1BGY;dl!nYqk~+00Y44p_C(_OY%w{YShIXMOR(IEzE_ z$LA$4dA#(z>{F1v_5v+x49I(OUfyD-Z7+Nxe#&p$S-P0BkskPA-pX zy2~>`TcLMX+nQS$kagF9+f8IDXW6(NaOxXeF89Fy=&sh-D6T7f@15s9W_M=xHM6^( z-5oz5*a?R9Vz4Qmq!?lpilsmlpf0NzH|CMrkQNoC2}UIeA}Il-qM@k*Nu!ijK}m~^ z7k(6Kp^CVriJHhr4z#GXfJAX{iQ6Ovk9+RjwIQ^Xt-EJ;X70UnzjMCtJKnn`fml38 zBqWCmqznut~`IquBnGW(50+%TPZ980RFI_MRnNzNBk%Ue_% z*@q}==#_pvDap;AX3)2f86iV3##D&?LWvoI@m{~ef}6~SNk#S+Y4C|-(E5=GJuyjP z-bzYK`y@^}NotXe=l%K&9NPFTVg?=_g`-m2Mn*2HtihuP$8@VCTlDalZm}khUP4+n ztG+|&x-wQYuFOZ(YqaMJN5Q#rQ#4*r)c6AnAK6^9YuB;9zEJf{>yIZ|zEQJIdi9XH zsN*%#{ydg8yFYq<;>G1PaW_{eEP29ip7mYG+*)AvldRh6OVt*HYRgf6_1)i1|_O-}NY1+MTyM0TS7~d6lQZv1ii})wNmDxV9euN~y znm2{Xk9s3Xx^}|xoi=ga#HO~23US-&;%vno3{3CfBI<=5%qh;6o?3b;3zKPIl)2Qh z$}w?^z5zP}^}z2^NA?ytGVoS)DyYZmI~+MBbC?0V zJof?HO2cZH1?cw zOFG!Q7gyUez1lEa?H*8_phL}IDmXhxt_3H9B*+&gUuAOyzp^&;5kS?i!|L;)?gaEh zCrLO9{HY+T7=!@FC5}%E0;(u=jMt|+#*hE2W1L_$1HoskW=i+4V7#A|j43vrzs?#C1N3C31ilQxP@x7=A=(mp1yk{E|vid`i~6YA~gx zEvZ3HSS!qR<__}(lfMS3Wr8?xoN9SI$&QfOp@gbLN&)oUA^4QNvPk)!zA^+~GS4ki zzNc?0Qg2?x`VO&2Bs~@uSd~mqfMhg>|5GK z=hS|EyHkS=U!^98GC1f}GAP1B6eAGnlA1vQKMY|Zn!yH!fzHB)>YW(O0cvXtsVI|1 z8jN-YsSl&7QlMj?>aJTO2V&f#a>ZSJ{??y(ooVs+#aj=EPrJnvq5pDZSW_&fM# zZkzin_f0o{5wAUR!~Gp@#9>%&fjjK>ya`5yL#rnLAS%LTa33a0BUBH2N)o4psY%u1l|yYL=|RH$b`6$W~PuANE(K2;gE1xI3cS8d1URJ#^F-nLKMf=&IeU)AfPRRNu*MF6tA*m?$JIxBo1V!05Ywn?Frrvo@( zW~L#hP($HCyoH7oY-qibI095 z@6eDBH+}hYEWhMEA`YD${4*yG4-`J4>U%%9{s;L*C=4iuomSB!>Z)B&mXe3aL;N<+ z_w;8xURlB|u_fk`vX<1^*h+I{+1ga6r_=XnaJ%R8q+*0{W!bD$uB;)&cggt>3CWzr zt0EFbFG%lCf8+H<;G<8KND~lz!u=Bv)9Y1*EWxncy`;Pn6{`KD)#x-D(WSr@E zv^@OYnN!2(2hW@>Ay5N696~AljI*;*#}9kg_*Vrxy`BE=r^IG+Sz=jgmAJ+u%!tfP z)ko&1nj^yRIh>6yFcu`U*4pIW(6gz7+!4K?4@HK}3(29>75|m!=l;*5`X;f<+wRY+ z?a?lyE19>R3VGIv>%6W0R<$*{&RCOdwPcZtaMju-|3*~^5mZL85;RF8F$x}l03S{k zp(nWKIKp96t2r83t8LPDXfJ5IpveIT=nVy+7j-fYEsBgop_6HmXjC|4gZ?V3rC-OG zQb6#JUZ28()6TMr%DP$^BUzQxGWQ>@t39ZxD-Yjub8~M9A-OS+OW+E`ki-fSARz&P z=DLMeDF9ADvA=KXtD1nyOT<>J>$6ZnnN`tI5Uti$oqf!#T3rML2DJ~=?G#<>KhEsT zx>I+HtZr-DU9DSLbKT!L5o>ptFu!w>^ZI_T?^C5&jgnS_J*%BU(oBPEuU5o6Xo;7# zghOl1*vr}|()YA}Ev-#Uc;@Aw64u!gQz-}vZ&eD~H5KO%M@@Tk16W7E0bU+w>$ za=5E@-?qPhDu?8+kaQD)2;pXb`FQli>2zU%LY>n_33!WjW+rB6Uad#XBk;&2+PA z2kM}=s|Ride1rSOX%%qQK6xaYj6uWQmMpMU6%f5oH!wDM5;v=1E8pdF(ezND!)o zEdnE)aOfowG)q{jh&+Z?G!tmW5|I`?_As;<)pS=AfSCmF!5>sJ%xWjQ*gXuh8-MNA z1FjUwA`at5a>i%+$t09F!{dXG7sN?!>*kdU%Qmdl*%J6YZ>}!dy}9++x95g>_MPs( zrZ`<62zp-*0B?LF|COa%SDpB%PLwS%x7XeWn6^jz3T(911$`Z0-^Y!_r zxx(Do3VNaPHC4I(HB(Tip&OLds%m|;X_a8q(X^T|i(DiUbu2GNah618QqU1Yts%yD zgyn#7i^MJ%H%Pr_a1djhz!;OP7^_mIidoHUVHloCWh7>DxR>c+BA6lcg_N%LQ%Fbc zfoq?bYDiQ|5c+Bo>uM6~Y7*;e66(J1iNOAaJwFaN6j>AW))xk)+GJ5sK$eG&^Nh#1yCKw0BQ5U4C{IiaHG~#*$ zR}z6}HOGib_8ks!LrB*TvJL?px?W_bF|4?)(qT$P44JSkFvdt90OK1eQmqC{g&~3Q zkHiCDJd|c)Ja{^R#@ygKeT)8{<|O(U-9sy==jPZ5ibe&rD;Nl_Y5J)yj0N~HCVe>_Or8!e>#VQ$~f+=t$AciUxC}35nD+F_NP=MBy|x zMQA-BpF|^DVnQank;PaTF&4OZ8Znz88EGV3(g?)E^RW>bjh6UC9d4)iI~@*0jE4?0 zR{T3K{w;|(L?j)ebi6J>m#SlQX--9=g~t$D@W%0Yv4wO@i-4C|w4`GKElzWIe9y6$ zr__aTm+(}m3CM~*3(_1242WEpKPNOs@;%UmI2P2ap!awouc43{S(XD_A>2F^@;)u2 zCUoES#czHcw{ppzzPFd%?CTwt&m#po_0HLC1sQ2f_WSwrUk=~5(cKMi&0RaOcf-F% z9da9LK`$ff9u&QDFbWC!RU}-v!KZc|}{BEVs6T z`sxAlTLRtMK`}&qG3XPhp;3J_(n2_Ya%PSbCE*%hPIL5O<}~oC*QJ;YCXcCMmg(0s ztM%-ZC?lv1Bch$G#yEr)Nztsxb5VA6o00Y-qaCGUwP0%6MHEvYrwE|sAK(;zki$R7 z!POR#hD8ModbjB*zyNL-Q+;{c3w2V(n)KbX^U4;%Ee_?sFvDN7N^U@%3-g!M%Lf1@ z_mgqeK6r(fnoU)r25DslQ!duV)`;!eoeOp>+P?U`*WX{PW<|A4=`xEJo5^L1O}2Sr z@-4rJDabDHmnr5k)rv+#wW}s|S?M}vvteV!<^`J;w=;XRdknkH?eROZx0LP*?yfu@ zH57FzYSebg?u^ltEwmaFhv>nxuZYu&XB7=0gJhU)6g8?@TxOidli`b_DE%xR=6f|< zx+x+-A|FphB{Ez!XV?ZjhT=!gK;5PU{=r%68 zgkXR;Gg#9F;O}}tZw0@B>2!pnfRZY<+EQO;#q#?I`&AQuC2~ zB)X>Tn{BU+-@B&d;?a?jZO7hQIH!4=!irLoH8EOY3K~$gHm)elvZcs>$edr6pd4;p zej0g^d_}A+??e>~N>hA^iG^j`Uv0luP_b2|Do(DYKU;giY7U)H>O$YAZ(35ZF-P7W zYKnIxE0wN7FIxU)Zc0u{!i>dJQ#KSA`Eh=fP#P-7Vy#A0}p{Q48U`Ip;@ZFW^TwL0%5{n(?IZJ-54RQt>n2`Qjuhr(|Nr@TEiAKneNgw|3asJTibt2( zY*?Xage_;Lk}a18*Zur_Ap>x1FTx>D@#@`c$sh02kM7wdvW@Rs=_ z;nR=6>2E+Mq0r>f&z|pd0~`(~Jc;WG4z!i#H&6VdIlr`RAQ&DgEo4NCGn2ZyKkVrE zu)8a1W^(6#Z0_%b-4Dw16m`l$vil@3&o1Z8fXlKRhWRe6>OQ$^*U9eAWV{zKyOe{$ zK{%#mV!S1cf~~ z6GI6NX+oO>P}~M+;^xuvsLR8qz%30j5AmqlU@U_YLfR?{6@sOKK%x*CQ#ma{khIu_ zmNpfn4*^9@8!5qew|o6(W_R!G+AU4?cJ_8>{`uygZ@&MZUEBrt+Iw8|(fcI>~7bbEh2!jq){+A<{#JaNYij=1zmWq%^Aq?1oQiF17sK#i(h5P{9FemSS; zb^7Maq5w07jLP%8Nc%jnp|+-`ruNnsCeL0sb6TjF z<$t#Lu41YwOl2C=nW7ELADTZTKQCX=!lBQEs5UBRbRCS$4c3ujR#Znq`FNQy0nhPx zY}yow8U8mc4gc2A@{akiLbr%(wsbHtCm~YaCp(82u%y7FhS$K}D&nKgO2 zWjVD0^5eki01dQji~=c}OvwTI4yCkR)wME3&B@DCbe%!b&_Hgks%jb~BZoZt4M9YW z*!b}G5x*0AV9h+chQBx3yc++-W=Jq947VuLQ`6Y5y`s!`#eV)Ep7`nq`vH_`$|l?w z0{}6D5Th)D*Zt%?xsW#o|2z?|B#%*$Wqju zYTNXfixe|P$nO-9vPH_pq)SUB(&t9sHGHB(($3z#C6Nkp=MK?>C5V*1PD5%3?ZkBh z&ZOFrxLdtULl#%}SzPGv>vKgLW)O1LvReYLee?jI%SO9JJ%jzY@^PwBLp@_JvuLN4 zG}Q`@Yqzj+x1Fy}l$!Q(Hrqnz#0B0T$327Cs>F^2=|+pTVr50rw4`6G+->LmW2`*& z7Tv@9E6v{c*sgp1BZfe*mvJ8vBWZeGcvb?&;C>*E-J&!j5>7@~2@Z5QR?ziUz07A6 zvN)8-l#3;y1Y6vvR^gR5qOi)#Sb2EDQbKZL4olP5NuAoknnm1zr)9YcVkNpPyW7GK zgVQ*Zn_?}z8Dn8Jyj3oWSQwWV#0!WS2gMJWVfWh0BsuB_)_E(%cNvZ;*3h%XRg4Jyr_@_vaHdqQt9U*axZV~9t=2W$^#`4&AeZg5( z`Z}O{gce90x{@exEpND<6bdu$Njq`IDTKR%Yn8Yl7^c$J_e89!R2ZvH9Z`tg?Tn{e zkQ8+mVlx!vE}>WCnd>Fs>m}%FjuV58AEc_$8_tTWOyM<}#>7gWNjlg}E=h$7S2!zt z^@K|EJP!H3V#H_zdnB2r6G)G}!P4g@+AT4FvPLM0)CpB)^Wy4Ts6_C>I^8I^k+GEC zup7xV=|K}$NEi=7N5WEi663Upc~-J&E171GIGZhd13FS*kvQv2?y|CCC@-56KaRXu z61<>bqy}WnWqNozB$u3Vt`>!~Wu9PuABJnDx-HQE%kkwhr8XPmx zjv^8|^`qF0sj-p?siamSDDybOL0yITeir(~Nks|j{P1`E^!sG_DYa#|+Cp918%U2U zE*Wu1BkM#;QDRg^zKCSkPcN6qXilB-GKvUkKDA8d@%#*CDPO%T!w?s7 zF`^N{ryMKk2scTbvnt0+?vix68OLYG%~4*~5jo0DJghTS&67`7?#s*8q0E1RP97Jo z7BMiGKL%H0zSoENBhl}2DlInOUXNY<;kb`-$V?tB%#IOXqJ9=}bE?Rzt^_>2_Ql9j zK_8Y~_kF6pNm%Y&6d#4p#egvPhex=KF3G*jgzTn>b{qNjghI6jId5NeKE5Utq zGbCLhu*L3cc)RZk<%+M36@A;#$KPko4BHq|8s-h|&dl3rcUBwyduG?}@uQJvD}(m< zjm7Y^ljCCQV$}+9uKX=J3S(gcOoA9xK{eFEY`6~|z;A^4@F+Y6--K_$Gq4OAU^T48 zubo&hTILot>t4Tu`tYZ)f7&$3zp#90n)V3(ACL3rUek1jVi{(d%6t4j9_P=!8SCBw zYX`yT&D831O@73)u4bGc<{i{SZTiM1X4~U>1N;D*VH@m(A3+PW!Siqceg?0=A+X>W zoP;-_9exSFf^+Z=T!c$-1^xu@!{6X0`~yCOk0A+Zxn5NR6m^jLO1BKw{%QJ^^{eyN ze(V569|R}-f7(A2kN4s!mNp^o6EBMg_gUQVBYEIcT5{3&cBxS)$a>i(LBzfJpMZB@ z<4Q4GV1qoz`yPYY4c2Ecdw_}Qw7pC1K|RlaSuh9ghk5WYEQGJaVt4|cg73fzSP6}= z4ouhtTVOl<5T1ip*oWU`KY^Fw=WrN)0k6Ru@D_AHC!B@z@Ehoc-@zZ@D*Oem!!7tH z&sou6EW7YTTp8_GV!?q*G*~u3eHcN;_AB}Tb}H6a^{>Mc!J=1YunX}%+OG_Rcc*r0 zk4JuDTo(6nQ=aj7vNZG5R~Ef~Lu#+-+n_yZLL)B6xS0i%{nWos{jIYj?(8t-HBK5$ z#PF|~qt_hxAtRyQL5vZ0AoJ|%EX4tV-2lp$*ipWd72@u=n;lI(#0!c9&l!4}w(~ar zzM-dY6WZ=<#CQA20NN>aCs2S0!AJTweOuj`Xyji*CF!f$Idwa43s6#`9!e}!x7+1* zIq!#Ur_|-LO*>^zx2LPi6OD+}rynthc8+&T)X^^dK7dzYyAovy7>cf+Iq)im8=T#*Cp$8@iet=fp|JY3gcNe5Agot*yKM2urN$T7`9lo?Lx# z)q_ipE@|uOX~RFneij*6z`Agj_=d$_tVn4F@LAU7gcdZdoxh-|iFKvQ>G7ro^Vjl6 zv>%T>4=el~(!d?Z>x-QsRsq}_U3jWROUH0e$1BZt`}Zz3p%W(vZMxX-m{s51wzs=p zyex4SSD)Z6o><+5E?SSbb$7QtZY=>&$=>vKtwq_4J6srdwn@NW=L;ZG0*1J6ds2l{stRkoMr(0)I=At+gEWyG{539eI<8%FI!NucYoyk$o>Ur{JULQ2 ziCp*Y?ACj}wr}58Yb#owsNYRB?7NdRV$T3+M68do7b0Bc2;|>vR|!;8XBK|L@4NT@_bql>j9Nx>`$C(V zLQBibF*k|C6m^{m<=JL!4I1tgOWd5jL6+6I`<~`k-z^xx^c~A3tQq+b6Q(- z-=w=^0y+MdyMyFPktAk=+z}*B7Zti<9IsF+RiFZ;N~ywWRU`&6h(ux>Qw;_q7y*ws zxF#lAzykbn!hN82W>>V&g#M(*%|L%WB0*AV|8XD%$UKUD`#pdc!c+bd*bnw^-%?Qa;~g9QEp zaaxMvUMAQtOrn7uZ91l)i0&hT@kFVlUBzkClPXn^B`(n@a@LCl?`2{l8KkKK->kag zoUO4i>%<4*k*985-_TJz3g&GKiuyVx^Buac>WiOurY)#jSkiK8k$YI!pS~|Gt$#l= zdG=?CbL!Eb1&h}W{l#OS46^W`3Fc8J7<84vRh+&)V!S8_0wIG@$)_BhHFC!7L}Gp= zq?~?#-LV7nt(B2}Z8bGV(+U*Y;PRHEt5bKxhM4K1;(+mo5+63Vy*ni$09mCv2Iy_bN{8$WyfYUK^f<;sjBm0mVC{(w zx~UNdR;iLkUid2u`{e)gLU*`c1=ZZFK&6&5_0JHFV#{r*2o~JiO3kPFvp|^3~e! z+Ylwp@ql{3%)#d=tU{g{<_qrbX2b~zQTR-VAv`gBY00%lnHMEZ%Pi8_J}F+Y_0Yzg z1;Z!~k3LSM!9P^Wa9ySq8sZubL&`BkwOZ~WX zMg8I0@RT(BsWEu^<*T2++_Yu(=0)ZEz5L1k?vcwIcI9nc#Cvc!h-;3g%zEY$=KB=% zAts_oeBveAY+gX?Wpc8R)_Hp3vCHwSQz8+Bhn?;oB3>A=DWp=Aygfbf=q{59|K7JL z<#JJBE?r8u)7R)8nxUzK876}0a=hr2BO(f~JEfk2@KYzRi^6|9d20AOmEa78 z9$^J2j0j#?o(E4Ig>P+Y2`*&;yNV?P*ci5&ZDKpvhpdPdcfpiSWI@oQNc1Rx@Q-WN zuWdd&ZGx85f%I1TLtM4CVT^nNl3(p2pOAp;tFXTBF}>L3@`-22UqoC$_TDxxyyqd$ zGK>J~5F*29GU0h0bq*SFr3^9M7D5GUg3P3Fpa_Phf%%al338a;7LD_bpXkUEwJAqF zRPvsEkVv%-g2G#s6dPkQv8*LtOw~!v-zF?YJn!evxgU`SVv{HND8fEIim(rGZXqJ! ztcZN4V6OH&{vVKZqbYon7f}76YKUJgk(P*^(nrX)P%j8uY%obzTU9~BV z?mDg3L*^CWMS9g>Rmw2~I#j$0jVcOM@$jH@1KJLKOk`*mdBvuPjMT3r{D(EaCA=a% zrz7t!D6mOhX(CViAWu^+kYsL8v`Xo38*HPo7gbE%~KE$U>b`WSw$-;*QIuNxtF^^h zi*8cE%_EQCPR}QYuU|Xz>#w$Lospn?xDxX=|4F^7Im^YFlavy#P zCx6%5d*){E?aPggjm^6o8~OcF<`^J%Vyrco_nU12x#8fa(MTjxiHDzBE71^sKugtN z_4D&(*kSK3vep(Zi}3Xfj$|0t+vpaduQC{)eAPQKjE*{%v@T%rg(YotFmZ~k3K-Ag3ta9w;s3FuPEkTKH(M?nS!#8{bJ45 zM`fhxWSu1?*iRFAmS6MuUN+aucir(R{*4))T)uLAYM(r-^GsL47i0z1 zA;opR#aqWR5~0EJMMW!qN}8V z2o?I}pw^TZV1X(v3gw@A4oYiai4wHp@r;aH_`pMA#M z@cMbUgAOv+Q9s?OPrODSg1&#C*bDXjyUE~jeJ8$V4F5jjHxa%zchF19u~~wC9G)1% z-#vzZpYN4K#5wGA+EHL~=NZ5E^?jdx=kqydUmPbFrw*Y89Iz9LF!&g- zwXg(QpeqaRSOxu>&=OSE!8Qn!_*jdytg0%iYAgNFRxzotVzwmR)F@KBX&-`aYYQnF znHpLOOO+v-Z7|z=p7TdS`_Bxyd*An-d!Boruix(-FYk#mjm?4vPHU_=t)r@6h}HC; zC*J`5ar{PqRdMwj4IdaxMDhlQ4Yd4yWqX4)d*_+!V6P7Bk+=yEKuN6T!> zzxMM)P5)RmMzi-bD@HpYMngg~$lqR$DODlw-2JqDc0X+iRmJ_Zs!VM^UjSUb;^xGf zN>2Q)YHxnK76NLjm^<&z1SN?X z_4qwIiap#A_m`Uf3p5DwhT|p7!g;QKXp3cO=nbxRzKxNf>e@-K(|&uPwSMm0*7-{V z>H4*SRrU93J%R1oqXBQnoQ~wGIjfQz=4?oQea-_(kzXi0B{74v{WU`9Al;a^q78gx zknYPbXs`rjkREsZw%jgnm3!rWc|<-d3-TcSo}>60Vw%3Xt-+A_VcNq8#OvH9Nn|gj zQL`bEN~H97W8)$RxyvF4$yhXiG%7k+y6)(j1|wco;cB|i21{2!RN-AI9_OFrk)=hE zuicGw=WLYtqfT^dv_Hy5A2XG>9E;y(+Nj^GN9JV4P?On!T1+p#g6sUIH_S8UMYCkG zO=i|yXL?L)VS0$jOc`Y>{H6<_)?cWx9r$JZh3lVYTqs$RygmWYG6C3B$P@B6IFs3{;$iuw8a`Km(;6=>QPij#P#38ne;%+i$PAzcc4AcAwBc*!^Vdu2(Ny zyLMrC&ri2pdhXqKpFO^N|4Yvu`TkG16(@G}9*J+5v*X4?^{;FlIQ=A9df}g>^JxEn zAN^=-@9UoWcYgim?~lKK1~cYm=)5su9%M|S(gk0wR+y?29x_I~B_j_(;#_v+*H+}` zfjoA#I*!4v7Mj)704170|IdJP8BB=qLyT1#apoCy>7+$;01P(3cvz1S5_uXV3T^Zf z0>{5bzpfi1OEp9E4$_<>X|}3LnrKTHUrYiRT!UPKz)5}#BFsk|14Aeg44#xrTKyKa z2)?cuT);MLOd|tnIVx}mzA{t3;V7uXXvg*I$=ccRUjDHdWp2=n)`k6vTFJDu7iohj=|1t0hqopI&k*aHkzf@g|-U9I4 zV!-s}0|!RwjZwH3_)!?KYoC4}eox;#O-~iN*tJ)$0$TIvfAFV89z1Qt{GoINwtlKE zlveRB$?3Ym(%&2gfiOJmVdT0P3a>U6pGv>?`=hW=8}Uz&`^1owFWJ*hdV z&U8s5BO1}V@pGL}x-)$;G8Lh{kzaN#&>;TZ+(;=l=^ZOgT2iD=Pc(VF{A zM++83?G{Cw7OD+^ohgejmTjH2#x2(Bt_PYoQ=AYDKTKyY;cqgTOJdk2vu@lH83@_gjzVvog zyTZBh;w{<%ap_$y#+S99uWFx>u0a-IUMk)T-!jYun5iL#gKG83T0rzuL4*^ch8cS* zT%QJr$(^=+#HR=GWQ)0ogHv}bOS|_}x_qDCUcR@@E#F(><$JWTdhA> zo(OsZHlzJeJEon~*reuY>$Qv8l*R?Luv-9-`fk6_u=BVjfN33c%fQBTwBh9e&7-|& zK&rXvv~tURuk~w$-Ta)H@=A7^ugj+Xaji5!NP;u;g`AV;> z6rtf3p&_F&BUtH@SMpf(Fev8TCW(j}!-8at=Z#~=Nn^wqH~0}_%Aky48)sq08r>l* z$ep#y!=4HMz%{OCa_&(qlg$>eQSR(Z7*Khh&%5bxeyQuHT@P=6ES6`lo;h=~uI#PM zo(EPOVOwvGA+{|peZ+2bv1)z=t46C;7YvCC&C}$eom-IHo55HWa)5FWtiTcsks-7gDWiof zc1enkq@^YHVc(z5jg0@H*cD4RXBXsmJ#!bg@i++=FaKxwS#`ryZ zzF%=~aU;G<{3U7JcZ2<0EWXYLo7e?t^7v4NpACRsFK$ zr#vr6vLwo!B#H=+Ks5MGVqD;Zg1~!NHqOaGj+3{`M3!()c#h>2Q558#^ROhs)FaqJ zzwn0O5vUSpsH8nq}?|X0G+aKBYBm4I4ZZ>b<{z@FyVUgWXBM~;k4-qj?MU28) z#%f2Y?Igi~+ES?o#iA{BY8@yYz`}Hffttt?f@KOK?UcWY)wWP;WgK*@f@LVvPN&JH z=iIlu1f1F3-0a?W&wKZt^F5z0i2$hr#mv>M&VlEp={a$Ob`t(Za=9RkWJT*zx`=i2 zO*3w$1N~(n*#TUmfcjOSG)-mwxeDF)kLntF?C;gxPm68UWpuc@ZsH-9c&fUxcJksh zeuDYh2`=Y8#ZU3TH9wr6QaeBBC==C{^jCcLQtT-7igcA&8~c^-1<6LAjA{;E5hJI3H)N|JFJ=#Jt{>{ENe zxs|1NNh=vIJuq7?`saqb{f{<37XFSf=oyd)!&`)(2?0rvq9Gv^%?O$1e7K)I!(L%~ z*dE~^8x@YT(@ax?!GIdHY)PPmsX^Tic;l^#nh(;T+2+mQ*+M?P$6E~yE>-Ycz1W4Y zzP*@PAxt9TrQQ_@8h2Wqnmuy4wzbZ+t;kZC8t9yOF0^7U;3_z0l)I#|txa4-*;@Z< z;7~q~p8!Jy85W4B3XCVd|x<=Bec3$^Jhn7rvkcjr4T>H_6LmzLhj{oiHC+}U| zedjYvs^8pnYRO6I&C#JdUaS70dbzr;`t+i0#qU%39X4;nTknj2h!wg8ov1j6w9>B9 z;!LC%ogY0H`8X<>@%QvU8XpuDZR}!n$%YXUS5DvAtH3 z$S^q$g|i?Lv9>pdvSAa;TE}1}4`FgfHC>Q(2QI9d99B&cqnNm=iN$DAVmjt&^PDM~ zJ+{#l0%e_Al0d9iy7(7Yzr&_UU>+ydxfcuhLLQ|U>yUE&ZLg^@_l$5VI-D6CSy=cC zqD~ ze#iCV9#@O9gowi-l84_`0dIURx500-YP_+8KIHO7VOBT{yfJesDU-RAp9&+=37Ega zolky4NPWI(y7Q;7@(c*|CeWWsDy24}Yr3Ng0XoCanCej^TlO$j@dr8q;yXP-uj0s5 z9;5WI*Ab<>hk9WA25<|uJ3oh8rAD@wxlq91qdMY_SGaM*7RenQc*v3u6IxRpm8oNF z?LlpHTO_A70JjTZ0_XrgV2CfETu5J?d#WzXP@3#W>hK09h3_gKNYV>4>tKkuR#P+78P49_;;~khH5M_=J5woRx08(vPxvq_DBot zx(Brz_-l&+*cF?5P}_sMz$al<+ep1!NNjF(Z7$HbWv|=EY)0(UHnV#YR^+xL)JGyY zqMf2ssVfINbrEgp`72#|A>Xf^*A1(HZ_wOAF2_L&k$9r(>OQ)jRL3{Ku!;4Zb`jY^ zL~iT&@up2fLzPNp|Nd;r$;WQLbzhc~4uYYpp*@{r;R71kAOJIR3H8Gb8RTQc#l>QVMD` zMGJ>}wcgYzO~_!%PHQ%cw`jBVVsch$v9?%Wm|U3Z)mJ3Hky>Z%OMPku1F0snDDO}d z3B9gQRlRC-jQzUgBi`0#<|tGFmr*W(7f{{Sv_n;mcw3_GP+@Snq+|UixKl_3FhSwl zOQi%istM{OmL=HgL|J)*K4`T?& zM`3(?6duqhr)M9bKZHcruH?#%h6N3*mhu-Ni!YY@3weMH&KL#W!7f5t!+cVfuJd{s zrlY9{V?*O3<`Ik#TEBGG&JRjy!OZ8bZ(b$XnHF1vTZ_>b>H-;03aD;7}l?>cw_E9j|E>4W~I=jN^Wlj8M^M zMqz(CjQPg;_)uJ)X5<_u%Wygid}=!4$!dN(-t3nhrKI#Jg2EOwH9><*C3QjDo*rW} zO3`el1TDV3gj<}sfqxn(Cz%G7WJKKKjJwBtP@|Ge2vsJ-VFdR&!_Sic-^Af0Lyu=@ zrib6VSp+<3ztqn9+IO`Nw@|Myo^h$tcQI{8MZ;9K0D${qu9;0n`ny~4EEiWe0oYFn;!hOOcLZ2r2;u0Y~Stg1DS-epZm8M{pYNZ+@|GQ*yjCSE!gp;vw94UES*yns*E?*b?Nld6Ogg~0$Bw!VmlmOj; zh5`)zVpATxS+WxQlG2QLU%K$1ekj6Y>95{v?M0`8Nkb#<9n$|Pm{*v8+u9Yj6#cy1GLl3A$CV94ZaD^5lr-ol5#aF6qB)cG`}Eo?afoJWrN29W>^PIwOE4* z_ZXIu(_y?j6SQ3fme2n98Ij*m>lDcL(fYQpjq<4Ajo{S?q;cTYW=e z?}_R8kT(%4&!KTsA*vT(n5h7W4--@4s+3~?@U#zaf_+xj(m~E&UrOWPGxKErzNw4M zI>r9U>G|QO_RDfT#J=>*K79QZx)t|D{9)mU|$u0|Yl@(Lb;ywqfzh);fv zBq+I{ma>Eb?3G(|>#bWaQI1-wAHL0T1+wi&mt7o41t!hQbGv_0D{65EeBJaLtOdjY zW9zJ5=gn9BkJ%qmA-rbYwG3S_=Tqs+HF*C0H#ul{Pr{vl954=Vi?g)v2O zFY2E=SJA(VZV>+anF{8)RewLT>LEn~9ncYBo3boL*`BQ%dWq`Q;<&P}IT-8J&Uyic znT?^Bs9r6)3@f;019tN|z4|q`!AW-KepWt`+Nz&^h+kKIjI6~Teniy0|+?-=GkhfRI0q}_=lpIDlnM`3QtkLH{`+OTHPf;ioz>TY^ z&1LQN*O-4FEn8A@=)KeMVN+i*H>n${HNYpQoP$G%a;kt!wH?H2(g-|?gO1VA(s-$d z%+29p!a>(ml8J&Mhp{A&XBSu)(GfK#Dz=n;zoM@=>#v@BzAya`egE~TI3M1w?bA}h zP{`x)mhu6=-{)Jy-{Yx49vgTsFY(9u3%rWwizu4rIA^H~;?wO$E-bmQ%VjGn5!Q&E zA|?JvF306!5!QIDZy9wS{YbXQm~B69%l3KPG?(uWA)2l%SuJkVJ>d0~dP?t{7YGJ{ z69>4}JdNpi{rd9T;ya*o?ZE_kt>i~MpR<3cW;bWD)uj&yp^=cO_i zO;Fs$lM^ZES*pmNWd77-$~XZ-*JOK=^ndMLnfE4@!9;F!KYvFl5W2gdL1cYu4ao*i zn;8MJf<_2Opw}r9$RQLg2>2DuNV>4v;SC$Uh;8YweZ6sc<(p?0)%`GfWL3k^&ljH_ zs=LnLxx*Bm*<;7rYae~<9MuhP+CJdM-%H&tLyO3Rz*J;-Uz7`wN3qvd6%h2W{9m*a?2$K*V)^c<@(o+ZR~RUCZ*l3I$QXk1T?TxY2}bc7B{5sNebbo>clSF8arxaAo#4z2`3MqAclwU5`u8 zzlr5X-{M!&$@Di3Slsna`Y#aHXw%dm)V;uG8tIS^l|v_$l=V`y$Fzg(H}$b9;3i2r z3s(inD4T@&K{|%86=K2RDAeo2W7HdRwzp6!j1|&_g}J4_rrtmn3`s0kr8$>%BAd~T zVeco|Irl028@wCVse~7Fx%UyGwRxgZs1W%voGa%#i$$9d5S`8_qA|rptFm)cOpZ=u zvNShA2o{f4t%SfdK7O3xm095<@H3v8NI}d`q)7NbhSTbaY9a@dRdAO$FU3_!z{&%v z3J2uF-A0lR+wC}jX_HzL3Wp;B69(o1F>S0>1OMsrmDIA~P>@iOw$7X;nfS3Mqu~wj zL{3y}rc(QNA3S*Q!(W`)-+%Jr;y~cl`fx;c|8z;qibac;R;hFTGeO&^l4X34Y0H91 zQ~HRst)+9*if!fM;9Gn4t{cAQ4+hICBGL5Wy>+4JqB_7M5AfKh;E{*IXd#N@WwPCC zy=SGQ=8Z)gN_vWRl=K&UP@;JO81^|}+-{$vygZtp-Dn(;aIvVxMzXfoL@$Zly z>EVf9r}H^f<2+NzP|P|FdFaDlcJ%vUm;K$x_OJJ!}S(qmCIc>%ff3 zuYjr79XCeALZMa+5kOti0L%dh zNCw_~O~emJqC?>T|C9jy|G|g{O#JARPtqrjczbHwjz(=qcXbpDihb*_r~mxv{`4be z_x>O6`S9StnX|nIP60{gHq?j1K$7~V*JeoarD1DhRVV%ShSm-C&gM^d3Z+NZzn?xO zZEIV8Frp)K-3GgCZ?V&Md#*_}-pgP@E}3az7$6vVITyshWU-p9ghwXfDUTKs zQIHfK1;so;7X5@nd1XwVI&cH5jo` zAUtYZIm4rNKQyfYNnuiZwduQLBcm}_f;G>wT1p@FbX{%FT&E0AhXoGPhWBJCh?7&}@V5*;hpk|8v)T{4|9Ww28p zm9}F`i3S)N+tRX@O3cudz3cCsU6MFH7~OEsJ$rYDz4!C`{(j%zuRB|HZz$?N)sa3I z?1ZeUx)X_os$$0G1^be+BBBENKP1&3+I82~4YxHk>}$qvIFA-LZ|**H;#)fp@&|4% zsWYB0Y^Yz;Y6tPIU58d3c;IV~cRSTL6O;gR&<#J(VbWWQRx>}S{f6~b-(%Ju-+%K1 zzrWNlR%I1a8ZE6aC_L7MtRKF)jY)fAOW39`eva8N1(oO6F=~Hi=f#f z-2V`%-!nV-Ss>-~k|oo{+>V?f{Nmv~Ptw3N{u@KUpTZ@(TEK_*FEoT~Kvt}}5s<7Q zK*xD8eHM>rwnJaM#?BKzDLtSlXaJ@k@-W6o{EKuEnu*R4RpHKNJ7RaOH9bAW+AkEP zRydQ&&O$zsHd`OOdgnd2CM;+CSkJb7WgBm~pZ>=EPCE%_UPE5gXsdD)GAyIe;2@({ z*b(Ah<84B_O|qCo2}f#tLWTK}7kyE^s0Dp@&ktTxGmt{aauU<&DQF_$NBwi+FQ<9I z%IxbUi}yaX?}znG+S01SyIr1@{I<_DeMRr#@4B7P+2I`j6lsRpAs_97nSsl^$Nz!6 zAiM=yk&uSA*fsp1s0?bhsDU*4p}XztMVv4oNk|@OQ9D(ls)*~kLNKwHMq}jHc(4QE z7I?(ygNf8kRd>o=4HAF_)DcQU?^+kKQWo4SuI5UXROhh+w~xKlgX@Nd(r*k632!;? zkHd@JO$JJCyD$d#;sQ}W{VaBw7HK8P%-=?Ho9m;NCDP5zs9~_pHTynY7h4sbt^!-5 zzU98p%Uw#R@4MW9+3)*}@S-^GyW-PjVKd%DT6|sFu(r?}A$vxF`gDSJ#f`(-hQ{H@=eD$s z@+K!sW0@-mWv953~aiao~nvgK^$P5V}VH5(E|!4Eg)IOMQ(7i+<_^$ z@AIYC4{=r3U+2E_(JPGDkW+uuF^2e`-e7eESiPNPg_oW{Zg|3F-n`g6GoFhmgX$|Z zVP%03O`a#F+hz_^0btVEV>Ig>`k>CW=-2{mf?Oy`Vlp#n7f?c?P6>$-N=Q^GA<;v* zz&9K_M%jpN%7%U>wswm9MIwe;+`Vq%CK_Ot8Rjs2EU9>7SD=vkhb<-IRmPSd&U%O>5+f_DWNUD$A8#g-4PFNjM=2AW9?)aWUR6 zVd)Z|ufrqq0ebU1Ma@&x9e}!-@8AddVV<`jxd{hk)PEsU!>FiCd^}^LGd7isjfZhz z|8)o2j&>uC;vr~Ko`=)@Pa=f6Ts4QI9tuH%`Y|Ptd-~jS&o<+u+~pd4l|a_oJ{C zCgF)iA(9{AI4hzkq4=VBe;9`^1)11_luD3NF@efpa5zYMgE;6d13|rKYfN%7lUy?M z*HNarWabLZI@nnh4ZQz5GXRm6;MJ6h7>XEWkjoUPrMW0XMTJ#c0B$|~brV|oCH^Mp-u=@V=YrD*q{(mbHvD5J;XLIWbvh?;`;m{G7w}r_!vS3DOdQN< z4r-zJJZMgb+Vb+Vva*Kb*DA@(J0l){Oop@Vf(;*pg`*36^yWyQh<@~@T?rfh7FaxG ze1%-8Mm>BN?h?DSb0RPB94E?>qKIHp3YglAU8!5t)Cl$wf<;B-6qR0qhEVgVs)j6x zhc#ik2-cFB3pV4au{df;60|E-RZ%#OKniFgv`xqrH{<;>^4ucpp;s%Yl zi{^pRVGJAN25-Q)8?Y5!iQ8%~l&U2DrEO>$I3X8rCi@8?^h!B2Vx=rmSRF!PmLkP0 zISN^FFxQ7ZZQV0&QKwNo!uqtC8&v_?C8!MS^mY`&+MSInZD=7SEc!PM-=i^R{wPy} zWDP9axxf?I(m3n~GYnHRlyybt$1>B9FVmR0;fm!bffKiHZL<}n07^i$zc^Sc!vUFp z?s%{k?qTy>PD0tK#`*qRSHp?rAa^|dyUVz!)xPZ>9KM)-?&BDh$(Oh$r{UW@U+%}p zu8*V-%vXNul25_}QGkl@sC~zPdtec1!*?5B_wcHg^s?|aWV-_NlVEb(@{iiP`GtCLhE zuSMvLiVFV>E9SGKm6f(uwJg4DcY-D^#&82;xPdlqU~Fw{U+l%$;g}o)ik;sJvo3vw z%_kM45;DqG;9f*K+*dfb0DT{> z^xC+?5P#a|vBbg0P6?)+9eBaZyql8oN(cH3EPW_imXel4Av^nUZ8-R#50{Qkw2vtA zBCcLMN5O+jeV98@giB26D0UKIVDTu8_EZnju5q-wW-l=J4CkiAS@A{MPG^T9gN8A) zinfC(m50d*{%0q92Mn>f9Ldc|)c7+cHI1`*NywJL_M0GP$!Z2s2necC+Dsky)IM7C z$2X|&1@{zn^2g|HV<%32LfiAN{|>U_fJ?u1oMvBs);)H{{fT>^`FcF|q* zeD_4I@IogfOxq;g`$(@-u0Lg1Px%~R9!{SG8~XBg^#qhXG|PV0&}*991D}p(sdpV{ z?B!M9X#K!Z!4ZWji2TZ8+2Q`1nN&-`sjoVIFSc54Vo7>LNdgq~6^;C=W1*lnjJk|` z#a=W(jVX$PI}O!~p`l~S)X4B%l-kzKw3WY)*s$;c0 z$P`jTaNcnG)*=**I>j29?-ZPmsk*5qXrA`IH5t9 z1!W#18ih{FB#mgC5}8SZ41Qrj$AVD<h-}FrmDeUH5;+qzK6X&5caJVgRAkWc4@fut=I))lQKxRu z>4MOyPUv<6#4n0?p@{c`Zq*`Ai}+P|l<$jp`h?E%G7--tIPsbgw}Q?FIq#IOl_~L{ zz~A=pmD1Pw3RyBVVboZ2ems(7nW-Qjp)h_y*@7v6pfZy+hQKY-hygGK!3)Iib>eqG zTg`*rL5u4~P}dDuK-V-zHG?qC&fpNKx7V;~nUqsc&m$_?-bTy#C;2zck z^}Qp%3HLBt>|k-n;SPERKtOPAm@hDAhP8q5z*|;ZCZo5u(B~Ie@ z_zsVX)5O69`}Y;6tSgQeHxI}GwgUF8{27wdbYzWy_+F=ReW|`qzf0!}0C53u z!PzH}4e%d7@QGV+FOcq$?f3Kh0P0bB+4}S&c)q=$X2^)M^fQ*4Glhs~E-^u>~~QQD+;N}YPYG@y^Nf9jgVB?cZpBKiOx zIDULG9@F%ors)!sxabbeqE840WidkstkMnmnRCWrc!-%yj;R`F@D0qlV4Es=FAn{- zpU&#F)QcYbeQ23O0#mYpEcmQIGg-tJk)Ts}MI0ihc5ERXIT}h(iVj0*6W@Aum|k{0 zQg-Y^de%+A-sdmn`wskp)l>Hl14_#7~RH@F>0uqoU;P~ zfODoW!b&vNA6H8H3uEJHQBo2%;}(sFEg>-^k%i8V3R{>R6(V=6xYb}e7I!Qp&E3{M zt6(VrB{|2AY>ym{oQg>MBIhC_5h()M)vNn6;eO}C1j06&R#;4)@h}Y! zupBA1hl+WY>#*M!lNFj0R2G`oct?f+juHOSX|VV}qdyof137`re6Qgypsy=1KA5QPt)TYLk@M*H zoHa$tTg_L=E3Gxb<)Kxjt0LpXXMR!M3&;Kw;r-9}W`73Xj3T~W`tQ^h7^gPs-L$rf zR{bBa&4-(|E=ox>9%a#<7?exLze8JYlG;84ZP&rt7X`IjKM&GAAJCwdI2eAD@-9oE ze^QnFsBoOdNZlbufep+7mH-D%(}N1TY5A%{L^de9FrHWfIUFhEksX9&d!a7WiSvp|gj7{1F+fzP<w*4zpA3}^^zCh;EV2>C1AgVhJ%C6yMJg-sw2yBqmJsIwrM4urdUZm>1D z(zn64sccj9_S9DMp0azQUFJh&k6Tuqhqm6Zy7oD(2PRkB@Md1I-mn-^Ywob9WrZs3 z>4&GY=@pe~O=Uo(0h4*HP>4oqT8uWFZP{{1pH?$7h*e@^M>8RPZM^?rO>L&ZrUXhS zZcFy8nN_q__=X?rf+<)6Ou_3AIsurV02mi;qF`w;T%@G2IWxj2VR3efonxHcJYz~3 zfM1N}umpxL18C2y7dVN%47j@tKmpnq&85*ez&2{3XJwk38)t_@K}8M2J7j%ec5_oE zm8@2j5Olb3qX<*UByH(k^S7NRPCoO^U;p;(=`-p6XLoJRbyYR&-Ei-ZH~-@P@*n2^ zF7J5m)qBr(J-9#MKeP9F_amuu`_}dc+B+X}@9gQm|5x|j@$>@hcx8|^=Xnb7xV(24 zWISS?>GQ)=iyk9D(5Hh6;xYe4b=Af;b)DgJ?m73K`)OZa+ldn!+ab0?7KtQHLNMav zs)ayUm9ehlOIQT9m5(wtp@RZyMFw3mU@DVXfv&V=TL_ABSI?WOtQZ!_5g)$z5 z9hT*4grmW#BET7g$(xtdI;im8)1) z4ykB-CJED8f6@9-S9Diko4YOaV&ILyYoUYDw*yC_r=x!kor?}eN2Bg%QK|_eR3@^# zg}3qZ?jZX#WLQCB1{11Ks1^!_EdVPU^|7lBiLHS!hUAzcJKjjh_b{wjh>sCL^x*n) z-$LvR6LB<9Cn^!eF5{qa#5iq?8miF|Wy+7eaF&iuSTc!g7KUyvCm*oqF&QC>BsIq` z#G3n2lo5Dfk|yWKAox^ABxHwymG_AWQ2EC6yXBE(0qPR?5YSlWa8dvhZ3;C-QAEn3 zs3#~L(a^4+Zun^1k^HgMPi^=a&+U7&>*ojV{GCtu(f9ZMVdU2^?<@m6ICYt-;+vAe$0Oz_TY5W&|=^4`xWjN0cKHdoEGO*ui7C%iYp0=rbTC7YNQ+%nz0p z2pX4gp>%UfxXaU=@kZWwDMBOo&g^7$a|5i29l-I&le3R42On8j5|EV$NaSrSEh&?= z@Zl>{WENOcWB6|V#N^psR~Q--@$nr{b&R2fWRD&FjUi!iS10A3Vx)#pU!T z#knJU=#3f0c61F$YHSExLy%7gpf=ZhA03dy0wCOsgvn;$1!r!gqPbOTQx~eM*VX~C$%ad`%$n-u+ejV)r55OL_Kj3NN7x$6ibu`-NXb_ zNlc=#^72SZ&16rE4j&5wp|VIk?7l358OM%%BD*!KWV5MwB4Q#XBN3@{Cq}Qx6Sz2z zCsHMes)D;lB0W0Qb<*)ACzFzHoYJKmr*@~5)PV9Rsg<2P?B0B!9&NZVZo@K7BItLW z7z;3x2la;(Ug)L;8b!^IR5e90HI6&8Xq^JiTm!Szl-69XrFlvd<9lA+L+kcDd*-F? zlbgEcUl^GDjjz34Y&-tkbKkx4q58q|E0(_Te8+n|oqMB!8Bfo9c0f5S7EgXG+(0+J zaASsdw6N_RtjcWgjv77_s`3cIWWODf{T%RYhg3jaz6q3i+gw9q+KSG2 zPrP3nP_^Y1E7@9Yov|{wE~+hH%hlz^g5dI~ns-~g*0Ox8-EH&Q%GzTK*&=nZvBX|& zZ?bpVLE9vONW!!N2`)k*r#vI45fk)V1kh0g4zk$uxbS1x3Js!D^aw_TE7F3A#!GP; zmxs_TVC`g4Uwtd!O0O>IEyQ3H*m3VJ$;SV=bmd*y7)GNg`2^N!tU95*bY+}uyTc*Z zYkB~(5~-e86QWq7Ql8&_{h$A!!Q#jV?>D$o+-D{j-4bL~`B#a*bY_nxf~^ZTkGQ)|=j+>R0A7@kdTx4Sx|gd)A`SynkR_@_*z=quJW4F%=*U`!qh2~FoQRz>&U0tncpXF_jK=Fw z;Ei9o_y%OrIa==^oGPhY?6Xk_s7V#%T>uww6$=L0Xfl{}Ep8!BJIb{G4;2d(URycb|9f?q-u~ z;sywh1R}LugjOCxX#tf=7znglIwJvwLC zaAXjDY1fSv#wycX-+Niha1hl7Qc&UbDm*(dD z)Ke6IRAV(s>$Hr8pfym#Fei;SF`abcnW-lhR4`6#bWaOStKx3iXymXu70M z8cu<%WYML%M5IupXfRsJa8Z#9CP+nfvAL0!6sZjZwZY)&aQr{uIO$jv1hWweJhpO)4HZ9Gh0 z7wU8Dn~U;+vW^Xub*OiMF$*@xNhFEQRQ>;wA_K@0P1us75Er7hAY?8y^(g3kRSp*G^n#RFGo(p&| zu5%nQSVdN_iZn1X(#C0{!w`+h$+Wq^TxqtL9i}t|jF-)$=2cUwUkJt7ho|=h8PnOU zazW9;hZQXY1NIcx^NI~epj^L6ibX4f?(z>5YMNTBx36t`skx?g(x-oETYYN%K!|P6 zubQ7$gg5WbP#U&vBkug|(;sYAoK<**ICk@n1FV*xC|r_2WuP)V-5!su3Nvlhnd3~` znkvl<)F-E==1D&eJe!=8S{!XkzL07vTOD0jw#T|=g^`6#D*MM7^0+j#0;OpbhTt2Z zGQ%wX5rj##9Ym2xECf;}Ycd!mQ%Z0N=PYdXQy$oYo#pPCp{thLx}E`ptj;aDGn1`PRRKgg(%@ z=ghocyoiT8?aN=D`%z0L9`9UqZaFudD_5`L(mPl!6bgR>DMF;<#3G;?VVK(Z3PKh8 z2*!laL!=Z{q8xrpCS#^OxerMiCZltSHkF`px!jDJ8c;Qy1^D?aoLA6BbPd!^()JSE z7{Vx&Ky)!b zIQD|F>S<#z1jZTe3XD(rKnlif?vvl?m0>ry&)&`4_+mfTY12&KjXq+75e{nZMsKZh zjoig_#Hc(>CWE?td3K8xjnra*mt1buDpViL=ox=4 z*KXuK!I3RxNRt^NZgQgeBbTvp`IBc}N9+{PYQYwMmyb8IQu2exTAMVZg9XucDwhPO`o8w?Ol6x}*sbr`$uW(UX46{xg z{ncLm`*53lC@du8oIFylk1dF;h`r@fDuqf{C9M%g$~CT$;YWpu^0!kB}8}R|e0y+4#9psu(W0^?K&@8elBj;wGJ&g;%Dx)qQ3 zcNZR7`_5G7_?hc&VdAcvPA7hTuoK7c;zv*63I9CbJ_HYSoU^QBW)?1rpGp6K*`$_F zknch$S4oFqUB%Zh!jc-^Ayvf=DV&53xrY;(|BDmD3m1hs+~WW~{gf0gs+G`92_S>$ z-iKBFAoke)P(uKlmPJd<1TjpiMh=p3wi$2%Ll_+DjWX5&hRMp`(0Un^gFjelR_Cz3 zWCuNrQe!OYDlx6-q0~T2v~PvsPlgRQ#-3g`sJ}VNmaKHsjAQ%I@zfKh7{_7-m`7jM$84T|e8f zq5Ylw@%-nxpU=0ypQ$c=#Q68&Rn z?m`R>3h9nLN;KZq!PoqU+jD-GfKn)RvsSHhoY$N=%B}Ehp z6(nj^P$xk`RYq5dl`;e=Yyw=WZQ8o2+tjt4G>~9hSqY;hg({7mz3*qA>B!IBd!O&l zcklDQ&-1(%Zd|ct9r)e(!k-E^@_FjXlXXvR%{_GVX;v?&5w?uO?RL-rNRjHWG6nKE zbo|owe+JkvVk8B}pR$ZWaGB*0f)5N2LS#3SjCd1;%xY>aD0cs1Hnh8Tum4XQ!qBM zA-7)%Dz{CmTUIVGw|DI?lQ109O5$bemLe(EMpsOcs#3&ha|1w#k11C`qW}?LgNW3N zC{%62%f$e3zczAxc|JAtgTuu;`Jx{+YTk-xFTY!ShHM=kS@t*z6jxTLSD8ZHUv?X< zpioZmB=u*I7|H7AxF$HyK7CzuNdY)-F+1-gvYM7%lOiG|~Fqa70_Q%s(0$7ISH=GKsV zWva_Pup5>~<@2&dhw!|7Qx@bgsv34G=|Ten2Gi2NS!+R1WXM4oRl}FC3gKYT$wLFV!cHrtoEHt;XD8*7OZyV1K!^ma zU0X#@Yy_&=rrUU1+occ*;kp~A2#9%?>b|xNW+)+h$WtnoUvhY&Xm%xLxvWIjurg zQ1_*o!sIH`GZa|0*I4{=OltJS+zu}|H4AJ!b|uBB6{m*9&r1I;Id#;vm$l?5f4U%( z75RVedE(;rLOxG+96Y#e^g^+K^`H6nd(W@Gu;s|$;PNdAto{9vw`(kqjU09;b8C=C zk=tqnC?6&q6|E#B@q#XjTthhlpPLEzkC}kt-2{~BV8Wz>Yn4nGc9tB?a^JpSQ@1iv z;poLmA=9n=3&yC-;sO)_d%5Ug{$#dxj}%iy@C@_{5GlM()v5Uk5Pb5rVrMl@b0@?w4>vd5 z_}+Xy-kP`Lhp_q~dp{n{M-p$%+gVY$c+wT&FY(mH58-Bnf0IAQPxB(b$nRYv%hoW? z4~8OR9hNSM*oe)iWcn2-3-ljAjQuNeE6P2B>0++3(ldojCexb9j$_vl?3QRrqde}$ zIxz539f|T!?Kn2oajgF>dZtL`ucEJE4;2dJvEmz)Co+I^%o0DpDbFwiO)8h#>9#4ooud5za zRXx?Akgf$)O$&B)@}gkPz^NXgZKi)_rZG_+6zUoidb~Om#TaJFuAaQq8cSR3mz6TC=bfqY6R4sgpkavQG8ZGQWZE0D^0} zx}mh?vJ)B5wrqw88~6|cNTvg6wlZ>cYCVi8+3Miz*ir~k3g??CV+m zK(?i2X}7$lckhzyBWs7j**vp0KRoateVve&mX}6;6ifW07$o}+Z7)1Tf3fDMTI?sE zT#D=KjvY)S=%F+&Ql7XKJDi)irL9 zXz^4lDIzvVDdMgHnzuxS6vr6;S@_{L0IVCl9ey@0%mKGKx8ysc^%jdS?g8@msS*l+ z5Y@Zi_MJZP(-XgXHMeu$4`1H4{$S?J1LWM_rt*CUihuvS*h>!0TKB=BzRg2Fk8FFe zci;NcEi=hq{yX~KhRC_+emz}geo+U0wUI8v-YOF*=%^{tp`l{bK|7_#=u&B|w2^L> zB#QQ~9%)PZ4(3hDAh%21m{VQ?V?%kBQl26uJ>Sv=<%c}M^ks@hRpkH4N2)id22s^*pQg)l7&Rpa-%Pw-0=_1`SbCJ&f zbCJxQ0uR>_n=$_dZAUe=OSMw7)EeCw+%4@5OI_YBUuP|E5rjscSM~Y4HPzKt86c_F zLz)^2Xf0S2kY!ufOeecc8o3EXn+4bzMy@vIyjh7ZDm;^8)MP-C4(hw;|ZKXhA z8wf3gmI%X-R+Zc0v`N~c3XqWUp;TZZjG~ChG!SqoD0Cr+s7e*pG^G_JD6#@YG0+w) z0p6we-q|r9QdL#*uHM`AyR+}yd(SzyS*jqD884SZHQV3PQuMGDie@hp`R3-L(LAY1 z$xAhtX;1=U#r%V9JP3*?@rZIUM!6WHT#VVUi2R5s7bDzh5e;p)Ah?TjTko0G#zr=z zkobV*(E81re~mh(X>KR+U-TlnyO-|}XKad@|AXsxRbE*4Euga{J<_Vv*`n2tZrRMI z|MU9yezmTGoVDh}9nLzua`Mzqk+TMRtKYzGNCPkJgl+#Gr?&)4VhWM9Eh=k ze(dsr`V>-U1>x0UJs-~?wJ?KCE#|srpD9ck=;YA#xK{Ppp~K>4Xyb9+s*};!Av_xB zTt}CmhG*+#BQSYjE;d(~J*HaT06>=SLva+z9jBCzh6tv%e)YNIRkac!0!9^Xx&u14 zN;jWLH(w1m|DiSv`x5N|AN4SOKZlT@xe}1@*r71DTJYBde@5`%^6iQcp5Pv^C9!Ra zs;A&F-xG?*l<3nS`czYWO>j*Wo~9VgE?bKXRZ+mcJ6NxtVS1ctiYfw&TifCJd^tRN z`FwoOz-H>uoDgJ$!LY`$TybRMxZ^;XL72T z*;p}itP}hb{`w!Pe_!)_@8i!t@#LdxzN#G_|C#dhTfh1E`L;a|E_)sH85&KiXeU_; zX0{fthmQqC?iIU>J;jfT=ZjiVY6p3Ek&~5 z4yx~Gb7J2?-pIdJJ6ZeWU~Rm%hcD&7KXT@DZSy<_Mivhnc|2*P@sxq% zYaW3xl8Azlz$iu|L27U#<}{<+5coXs7yB#x9{(OryH^~l^PnK-fdoemHK{qW-O=nW zme7-3kutDyu`Q*xwU$b=0VN;$d`@bndZ1Ffb>h`a-Ic-K4?nAj?v-25zRd?~tFFGh zOngxHmGT{|E#4Y-yH4ozIDO80&N1hTqf>>cD)%7u(x%Dbeb6W`kw-q+4ku3hA8 zFn`_lCVMNi*bskqztjV3==K@H+lp1gLZC4SEUpsbR-_xW_?#*S|2a%!#KqvfEFM}t zR-dI<5HtiWQ9O*O#I>lP+>nGQI^wRN*}*XMMWYR2LS>sG0;NakSB@!H6iw-IcsXJL z1RENE;{@>4`j|*H2=vfdy}JnMwX4D};NOie;wpsKLPWH-R(}K#b@|e;Jxr}n^`!bz z{V5HR6ppk-!8Hb0EO9qvv*7M7 zCDElMx|BqhlIT(r-6V!}zeGfBVW|>PyBO1Tc{h=?;{JF1>4z#vMD+|@3=5P38Ntu5 zfZ!>CvYv8qMUhJ91m@K{h}ZGoII%@OASysE@a|6pF+!Y-7v8$*-<6Jt7?=PSCHKP; zEX)2F7FrEa$Y!kscp0Z)8L5)=@isCs!JznyCAR70DebdnNY11u1F6V|f<~ZsC$Jjp z2^$M@lre(S@+nvOI8n$Um=;P7?oFJy6r9s>8Jfuv>L#_sagm zHLyL^Ew@?!&{fU3^-AxH%YNF%Kt1-ypX#_5d<0iT3>~xHl&0;9{ z^dDp%vt+ih1heGHvn1tNu=!y&$j``!`NjFZyq4#7U=30keWMDkl6O4IA?Z_))SFVl^nzE;%OD$l6sh3` ze51m@!GZMui%igrMBzM+XKD7T>g_*r3uIbDs=!fY>c!% z!`=_G?U0E~#%3Y`RP2@XY~4XetN@FDQ>l_mZo^X5InzBo&=vimFxQvcmK)5eIi3jY z;C}5Mi?#b^tleN7BBlNp;bfPy_uzC_g-#S`UTx6Y)1{>8b@2uj-dw}!Vkzmz$VAXQ zoCR#e-PjBOF4xblxL7+;9R^&^{Nkw{M{DDV$;K1Uym^}qyt-~l?-caoi@={R*M|8w zMW=R*v12S`Y;tHa$C-*(a=@}2#G5$FCq03`H#Hk^+4CnyzDEh^Xy0MAdcO#xxbJsN-X7Ffk@H zO=IhaG^Q#{LlbJ14o!g}2xjm9Y`3W$-~G?ed3W#q|Nq}d<4|NxY}gvLH#-}ecl%%T z|45AZ(IXlGVT1<_{#t^$OgS9$ zDNQ*AcO93ZAZ}u26a;u&k5bPv{{|;f5M*&4rJ6k++;Vkn4rTL10ul@?b~E68-_$PKI zk73D}^#{YDw{c!`EN*P?bNkbr?l%1j*? zq}X8w3?ZEoUjIErEEop^;_zH$vht70&C20;g=w85KrX#kx&7YX@35+R2A0Ck%F~rM zDlb=_V&K?)cc1Wn<-^LKp%ao|LT}|9)>?!q@0@fBHjpmqkF{ExJV|sWVl}or109_o zBVde@s%gk7XA{(Xe4B|;(~viL)=)fhMr6Ttl$$IP>ZM9g?FI*F&;&SE;1_)O9D7zkzJ|I!j0zr3GkJ^>($q%WkvxE6Z{f`DltkL-T z?B=|0StBTkoRYRl5vHVQge0OqZ!Q|t$U*o)bEeJ3=WgSbs^e1zxKL2JP*Ay0K&IpR zN*C+D;>e@()ayJr>lz3_IuPB^6HF_#x8av7W9iPtZO}H+2I-9L^Rr296DPHOIH4WI z32hVCZ-)_qY_3FXmrWM8`)$E)Z(U#%X2*Fh3oIZK} zU&yDE>~LMo5uG%VG<3M#dUjD(SS`y&T9#r)A)VHn3d9pB=&F^Ge7Iyu#yyn6xbRC7 zNJnECbh34b{+QQ^R;My_RnK9hwkS1`E!EN+Tqb#Z~* z6BVVNS1$4DlCKK>`l`$V@Glp}KH2fvxv|d(l}~q^@j+2Y2D3Dq$eCWt0b5{)XhY0_ zq{0p%PrxDGu-NE8v(IrzTunKk$VMNVudm7$NEoc=tAye4vLj1bGRRVdypc`^ShNHQ zBs~d7UYXwB-~Yhl>iN@^m7m^BIG0S^45a2y~+YR^`d=tK9M6Gr5T)mU$ z-7xQAA8%lh3vV{@D$l}7HPE&(EDI(r23wQD&)_2g=yml5 zdj@hqG2FWLcp^GMP=KL#b4nN?k=!2E(6k6*V(!LONlG#OBlz zH~~Jlzc~^i&V5B~u{J2n#FI)U9fviEn$35$7Nte$WP(Ohrr~F|QtfbvI<5-p(FqHP zWmtlBLTGU{;$)XbRh>Oz6sro8AFWam52~!ig8y-VkD@SW!2C``fkcg{5XD)V*DZoY zM@i~H>Qaghr;eqrr|5X<3Z7EM9^(ef=GF3C-PHBn?PKxPvT64O*kAQT(9PkSooD-u ztC(T-Lq6J5{So^-FWp!0f6X}0&W+W;&w>RJ4_O(M%VT5=0t_G6yI8dHDX+)Npg(K} z)080wtB;h&OVh#bCAnOlz0)agSCIh?OG7b0m5r-c_II>zU(r4ovI;E&gS(!+aN%6< zBg;84#c{v576Ld)!DVp1c6ztfs;r=f^^zyP_ z3`57!b6+1GzI3`WUHZAbe{}S@2RD`#xUwIN;l80wZ$+VS>Kl6>Dtv2n>Q}Hb^X2hv z!^=0@xc|@B_*sF^yMZPel7)@JHet7SpRnI635ctj!brdy#v{M(QCQpJHN!ivEEfbC z5(FxEWeOhIqk6NN%k33cP-2D~1Jhr11+yrtS;SFQjPPG@o)vaW)l29%wR}@iMtFk1Q|Ic`}z(#Rh(f4NNy_q+=v%521?;5<|^=Frl2{stK zfDk)P3`rriUBb7?1}kY$Lo2Wmu^^#n zsT#ThMP67A5tq?==-u>U2(UZ%eES^1%fWJGq+iFq*QV8bvh>Eg*_`z*=%sZFV z#MocZWlQ|oDJ7{q1Le@kpUF+o-v~$*v3*4Q5~YFDN)?$wfFkpuUc2G?gHW$2bcwrS z2}|>|-o%=shoju$b=oXe$LlH{=TGw&_3!C#aC3#Wf_H1({J3_UpViLt3)%&4R#c=b zc4|BM0qp?in$3e{(J0ctTpG>>%@%l}6Q=?-+^D$d}_4uzSQ3q#*o7=0Vn+aBpzmF1Y=%tmpqnV8=3_WiA(KDC#Hn;_yPKh?LEIVWcurn2rsZ4iLyp2h;}Saf$Lk zb=;j@v-FYq53ku!Gxt$Yz!^=CZfif^-vI}MfvW+)6xk^XRhq*H-6U+2@JLv3!)@XAa8I~5+!y9ymT(Hj4uXNa_i-X} zmyLLf?B5HE>=ilwoPy_ea720=?T{NmYuw^&aJD$@&Y;7bvwnZLII=Gmq+Jx6_2Y0?J$Fc~fWbiW@~Vc#jF+46k+_~J|` zb918g(2;n)1@tfPPHIsB_n;Ml|IlX(=+;aJ*$TIpz(lT;T1f5c{j`imX(Ls$x&9yL zKI#Qk{EfO2%D8syS8CT-7s>A>>ffM-J~HM`8nA{eMFHciQ5Z3%rY9`fObn9GC&3~J zhCJKIV`d;GtjfFUraKiK95e6jmP|GbqwvR?E$o>H_KY=RDeYE|)ob-xnnlg~H=%o~ z7X7c4NcDD+n*}B7bHn!w*a&P{&Hhl)Y(WM4k6|;uSWXnsFcd1#sR>iR7p6!SrU;7A zGJ59DCHhfr22PPCaPQNkdtXTk*u4kX=@f>s1{%aw&>tZo13KQxw>|Y^+fxY~MQba8 zqajR*CcSHKNlsAAIF6K}0ZfjTA%avQNa-NG3%f+Km>ADuL?{)aUG#`v(I=ST{|m$i z?UfTOyj8$)?Eg&!qZrNy&hBx%nql@h-v2;$iau5?(Q zmq|R6fahz7Cpqet)QNiGiVct)Q*_)^P5mrg3$LQkwI{TMBwL=6CgRJ`)JR4a_6df9 zidoqUJY z>2$_k;or4hbE>D-Q!=fgA;u=_l?@NYd|_WG01yTt`FC*73MNPhhdrhZ!422Mv_qk2 zO^ty7nE((3m*u2`;9qj$$N<@3APH*Fy&E)cP-6~BxvADvTdFH{FvUqKo~nm022(7B z7tWhnJ+D4RQ!{I#We9k*8Xp^t;ZH`THbw)8chrSntca$gN_0-6r*_Dtj@nFSG?PD~ z+sEy#7TPnNUOavoKNS7NoO;~08tlf#hPh5@SgEc`PJ=?=#8T{e4(wIYlCbC7tE)IG zik0ix1-rlUyN|EFxoG>UY~w4B|MK=Z?qW@A&Z0LKEusl(|AQ_}ySdhppI`X!kNxkR`K15+`S;(yh*b|lsjthb zKPg$fFZY4A4i%MhH?qN^pryJ}>oY|__2iTz%t&1bh9qgZoD$fdJmOvPX%>}~qfbBt zA-MVug2+X!URbg)$jga79dFYOgj|=}7{UPTWauELZM=*3ag{e)N`4?kiw06a>Z#_b z!SyfX4~xZh7~-vCURY#1pkLAeS3s!0i;J{Xs_VWi{WQDn@K`_0qRr~}$2RBE^dUrT zDWLdMK&^yabe))CP%HQt=iq_;rtl}s2@_?;vD-}(lQvQ0kjW;>Y6LSd!}$8#_7J7@Q z6LM6hCG7+YDN~5*@F^3Spu$KJ8%P*{L zq@Tc``SrY=C%y@2yiN%FSaRqkH$kkB)o!VAtKMp{+AN%!ebzP0Fth@-bll5s7WT5M zt`Bn*aupEB732m4|CDk7!5vv-2*%wSOtv0(w2&0sUb(61Az0b!MH>v4F2ThqdhRWk zQ59A9ihK;qONOVr(gR@N>F#hrZu2vmA?4(QDp(!+EgNJSVfAc)4KXdm;t;m6cGkr> zg9n|+Q?xL=M)Rh9Vxt*xeZs`E$Ie`VueV&OH$+GxGbDA8&=#aE^$0s5=(WS+_fF#- zMF-$5(l#WCTVSsIyq={;v$Xr<93VPX1Cit zcAtIC)@7BrPpJ)>Rv=L8H}S>&lBWJscdxmV@U8tezO~!eWs zO?&mnHgTTe@4Gvn&v)nZozLg9V<&bT8>hXgAxc6Pl#-JMg{>u}f^Gxqr4yS}4FrX* zqAf!!l#bGBG%X+%w60~^{-_2E6mJE#bSbS=t+X3kfhoWmgu=#X(}KuS%80%9{p@qo zU;Ar|lFRq`$NhNT_j%su`G1u0GEgM=zbu+uE!q_~%4!wFr=C(JeQK3HuF=#AjTP8{ z@D%2AYsHkttJm5c*Z$~moy3_7I1~ z(1G}E?fBo7m0)|nOl4IiY!*~J@7W?21Qu_5ZT|+EAXvHZMH1EDVIXzu?|7;;*-c@* zR$s?3*n<-mY}y+50jmaM(~5{qjYcD_j?1QIdiwm8GbfIfZY~Ye(}R2Z*S&B8tnjx7 zw`@HC36L(lYtdccZk_;*x(N{EiAHRicFmL|I=0RGh!}D-jhD@=%yI+zk(ywiVmHp- z$m5MKko#pWB-6X)d*z4aAz6^+5TBz0bIwfb!4#jXv_GQ3_U|#(r_8@7%r=j^HX=iH zW}BJT(B8N&ggNedHOC1`CBBWbTM#Nklr5?wPM}0c3&(`Bf*|z9Y9kK9gBQnOV|01e za13MF7=*H}mPs}RqLO8(W`bH09Kwp8Adx^c0doL;H-K|#fAfjR#Y(ZaqH)A6m~@1J>`Y5laeLG-N%= zc7KBX2bSNWN{-a9BtkXIUiVT&i5W=Zp-U zK4zb_FWG`^lX_(2b@p``Ri!FO;~pm`SP^A5UsSdjawFI)G6n6H(=so&Hq!7H#Z3D% zF;h@J)g864IsV_eBmIf6$p~2Mjxh4C=EBAxB#apqMWcn)*btZxqESnSfWYOOfOHwr z^0L5|;;Go!;O@f@UOV~vrO>G&zhu+4?LS!e>|@X+vqvv&9DSuURvM+!-%B_0zc~8R z={E=e^442W;S_N1C~z-K5}H9s@SUg7J9JPH>iCCrC`IOTY+^>X8H`j^167xx#7+;}=4g z-``};=mfjlKBLXoSSdmqfAqjTeTBu(jvQJ1&0RZQJw&_8WOrf9uU<#Rqd#qZ^a5>o z#ITC@KfY(jcfQiM82EZ?`GU~kdzG6;=7CA@ldWU~a#oWY;kgWpQv(^Akr&K!IG)QL z;xgn0^xg%hqXRt!Dc!+e@Es;O`enC)4@E*br9-(z@y!U&F&|1jkpfyoqjkwh$j>ol zY;fAS;}WGofuxf`e>NxEBub)1GeWS-pDMuMY^XtlhYAZRz6IzIyQdWbXaV=1#5WC){5*YmAn;n`y!}p9XaRDOeN>U?iB8fEmv0rSLpWz?vvN4 z-w)q!J{sN;?vI5cPxe`>EY7kNL&{9|yZ*cV&-(?x-%#ohrFjkM_BwERik&q4zNDg1 z>gTL%WS2jilBm>~tmCqpgm`Nz78PbI4gwuf*L0+uCSzGO(mM0Zu=2x zKewT@#dvDN=neal@4kHQsz|w!7th27zVzn@b{gFGw(s3bC41mx5ST@I+B~=;IlO-> zV%$@{!0#7kaU%ITsbWsMeTQLx8`}q<1~VDYPOutmeUp%sYj9LbW1mSJndeZztVS_p zSh-yOS?LZslbvTi!D(oguZdSdE8`>sTA8v0OVqPGbuyWN;>5)|Cty0^Z~*2Bsl$*n zUQxY(imHcuHq`=XAn>}d81{1OB{oI^Xb8iIw+qpR>krUCKyApfxQXBJ;bimzXvOzZ}xtN5GH5SI(h~fQZ(Cow*3b7=fI2OVCxINYv z8;S9;pPRdy^oa>?KZtIlX2*ru=g(Yu z?ObVADVSe%PyMR7%{|Th(!o7XFF$+|&CQ;j4<7+r{=q>1TydM+yN&zZ^_2^k+_D^N z@dzPeS9NYh-DZood>joqb+RlOnrJ$TBpXtWB*I}ciA69Y_|PVJ16RQZHD!EI6G5;L zM>CE%hRha|Gfmab3Mf8^i{N2C)n5;}27+C&)tt~eQcvsgRRy7jwWj1$IDu>6rB!Ar zRRK?;qD#RmtKQjE&oQVql~XBE)9NwxEPSUo`6)l?cz%-kg{u06ySlIj-4)LcV#q2m zr2tJ{fUH8#|A+9Zfoe}nU!1P2@^aeyjn9&8KUsxgL!rfQ>T zEMw_lEg(hHssZaZSXV{mr@*9XW2xG0P+GMG^OFoDRDxQN(p3p)-84-|K*zKNvC^>t zv9oiopB+0;ElQs6%e(LTobNm5eCO=A{?~t9{0l(8K9A$%nKyQC7`@Ck{&vrEdHTm< zE5P4JN2kC2rLQde7HSQ238*z;8Z$kD>QfCRr}Qb(vz`|`Obnyt9iT7aOHxAvbX4Am z!{!b-#6*~ebtB59CCa5mC#f8E0&_v%1N>!B6Z2;DiO(Z@z_bF#k1(l9+b zNLoNd9KeN89(@GN01Q=F+%ki1U}3HBjIdpRA5k$h&Z-lpu~L{3F;qJxgfr82=6_qcq>ICJ2;uqfo+rNMWG6NP(DAiDArrP2v=IWCW% zy;IovaJ!RrZ03!^$#O50@FK@7`e-YWyl(T|v+X4)cWnqQzh<=33AxL)%swvau*Rzv@M!!&TUh^=RXYzNzA zlNKu!z!_!K$Do0>$pU5Z`PwPE-fXF#@BLzOUarX)R1{gEGE0tof@9QmPzuMCjCIg(9^G#>qupVjS}evS?TR9bxKf6AT~iG>ge5k@rKm)abDOr zy;0b=cQ0O{-=Va)iXNVMpSVbrWJlmXlP48Z3w9}r`wW{TK{iIbL}ZgE!m8O2?ou+4`)tc~FTP<9 zqs8IyW6OEG7K&iGUMxT#2@zZ90S|gmgR|{(%x-+(*1CfmsT_n4*|??T2zpD^fKhL` zOKq)bSSGXW#rNa6_9ocXMz@uo`;CSgIK0gbWi)beSY?wqY^k5F0z;a=BOA{Q^RwN7mZuc4+_2V11X}-k9LX ztl7em>Bv~Tc3@SjcnY3%OAtmDN|v+T%xGzAYiVi^q>4>+<*VRHTMIblZSKg$JeVlenQ@_tf1E(J6?d^V zI7ua8()_lDupITtI(~${Yj*oL(pL$&Tnah@8aHE zu!72pGs_KNXd5up#u*Aj20m8$e$(!=h>4sAr<#D61Y}%Gi{PlWt1WHW#Xm|M{9glY zwb(q=-lwX{$HPposUwsO702 z&@Z!JgSTU*QnR|3>-rK#e?*))Cc@0 zcoog-3ROf5>A0Fv-&6%Pvl-Z0gD1?51*=vV!FH(++$p)5%!2iL@yqNNGvmZfVxUm# zMu-kDheFMq6pv!&mUJm*qX8E?R>nA{eDloNV|KNxc@$Vm0y*g;zTaau5tU6I7mq|D znT6=oohiL=2PncEv6|7T2TEc0oVcBH+h4KVm!i&Dim1O*3fns?H4QdztfFb4nleO? z-lT`w0f@YY(?kY~3FiLsxFZ8X%)u*RHycNEb*!6bWSSk|X=~I&3Q-Ev3;h|OCXfc; zV&-gK^L7!ae`7}>7BDO`X~;-yEE)#}I*UI+{og9=U@wUVyyH4f?o#0%mC5GpvugTgUsIabFr#8yUtI5O3~TO~|b+nV+?hm+ZEX?ZRY zXllqNTiXbo5ygWuuh*X8fU97gA;1|fRyyKPOB)UFJi;Tm+Q1P|fdDkR6M7*5@}j|1 zNe`8JM8QUEJz{36NAH1?N~zT87vOJXe0*GZVtjo1cjM#W`BTsYe*uv6lfRqK)+;G> zF@5BJj8|)H6xS7=d*``#W@l$+XLiRnF$=B6R3?9yIyFag~U(+ zMWj*)Di0-~mI_J&qJ(0%N<*O#8nDZ&#Z)|$(5S7dzDbo9P;eS7D6(8OwbwoO&aR<< zs!F>%cXsdYo_oIYedjy4L1_rpYYon9v;fah7KG+#3!KG#OQ=O#$$vvxZ|@9kwKqG5 zwLfuxbV?OGDLT=ajvJjVp(8T`f5n;{&|NSJ5vwV%dSA|{A*7Qe^EjKP}zq-PBFdq7Cjir0IlS7Ul$ z3&1T4~-x zsZ=`cfrpocxp(rbmY7vntIALQ>l4)cM73UW)isuGz|*}q^4~#g5Z8v<^OciUzWDp= z-|m@3>!t>>H%X}GEbc{rifF`)W@EW=!w@+k#}h3VhDVs>BC?o(-8OZMsFd18bY|q9 zuTsB=6zUb>{O@|Bb-cd!IsH)V!4Qobng{NKxJ$VA z{1)D|+zK~YR!3^xd8Czekd5ROX}5Sp4fBF<4q+Q1EXs0)LTp7LqCga+^#L&iEC?}0 z#ypAUY}qz*Fb5Z{SU;9kswM#DJh>nsn14y{Shk+b++uFM#O z5u#>O(#?9H-d?iK^OCoMai!mbkq=;gnT~;Ozh~B43~zmtaT%^|6it$m_ z7#zqJX4l~iwfYr-)8}vXTp0ctf0}<~Xd~zqFnJ$TlMkrqP*30V$JX$*!c+WHLJQv_ ztPo^9$62yTbS=kW7zbf)yyL6%e?=Ap+}~qU4HYk6x4~X=k%Tpw?yz8NVbh64^RLq2 zErIT}sKP~q;)1#=)EPwT4c9bgl1#_4Q7EgJ13?EljlybQ&yUgkeDBwB&sA-29R0=NF4=8WdNx(DOLd>V;}$r=s;rz9Vv3MCwaMxAt!1Lrt379}`{yPLiT zi@WS3uoz%8;fjE>c3NIM3lN^Vn5>tK*8$q#YqE{~*(^I))HCgvSCdLjn^s$7u`}vq zcJ>}$^|edN;CJ(X)%Vu^zTZ%c zaIp^Sx-tHrb!a?NhcwsF_#0{CA1%b;>$sBUabo^?ek)_@lAbEkKrnx9%CHkQ0+KupoHVQ|nM&z&*hn<=(^to6%$x z>uo*r((2cRve?c1-JvS}2gmo!upz32Blkcm(p;Qd=TDm}&JDGT?V(n))s`lUQ$h`5 zLr6fKplqEnRqKSt)ESYH20d4645M(^l_!8aJm^-#OeY?krcnmmxyqF=fu<2=y$rl2 zgFeJw7-Z>m09b9Y5pe-t3rm+QUw5FX=g60{r5oB2K~-A@FJ$#&<=LZa4*$0NSb6^1 z-Gle`LG&4j>}l~F7vnnpF)8VDQnR!{+9rvF*pN^M16LFp8&KqSkt=`mnewWt9ZfJ@ zrhvktuUiWQ`T^UCDAt8Od+n6VC2UHw61v$gp*!soy3HO>_t-Z0yyQc|u`&&a*BFRJ zbew5RvMe#R0Q*4ebe!pZisw(RO)cv6sxwnchI=jumH7v2zcp+2S6@E5Ys=Qg`E_lx zcHwED^F`HAKsVO<)=a5MS|Raf4iP;k$RweRs)nM|xZwUiQw=3h4I_aw^i#}KBUlUs zC5)MB;QvyM!J=v~q{fXaXa!#s521c&8PkhEI|8-HKZ81{dJI?4dS3_;KLHV!a##Eq z5oASiCJ8C0O=uHe5Id|8XYf=c=4o0a4sAYxIPeUd6OUUIv3SDeY}W;R9o|LJoFro; zg>$MJcL{jrxFdp7bj#_H8r`KXcHKyVjOKtaSTJv?6981DjJFxxV=m-PX5yo468!qq68V1v`5kRsxsHZ7F4KqN{dlPKkK@y_=5-mFa|=zsZR*E8#x_ulXRe6jD! zFaOf^{MCI|>@WNFw6wLp*0N(e(QI7SkVf5a+}ndo2H)?y`cBWEuX6%V@1@5eV|-{w zvS6zZyHLX0h#F~w+Td+LavloN$-*;&0QCXYeJ@$Y>pW9f6cJ+p>4r{pR!Wo_lpuor z9IQc6=z4*H4MPsQy2v>eZysukRX{8b>L~{h2!)_xtfeVmrBf|iwI+_yOVQFo8V^8E z3&g2L1#xT{uIl{gjf3-*Q;I7vZ@=AZU(7qwO!p7II`#fZyw<+{@&4cMc%kI2TxQp^ zFd6T1W${YVU18RmKQyVH4G}v`j4THv=o*(x%ME}G2n}emC`u9vvIK_F!^sG!+Q+ju z$TN8~&uZ5B%sdoUc}G!Q>|d&%{Yzyc(TQCD&>*eM3{tCx*$kn}uE5z9AQ6J`((-JE z5ee1>A52yp-Bda%Yx2x3JCC0F3XeG%-`Bc=Hrv-Xs@rm2+J;*bf3U9)n)I{hT9z;? z*QLJ_M3}T;v@cmXOMAkZ0`%4-UL2*`PVFmA=Xbr4tvpCU5G-zp2CvUP4NO@HCaVh2``Wh z!VNk=T{$@DiFz!(%rk>b7ZwtiYG7dv6rxI?z>(&5Q6e#^$WlF**@?%nwOTPQz!rWE zZ^i<~Zo(4CpkbZVkmY1E5eQI$oAHV625Wfx+qu8azK$*Bcvh8w*|%TSm4NjL;~J_y$IJOgSRCSY?ISF-_ilBK+GGmgR^U z&W5phY_vvEIKsx@DC1VDv=ma1H4!j|=N`L>vk2g9e|BkRI>;ucepXNt5ulq8AH`8Y z^3@&8>Iq4?Kloi+&hZyF9ePTO^^D0{W8c2;UaCnG3ft|wtLoZtzI}M!!WFgZnk@}o zZ{sue&o0{+j~~NxaR?W(7^UwCJ0V6R(QC<>wOO_1;;bL*4Z4W`1;HE0SNw_`8c=0L zL7_18SB3^U#{r$Q0JktHV_7yJ;#hIJEd}5y5H^N#&KQcJF%(0C#V|Zfmzll_rq>TC z0R&PNgg`vU3h@T(2%m({0VZKMz_O1+!nnx9>hDjS-{kxJi<=m2?Y8zF|50JX`eiw- z{_448rT;hibN_UnMgH~ei%F_!W!?9XqY&r<&XY2lbDT&Dl_fVDfjIz`UUp(inE|v- z2+Kisa6q8c5EP{xOkxG)av1ZD!2OzZ< zuQ+!c9&NTabKWKU$zbNJ#mQVGU{Mgn%&W^;vyiI9m2$fPtE5U{{5WeFRR(iDEEjs!QqAZ;@tn@7kr}Tp}M5ol!&2Y-4FEh=`l@nD-rLp!?jNOkPLqn@CvA<)SZ6VpMSv(_$CFpV59&5he88bz}yrmH8FJ4 z2utZWr0{5A*@0=Z?Z^RgVB7Z8*#r0=3#$(NYA4OMr{LetnmSk~6z&>)o}5dap8YtL z25+nb6G*xpoViS#j#Olz*_KNrnv-=PNZien+Fw|JlKdVrDc{XqDjRUU7ON9EzH_G*Vb>|D7dRI*rD` zbc0S$qU0c)N+vHO7ruk?lRCkzIz}Kp$P`S7-bF5=A{4{1rHKT3#CyB=d*4Z_c&@%( zC)@QyfZv_zo}}tlCuWwx{^3<(OY0Nqbb0|))HLw~ijsD|%5Hl;LdZ-i80Fo4E z9PK23J5uyu2et*AD;7(z3HV*u=@iekEy=K@Pj*jI8l^^eqtZ;|@npO--aTHaB9kRa za=TniNKMduFfmTZQV`~^a;JY8adDE+$qN+X4{v$xkVB=K$8D7ic z!)K&84dT<~c$PMS$8wWiJZAz{CQL9*aPFusa@le2|LCq3;3lps`rhv9w_2@sSK5_U zNY?6W8ByeqY(b3iHp!GvhCsuoh2kmWnUcn(EheR%!nBZNT84oXn9vlGHqbzt41{1P zU_0dFl0Z96+LU3MFqD*sT?HDmd$bg$lf_nv$1xg;BR`; z*_b>zkr?MN-oAhQ9?aZk%r`f~9tWjiz^nvPF$S(3M z5*}vPxgQN~_PCnWnRpH}%RR?4OPHg&baz&mg70CP-OZk_;+BPS3MQ|kI-kJoxI*xc^u?e?V$Fi=7?(rjnOoRUs5=S%fkpNCp&Quv#fhPAyx^-MCOmjs=d6!;GJX= z%1XEDuN4}G)xWHSrUK6D+!r3L`H3m2Q9vuif(B(qs=_9xc2+LZjMeAVIGAL9kn>wWsEu)N}7 z>p&rQum?8_X_f30`VtYQDYluYddH!RgkA;Y=u$3Db9i<9f(X4dt0% z+m-JA1Q})kqnH#kV#{J2ifMj7q&3jXT&OS<_~}5aA5p*OZNIZ$LOC;n&Gh;-W2EP$ zx2C(&eQ5_u$7F(vNH6n`VRwpCQva7Ij`rC84b#UP5?q$x8+4pHU zuSxgaOYye@3*|RZl_@i3Y-Ow~#**{80p@Vt{)!*q5MH>8_DuzSr56d%6F7!vovZ;f zz;!c9NFVV<ToG_ZN}b(zpxZxu^`j$D!Q?ksHwBDL_LsCAsJ?E!>cz_A?Fz^00t(*+^GG~xc7`iN7Zp+h=l`78sHQCmfms$avRBk7oYA~eH zd8Zm~R3anZ7&O8i+2)-GJdwVjYlC%@d16SnuM1bJWuH6vRBXYg%b$9sc3nixOJi3-aQODR3NuIgc4h zWpYd^b7Tzs-w9Pfppb<6u#Y6vM-zI}PAJJJRP@wJQeCv`k4b5~u`XpNl!&=o`I=PS zq#RuA?#>O!R(gi{Q4!s6BmW3637+SbZ?KEF5?JrItv`DgWJ&GNk^~#&vk`k55IVLpVV?H9-Vfbd#2i668bB3#3ygBBWCjYCm7m3#2cT z^FVz~r>B2qI3um)*X;9Ws#Fo2CX8mp-k+I9?YnIIa(nsDsO}Jsk`oYQ!lJJmHkG1V zqfAfvU)@oaVQsN8aucEnShS?v4}0GWnm|W6tec6##HGqoZGQMg&r7~5_^Q)g3eO17 zXBImad*%!CB^RZ9eO+W%gfSu)B20mhe@GtmdP9S(i}Je?&(6&kr^bO#DaPvGV<2Y!GRXx$cj9GVrlDyK60&fh%Q&r znrsUc5p)E_u0d1^(h(38bkgY-2c-0P+g6+!Em20a zaMS8Cdh=HUJ8<2d*G^wN(D(k8#be8qLEiyH-{$I280FAa)9@JaWYJ@Ya&eaWfc7PN_Y?cLwrM1aA-;!m|;2CP+tl`EM>W= z!O&DXra+Yci~pK%cIg-5fu{QhkNgftK7XV2g&((LF9a8&3_%Q3vyWL<)(D$)9Ku@~ zFAv_)*bi23d(hegZCKBcAcG-9>e2EI&cT(C0lo2kGcZSdKv^Sh61jp{P+G(mg-Z}T zM{~LGidc+sdk1;mH|X{v6c}V&UN6rZ6KGIV#R=0huL8g4%a=@pL^JOuambsAR54Ft zn$K%e))k8t3+~g8 z2aoH{AI3L3HdbwnKO5YsJ3Ew)_-gMe;d|2eBhHz@nfhYKQe{c}n+|6_UgvL=S^_PR zx+<4WnQ*!FYnlnW7gq?Uu~ZytayBN?|%Gy>jxiN=Z+o4^Kckvtp5;R{jqJF zW%&EP`+es-pU-FeoH%vt^UpYq?f4ScYr5Q$Hfb7)+I6(BE*q)}0&TD@3~5XnLY>;J z9U!C$fz%2OQKW8BE1IUQ6AGHdAMgi%foN9&(=;`x(wdDy6IMhL-tR6+-Kq%Ly8G_; z`#sO|z3=mqs%=-p`8Hoeh1E~lH$0~1)~e&N)t{k+8^muGe^Df;n6?byDS5B=JPG$c z$&Gm4^RvIC-V?FpuQSwsih$w;U1vuiB6ijB8{1%11CAa)H zx}?Bz4z9VA@V)s6Klz(4-c9hn<;1C$jK1#rx$!mEFOZYy7^pboMzQG{5eJ#N`M${@ zGomOk9dn~&oVe>*yr+H7a`Ny-2k3c}_&pt_m)E?zXV$)T1-@m^U^h)|4mc7?aZuVO z1RhOqJW8R1t_%DHdl>vp9R0zypCQkS-;fwC*e2#JhZ#rX_(1$w@q~E9lKpNF3dBu! ztJfFC^Zb_N1mr`Ptic@5w4fPObp!!*geuFA>t5`V~!|t3a1hGd*646d+-U^C2@7@3zvd0sR)>f+p}}7#x1Sp0CI1F(D@8Gdqt} zr>3fJzfHHtRu;Igy;gne3_UpWR`oR>V|)&`@mPYa3<5l+D)#{OdAL8bZRDsKty}+gI#q*Ne6L2Nj!NR;aDe*k4m3elO znUctqB=eIJh6O9bH8{(PH=%=UuD*AH21cn=z2L}{Oy3~SlIvht7fTNebU|OfFVGTz zm;&$s!jwI_vUI$99pc3h8uybU)vMR4N9byvf}Fa*d>4h#@Oee1A`6Bby1y8Jy$o`@ zbs3xt0iu9J1ZY&Fcwx`r?k|77v_G{q zS-*~d+V|KGp8nx;^=wLT(|0 zEVzng@&7j}kQXFnkl)1rjE-4%HsIdz2d$B|4_7LqBh~5j&f!D5X3%= zEpm!GkMgL7UYSMa>hCXr2{&o07?J}H>qgpOBZVB6jjMCy6O<+YxE!aNi^r>ULM51x zMLxL{j~9AiK24ZgP;iZ~BM9FC53Q%ug*mc-dT{0_HElI-E(?uv$genbZ4LTXk1}4u zrm!|4zx#-ov1klRk&t)lbtj+8ug$e}-sDuK==KhM-E|(>*X3$m@;1!v`gUM^=ID!O zE{!?WonuaIgq?l3+&9#{eS0+BHP%=C%nRwSzBKeGHe_eZ&~w@so_%%t_jED1M^$Mw zX#Vj$Z^_?=8a`42C_u>fgBJ3>BmfHlO8|`4f$JwXD?dK;{6tcXhT|{P3YCZV>>aNv z1t%+P%U8ZKP=4xl5$Kg0h*Etid}hVKAK~mdxQ0g9Yxoqu4GBm`+h^g-;xr+A zlPtOtOS3-92EnN;PAf`qjw~XT+@3+A$f`}Ml!01#0QqL0$^|MT6+g@u<{2}2e}GTb z4*srt-?jGG6R_jA^^~%EN(KAjO3d^I>ru?}k3;M65IXBhOhd|wqOESGpRB>UQ-V&d z)_^!JWwWMb*$EnwY1(Tcxtho~q)N80XeUEF4}>qF3Ooh`Rw{i>vg8JebafPqN!7AK z^l}nbf2`d}(k!4EP7;(21UBeAsMvk!(|@C3G`s~s9V#&HT@86l-=i3&8TFJ8)3t$J zzq8>5k7#;<4s$;Da6+J$eb(`OG^!cG{+@?M4;0vd88!{U6cn>3onr-N$6!cr%a{7v zbEB3SHMmVG-UBuX)t--ch)+`76Gljm9O?} zrZ4n#vJ-T2mOlX*yns$zY|FDMW70RJV7bbQ>ZDS6hLQ4gHmWK$K^XxC#Z)%WY|0=6 z-N@2~O`9?x=%r~%@^p{^{@W5xhUy?3@%Nezd)#r9`Uh`S*C^}M=Y^;iYQ7X|z7Ez! z;PFodP~XUY5vq+?G{2rAf%3CFv#;0K)jQTV>ZX#qxqEY4mtyK6WjtrdO1xX-UJhl9 z-ny|fzNMBAN7|A@U)oX#7wej;OtklCLexr|w4RQv{s~w;{Qyiqy&uyS#?~-BUFo)A z>80s=0MYY&9PoVAZ5J#yn@c4+LRLqIk)viHmkS!$Fsu}Xlw~dY35DFgEOaCyMhNAa z#r zcCZ~UejDOP{Hl3bxVV@&G|)zA3j+6{s!G%%64Dg4N)`174Z_B-CMW`lCMd0nS|z1b zqpFcg6{$6;5K3CWcF&z%8&j#4XXnoB?A-g^^PO|PkGSCWrFp-_#tY%9DkE!C@x16Z z@HP!?@W$-CO{J!P)tSl|*a$D=>fCjLRueJU!}ab?rdA)Qs}LDWa=rTOU|6I_PE@mm zv;fs)vR?(L6nP&W_)AfxYKWBwo=f+sS-QJS~8iwhD=9ekH;Me zx@%n_`smg@jhXJFBSYTS8fVz3H$tm)It z8D;`e3B-znPk=2TuY0|gfs`;{3y11+G4j))uS}*wj@Hp56SdVo+`lsrqngDj{4 zQo(qYyoYG$2K?H;WV4o+)GDKqW@Wuk0@1%jK14LeCAySYh{&1G=kTOTE{3I2OONB3 zVeYd=$`w*=sp+lg*wveA4Ofxxj~w+~bRPb&`0_X9kv~rCIDG6i%+bq4lnT-}k$}E+ zfl)!bl?^T#bc@Snvsz6yye1zUCh{MPoNRPT+Tz;%1t`B96M!ZC4t2P4E52$w;(5*B&qYbT{ zgVnGr33?HU==p_{0Yd4udQKAHd|3x)mPO8YL8drhBTz}MTmt#&NvGaY7x6$JQlR_VGxqDDtvg zEsv>0e&m^%mYre$*5KH{z+^}6VApuyQ1sc(wnA5HKHvJiVdAq7ST0oAlxs{khlhk< zO`>aG_ny|mwMt%$2tkiK;P!2A-qu~25^T7pyh}Wwj;a0wsw#+N*=$vKkC|b`Ld1wA zsKXI>2T-fv@zr^b(_A4}kcW`U6((7(FhK3H+^3|$E#AKJHGSUp0C~gIM)_oWys^+BmimB4!;SF70JbZbXVI#I^;cl?NNHr?r$(a%C3z3}!M#ORfN#NB zt>G#v>y0d}(E?1ZiY^j`IRKl+h5)Q!8fxdV2swzo5&$j{Q#P?Tp%$^HjYf%;;Z+Ev zg~C(V1&Sf5FiFNOfYg%avl;4~=G5DjM*00WBR`(plh?(E2kG;xpS-&IrPbdOY2xG$ ziKfNh{d)D^g#Ayy$B14hYN_|2*4xpKWDC;|>$hM;7L3SX&?80DK;*E4)hQ9Y3c=IE zp@MM3Ln;i6Bk#!oZ9tO0dRoQ74+uhU=Kc?`CvYvn8|oJTnX0&UU;)6v`P%&d;){{- zFr)Y&4(Mx1D{X{&FLLTHwQ5nQYRu2PGCWvkN#`5-n#sefH_i|@S3Y_E)gv!`m+;Sh zbc<-Yd-l}K2+pcML+rZg-yk=NqXSFG4Q7u8x>9D4DxLrxRY+=5AZl>^jYf$8t}tAg zuzGT3J{0ocOryz_#gg4yr|L4!IG`!6D2mtRo**h13#Hd@SU9^4!;s28PRYXVrhS6D zwKaI~xIZTEJoJnh)~l@{)7y?fU*mIo+WdpWgO8eCIYQJpjU)YAN55Ja9cugj;4l6@ zUPLODQio}FGs880KNRvlmSOU7r-36`Ip`@?8;`kyRz9X60K}K zNM3F2s?TkWQnsfz^Hj(7!h>(qFFyDp)76#9^!8u|UPme7HW@-zlv~0*Y7v6M zs~H>(gHd7_USA~tDQndX13nT#|HjfLnZp$v_$9)BS@(mE#vW=zLKC-Rfrd~=)zgm3 z+Gu5GCO1gDKG5Ef3ud!fS51XQh=8K%17<8xTc~~XeY77PCcI0C1!C*XQn&~Vse=I< zc2X(->||zoSb)oB{4v~I=y5u$bIfklbfC(lR?Yg`1{!v$rVIY7&}un2W^u-_((G(M zZoUQb;bLH#n4az_Law-U_$6cbLpL@7n}BxMc29MBX7a_-ot(v2*piHIJd9lm9Qa{w^TQk-mnCaFuEzZjj}(hyTPHwvLv|}ob3=ne zC>)QS4Uqpym*d#vcFSX0+LRajs)J8;bm)!@M!nJjt--G4fXBIS(?YGyT5 zORzxwP~wvpf6nK4#zR zwf8x*54&-8Y_IKPZRg#*T{lrF4GBryLTHkr_6H#Cv z0a6hZiU?AWT2=XjXlPJlq|(^tyR+lO1{EnkP*kmU?v?lM%J-b}ecw60Vwx%0EKUO( z_6H(S*2a2$siH5jW=PWMd)MatZOK6Di+RH#&Dw;okc#jjm(d;;Se|EXE+_OI;1+4% z1(gZLJlGs;j=}@O=)NP+SMSIg^a&D}tM_#h6|sSG(PJ=&0;Ixu!Q3pFc%Nbo%w|YZ zU=3i_=y}#;)>$kbc8Z$41i$Ga-AjiPM;cDZ4V{XJqXYUgG_Vf{<#!ElgGa^XDV9N* zsDu&9l^(dVGFu7@L2Fk%{Pd>1nPN)s?Z}qDMhzVs*y{^+^>1IbnmIS>-tfa%rNxso z#lvDpva+R+=NE4+6Z+=0>LW=LHa!Cf$%&Epn)ZfFy-L2rRvz}swE zaQ`3H5s$%GK$*dflulncSH zEOXYN$U@ko}<`Y*2);+o0>3#LkLw$*)NiT-up=yzN z>(-e^lV?x(Tb7w%)b9F{%~~GRee=5x-=p36-7oz0`sC>s#)w8I`Zww%LsQC%KK1s$oq$=6wGzIx29Oro-z{3HwbC)!l zbe#BU4!18z2yQNt+lw7UMPzKis3#afBWVo4lIoY$5TPiGEpZAK1yxxK+QJum{;+F% zcWt*f>uukX8SUym^NTh7a3b5iY0a_LtQ^l(yV?er-(COx+n2xd^scX1oKe428Xd#F z8?%3O3Szu=^qEs_y<66Oz9!eaprf}yM~5|6P#7JoL%QN611RV+T+3=BSNia>*X!mu zlajdHZe*HP^2Fa{2Q6D|5-l6e673D!tX7}b8-|Jb5sb(%>AVPs8g3g<5CH?YvXUel zBFQus6#=+zqeB*zW~hzbYi~-XfEV68u=eE_R}DUNAXRv3(6Dki_tls8jBY%3IJNVU zC#u7CoVoxRrm{S9VoPn^#!-XY)|)Rb3zdHs+PvfFE0h19KJ!3N(x{)ghR3y=;G7M0 zqTl`)zCANRQB70SjI3v5sCtI6f>)cFFp{V-Be$4IKr)*nuB4+>7SowMkoOGoQnx3OPRE$1=6^1mfM&BRla5Ei&E+ZTS`Sd>+@EYM+{_NIl6 zS|ay`XvyAC3E8T_1`-aBzb9_{b^H2jEza$*eBkkkfTEof!mVvOjm5#RY@5f#I`oXm z8{=6Aqt$Low?)^qCBnGn6fwO(9O`$a#EhM5l|G_;A@hsLdILd~2$S%Y9~a z@>w~F=cjR0(}LfDldda>f*DO>1)^?^YjDPP1Ed402o{2xmVcer?7-2B5Bfi5Q0Lr9 zO`X1qyhuP1lt6#4M{KM^@=wj*x&&)NU2S9v8)2C65}5a3I5b65^+?1YjmKa&nMn8o ze%Q#SeFA=0z=D7ctiD@MGsp=jxL{=)XiS76!6_Qo!{Ml3@WE~}5Qrt>uz4dI)woU-|aly=-o#P*8%wf)rCckppYvB@W(kcx&o+`ma8D zJZbIl^A6uL`_9v=i`~QR`s!R??X{ujYG;Q-gFje>qrDq0jqC{TA92mHvPK7nGw0rPwHC21XdX^ z!YUhK!x9FVCJkXgtHnBlo-klE0_}tW!#*0nOJkZgb0pi^0eTCpW`JI!WeD_5O*%{? z0zF0PjRpd}PG`2;InH_o&@}<>9%LpM+h+bJw4aV^bP;k<5Ipe!4M=Y+M(f+Nzr_FW za)YZ@ur1}q_}spDV0qixv)jbsiTU}v$nbO!J?M(LpV}(UtzrcF%izwkNJ3@w&$>hy zO{2MxBhbYFUlyuV35qi1BnH`-OwQ`q9@P-{$>j zNijB){x>}=ljeqUX@AP z4TVZp<#M*+S~4Sqv%JdLLRBxJm3)I79B-m}H*B7?Rs&TEjcmE8el7nWOfT4)Po=jM zTcm}1?pRA2ueg|drttj1#|@13!lv(U-nWGAhkKrlo=a?re6Hfy8;Y(U-|_yixTBD0 zm4cmAJ}~(F+^b6(^42HfoqR-!RyXeX#yu5Wc6$lDM2BDDK=^}sfc(9SO zlK7$5^VGCTwAbH4i1zv1LMYgngRXzGU-q$0+-DsB-JN~T+2?nk9Xr@Q`}`KaCbsk9 z;M8YAoDipk7ei<|mx3C~cw|hD(#=f@%`@XyGZ$bpXd91el7i)zNHh6bif z)H(Ir61foM`8iP+#rUKtgU5YkfD>yJ`p6Q+!3LYRak!wAm8?y_C+gs&5yzg_Ck-Av z9~FYq;1LLfo1?hb7-NKpL|l5-i2=JPW{mAJO;TD!Qw?J>;geo(FcNLXti$0zNRVd^ zr_1GZa=2Mw;24YR*&5+Gkjj`Y$kAucG+xIPXgfb?g!Gf^#|o(#@c2*5#Sh^p z&GzkWGf7BcgM+sQ-qg8=*6e+%+`FoKU4Nf>*`coIUw(Eh8SKfe3CBOW|3?GF)|GFR zi-T_r5W!u0wwC*CM!u;jqHkJL{`4zD!=-^EgM;h0Q4fL)*ZzBW{h{L^3Z5|P?Cn$x zv>=d;2-44~KY~1(oIrL+5v$3ZWq3F&Rc}|549~FHDCQ2ISZdS%7&l7mhvRw!UOyAH zS~jbqG!|7{U(^9+meQdh3Q!ERMjWn}kmtu?-q6&@|C|ynmI%utm;n)Lf{`MLg3>4# zkVm;dAcC3m^G3Og&MCkRCGLV^mdd&SK4f;}0H=f&Y=#JhpkQS?337FxkzU-KVNRaq zXkF>VtG+$=RaU-9xc<2R{>@^f`TI}o9k{&iU!yxx`l#Q}?Oy*g;?LWTJm?+Cx_`BK zq<`11OU?e6!_ngL?0)ve?;Oi@zp~+RZ^gE<651K}$rLqvfMPGYI)S3o?_pX#Yz9Cp zh3UZ>SJoE1>diRvKNdMSS=zL{>7{PU%QMETm4`bF3h#*WL`2~ok;XmXU359!5w%Gu zvH;i*z!}s4z&nr$t~;S<&yPD@oEwmfdShf`gp5QuRuDQl2!|75vB-9w0s4K2k?1$b z^cxyjOkXvR{-f0?Jm zFJ9mAjaFy>jAXwoEd|Lo^mVuSR-_W$i5K>*8HulM)j2bdJ$;@C&KIY-^?{ybV`z?& zU4qAgmFy{Y=7S@-Q07>r`KtxJr*-U+?aF?Q3WJtz^y3NSR62r{I-+5F1Igl!;FM0_ z6lJ)2CunFbry@;nf(}N|#a-Xp)-X>uvQoqtJ31#oRQ;@VCq&n6Ud3CZq(97+&I zug9NIbCDtg(87REjW{@?kqrQPye>Zms52&rM8ai@L}(Y3^SIGyqfZ03PG~~R4Oi?< z3Kny#&R9lureJSUenMO3c2!Hhdqd$py5qVsm03$=N{-Givtu__WgWj%m57vmnf?rX zxdZ)MG_^EXxoiqgn(g>tuPyAIo4%ShE8yJTx@HHG3L&^T{ZC6+E1$d*@NF*gv+blM~5C*S=bhM zwlpN`quB%c^rBTnMl`L!`t)OIhVTJ&_yRHjD>*2X{Uu4sKBBMBe-Du$GJQh1?7o9w zSaVmwplF+4SlpSI_~MdcR{DDh4f3Zm1#wUDp?+s>jmSx&At41K=ue{IEg!+-;t1n| z6L+xV#$*YY1fvJ<3%p+AqEkj>yhcIL-f`AMm8`jVL)OeT>a3D8Ldr5$ZxcSV(%dSC zHqDa1MIfnDbHK`ERURPQj*3Ln_*-2>5jPSx!~zeXa+t7)52@NBqD#1SbahAa;SMZK zXJ`0sV@zZ^Bl*1lc45}DP?*hWvU;M;Rc21I;h*YV#+!9kyG15lS6$AWY%NED;fk}!*E+RK$ad?yGn#w>^VE9w0 zFja_6!9lu~?ToO|novmaV|0KyZMSm(cqX3|Z>w+eLW1B|zJOa*AF!mbDLwq~hFIIG z{@#cG{`R$_V-IcdyOLBsTIe}? z%~@BQ)7eI2_t7%iEKL*fIN_fJR%XmjpEaMM45&@^6BMG@alIa;Y7~1yRH;1Zj5KMv zBz8`jozv;T?6^7X8cm@6)xcd*QyMU5d44!IN)-dN6n#BqFkgQ0RygM%cxEs zf9(g==9bkh7Wck`*WP*mxfeyp=13@*dw%b`hjt$H2u-^!h4vNs(ZR}bB4}##sTi6u z22Zc6u2^~asc)uUvlYc%rF~+zy(wijQyQP|>qDZ~0iHr21dXajh(a2Kd}g0H2nPbG z&=sCKdqq?u_@7m0zr6FyJO3YdQm94sKJf?5(xaSV&fC z6lANk71+64}rnZv*Cw{Ne+l^*QwLaO^Hyp6p ztenNA(b5RDr2oXTQ}xmXL=pk|kZ>=sU?X?Czy z)}r?4HJsyrv{!9xQ`Z?j=broJ&uhnVoY**yb8X+)iG7pU`7k)KA#3aq@y$BxGOaCRN{9MmQ=?8QTDNJx&;(K-NNjVZ)mo>yLn95FRBxTcK9nw+RME9! ztGoAHJ0D`u^+%WJ+Slj2=e@6==XsxVtjcDm1p)@T8w07Jw=PuQmTl}Ah}dO+ZLG;$ z?@^;Y7>CMF54U%lEzORm-cEO?Ular8I=Q!D7vEv>b%xt`M+XknhwSE>THa%)+8G4x zToL+E7*Tnq);h@LXFlMDg}q5kxIc^k%G4> z1@9xIpth#sDjacE^<$0Ny8ix95dhT>kk|7__5_F&VBS@I$5((G=r~6$z+IDC*YO;>#p`Li@Dk1>+NXp)&wZ*E`P6Q2w-pO3`d3fw&hrx zyt^&jEUVGLL~B@v4zFO(-+=z^K$ma8$op3rhNp;n*ox*=DOF!AhZEqsJ|(6y#VeROhB3dpscuan)$=!EF?l=^ZvGxfnSx5CTm|(3 zErWhD?C(LpF*tPW1o!*{yNF!YJEKHb-DyuGTFcXaB_!*PD*Z+ukCox*$P`46R7Fp!MzH;hiFZ`Ls>) zXNT3Us^x?Ez{U?y`g`0vH~QpnU^?TiE%N{6{DD7yyS$2j!u}S5Z3~Dn9A?x~0jX-S zqupVb?S5wXCxwGh>;`ea?w^=PQl_*%C<}&DBETInNaLXAy>dl<% z0`g=mDu0e=c*GIJKzRinh*VMAsH{@eT19~L`g$H2Q6|&K2?j!pteCMm6QYr4u*e#X z2n!s-27)W!xCpZ9Q&TBa57|q9Xf0Mgru4@sJuaa~5nO>>VP&Oo==}NffZlzXYLo*d|^WZ%GuR9OR6vdD-9 zPy=hMVzQwE${Mj(X!{|~l@|voZ8T^3Wqi3x+@_j2RC}F(5?BNPuW_bhN&F;0`6>W} zZTLj_JDXPV$eS^7Jj-w#!(*1AD=7~;DOK^y4u?*|8sFtf%J|#mDHISCy|=s>Gs6%; z;0cc*570^FtRGm_N)CDja=DzK{JWR@^8SbPwNm{QT7fJkb< z37{_JRUPN94WO$Sm#4Dgj%@aWpJnw9oH-h%k1YW*xI-psRgEJNU_6oNO4Ypak(>sA7}n}YH|yYQ`x)#uQP_0GpE!K_+> z1x5Xf#-V2eh4On4KAVNdfa~u>@3MX{84ps>Pc!vu7>hQmRL3CflI%7ECQO~*hHW>Q zSCO4rL{4V$sxRzV#M29$7-KL)Cj^)v%wnc480HKysa?uQ-;h|Tzd3B}H};z$IOEw8 zcDwvIjmPk}F^l`_`%!={_dhm+TwrBm1^bZ)d{WliP>3lfB!HZev2*y0;B( zBYOvq4ltpC?t#GpQaFlVe+vKV5Pstec<;fZ2bq0OPCv=~D6$Y?4oC1pjcx<9`a8%8M;XzYsdD{})soG5OwCz@9aH%?ITb|L1OIop@EzK0;ng$ay zrPDC1X&Q7%K9wrL1)?o90q6j5Bp^w+r)Xt@#pS*cI@-pIrd!~zrQEGoX;=kI3@|ckb(lF5Fik; zD(bel1ksh!t}JTa7914LrdaLJox-p!3=gv4(=IHIr^Y#d)H4@mH01iC(f$ELJ}G zV4J+w+4A^vw+`Vs&1B`>`QqZYDwnTZygodB^Z0zRHVHR<_t@dXufKly@Uca6u}FE< zIoPN;Pt6`3e&YMypFF+q$l`C_JA3v$&E$NsSiCh!^j7}zvAD7M>%;}ZRlHGv&o=&% z{PpZ(?FsTb@I7FLoOpX~?(Lt?%~jqZdT&h@;p65h=jfR~JoRCfFjf9hx%Pjll^(8q zxbor3hb#Z5ehYo2vV}})`w)-%W)N3BKh3bRwOqYAZDwUlxqAM%ft3+arnDuq$y6q9 zl+0!V4+!aI$SSf)(63&Cas^45LI#QxK@bRCGzNbx?o8WrJoKp!I}dFsnQYsc8OyI* zw_-=OnD|0RSJ2(zuDmGj-*Dt-7YO>s`FDnw4Bu{u z+DE>O&>T|!lV7Jn4kDuYK5ky2xw1y)dZ)3n3iFhpuB9ZVa zdZX<123pJHwUX5ufI(^I`OyQDQ~9B8rFU|2YVF#Af$`DNsi~pfC(GnVrEGQx58d6p zW%6Q)rUA|M69_d%!lneA9v8((vj8_Sgy`ZTUi;8ia~FX2M5<=cPGCHS5NrI$CJsgttk`kDT&QU8K=~| z$ma7+Y+e!sc(=&%>KiB(B_}@Mt8AtTmZhb|G~5CQTOJP*DnQ{0FT5-*b>$_sO<-}E ziC-CMAulb!Af%-co4O^NXO}Kzq*^Vih8owR5MN$R{}hffH* zPOH-eW4Bkuw71tr;Rs9cHk^7F1v}TKIG$H`xN{EA(0CJ_x|&>cI5VbpeI(-W(d;j? zt$c(xI{kroyn*z3{0>RWGg@=h)o5&R(nOGMu$#vFyAv%P$wJQr*Rm(O=c^ZvX&AoI zZ!$YLV{bl@iFN8I9ZcwXK5X^JR=Gp;3LUBA?H-LcY<1nb+_*gL|=+2tO zcsOs2@9KM!F?pMO?V?RI8k3=|E!q}cW2-Bwwck1#@uj2Akh}8{kF&q4^U*-_;Gg;} zvLzS~MmKMs*p*8Ucr80;kKSH?2F%t&jP3^0QLjpRan30`RxPr`aR=cr*0Xdz3cMPMkmdTGx z4Gne}6h@=yEwV-vbGyQ)V4E1lAQxp(^c)AxAY(L!%arv*Ear2&T>K1WMLuc4nU^vk zvL+Bw21M6{b%>e@g$pd!h5(kZ0D=)z9pM3lqQ*OhyAoXtYym3A+e4i zur{6}-gJ9flWB2OYizPGPKJ-_i|IgCUgNQ(Z4@2g&8$7cTT^D6_Dg=Y$r8}%Okus< zZ{=_PXkdNIkipY$+DYtvf8xcq9pbZ<=UzLD$m)kgggB>?5z#A(nHNM%MigU0$QN89 z6AZdyn2gUSz;M!q!MI$;(?G=pR4`u8UMKSf?c7RrIbARoq|v)P&vYNlzX zOwpz0W)bTsnQV!K!~R*&Q47&Ib%&Jl*pgW6D^fm>3I(h!LBgH`n%XZl2_UXi5#0{4!c%|DLGWXX$H@4?oG=pL8p-=bwZmyQS(HS` zYH4)%I##+kv&ZJP87(q(^SAZ%g{)X#D!q2}!x<2qnn~L*GjWNTC@#b7^b)gnSQr3t z-NQ{W0k}4-v$i%-jAEUoQvO-cSqI>|Q);$*05055@Dk?tKzz$;k!Y#I?{~|K@lzn) zcz+o|LM~5NN2$GM1PQy?U7|K|vLdJS^VS!a4-^F<`4G%bGy->@Hg8EY5s2LIp zq8fC}Rb^UBhV8lF?FjIk1Lx6N2&f0dhuZtXOQlt7GMjsP*p7+R3r}s`Dr`L1+n?;% zHWc+1IG-!#Zr%Q9op2GKd*kQ{3*+Lskjb+$H6ra2QhUa>?|5S4%k*a>{)ju3A*yvl z2N~yflsIZi%{XFJAvV*ORM&V-)xBbXaMgrv!2vSxyaxx!Y58>Pz%>e(YFerVWCW)n2*Suckw60dUpdF>Iw*zv zoFi8k9646UIDlXy5IhG2IdG02&miX#!8ShOmEBQH(3D8Xn4m1b;wIb}qTVdK-Nb#F ziD~n;wx)PK<#q?Ld2lJkWR_D3)R3vvec9??E^_tXE|P{a@*W$xghf4aFUvY9>j8x8 z<*qmC$#uEpwfIS0&X{Mq`j+O;pwLeA7`ifpR@R(2TCSc`?9kM-%5aFwFtw>`OYd;c zdeua>Y#GLchledaL{E>O(wYM?e~+HhAuX`YQyLV5k;9I_$lNK)gv?m9nE9sO4I8#~ z{gd%>k8SEa!}xdn9sBtBdVD*+#P>@sc1S|(#7X2NP6*+W3#6EY0xp+9##W#d+Kx+6 zt8Rm}T^qt$AzCU5NL?w@5J}u5v}{O7o2K@UO}lhAX&n;#qgu930&Nl`-urz%PHcz) zBH4~X=)Aw@d7t-v6N4QcD~MeO2ZPZm46s$I>L3OiS3|r^B#p+j?-LmuCdiw;o`L_w z>kVGT8ss2WCK(cO%+Ni3hM*^#!3Fmz)OBRPcI%cfE##o6gcn)0XT(EiW+*3 z<)nxco0kXZ_8q6og&2B-c zJo|$`+nrxUI^&7;!{6-ey*FAyR_ygI(=CbZOvg?{7;bx{1n$ z{{9qEIh9Hz91V7RgCc)nDHKd~HRC5iWFQ)AV}?($4mITas<&;`s)2ZXAd%=K8V?M( zVH9h|wOUjQ?-NOub)%m_J8eJ?siIIT)a84ZO17(D^Rc{w*M~k?pI+5};<;C9-!XS2_jVsi zwu)u71_S1Nz8BXdJyzyBrA3uxufjHUTmB@{plbByG}6=AZ-^;kAgEs(G>45&BB&-9 z3@44YSU7AnawH6u(5SM!XnwQDQ=!#X7>za%ZL*?*Q7SnOU&~E+RD&3zi*N@tfb_E& z9$27e78StP;EPG2XL)4a-Jbmg^BZ8l@NUdK?wH%_n!?Pa$0N7dtX5Np3Y?OpUhyLp z?Q1^Q*E|pFBt~*3T+r9I9ScU9kqp#MlX_OlXXe3Pg#%5p62n!*<(Yfk*Y}Tv_04Y4 z;(GC!kMNqtj=pNXYxYL}`PEElS!z7JEwJ5GQ?sJ!g^rf8eQ(rXi0k(KVRm*jbrSqB zU%!Y)$aa>!nmxzd#vec*2`D{D+efd}0fuowVD9gjF`b|#_3QP;jbemGfkK7b57tLE zuUv7(Z2`3uS$~*5{({Zt?C`+E&(iaWcod$O1w*N1)p9Rf101rW3Up!&$uKZFC9s!5CHNc9RX z-}t}lKi|{Q3sv8&S#fPuT|D6R>02{_gF}038<+6T=DMcuv7en79JxH28l64<#)`cz zUu*Z~{x$5yE%wxp%iGHwOEndNXmdMav;Sp67%4)ON;#@U6B$;`+z-Yehhqu$X;($0 zQd=XqT;dc~ja63G0HMqYff0mq0*PM?63nkiKq*#MXj%J|Y;Mx4cQGzkM0pL=Uy35w z1Z{2tT*55^EA5!I0xlcmq@##eTDpy-le0Ebz%4ybj^05E1szU}@$wu(QM6ifEf0Ui zkrPRVC4#c!BP-)ocK7D!fzw}pDAQU^9+gGswwpb^k+}<|p&fop)6#_e*AmRTn~rQA zZEEw_27lA9>{9x}{$Sg4Z9jRlYZqhK<5?ExRlu=@3CS~Z1tl6p6Vu2hC54-`$o**5 z5?Zg(VW7d`0gzsJcPtKcl4Z4Cug6m+C5RF*mP5*r1To|i#9$Cff@q5p^&7yt~P;q(EfAA%l=o&aniILcyz51dUQ@2nGWIk7Oea&Z-7v{7yfEoP>L2q%9C&c}0>qwoFI%&te-Oa6_MgD2d6>_R5cu55t z8oOVGq#8aLA4)%?=NXY8cN{_Tvms;4oLQ z44O7~>R@bDa{+ql1hHbmB(hdL8KN8~lJBgTlkg7PW5b)Ad1ejxTc{0nqR*2$H({ow z%sh-Rl|4_Gb+ji5vrb^9SDRv;os6kT8EdTynN0+e1;Eus{jntkTqqPJ{)%A^wMvUr zva^GjslA=mHAR)+Fq{;cn@9YNKWeh*%;s1$il$^=k9Sp7(M8fJAr)>>rp9@wK-1Vf zZ?hu2nqd@`6Nc!>fmeRV;UD==}}P6hU6!`BLa& z<&(jk?Uud%(7G$zZuUjDHB?r`d@ZtiPtU7!ul1elV?rBuRkVn~Sg31o_iGF6FTK2D zoqeO6M6H;V?rO66C^-Faw7cX zs&Bn}6xR-S53L+n7mc}UyLJt~zWmIgNMa86TDW>K!#(`mp%ZlL zUU+tVmR@D~uB=ASCv{c-=e^ovo4D`z@9u1$&+j|O_Sudd+llSi!2~;g#36~#4g^AQ zD1q{Zjtwz{%6N!91XH!Do78GrDRd8M(=^sr>$-_Cl0ZT_I$EhxD-CIXRoWkuCawFU zs-jg>k=F9azTe-Soe<)Nq-Y}C-7k)k`+i>E?-%tYQ+*{FKX~#Q=!@rCg41+}FihAb z;xwa>I8MUvIXPZ&oP%E@1!0D8O44ec_o7PT4;ycR=W0S&j?tJ8AK7H=)YAT9=K1U5 zBJP5IC}x-8rSUH`kg~La7In_!am>oyvV5ZevY7swM|#H|_Jv|u=mvS78|pr2=zxam ze@OV+%%o}l)wxcj5718Za>Gu9ZTcF+*#AErsNRZK(tz04s=po%JhC@*@4-fU?-xrN zMC(5ksS0^Vu|*Imks{T~G->@uMM^O~8^TcFju7 zM4`WHT)v}NRmGGG>^k)^(rGt1(Op)n&oEubme8)lvb^1{=h0_8uh-G8qhGq~XcOQf zzGDyIlKWf(^J&F3av;3Bn|qyhou`;6JFYtl=}=XK!_L!AmglV!Dn%5nT1H%zBvCY4 zk$b{^GA8Sc)9h!2S7qS1Jp*qKQ!bH9_vqVq!i(>RH2_G=7rNZI0MtiVcKp6l+-o#@ z%mF#cJeTP|Z@;t=X81}f)*nqs_VHuSr`~yT`ltVacb$7T?hTq2^lWfa+>cKl_MG;x z^>A>T&7vD$+vO4$fNx@1m)Y%hxhx`cjTS7yyr2Xb^{W!0R#GQoze>fTH8F3D zTpVI9FIJfT#`zuR??{cSgKFH|?CxDzBuPAO(*68tPBVN20X&HiH?4xDyp zr)EE(?NG)Y#%l3mwLVT5v-CKoITJB(#tEO#>vh%W3Rx{vjPD1XU5-!Hbp(m>ekhk_ z#QFl)!8D<>RPRAm;I%?NpR1S1eRN>-%<19vPxL*xaf4Vn*Ymv}J~OsDI#3*quVSL# z_|}o(jZOBD-`{Taj}HH9-F2w@DU?AYFG2JFQ9;{yMlGTW+VesH8t0vPD zXl#SzVTz3*(d_pKxKJlvru_HMK5e+b?IeTbv#UzTA!dVsgW|J^*>DJABbJ3rxm@YV z=2lfI?YUeWL1+gMye;xH#CZ>hpO96U?gINUX@R?)6UTMsbatBkoaA6D5dq9xt}L{- z+v6>9HXd(%lheb%Dd5H;ShIpqZmv{HWu{#2E1TdW1r_R3n3e z4=o{%(6`nZK*Qw=9s@K8%EKHD>In{*h|nD7J~3R_(z~}a8SdP3c2)74FaQ0$qodI?3fA*(nAh#_edCxx8-pcds4tF#$?D4jEVgsEfHxmuF#jMi4ohK{X2CKi? z@yFfy6Vgk+S^wQ<2e$p>(4GzDTcf4jKM#1bfwir@2fx~}Cg9E#lgVS%=F)eN)f$U# z?h2_*UnMR_){@^To*dGuvr1wj8SzPee?FN6VHKu1fpk*#BA8%;Kqq>U{rH+LleGF{ z3FI$1dvj8-Ws}Lg$A@P><~*E8vM<)z+O@l!%|rXh?)JKE57 zgFu+Y(v7Zjf$KWp?&m};jjqB>rRQN0VI~X)!EC~SG8%_mj%uHR9F{dtmdjOFHf!%{ z>0)7^LQi%Rm*z>AtJ*#?QmQi5>X7D13wUxniBeCtsh(_WYp0%Ufw6gco|Ltjjiw-E zVQqX{%%y5n)_!t+YO1jb|9Ne&dkiktKU2N9i8(Uz%5WKG9p-N<_O$+M7j|5@|KFE( zoV$E}`}wRT+Do<5nU3nXr;6utY!$TRB*H~sQK^Sm&gMnOrbu1W;qWS{$nSBv`DJG*a=jhLSvEU(5!K3{2#;W@6w2K0|@SFuo7j zpC7^s{e2W zaq(GoH8b$xOy2nZoqfSmFWzrpO6l8&cOCq3V6?nx_Y3Pvubds-xVv<4Xd`p$E2o&~ zUynT7*oCq1hOaxbZts?%@3ZMb$dif1;+h93(r)fL(Ka%}yIensk~L)Sq~z3_1gA5s z?z<^O+XIgbW13cnqluJ0W``x`^KqwB09)LpJu@SK_-DL;7^=S3Bykf^0}vG)UR0tCrxb%$`8e|p(Mt?5*U z32_5?QhB31B}kT>8Bh*Z6 zNmMW3eV*GNjsYw)N*)hdQ zW5Hk;ZsR5sv$|&bwG6@rsLgcYS523+gJA^R>qW>)UH>D!>|>j_&p7@&-(8ID_~mS$ zFZMaPv(NVVC5aQqjuVF@4uS9z$P2K%&=@FC0zpG-Lx8qZOIax$qZ`nwRkyBXbW(&m z1vPGHNYUO9>sBGPbYp)^leP&}>K|pRwxJDWN%s8iZ0DtvQ3ikH>>Lu$_xpW5&-36z zv3`C*_9T*uOlkrHvJ7iHo>)aiTKM2_uz2&iTNtU)Y1^wS8&>vM9d>h>#nq(cODy%# zwR*itTV|9hOtkSr^-Dv?TN_{ByJPLPj=q*vMD{bnKSo&DMEN7pea~!tdc`(j`8VQG z7pont3lTbM6W$C>vjwt+qi4^;U{-(8+t7K(ZJNs zr-ufz-~D5BYjpPZC{x<|^=seU*}cZQs!G~$aA@~Pz?m{KqFmpYthChz!tU3)BYgu0 zkH65}R?2AztZ40Q2YHhm1}49q)_qD5v(59waBWuGj6lx zG%Zs#wcL*3JvyRZU3py?fMLbSqk;;xVW91ob9Hi9h83w!&N+wA(uGiC1HE$3% zrarQ)EDs4U5`MwIV!0+?v7M?mzRk6a#4sve*)xhKv%Oz zqJ$^Mlthjxarit@*do(9f^agJE)1?&R_P+k*IK7X$1eeoYdw=f&(E2 zV@75o5>3V6g$9Z$kK`~Di8M+WGb|g!En&C^W^&ujBGxS28Z+vd`C!x`{@(psx8{Sd zh#vaXsZD3@SRQ~s8kIkEDd=B^eg_0vM(8ks5;+3JF@X%2KqlU#nO_?Da)}{1nW~#o zRiCiid5+_AFyeUy?xFdKY=eH1>Ogq-cY+X<7{(#xxg<#riVEVWrgBlunQ%`o;m4V~ z;i+Io9#UVh0N)WT@(FEv{FX#o$L3HEOpl;uP6?9(CJIa1#!0&;%+cwP%*5- zK{*wMF$9AdMq!501WoIO%S!Jn*X07W9Rh2>Ff*7~mZm7ljbUao>6XGQzpO7J8oZEM zxYgVfZW^Ke&GnkLFD0C!$xQl7FsIfpEA^M76ZyLY$`4J89FzD*?9r0;=J_-k_61gByJa3BTa+GJEb^b_MLcm3L%KfsC_!zQ6 z{QEwDm|NEFNktOLaF2A-!|)_Q4HqVKB1D44L@Z|Fc1*(ULpv7Ts z(Lq9jAdmn*9g9|DxZxrk=i?_e{}_)%d@Xv?g3@>eMpek7nMNWqgVL}(o6WW-if)5B zYkpEQoNVgfod|E?*igzH>~z!Zr?#J*eril-b~<8*_h$AU9Xv^O$?fH3>s>lTp|-g} zYLq?%m1$7|tw7haoArb)w>994ByE5PPg<9+^&NtsinO?Bny$v~rcxoy(sY`&UnaFk zfa;4$2C7F;{W}^Btu0b4r>I&H5E`hJDke2E*~Ug*f`%cXVU|I|tb{uTH;i3v7#M() zB$-7P!ZL}QCbOVx7H2~V1MZ!A<=#}aTe?ALaZ~^=9&e$E^0Nt(C=mxPEsjt@VZ2FD zv5s@?E$iW=ocrlpv!DFwiDv^+OSsg|7n}F*e*ebVOIlrEgWQ*FO||rotW3S(GPuK4 z6)C@~g7%*3`QC-on@>;w{#Sc4UA=D|JbL)BwXJqtqP6*GQ+-?aiJA(|$_A?*esu7_ z+2^xwHnc`I`3Za+BmspZE(P>?AoTi;+UZc$588`0z zFX7c1+{AT8@9s+0TiRW%q}9XP)oW!*NHVLJEi8K-*+@V!P&41D%FxryV9{CY@#)Z1=mnlJUet zI)1En-u=T{R_z-kp1r%2pFaG>L(d;s zbNJJj?jmPMplKqe`$J0(TFx>eb_sQWkO2S?lUXrk14JNDkFYRh^Tn)0NK&1eByTAW zD`t(=Dwiu=eKom``O>TOU8O82hh)lx$^cOk3Xv<|@Pi*fB1I0PK{46$21AhtH7h1j zF_|Gy6rm(dgQQ{aO@L)M9F=14B>Aag5f!CU>8jQH`no15`hufQ)ay&G!oEy^_*bAD zh+oFiXY#UK#8_vDDBhJoEPxv)s2rpUoVC1JumPM`!4B|mJd2bXU{kDS1U(Ac(@ir+(~UZ{*B7=^nDB;Ugg~V5tlL$i7bdgG*H6_)M!C* z7_nKBqS44=Ig^3%N1vDF;8hqSg7J1D2F6Qk&Q8zI9bXKZm%;Q1AB>CSl zQPiVJa_ZtDtCcmG^f(OAEWxT0_kt{W`a_(E;Rp3Vl~R|Brf#iU7hB6Z7ygRiZ5#`nx~As?$)+c-Mjx+1+iBlU$=;VC!Ka8rLp&9)h*mLU%`i#>`Z zC|YfKKbA`fCn&f&!D`P30wN$Y4)xNc=3#`IOJ^b=I-R`U1dZ(aMaBgNYT_?b_+L+* zi!~Pw92~;}=EmcOh4+rSWg7KBYgKcl3V*p9%LOlAXjC35{z!Fb)AI6@qp!ZQu2xD{ z)~>GhCrZ0*evi~1atEUa%S0>~snkkmGtu6W-ZH&qXjjcs?#Rm4kV}qt8=Bq$XLVD5 z!ygd!&u-NfbbDamM$xHDs09uTX5pEf{i8xdn(&DhCNJP$a~WCeHN&w(;2JDqAS&{3 zXH=sid6^=>pnk1b%=SD&u24u61C4Zu>y(68H61dVhcJu_*D345I^_lWV8|MMsQ5cLQ29 zS~p?NTj$|oc}vaAI@B`P9B>qwfGA?MS}cYua8`^0i}d)!^uO;Mw2^)9oU&OMw9^0& zh?9`7KAwJ;xD{}&7^t&;-8+z^ZadEI=}xVAV_k0L`G)H8r*l(($9n=52{Xx4JK^4_ ze)|8w?2+ya3ZgjLu2^*xAw)#IWOTXgnBbx)VO|@J!CyB0Y{HN1qM+A-+09Id4j18a zMbH&EL;^)9C$bREL)n}34KJKwgKyf?sj}Org-ZBVW2LJ1Ieu#!S<>tuNR0)a%MtJv zP&_A7=vcj!@CMiCcE57{G->lV1+&W@^m0Pz*vuQw`!~OU~R^lpUqnv0JBCH5GiEVdBA_?~-g~r<3Z3#6pm2v7S zmu*G-6rq0GBq1Ei;&#h4V$Dsgdw?RPdAsHSJxv41VQ0W^!+R-!iqqDknz*qUG{R=F zR4T$t4K@r~EZ>Zspa2gh3izm74L=kYjmHx^zFZqERM*{qf8q^W_j-h&n?)G&*#qD%k0AjFl1JaXAcZru!-I=u zI82-HRhAus=AJZmPX}OZCX$(;DA_YM3ECp8%M4t`ZMLKX40rmx&!;YzWYPhtbP5%b zgYbiVK2&w1=6AeG)e572Bh6m%qsC**zz|kZ1KUCgfK@#X`>Nrnh*dMbn?GTGmBxuMKnHyz=Zr)Z-Kfewaj$U!WE6 zSPB-1Vzsb&R)Gj@;miRHRV)_5P;p=>X0!cQ|6{&fW1Bk9IR2h z+J|XEVwx&cu}N#c?8_vy!a$n@F?-(koCF6Yu%NJ2iO=!lK~B0-#MY*g*|ELENYD)Q<^)uDNnf= zZOqJ}BX7-ibO*oD-p)23tvm8+GU%HmZG0aQ4n-Vgz3mN z%8N6Ogc|}A(u%&0?_P_ig`_b(9`dR;SUXG>#%}K{tmV?FCWC>|wLg6G@W$9rzPW#Bo8mQg-|u2a zjs&Xr7aIy9b)5%}CDL0SesOy6)Oi>{xI3f5)1`au0^Le zaYn1&$i1UIr==C3&x?>T6$;9WpZffq*Gp}{mb2g=EXA^srqG!dswKl1FEuxZ+s;I& z$Q6)Et0-&el47pNW^1@2I?~zZmL}Y|P^dN1hKFq+OohY#G5|@zoJNEEaK0eOWM$|Y zphJM1gPUg)n`g6?;pUlgnkSl8l1K?yQcrpZJ0}F~OOY4g2yjU)h`!G65iP9;y+)Dk z0zI)vyva$MN-=H{m*RHfW-qodxYWV<^Y6Zwst)uA^rc6qvo}6}V@9y-ta4X`zIWu- zsaL1VoW%$9d}D8GdUN7@c4une$k^z?6jh4V?*ziVt4_I4i? z+RVj%2p~#_nBcceIA?aY3bN`9U$=wH-%_*`2 z79_`$>vkAvIjCI6BbT%ak!Q*DWV<9GV)r9`8#D7yLJa|(l@%)9M_s57rKx~mNaPJh z>G(uiF!NkGy=`K2Xaq|Ts*#a_Z5jIR?9k8zoP^4O0bgqvzGkf4*MxI`smG#hk~<4y z>?tSZ#B6pteK8u(GlXLNZ|Qr;2M?CmrWlMgLpmKFiI0qqmOE>jdXzDfg%vU+8uEN= zYnY-D3WGFfX@>!*n(Zt!YG%hT}&B1#bNNR=J%y8KBDM9j-LVQ2$kELh_TR~PB2-6!Xwz#zx znevsp`zg8M<3rtcXQJHdFlfqjYO}w()>V{OP+Hx$F&XQfto3)=%pr@(BJ)~fU$LcS z-)Z@FeKLEqq_jFvUpt{FuxiydwZ)yktKQMT$-6I84EsSftj@PNhmv zv7Ab!2Yd$@A>Ya|OhkVTlo$Xd2H{*uKb&>DBbb&pkfkP>Dsa74J0vSd(8w}RsQ&W>QLw_|l{7i{elu@znmws3Z2@m0U%mvBPz_z9_a{9o8rL588_S#N6L z|E1)_2qwh^kf`X1At9_6zPNHz&6Qo{I#WZq)>vAgE_azdDTmpxe*Dtej2f-rbAq-_ z<;{^|b785zL|*{A9;+~fSq3V^EE}i#E~9o}nEEMp>EX!<%XKul>@ zQ4*jeHt8dFdn9mmIh(GEY(jdVk)@Q=6B@yv>-Aj;ez1G2t4mUF*Vxz~R&XCya9@To z3F<_5fB!Jg4|jD%LAmq8!)wLbc7nC=v$3{JlDUE;s+LfJy73);!aDFGTjH6iAEab5<%&Q>2?>UCk( zmbGTe=jF(kkQvvBIqSw2+|MX>N)kaHyh!G&UCl175eIW?-TK0FBit&vZGA)9i|^bQ z+@R1k3LzwiAD942gdD7ct$+iCWayEdx&BCyqld^YyS|2ZK7Ne4vsPCeea?iDWI`}mG3JrXke=mKyPZTz&|MhY{9o(Y_?(u8INw~*@rF;HOF#`3y zugQvhqJS;S^gdY;E>R8To=qJ-dYC(1zY9G{5QU~DrAOFLCwFftGoblZ~ z=}sq|q`TAG*s_EyDY485tdnGi1RvoM2vp9*Hq;nFC=+NV&;Xgb(CAMw5MhIrW z(vgShsMihgW_>a-_Z#t=6yBYvPbJ|;V|)!Tj_KwDh6`2pQj`M>X1$(mGsGCp@sq9(<>U6V@HBvYyE6Qjd^ZQg(}&oR$2&;QyJ z=lgIFBm53{x(^~kE+9-k0ECM#>Ty*3V_~iG$Dwbo56{HG=Zk#|H_*p`KJ7DH*GIg8 zJ|eo%Cl>k;v^0O7-LF4^tf&g(u5qH-qJ(?$gQ`uGl&}w$d!vuHC@gIV{ND*z3w=Hl zjGIK4OVEj4i4nX(M&~W#T{n3QRaJ6GDiKA}Bn3<+wn-`#1ZbURGqi%$3T=%jLMs_U zo}T=lGSn4}!Hn6g8K*OXQ2dAX2jg6ZLVz)pp(tRyouLq598w)7vw}R>gF=1-_4oO) zf9VAAayl{`O-G6!SiOrzZ4_!#Es#OKv`ophKuggLi!NuZI+>8fa40aIV}tRSgVrvm z!%lR8@f9R4CKLW@ohy+{gmI)}>#4yl?Ze;Qac0wxbcY5)N=HdouDkz@T<_0+-H#{# z0WY5267*tnBsa2W=TG-y2VV2z+3kD(`qndRZ*Q5q;`@WSeO*Uz%K-lNi8nqyKB;EH zJWynMen^jWs-}odwKRt@>k}-XgHV(}C`zD!adSa}Qi&5vgPg9k%yd-(pGNXTjd0my z)(EelgsYO(3jDe?xj94={c+%Jmg>q6z3n9-oJJPz6#ef{I_T0ESTQboUTM7oNaF0zP+J&LF3l;hGypWfzYIl7hAWTduYqkTMnPv zc3;W#$(Yy&aA7-dRV0@&SD8mMkG7R^JRTJ%R&{E1kRihAwQPrrSS}2mi z5t4m0vE-ioWerU;C>R)@X&F{D*wIItaY+LLl*AgpI z8>M>HfnK#ysuoC!i`q!q1~A}bLUAc3fq;c90~-=4t{)hvSo&_Y(zfYDZux^XuU3qI ze%+~gEwApHIZpTfThHvC@|-a@^!xRj?z$U0Howo*j~qCdZeF@%8MZR1oK0L&*-Ew9 z1bI`Y3!w^J3hNjw3T~=R1FT~fZ5^|Dd>rQifmknVV|k;eRH&!`UA&qic1@89nj+dF zg?$A@41BCCSZ=7IWEy0PMbqJ8Q5R!Tmrshi7>l}`9o6M@cR`I{kx`BHE2@j)$U030 zBkf6TjqQ<9AwJGni~Or{ETLSKF_L}qad}YI$*CY@&+31mM)sUk)B`dIMX4GEIizC# zplgx@;&kImH{=CLV%3R6yr_t7;XuX0gZtK=O#kdI(UdU-o@;2oC9|Qflxd=R?6v1C zyE1otr#`WUJf7|Bi0*8B^bt~6 zGRGOh^pblJi4Lc;!)RSy$uT-TCJ>IjwDJ5|wtWwvj6~V??9MNbf&nGFvj~Gno@Grr zFBbrmhOPn%<+L1L3H)$5i4sDa4)PSyy+Ha2Au2B_1Wq*9#^@pUbgd%4fM?OPHc~W_ zUcF{GQW%Vh<-9x2Ut&$zjc~3JB0s3jd1@~ruv!-e9PENCX+w1SO#YKjURD@71le4V z&cLEi!@yb?k*je;aEuG&PMtl!k&9@2{FZIcsTy{ThW#I4QpoJ0A|%c}2;6+2ansoO zB*9vFp`fD-k%!B16jn57I`C6i_X6(61XG6aKN;$JZqhi$1hSu9I==(r7=j3LH|vM; zr@1QRK-+qe1cUIrTQLee=g?ksi|kh9$Lx569Ybq}zdCtA(XO7Lc2$kZTE(t5EKuxR zALB#<<5C6jD8txzyU}QyulewFM_^xNCw3?+ut3SR57zbfG_6=#B;-99OJUemhw7N_`V;c<`G@rDt3|HTZ2$$ziWoV2FV$Z~dN_VfQ^jk2B_*Jw988%^dWA{j02g6bwICR*!~yiFnW4xtMI z7G`kV1rdug7^a**!;=mk^E7ko_NQ}bYvETNE$p{& zNZU(6xsGX@tH5|yb`M_NGUfisf!l??K4ru%Y!HYQCf_DfpCt@q z<^RTf)dxj&UGaPG`&i!YW7&Ny`+>+Vtn9Kp%A)%g-38$RYL%>_QEQE^N@qfe8WrML zTcz%perTEqNm|o(Y;h)?{6WotLKBoswbDt`beP&{n(4G-Wt>bWHlflEu@l*kp8IyC zq#h8UY zptitfdlWWXw!*S@11u}nz!C=gVg)u84X}92VUbD{A*Rn(1U;N`0hqW5_f+z0G;~h4 zQ#o@F19ty-{`GXj%?BTindmIcOx;N{vtqf}qA}A5%p84qTe*GJx$=b(TEjbdL(0Ve z9hiAyM&?Zao;msxQHnguj1>BXI)U*61w>1upjOr1H<#1Nl<%9(_!F~a(=aoe$=`8r z;R3!D<)Y;mkv=ssV09`ih@e4u8nj-K>n?>(G@-+~n28Z%FbTw%G@Etf?fKW`D~l_U zEHfT&z?v5CaDG~>#|zEt?A2<0qgrimcCJ}_!0kN5y9-Me=2|RL;p#;m)|f#M;+qkV zLaG@td=7(|7-1L|F_`0N?XlPu`uvG#R(OK_qi@UdsAPi)B7d~widI5$b?&7Bn_Kr} z-)}~)_3^gGBS#QUk>qgd*QpcG0ZY|fRI?s;<7=2f7-ObJ1y!llH@yOFtsPi}&bGLc z0R@#DO%9Ka!dqw29p)rV1a=sVO3{zhye?DBLQaa`uoE4rfC9u?Jr!QckxeitUa!$E z78?u&&l**|s2GjK&sw#j3LmUimN=2Yphp^|qTZ?y!a8&%B`m0sQ>vbG>9Jm4=J7Z# zl2hs13RNdslc)*!Yv_z5rw1ie2O5y-aymtYXl0VM5egh34bdoe2LtdG0(tJV1_TAD zXcH5*P!SkZXko%d!6Nd~jvbw?tp`7Q^70nnx0|*fZ%Q87zir!|$9HaTBW(#Axy5B~ z->_kO{N?EW;Vm7LyB2>jdGq-9pa1I9XHF*?w*fnQQorC&bH9b1h$_)}H4k!Dhp+{1 zRdG>~b3wMzDESr)k(Pn{e98G5X@SYgi6qjZ3jUi65;)zvS(nI*h{aCTs=rAvs1Ktr zZ$Wj;yo3>vPA~d&zheD=9*63yRpta#G*g1!N6JHp zR%KwRW^#No5vr@XGoGLt`TdZT7Rvt6H@OPA)AaMjl{Or}jG5O3;li5nQtk2rLBNlD zsg*vVepdxtAgHZWRJ&d8uxo!XHBi<1l{1g+C7YkKxa8_pTY7Xpo%PI@9`$wkIuGOA zr(SN}^i1*}Azu7&lChGq4Xz_gPA1HWH*>0Og=?4XWA>4@t*y2_8;1{P^Xf4x*8D3YEm!_V)bYIe^UN=s3FDQAcQO$c{ z+1>7StE$UhT<^ihwPcKaQUVz9cwbwgPu^GAVETP^)gzmmf``K1FVoui3fqe+xT}zt zhJo+lk1FUKO+j}-Etx|xw`cS+1A2J`+Dh@digm}C$2U>L#d%iD zj~=rg-ClMixq6=9p8D~FIAW| zor&8Bfu$2HO&QA(YMHv89FF&$y(s$Am6jxCgU+_%djyIePH)X0GhDQt#$aT>^AgSedk|$P6Xli`WiLbtWuolXET0EUNyhRy?ap+= zThYv0r!=2Du-we}|FG6wl?4Ci`_V)ZBdo4;ismaSeJ}arKmE+K5%B zDylnzqT0Ms5!J?(u*jcL_KU|vk^==fW&)oJ3?p1(Y)B7VD8LsPYkCkHN1b&6yMH|Y zdbAxlmh-`;(H+Ig$I5Oz_W-TBE0&8bTGdrI5dP@H+sf^$&Xq5WP_zz4n zb%?3cz^w9rVRjaw@Io5yG_{TEK0+-;y9UtC17`0*{bXj*30P`a57eS#s@lwTb7#4J z?h1Ej`65xH5bo91FAE;j`iX@K|^v%!Sp8B?<~JFDR%d z&RTyhnW)A8q`hiG+q|yu{g9OUQ?_MGvi0@KvLq|AKI}-El{)cNoutarVJA)@aZ_v- z7@=(vCnSHej)a!7{uwp-HyAkW{){$1Y)De4g%KLq7#qZlK(?`B(;rKIH6bi87>jn! zz4w(~*_K&L2Ey`dpZA>S-1D60oIAUh?iEd~xxH%GAD``E;&Dosc%lIt%_?nwK z-PG-Bm<1$3w#niuPr>tXv7e8N*sk2T@C0+?V=pR+WS(qfge8lM{60JnFY^Q*Umy_5 zEhQ+y&tR9UWTw-B>2%c6Nm}w5+LX@)UWVr%i)Mahnodq%o@UeNd~cU8N2ZUwJXU%! z#W}ZKbr$Vo$TiUq`WY~CZqe<@b+{>U8<@}5RnlE1JL2i4tS;GL4wIvz#L4*NI3wc+ zckg*2nJAW_DmYGU%0sC`ewll;I(Ta8AY2|V$U`lgW^3o@8lh&`zuJ_I(vAs{i`vsA*;FMlP^bk`%lejr-;TzS6CNcoL2E8`&Qc6R2<6JBt8Z;X!l`KctMV^zR! zD$;C+SM~IXTUI>F4mNT0m}uumBN4Y7PCFC=#DFsI6Fwdhqs3fAB!=M!Oh6Gi8(E7y zj@Tlw^F9+z)eKcu$^7wc^18}T!1K<}x%1%EL3VIrrSep?H%?}=(pxf7ef_d%;!A}) zh1CKtUTIVLs>`q8(4PVWK*HJ5ODP` zH$sNZW?Fwji0zTA`=G8jvZ>`3=%-)q4l;{FaMnS&JCybAfVYJ{;bLT@V}vb?+!haHg^xV6Xq->?VT9A9p^#&hTTIVklk9=3c99M z2re7s5bPd&KlIfFo#O}P)6>_mPSH;DgaJTJfm;$b3+vRYTr{Vdq*u$fuv(xc<6!(uP z?jO zSEEHmkb6WuTBQt#*660By9bq_iniH$)K#^RTSGlsr5eSXd@42vBidHeZgK$&D-UX|J(&{yBbxA6WlQoIc zXLE3UB~8t?9bkS=;yDR3;cNSSupiNydtG{EBoJ(AF}?1C6O2o}J)%$UciPJ5uUVa} zJhXo;&qDdSU>gN1ujpj+S-Oy2%HGLxlFe{l)z5vvqqx-EBNoj?v?Se;W(#Rb(kUh6 z(q2VKstCvj?pJzfJEQMnviV}B9>zlQ784AU9VHe-9tSt*p+q3H)ZO1V8y; zxYP)_=95G|vb{DS@-wwe(1G0D=i*(X_+jrIbYXsWv0 zsGA6$lbs+6+uQ0*@=u5!#vLk4C$qEJkFq=)9oFym*S)(j>IA(DQDHVPXPQ>hG#y>3 zd~;({*e#+?;H^+bolT!jGb5c%vvibf6Lr5CRccnR-1??U^m1vTv{brNvXPRAMoV?^ zq=vt3Q7zOtQlblBzgpt;Z^$T)e^+yRK>tV&tGzE(1UqX^wTwQkX7m87xzWDAW)J*v zTt^kxSt#Cgpgl@xCJ;cu*F3Qko2X*1DY>?ir}8ma^~)(Ts{PIDO?(m;PEV)9^!NVr zFZsGH2A0RPzu({{F52l--(25(A18gj)*f>c{}?*4U-tc|?)OL9?`nvWP_&hpmhV>{ z@pU;Fj_EV@f#rzs)2Y-#>RM_kWh1GM)KqFNHLw5hQVOM_$FLW34^KqJq&&EHB^LU>Jwoe+XG3>lL5x`>)NRFM>%zg-Xe30kl z;KCpq>>b1RqSdM>c5RG2K|g@VVbMh|C+OJ(T};qKAMU#}ZsGL#Eh8#c_lj1!4im1o zRpZ<)o<3i!MkaeDyNctt&>gazu{|JpeA;rx1ItwIn;mYi{5*>Eod$m(k90N8w z-a|I(tSoGdQxYHSYqzk`9zZtgj4W(~6>mPqNi5zIF!OhS^#RH9G3_^}H>!3gX*GKx z{QNNgRxhJ0@tsI2d4@hQ@>65<&R$Wl7RnNMI5l?_OnQ^5@$!+EF1NJYl zEiKawocj$g9J~CbyGQ*ZoKCpRgfjCPwvf4&Ve+5JY%b$msr*4!1WS^%;J~UV98i^0 zW>wmH5dv+itBS-TZ=@%5Rer0Kh7w=A71EK!#U#c|?zOw}HBrulTt=(kpL!C*@{H{eadJxl}Q_7 z(*EcwHDqh(q$y=B)wF>!fe?QzAWhqtgfh{IvWnKup66_*gpX>=$@jdz_w4*Wp5J?~ z|6EyBVV7_O{|C5!mHG>L7WSbA>|>HK1GqdBBUG$eRR@`wI0?lIaXL7Wh?rzdGB^7fsr9rGR5D0rPqKgqG-2_kZd0Md|`z z>2)G<5bddDY) zIKol1d+?A$yBod(r-5NOb>!fbOgkBx(C!y>=N8tm=DdK_FFQ2uZQ;Q6$hPOM6<5vK z_9~LOHn&QdTb1o3@vgX<=*qG1B6R6f+BY##{{F-S_q*rHzc_a6*djWoitgkYhR_rc zI|Hb&x@JIgD4umC%_*>irCn*60|W#X!LtaS6?uYp=0(*Z6jGp&0)-SPx1-kyQE)kF zIvK3U0xPn>3M{Ba7SDP#>?>6o7tY()iuT-j+g9`WY-fZ|^hBy`N;mdT+^CS@oyp1a z>HFD;RFL}nq+b+}OsC^OJ^41E6*$(%Bivz0Am>9 zhBSw`QqU<7LL{7s!Gshbcq2gpNRV;uc8Bq^INR%29o8qH4g%^RpbmnkgFpmN2dt^+rD7i3RY0$0-nKSkOO{~rgG69#`Ae%LO*r*vpQIg=i9>CZ>!COd_2t9_dY?!g8ZP=~dE<>6Q~UPOJDH>9j}DZ|G<|^l3{mmr-Tag6Z>bRyaks6^lAh#aNm|ev zG7iLzMD)EXw71HHznOG!J=zztYU* zx%u~CYC^HUr@TkhFbo?i;|AsOd6erRb0A<5{|E@kSSbsYY~eY+hhq|?y9chMEQ{y6 zx^pX{_1>Z8)D=D5c)+E)7At|b<53@t1(ey9r!>fKg)w+(R_m`gE&^CFr?-jWAnDydBZnK@b zUVa}F@k#j-`vi305XriIe1d$9BVexQjTHzf+?ZuXV_GyCi$$B#Aw>xVWNu6`)v%_5 z?V6evn^dtg1H0YZZWQm&n04gtr@q^DX=3qe^EEERX2iyIo z7z|Z9;0`R4(Bh(inS=NLcKfi+MZW^yC&u#8KA+HKcP6cjuia^Dvh}vYV7oSuw%Krq zsk8y7D&o+f%@7eXa1pvdnXNWLwAu*D?7T7y@30#xeSnRCPTN)I=jP8>jDMgLmb8Ms z*bMh~0+Wc;`T(r%TI_@RT%{Aj&PoG1rQ8~OI-T!`r1NTa=k$1I_}gah-l6PTT}qja*81o6d~>vXi7Y3h8;xwaj@;~Q z-duj0jGk>yuU+=ToKB7h)HTMAgV7=K$8y(T0|}=3j}tl_+_^2eBH4WQ*O2p{mv{S4 zLC#auCvGTel0zC1BIFQ9JkM^s8A$@q0zq(rF|4F!S;?o8#7ZU@Ar)2>!_YN&_2|UV z}r-z(H0nxN zt_visgsem41%H6HbcXmb?z8h~aX3Gp2Yb;;Q_pa+<3+NkCBN&)VkA#=Y%OhK-zh!6$$qmMy3`9V zXE&$4&=KmT@+D?3WX_@%COxVDJ zf)Wjp7T2emn}nDR>Nf-uW{YfB)aOhHnP0qL{n^jdFWUA!1{Ccjsrt-;iUAMP{=t+m zdtYss$t1c)r>4d`mEKmZz1M~|Uehe5%w^U($il!qS@2oV@O3Y5H%24D) zQ&(xI73$RnXlo;@N>^!URPE@58uhVC8!g_-&=`aGvU85@;E+~P?C(ZzfA{czFN#l6jW zf>{E_^C)CVFB|&p?trDba$N}aeF;~LcjaqLy`E#A<=At%4|1}fYfr{{fGQQUh2^Cl zpsGiax?_$IhDFr8(*An8-2P_>zR1$@Mk8a4nT#=&u07gK$zvb@eDum&Z+>RjAoLvh$7Y^_F zHXF;dTwo(kEwyyE_U*#*rtJDwZ+}bM?*Y_bMZ04!fxEV)my5o^vlduA69JWU?EaEf z15zHhu*Vyi2$qA_X`jMwW9bOA3C z`l9@`8&~0+Pe$+XEuc&r`sQLo$y;*XEuv&3A0JRMX>H<3B#Tb2N`xW18Xlx-{9d#W^s=6vo!-}& zz4n4SOzG?yNxSuFn1Bb?u-dJ_;;NYry=ubDN(^$BX+n62iBR$EA{*m=jPH-J7?)U< zb38B1o}Z99IL0AGaY|v>PZMOECMXQeB~w7mZa&Oq&Xt&u6&&O6z$I@v8pgUUEL6`q zQ>7v2QIu5JRX=w&hL^#-}ATvLM2FEMH z#sVbrga$&9=N@W+V*{yUa=qvhDD)d#*R(nyi5ehLv6TSPxEYfK7=Av)*Ybn>FvQbk zsc*D2F*-2;z%&3MM4AA(jYtzFNyH?nRHA)hw6{EU*ZlUSQ@s1;MNA;xT|NH2NB90% z-qoxGPkQ@|WTO(``E4xj8>x0n-1cnKQyuu&Q&AjVR^k8x*NwPsnxqPoBfVzUi2Fud zGvbVUvc$7-UeAM18damNi@2!QjA_a#ToePU9=0iK9XuWvo*|jCAW`7y`zESQ7*yY% z9Q2ku?@!iozy`5=Roe+gi8`)Z|J_EYX%S>V|k&InDmC2^cgYf^lLhai5z2+9HXrxYC=&9(BA}T2SA%G z9{6Bt(wUl^tDlB|BrxI4u-#S?`%3g$82y3WJ4;cAqY6tNo~0>CgWfX+no2YEjN}06 ztyuYXD{O6WFgP42V+Knln6OMZ9hmBWhqwr+p5n?-@wL`VeNneM5Br*r{%((C9CdUPoz`zh39E6#WQyq$~sSF{-x(txw;5t>9bj}sP z44@atI2WcWwKY&|Z!6S`6pl6EaG^l6?j8|mU96$SL0HAcPOgo9+R`)RMMp2mBa!)c zrf=?CvVrxyQ?0U>AE%CIELii^OvL1A`L*cDM^}$M$bMA4zxpB|ZNv0(1@xI@ZN&g( zdBjz^`FbvIjWgWJCUrNI81F^12K&DjYb*b@@OaEoR5#{$FjLr`78kanDw?MuB{miW zEw3uRsw#3`I(@5JY_E+bcq_D4P`UIokM(=ZbL^NC!@D~0u2^2!z7Y0yXTS5Dqd2Dc zrOH$n+F`>#;G#H>MkkY*CR~C?u~kiY1x3X4I{}AAI5;>sRRY*c4G#vmmrB?SEA>wh z{kon>&Lu`;B_rh1i2Mj5uUt7c7F~`mU1W!&;~$+^lsK#PvwnddGgLm6lL~`UuY-X1_GMTp4mQ;YFjZCJQxotA5 zw`j1;F3{jq1_rLVxD?h)E3dz*#ooYGB7KCYGjZm z8L%y3`GuzrrR=8;et&Uq`P5^^p=W+xmLFJ^jxI5sty%xr{!{FgXve>fGggi^_-o|1 zfR%MHo1B0g=ztvP!1^M8Ghi*;BI{upa5|n5y6q4t*9cNUl@u=ti%1b}TSp$i{1ZY0 zKxc^uwa&w}P&a6CJ;Zw$g4Ig!)7^|L&3wir##q+PgERcF7RPEMhfO3{c-IPYlqrm2 zWiW!3A&=dL5gxF%Te3C3r6t|&w9QKwQ~+NU@W&j%U|t!W1wGClfc=G16ZECh9Ox$? zH3)h_KImFD1AO2^GNjUV=#>-UzMVUQZ4d5TkP9_$bn(g^TfQ5zlbz;;^CK%C+V(I@ zy>+m#xi6=(Ao@&S$UeeK|2$+w1Q`)XZx%DVlI-i8-N#vwWj?_u*8%*nA>{KRsT8_n zXx5PYJgn>Zb4m{qyF)ThYl*Cpt%ga$%WplO<+4FlsqDb3IclKb9DGPvZAYGw~< z_4fOHzxVsDu^#w&U;WE-BLUJloS9$r!iJSSXlMv+BU-$pIFC)J93g~J!_ZfXUn;I5 z8*-!GP~J`#taL%W3v8}37hd3iY6p}$!03S1R9I($pkb;3Z_z@t7M7{Oss>d`7D>2w zW#M#kx2m8f{I zn9jF3Iboe&o-PKj4aNzH49FZj`vE=Axm}(tU7nlBCf&t&=+G*&!njR(zfZ3?$saov zJr+HFs-108H*NYX`rBC-3OWwo`k=k@2a^Y$RESTmUVVZGqdkBA;)_q9>W8;p*%JMO z@5-v>3mVQIiGKb~^h#_TK?4KT3|Pbr;{QJq9Nm=#BHzTx`dU^NqKS91NIBxubQyYUhDxoWy;QQA z_EL8G#HlJ)RjL?OuG>1MUF;IEUZ>SLb?v$?9V_ZYU8>fe%%|E}aRiCs#Edq0eNc+V zwB#E>BqZ~4!pqAI$SkJu9=+QqGiWyXeSv&-)W)q3?rvTOj73>dbMT|-=flwa@75o` z7wJ+L)a-bDRwcH7bNE>2!3UD-&3P+tn4$L2zUZOWiA!cz5y_!>L}xb?*N~1VEuF+- zL0uZy(!k`Xao{Z$XtF?+1x%Jn7F=V7oyo918S0Z^YBJc8p-zGpHPm59(NnSAiIp)V z#QFR>!RG@x;KNglX`? zrChlowX^{oFK_4oucdc;YS@s4yUTA`969i0?O?a+;xgJl^Lr@P(H85KP zi&e0ggK7@u;AI#~){OKJr7JxY*WSZe!;a)J2}$u^A0(pos|1yg6B@l6=QNORv1JGX zRjA;iivtT-)r-0bb*DAqCN^;hdZ-DPX_Ezew?ytr~ZOF7OMFHGsknZ zO#0nH5C)X>K>Gib$$4LkIklVl54k8$()bbC&qm_gF$jo1XMD?U^qA#`V`oVOy4-?41FB6jrkYSqf}Jd+hW{q#43XGtj&fwgACY-H3Vo#X*P=- za0bH&yuq+PjyFgE)1pq%`tk!=&p`DgpqfqC7U_W6qFVoH|I2}*y2W|fbIiukh4xXE zb^=qWwVHe_OT$YyH@2}eJmq5@6*eWU?30EX*%QnjG!7M__d@<%R;aK-p%q43!D59i zMrbwy=|gLbP%AY`>m+8Y7HU->a8LycVJ$G3eK-;_?DWDWFO+-ddY5|{uOlzdkV3?8 zE`+|%CP5OFw&+4?N$pZIYPBqR!CNqzZkNyJaMNo+L6Z8{3@S3zqIZ|2MuflViztSom@2lfb6p=SJ@JFoEO``Rs`c??nIp*9}{;(o3>alT*~% z7Z?BT(~f>#nKjKbJ20`Zq^_y7u-zuwv&WAs%(RVr`2LdcjM{gaH@CFtC*_yrO)TDA z6r413r+=JTZyYs#{_4iH9ou`(6lq6$)14Vw+G)Nu^b6Qc`YQ&db~Awb80f(mG5riC z4~ehT&tUL-<1=|r0CrD5TISnVwV&*hG*kh%Q5#vuqZuJ%qhg(6o8p9mJ;e60AF!XX zEU)0`%h=dUdogA?R?)}c9{%a;Bf;Qx*@T}Okz_+?HLRw_cxv!=+1nKp%8yMi*jKgh z%%1AKv?ixS55xVqWfAQNC7l%e#Sca1hzLrNC>lZ<;iRHp@u7k_q5xjO(w`)b69xbd z!f`kU3^15tLP$^vN`k3Z6oKU^x{#`!@8U7fkKn*ha(XbR^XEJT8xHH@S4lp{8A<@p zp4L$YOQs(!FR3_MmcPGdfAsO*nmt{_4T4)D9^4-GU~?#GK!k(haq*nUh|0JJAMtRQ zKgsv=%y)V)%&HK>-OKY3^M!V2&tj*U=Kq0iAcrTx`Kx7})6(L+N81VfIh1^imPb#+ zwm9;l?ijKjE(Ru~l&}k99NXrz&rv7?pgev)EGTLd>WIB7#GY)co7h6^(0`&c;oD(` zwCGYOsZb3{wN*V@&1lp~GDq4x5xD;{U%jzyT~+*^d*Ac3W4}Ls&;RqscAV$9b=&u1 zKQ~Q?$TKQs9c>CFv?RiDX*UEy>XHbiQI$4dKn0Z*2?=QkDgA(2hLF;&ElUek^8u;> zGp(TNHjSWu3QX!CAKF4CR&(yNmv*Z(!6qau+3(rU=bYd9-QPXu++Zx2e~7k<1U?CS z=o)QNq|L7m127fRU;)#`HSScOAaU+QF@RV(XaHGN_)RF(;Sb`?O940FhQdyOSVfXb zXgl9wwEPII^{HB&Gy5)X-^(x;$6)_p9Daua`D0rjg_GM(dm1^@)`&6ry-BRtzZdef z-*=LjWD_~%#`46pP1l?@=S;DKnRYCxX-Z_Vx#T*M;zW|JB1;z%Z- z)BZbc;+iC7C89)Ps+QKMq=A@bxdJ!T(XhZaq+t~5a1`c2ghgKItlIL@pNkEg#I-+7 z)n4HPxwm?F&a0IhrBV?R+KpeQmK#Oh;=@DQHOxNI@H$wlvhhOJk7pX}rC9XvHWtM~ zD0zpRsN{GPPPs(;-#)#4^b3Q9!QWEzxXM2D^Tp4LG>5`SrPIA4x+DlmB%VkX6 z%e-8I1>1S-beaO#I}%TSb@yau@Uy!oeU~a5?2V!v@(nm2n?I1>j}y)v@t<%|>LGdZ zw+s07rh8b6I6sX4G)@JGz^~vs2qskEv|YgEQDWXBzkjg@m8j0`RvYXO9m;-l-0m;~lfzCs9fH7O%+U z!Kob;DWDAn!>M4QCt@2heQV_-8wcX)zG`J4k@X!aWK&@p&&k_ja;`7E<)Z`fd{>W= zj3XyM7G8y0;w9oEd)?t1bcNofOrT2)Dhvb`VSS9T*WpdLhdsl0mB288An7DUEKIIQ zZn9NI*_=p;)krPZmLO@R8i*aYeEWhMLdx}* zY>V*f@#8DJ<16B~;gom}tLh2&$#@8SA^1z^A0hf>29pfdu_3mdu{Rj}hQTiwJjb4A z^bq?FqhDb#%pPZx$Owbqww_#IOeK<^P*tXWsbgA#FGyfZuJkD^!1LmQcv)nep6j(M zv$M0f?Ar2`FfW*|l)PoG&9q+l5Z~~g<%U!4?vbZsMkcta9RB9|iX;AEyRFDoJI?di zBQE34=pbpb_W~Bno30WJJ5fp3Q-q{M5v#ZOQYuQ~Qnx6gZhx*P9h}YMi}cRfT`H(; zk>X@qE?PRywBAH#VFB0qD2MP`5|o?=6E4;;pY&ipgM;bl`ioDbwI~WM(j5w>`(njf zHfH#~n2gA(yD6usMidp-8B@CTEQ(3W11)|~ z(24iM+`KB}Ny+zhJos&NQ&dZ(oq)usNTdKu(@|QdN9jD}OU?TOSj(l-4c-olMg*6$ z;;_wwddUh1meJ)1r#F96FvEvoTYljFi_In`)xj$^-ORp=p<<##2&ukEp_iANj#$be zy-``KYWVeRKyy_7a};lgOca!{M#8J=swPoL601_F6^l?TRw|^~Y+lCm;SJC8vn|hO z2(jD%1=1In<*K~qsRPH1P|M${jGj7Mo}lgL4kE-VyoRuX2tVg4U}u43Ikuz*;l<{U zI6SR=Rohpk4O?zsy)?pIUK;1Zx`SKWsuWwV8Wd+L7_Z^s?pecKd5w@KUVxlOh>nEh zIDED3QE5k#+t*P08f-uBcnEE!NP}4bRiFZBGO}rQImx zTv_Ew_`+yAqK(u?*ht%!TaxcX2c3Ed!w^}$f1MQ1!E^>PJa$ltIA6D;&Hf_Vy%s& z)I1=>ge&Odt(Fh^led3K2Hka(*mi zNXX1AI{lw|e5>V=47NN%9LvSa_YaVLt}ZaLe}AG-ZATE;7*D*UhMj$5ppMOtEsR|r z6UP3F$T+s>|5wzbK67aUx$h5rcj}SdASPexHUdM&c1>(70p$ki=s0#$RIu< z_+j4HSY{`i%CIhaQ$!!#z)K)|$7V0AfKB>;8C~4{@GZEe9 zwM;P$RJ)AOL!e)&Ll2;9k^>VU2%~v4nHE55c|FhaYx*>1BJeVkB)JOsVIBm0Z;$NM zVLe<5D`89_>;w^(BSoz{HiJbfp`5NMv5TG|R~^?#CA&}wVrrlShi$J;hFV=HkJWV8 zMcyMnA`kH1Z?o?+2A$%-g#)aNU&w)My9!i1?)wJvAA~v@+avA-=ziihJF$SwF-uz2Ful6wfrIDsQy^y|=zMfXojwO#4Whvji zCQRB6lkSuJ(+Dr{J$tPJ-@X&RcmvjAfp!!kh1tS<;da4A3KLK=_-C{Byj`{xVjK1q z`?`I@c6Hbhd&ItNS8SKftqIHK+jL9Hs|k7K79?^zc`A_*79bs@p-N1s&{YqK^*A1a z_JuZ56{yjJHpW0q*f*9oMSW9%3V*=R@y>6cW-xi=itaHH7M)!bFQsU;C)enI)VpsgGCBff@CW zaz+&|PsNuv*f^u!1EO-i9^u+az6PrIaz7wCqSh^uNxc1!JQ z_$PS_6yre=C~BEpqoqqBliDPkMB2#>NsJ*0orPzAJfoV$Iuo7eHOB*wLgz7fl+lr1 z-dpNbs+XD#m$3o+paJvNwmKhn{G*9Xl|sY4?-B}C-9Y`1Zm=P&$l&c7)*z3%IeB0S zIzlg~`-Vq@Y3v4X>FxCiQ^8Km+i^&OzRYy)X_FlzAv#8Nx4A#8d)BaykRf0-#J(2} zhb5IJgcbt}6b7W+S`&M9_i7%~p*2h8$39>${v!rA?G^E2yP+5Q z=ui7-A9}IZZ;9_)JXW8xe5^*^M5aHe?W;_#ovc*ZLt+d#9J zu~j%3Z45nMp9Sdn{@=d|(?AO)19*KxN8S$0$4C^~7?0kFGSu^AqUtowV5rLgTtQ?Y zT;VDmhV8J0k^cVH&YaAsvpyphtINrdS*=&4S)8Kg0<}zc(M9z+lHl89t#`tW$N1Jx zE5=*fEiHB=b~aXysWGg+brs(f7Pq&?V$w6NXJK>PDyF#pe&7+!VCeb~8^XeamNnEk z$~BE8Q~A961@#KBT$EZXH&vmv`a}3^f$xw{exe0ul|z&Lpl<;UynwoUV1p`9n|tKU zI|>g2X%qL26}HRsYF4l=Nmfu_u(A_XR?gFDV9kto18WXhb5+(H-G{9EJ`z@vS$Wz0 zqH~Ckkt0qU%1zfendWV7mr9Dq`vsTCI#SCT{!5!NX69x} zGwRHTNnjLf=lvhgl$wb%Wwi;-@Jzb6dgiAJ-Qvvg+L=N{JagKZo|`UBtJ5DQ>Br+t z=m3Sy*F??!M0QG;r3r~~O=09fwhNESBURp^%1bI|9)Mm<4oyJl@PlR>_MBa^Rht+M6X=G}l}mKM z{gyyquB+qiybaM0jQRw6OiXk*o{t%0Y)npcP3KTwbw30gKa(8n1aKs|h8%hN^?W`W zMVbkuX+xR`W1>89VM3j#Q5BodMRu$lR&_ClU#r_>4r0IBkMQAb6V~GXKksK`|G2kH zHm&}LtsG9{v$^@)*<3lN8o6w4A*bZT6y)$Hq?e{w4l92Z+WpeuKL@dzyax?AyLVF$ zQbsaV%NUtbrkuHuab>WGAnFVn^Qo$cGH>PQ?qT5imBaP4>l{`Bat-xu@gkQI&&KEC zrMMbjUkOTFMDlhuQ;5XkZHP|o4C;tBmn)^E4zFbjFKdH=#Wc(dreZqdibKap9BSf- z@*5H%JIHf9_=uOXqh6Z#(zKU;!9~C7qJF;~yv+Va;zU=pB~FH0m)RZOsz*JPcr*|5 zcsiC9g>TukpqF4c)BUlWhutPUib`6E2fq5@6J_tx9nX^Nt!yfL%e&VoQsb7{WfY6u zx3ph(hyL}aTfV(Ua)cCV5&q2Z> zg8}!Ee?IZsXTEjhSZcsGln7Iuj&O?c0_*N&5gU+F+me4W_ubKdiu=Y7xfK4v`X zXt*B3(}33pcoP&G_anhE!JsuZ^I5&-R>v8VQ zI4yspPs^YA^+WnTo-}+P#nin7^~-iZKq1Kt{WGFAv?!6Cwjk>U3Vm9r8aKwTYTTd! zx<`t+amR?zL3NP$RSR5wet%=*n9dh*i)$ixRV;{{47FAeiKxQJ0Yg%wBJM;cn-HI4 zOKz^|U~5XBSn~-rKzi7kJv|l+tm$!CV9kOL`&1aa0KP%-?L<9YWpfR!Mrps$H6$CJ zgnr?F9a`f%alEqeBbATG?RMHK(@I{sq7bFhGjdw@+BE|0I$V$Gnyx!Q*!ZK#fJR<} z2znrDyQNV|LTqCdJE5aG7^tQfDI1xM6NXoeMnDc~HP1~LzJ$8eRxXmnu4FP07~^as^2qWC8KE3d z0(Kww+iIN5Md02S)DB4dbUF=TH2(>CLY>G@EKe9Gw)xLp#UqUN!0BH$eiljSr8iL{ zL9d~Z)4Rfbc(c9ELJff3Y;5Sj9nOn3?6CFO5;jtA!!~Q{3b&>@UkqSJpf8XJkoo`) zSltDoD3k;u2-dyybBpXOI5}sXS+d^N+yY8JioO++9ioy`Qv@3_jGsNPKkRH(f*br@}Uz;PaXPc zCg_fJ_c=^0QZOSN_@>5;`2sMbpjY1LFoMtq1c?&kX>O&&$b8caGQJ?=PI*}7@qBBjDg1?Tip>pb#pCN+A*owfEA0)XPFa;Dlzry#xeV zfS?#W;gX?LMIWRe-K~oVoBeGYD(G*6=sfg}!m?P#xyU3PCrKyA7CBJ1pFY6*pL& zR>?}NwqfI8YTx@y4=#9$9&XfwZ63Er_7IQ9(g~m4DnKP#s8Z@c zAHDD-Ri!+r?wU!Zsu6wLcUqW25c~}yVG@aZqf{6>a}bLeTwgr@-LpqNx1Pnf|1lr? zbqy77W+SH$4SyL6zse6vulBnfd|*2vLco4%k@hF8zq|)?4f9akzYKRbM$m{VaF|xY zD%65%wJ9hRqW%rbk#wXOA$-IWDMv`{<(oUp`gD%neOhf&)bMsxPo|hDWmYqWjB0IC zP$uK^QQYbDba9&Gr_0maG(&ArrnjN$GZ;mcHB@{FP={16hfA(i7w2M`x?DCJMf9e< zMK8&F%U;f_BYJm0G`JXIqy{me`e65irNPxfGRU$V927;0nMfy!36f8g6I?>aOl;qK z2rySoF~IzjcGKXK#-E_+TO7Y1@26u&LlcZ0zft@4?{_-KkOMh+2k$g+wwcQ_#hKE~ z+Kh2V^~%Z&Opx@YS((u;*?11tILmI8|G^p>+on>5ZSdH0rXiGk1K)FD-i2Ls|8Ac` zpK2$JQc;(ysc8)J?zDT>ec5ers{^CVS?AasmHQM?H9pLBRX${V(sT(ORV{G2-pk^p zEY50xU>~ywVyR6^;0wir_#pk1w~NX_H8lz^4ZLy?5t@rVq!3t*4hO(Xobf}CJO2M# zRcG+s3WKI+k>B(Y64g$^;Wa;oNeiYPc%K$$VYn)Z2C;UiK#v0fh1S2fMSl@|4OQK7 z_CT1qnpxG_s?6#wVs@K5-ZcXC=e6Cy7(p*-2#~qv(BX}bBK#MJzIz0%dzwA~g#N94 z4$gO|G_*QIhFDJ;8iMXgI60Y47L$ZedXnWNN$Q}<9lIw(jc!Nv%opcN^Q-fQdDfTa z=b?K7ZZ@4QW=TF<&T?73FJ*V^o@NeEV_Ul?;Yxwk02g4H1_IDM0Wp{k7K0=oEC<Npu^S&onU{SqPz?yz^$WwW=!sObz@ zHvIxUtJcFrI*PB4;!zsee^g=5mNxcOTkClRjgFelW9I(*0}lrX;Zm&hMmCh|sT-+s ziX2ZZr8tzDOXX7}g~K!&J`A%egZV|$iVVu_xy>_Rc|>dSIB}D3ixjvAGT;}>i`?uY z_AIK4#l?Gz2DCWe)iq|`e}DGjEM%}y&0yiiLV1B4Uszh;(8An8et|6DeR>A_wq~Hc zsa7e=Af{!25M=NoWFXTKtPNs$8DEz%lIP^Sd_ykFMwx;-yA=9V9fAmBpbWMA*WUZ$ zKYJgF29gfXhB+==%`AK)Tn>}t;iWK#!gJw#n1rz#KK)tWhH}o0q0#0l*=cu!o?!L# zy_M6~^ZOd)H$~?+K%Zhq<8&$f6uv%%(bRv~uh!7Ek}Etj_ey@smaQvUj^spEr7PQt zEn6DN*0p8LbvBW+QW7UwvWbncz}~{PC3ZG$wrmS=>64bFp|piAg}AVk{0PKr<>7`F z`$s9;7i;!MSqjDa(akO`p>A2yEdkxm%pJ*(qzid0l~zdKht=g#-dIcLs{jV_I@ zjmrG_UN*bYQNLgRa{ns>chc{Xd+C1>tCY?h%OI4g%rLW*S<6UMnb`~inXybhBW2(~ zd4>aU;DH&k+pxKYMs9m{T6)kAXnqHXotBv40iTD)WQx=~aY`g&%FJ$9vEH7AmLB+e z#rpZD!>oIRbsSuXOd>U(;a6I%#%cHY&KiCJv=IlG;NC{q=BMX9Z`WFk_g^`=%KdZ|&{H7kVI| zD#RygYVqw}lpy+m6$A5u*mZZ;B$MOYjN^phIKi5~RD42E<*0U>NU1WUY!nP8@)HP5 zkcqJg2~14TvUQ9RZKFi155uZwXO7Gtxpj>7DI4Q(YJ7IQI4+Hs`HnNbF)R|5@>fEE5Nh>9tN;9G&Iis1@2K}w zD-$9Lr=qjbVpNKjg@`gCqC$wM5F%O@B1(mbvTDkOU{$ryHO;VCXzOJ7&h=I=2K!7w zb}RA{A5dAgMZg0!m#YFHQRw`}auDQ5ZY*~xx0qYXS##{gg9gqCnK*_tj-;0A1adiA zeRZJ&5t!Z@b6p72CCqdo0fMZ9Gea|}nc?}N`PBUIO>!rFFU{KBjVzqX&Sr~QDO(mN z%f!hFak4_3Y+0Nv6(`FIITvR@h%+F>87PZ0@KABe+JwWREoRw~0S&UP%15>NGp{`f z_yL>-*GL@%NqcfJxs;TXY~!q@Z8k_I>4C0;y*0=~V1c13uxrKGEYujdQy>qWngILX z5<~jGB~nXophiwkV|EfGA)g-utyf#n7B#t1i)d5YtR@4^uKBdQHm9x9Gh>wotn8Iu z16wP*emEW$AKnA~Uom0v3a@Y`8zvLuCzMI?CIl_^7SzIC*I}b1S{!nd?j{{0*vT#m zySNt)7}&`!3cED$vTtCUz!z%EY|zri|M%T&9HpglRq(_<}Z0m(caNVCa{ z$zpPoC(PRN={ScI91727F~?^z9G7+T*C7t1ZoXrxwe@K_SYN3 z!*o0BWW9^q!xDyLNT9m){P7d6l_wmOkfB3Z)Zv((*XQ(2UFMzt3x;_DIDN*%L!&!S z1a-8lG0zJRO)T2YOvZO=WVSis9bL|+Dt)9%yEBdU$-knfhxbV>mC5IUYaZxfZWDu; zV@n&yWm^+f=btw`p6Y7-sV3Rptt6u}nDWkgi(YBWoA=InH@&h~Na7Wec!eZhA&Hmg z6P3ivB=LeR72-Q@5FBEhuOhO zmOY6zI9NI%$K?yu`dxE3ghQn_K$3QG-R|t8<^BoWRyayikobjLz&wvMg+XcH^nhSm10WUb<3l4b7 z0l(P@U#8zW_(cRyqG^PlL9ne2c)jiwNh%QFZ&*S1NxiS#27%3PLpEEJ-XKY!8hFv) zL7P+q8h}lz0ty|;QWNa@21wsc$I^FU)FPPo&-s`9lAkSbQ%yZ?^tU&;b=oESd;Q2y7nX%0i^!+yr}VAuk%vBn z&;5G|43l~ZErcNm2VEY$o3C>njtK1G8y>xp5N7F$SEMG8rdcA|>iEa!*SHPHwz#Bz zLC5_Uft%Dx2(+-!l#p)){SBneynP%CQ(McM6>TGMzhww?++fuq3|EYM#2yY-o7JMr z-WBPRy11%ab@RzRBuYnRpQVk?IwUHBTmBK)M_e)(Ojb4PvR#X4dF`^cO3!FkjaiFY z!Yt$5vO`#U%a%v7oiS>ei{$dT%emFudd`~LvSig!PI1dl(-OQ*ExUdWWaC}p2?iS* zsc|3@SO{DWtOnKtn}MnTX?EZMFO;HgJh=~$fVIfYSFD=*NP?kKJ(#?Se8I&a3bLIf z7@@oVZ%Hy3Y-rF?aKY!p!3D*MgKN}Rko<@Es*P>ytitcdy-6I$zSnjf+t=||96N68 z>+8hVcAPZv>y#$#+O-tYZV~g+ZvBFRnuKI(Sx2I68q=88@TY)~Xr)mo(xj}-+NLd{ z{lORl!U`IQNvNyD52kKWH|T`KNWyuqKUyT<&srfn_r|Y%&VBE5&V8QqSS0vpZqmmh zZ$*d{VUc5zTMsb}~j6 z*FIt_7IQj_d!R*!5 zyS;@`ZnzXu(6^{UPM~Hq%!1F$$7S+e>yNGEn^rt3;2vRH&?AMHQ=V@NOBtXdCufr3dLqGBRt>(rkG}hV1M(btT2%_3h z7FAGFcfp>w=e3E+rS9&$R!T2*%OI@Kd};aG^0FrS18AR|<_i3cbkb8#FfD z#v8ID=Q7kamopZiKRdEUck;DhM$f?~TRp5ho9Xn|UN}2A)Vn4AknPFA#8Y4X+%~gK zPCjzP?DU&cea^#Q@CO1uW%XvNXV>=%(H$G{o>Q-!mzosGANEQE+Ri5G30W;$LY{_5 z_}2#>-oJW9JXPF#S7lr3+EKOAM}_%nrNu0sTm382&yctwNp`o6;&BB13X(O;?6OT~ z>WoSxAb{QK6;)6~ifc`p9XR{S(YXVE3)9MWU(WKz;MDV^L)dCf$&8tF26NRTj8+S?)$O_umlJ zYKUqx8j-Yuwp+WR3EKax&!^8eE&Q{VEs5uZag;qv%jrTUTO}PODUNk2#Zp906;j(% zvCMd0jKr7HQK$LqljCP#}{eLSPJ&q@Ga)E6xCS6Sk~x$Vb|JnE32I zLVUguM7-{G0*(F@yb7_kICV<``A z16U7hzu^Qq286e4&zEdzx0VLS(XY8>gBO7fOQo@z=`ehUAjv2J~Xohijw7%4kqs#P=m?<)Omoez!A3P^O{z=gE>GhUxh_CtjfzWM|-RW zH4X;>WWX3ut_YEVCcx~f;{|ZtF?`0%WXMojI5)rgt5WZ{=I|}ftX({Mn%R>#aX6-Q zS9)S0Bn^^v}wt*=Zy)4t_M|MBMdt}i_>H_+MQ z)$9!-r2-xN^RUZ!a-h2f6`q_-StHOdR>zT#IWQ{71%e9e+Z$oV8W&HGIuRUdvZBVgUEa#Px5y~LS-lMZQ)~x{97fmVXX&sv381_ zPEIF>Tr)1Bxv=C4xC*W@m*8TuU3al)r|zl_C{?F$?{Zc6?o5qCR6HVdqMnP0z_{&E z@&YXgKwN&`%>!$A95@oMo}krp|z!O(A* z6&zt6-hECBB#7VtU!Z}?2$5$K1$1@N~++^(72K=dE5rlIwK z5iACZ*Z{`XQUOS+0aO)$|A5g1V00bjc~&09S{ki7D&_zwSm|Y(GjH|2+e-|rOcuQi zP<%3eCnq?qjcZGFGvpH#Ll+n`OJ0dMDKg7uqKGb!hq*ku#}mP^&It2I^hn*hFqT4i zErdHmm`b5SXnSZrbR{I3#c-&@%X!S>V3uHOM7IPX))E94Bv}F$qEHj}0X8W8Inx`a z-PVxj2@ucH8nEW1cP# z)9{Yehm1iwo2$JH`KYK#`2}(n5xn%FS#$2}Izgz?-q|~MXJ+S~^PTVe4n5wEILG%V z(r(;(XS^%;&qzn}Ec%*^4~Nc#z7ZlwizbIS!3Ste`fd>WgYn2autN#jQXR!Pe-kf| zcZVxvXE6pU`H8f(-f+bb_c!A10cD$NK7-vCSLwCEiyP_G__y%ygq#2R_oFkt%1iLJ zy)*CtVL+b0wo~U{s?B{3FWlq4EWnp5Z2x4vgKm;0RL?w0%3Vj`pK}-a(b!hpdz>I71SY$iUphCmNwpqf#o8=m@sRNS2V)Ip59H!%5}&JK_Y6S8T=+YSn}zn6P4mgI0R)U6<3Lp6sgxkFqF3!N4+>j zydLIZ{)pqr04NYFAb|-iUvLD$wvwEvQW=MTvluw#B*;I{n-WXQ1~d5b3!q2Hkc^B$ z*p_kMcxVuQx^8S49zKC{KQRnDG@)k-&P3Kc@VbSgmT3u5Vwr8ocqlq$PknJ}Y0A^0 zY^qS91*T|D!SH&hC_r^mk%|1DbXjvmOyWuScbY;fU_zA*=q>nf*Z^gIjqrNAoSa$Qjvpzt?R(G=x2%dR90P{$fHv2S(?PS;9?EV#|i(Oc9 z0iyF;m#+XMT+lp0&*0bo8NX)p$#n1Wa!dm_0ohlvIMNnj;Lk@=(;4x42R4s$CjhR` znZ&h!+$`c~;dtJFfhYQqs$Be0roIQM`hNn^y7cr=a;%d{_P+nz;n|vSREsB$<|p7mH$QwxWlRlYYFY}r%}sWl($Aq{)@$omUmunzh=8w!`xWuflL`*pLS zlqzz##YqU1G0rJbq8Uok)S;m9YrFT^XnoRYF)`@08ZfV-Dg*0Ktq@F5g9ZHpLFTZo zx3Y?qDLRzjQH!chi7Jk#RY%o|K=Eic91Kp#(U#e=TZFYfkH0wmbZlw+ZddEbS_kCU z1y>USv)$NkBspNEodIP*klyRVkE6C9G@vdXHO^kJride2T-@s}+&--hKmsHUdJVVt zfKO{5M!GCHZJ*3UXyqZVdXXu5+k~yYo?UWi68i7mk z9Gg^2-gBoTwUt-RxMAiJIt>)e>Qn7p>3r~@m7RN~)i{wKz5HuwvPN{B_R6txtpoxr z?8YD~54=AE2D2b5T22CjM}S=JMAO}Pc zj6g)s*-k`<)j%W}5dsm#paIJ?lzc!yQ4Dus!U$(RLd@c@W+)Na^c3GW@l_K`=1KES zlb9x*rb~2%u2M?Z@QXY#z#xm=j})h4zV>51=>TZE8{3Ud7p<;h?6Jk-V|B8RrPyG<9olfWOfL?)EyF5U!>$}~>WjNiw(*JgkZcwlrj}aIe zjLXGi`3Q^yFg!m6s;a?w3kJMG?^RH{YhDj(V&!%)qa^q?K7KoqbwrMjFC=o#WbkP4 zY>-5gX3|cQ1hs8cuUoZLYB)2@VhLwB!MvFaOQxL+^T(V_CPeZ@i$O_nmdZyo$Ff2- z#1OYmNR%{bL?W^jLNZo}tgw)K-MBC8)a^>vwu;v9)f7%;<#(j_rN2o8Ns=T;7RiEP zGy~ItrNByHH9!M<^}W5m)A?{?aj_w7EP~~bHl+<2^hLLmJDU(B82~h3KaMeQ*KSR7 zKT_qU8;s4Si?4+3f{ahxLSN?C>T@KobXP#y8dnae<$*gF5VNvllt643~ zOkOyA;g41@p|o$Fn|roX()^*xQ=;M%%XzJqiPNCx(`@$gWa*9huM9i><%2J0Mh<`Z zsq>auInvPcX}fACD&zmtTuP`zR3ubKF-oIK72%;2QI#k%qAzWqDo|3OQGzP4WXd9%8Y?PZ(g&or zs#3@cswf`!KQqQPDKCBPtj?Ts{+aXdod5in?=v%DtqXa9bB%j%04AwIrtd*p(Rb1J zA>W@s*R1`otj=4dqXz?HqlX#K4zp4#;Zh0nB@Hm|Hgs~Zx3xz`Tha*yKPhYyC zV?)PC7j#O0HL>Gsm2d3nPwyV=>C6{4w6?V5de-KCFe2@H<1lmR;Mk9N@mRp;3yr-M zLgmISFj=*JyQ3~N8i43-L;H%bUWEZ9*821ioCle8)MudyvoH~6o-2l86eD#f9wYhF zW9VS;W)j8Og;<6=iQ|=qE<;b!E?60xSqDFo=q6R1CA3QYLI{WF1BL^0xIEuwZsoh`F^>WG3OEc3CzMSqV z>w2lA8zuJc?wu1&Evs@*+H$K}nkIJc#@or1{)|lVcKajp7I}N-$+77#AIwFG4x)?t z{iE5Lvthn-vot;~ZSLg5XJ=*~J(|7qtnAJ#wck}xsvbTZb-$tXJ27S z$zqZYDk-I?(77Nm9XuuAsRWKCG6`x@!bzzhQIm1(ZNgj&_AL`2tMOFXQl%m)>P1SR zizK>Na$&PrX<~vc%$l`2@5LhR^?3{{F6Q$V7c%oJ*R}{j91Qt0mJ-XMoSuWFIkL10 zOLJYzknUw_y-hp=OBt3*TWX|GAWI8X)Qi{ay;$hQmELo`f9|DwAuSMC*|-Dnc%-)#LvD6xfLqV!i7o0qJgm?F7~3~{;-Hyxf63T&T;Sn zrtmx`w#HoFCVsrsVZCGa4SNH$DSM+mg*)+YpsmE09*<(f{+wNJ-^0!Jy}1kZn@`r) z>-3eIb^3MtdvkxVkKz+l8NZ9=n{$639~?Y>d~k5QZ=kz-`}Xec0qP&m=yUEwGWU|B z^K)!GzC!f(fy&>y&2Gmh?4xtHiDInO?R|Au=lGzjasc7^51{__F&{zgOIQF%eHvY( zhv{*8f@W!wk0Jb*SE5UH+E>)HB5BMKw=aU04?)W&<_c6%&;kfT0|GjX$MFPa@qe@c zI^A^oG?P6ImFf$qR1tO!cdv+$ zrRIUkx~Bfsu@sZt-X9OqFIVF0O$PQh0(*PkvkhtJ>SdIMGV03|OkNiyf@1$^sY&30 zd^-;Sm&X}4;$8KE89|C_spL~Nculo@f~l%J?0`mLpD)1CVO3EgNy(DPJ3dY@B`tz2 zOlC=6(EKKT9UsS6@om`DQtWUEx051y%iUt5W04jR{M(qWL$OnYYXnY_YUt3nF0ylw z3=g>^As%zEZZ`KcA3GMwxh8qP>y8l!Qc|;cpnV|CDQZ%aTGv&(ggAS=M|&-!H5IrG zZ>$N8YC)gIMq5Hd8)F8VpSRz#e~jNoqqOYlL+J4##D9qV*18_ke+eLLt*`>H$@~P^ zaWAtQGSsV9iuF?=hU1aN0rB8@t96&jhbS-SXI)M!xBkN9Sk`JSn5;(Cs9|cHnxI&U zAWeseF0fO;`jZX?0ED1kPbjnMb&)X1C~??@jX_Ly?$xrfS}+i1B_&Xcs4BCuMfP|! zIRM-ZA@IeM>|c-yXZ%Ymz$;N1AaWDn=u7i67nPLLTN)h9Df&Epfu?^#{hYc;(EzXo zN~dTa8%Wu=Hb9g3Q%gbG~G3WiOQ@%us=Q)7miab|*H znWx~Vab39P9_^il4dQZj+L5})=|Gv`BS##h?BE!vjRdhcw9f%G)s8rqCFhJ!uC{jQ zMl$n)cU4;2_ewPPj-1GEN=LE=tMvE3%z1)92D!a)bMNx@%Fn1RS_MvNj>%Gw*k7R( zx^NlA!P{SxlW;UR>%4$CD!O)x2dd z9cR1(NIc$TfVUv;^CHBr1u6mrJ8lh}3;a4j2a-!8_^BbT!44fe+;R@L%SrN!1A+$Y z^$zfM$FBhdx;|dOMl<*`A#ubEF=7Y86$o3X8q}$|PdZgh7umD9J&}T^sY%s@{PGQ5 z%c%2Amgjd=Jv*iE3>a#6CY@JXlff`S)Ng}tjQwBQ1Iz!rJ*asBqWGcbB+2yX1HzX6 zYHdk1o18AHW>iv=rsP$VrlQCR8uJt`(UgTyNS3X*47MP&gYqT3K@kdnP=rXOSW_>W&o%zOM?4L<%zC3~ahCOaoS! zTp*bVmt2Z255OdD9C8^mp2Gm*R%UaHZU1em6@dQA^E=k>>S!x^z75>UKJ@9SukQk6 zKiYdNo!dCPX79SA2zgKkqwFRFk$yw6rIM`BXVY zr84c=gyLu0+Oi2&@az7qe%h}jyp#}PaG|9s9>#8oXv{Qb>W~Ow00x<qe!-$GB#z62emPO9UiJcrEqnwYHp>xNba*mV5 zs>rVL@wOxxAi7-v5Z0chgL#Rk> z5Z0!wTam_4r;?OECe(EzbQ+V`I2Kc)@a`_8=%ul-qRvvltDd3@*G^ZUMYzTfX@ zyem3V{P)O*$B+ML?HgDm>oFxAg?EdE!dbcz|GDVR7hZhxO|mb4^5%y$b`l>bKFckq zZvLHCPHivv$c^pSuD$;H=0cjxmrA9P;wf~ZRK&Wp6|&EZsNoDoRxYiq(98hF8lJ}Q zV9NQyL^7L&C?0_*J|R8{Q7of<%t2)l3z7h;mRq?S<7O2&(?HZkkwh4oEtOcMx85X3 zAd(=9lu7#JUz91sTZO1{F%@(L^e zKPzyQlwS*P!3saOW^NI;!%7k6riWHzw7O3edg&_WtTk7ar&(o9gOj7#&uh(hC;iH@ ze#f>Z{{-tGtE8wstAlBdo94=C-b%Nrt-xqSXS$=8j4#K_`P$22%?ZBI zWOC7y^q1CL@0aIlw!fI5NJJHSNtj!O%U>M6d#^NZSzfj+(UG!cmC>TAy(GmgQ)SE4 zq9xoBPZd8PH)sY$;H#U_dn~Ft{Z1l6q~AFHf|L>aE0C7+yG5=Q)GYk;2u9l$sY4Xn!19B&Fn zTca#Wqmt-&i+qf|&!e8JomWQBUp=qof$8&WW-zZUV57X&N=|RhFOjT7grB+m^;w&kg)jZf!0XHR6o7>V!91Q3YK=h5O z`anIY*WV_epe87oe2jYXg@uW{HlNlO&M%zr!NzFbmQwRJ?Y=sH>*CfRCmMr!w}m1{ za1?V+Ra@f)RV8uQIF7kn!pa7>tT!HWu3oOkL=n#a=ND~V}=@h zjj4uM&v18lCR>*&ULV8$F&quV2ktxaJr?Uu-+%urnuPXFI5odZ0Cxf;?L-DRDtTzIBWQ=2Tw`(fP}Y7k4eO<*SP$C zj1&b0WGvHJ3U}mEET02#6e`TWC9HBu;W@p4!{fyy=Gz zW(Lm`T4U*UqwDaO!^0g*TI{d?5}77{K@GsIPBP6|k853#rID5h^$Lk)%VtX-F|X=2 zm&H&(3&1H0Bz2dwrdAc5uob5HMP1jBq4^u+1Y4F!Sc%)^Hc>)Le3bZGLP#|3a(%-^ zTv~07=NGV14K=_MA&qa>xSZDt^J#bIsBsArx;q0wFz<$pZUw@HP96$ZxD5TxCC)wP zZSoC&x7mSFmT0kdDICsb($yRWokv9G9%#sPVrROi+UP11>^!=?{FF$N{c}aTx z;l$}Xpo*lnZQix@!7Zs{r?B7iYO$v<{sw^I>T$6Ot-a0ft|=u@WtG8M<0}qN1Gpg0SZ60D~j*o z_e&pGvpdl>W?~9+Gq}ou^SdFJGQ|3aOvF~MHi0LrPQ~G{dL7W~P#FIlfqS9>8j%2v zg2W`2UTsRu7cwPDaVRRNBYqi&VkUpH3Xg6&oxsyXnaRAPd$lPqc3i$|KN+K}m*BrU zVrtAq; z+tvj9a+h z+sT`6HQJHMxpSPmnEWEp>!Nz2a11%M>`Za1E)*-@jA4|^2UDFW`W8g?WVva z$pVL05HR{GF(4Wu4N)Fi?4fB>W`kR-;F{_0w}VWp51Tx~Ch0VN4fs9}v@<4JiW0R1u}5!5@HWNTE_?klGR&(X@>!aG^x`qqHOn zk&=L~znNVh4)mm--puUGd%ySQ&CQ##iO!_)2a)4@{gY`Mr?mh9plo4q;Vz&UV0T`z zP$ln_|BUKx4y*3u=focQOEO*ai&SvT!_n2zh&99;dK=C+NT_73`rWMFvD&_!udaP$ zHEC}T2KnlEJl-2WAD7|}t^PT=F07TRXaoHvTTNfj9vlA@tDOSz*r}ikeDewl`Q{C| z+^Uo-E{QPycj=}u%l0wJCza=L%O1hiW2Z-k9K_*1iyr3Qzji?g-@bMmPsXT>Tcdhr z)bEehHN5?T_u$UngWeZBsfCG@?c*Qr-Ls>mStkP2hUhtAA96}LCE5txKuDO~*%#(U z3hFC;_!jEwV$6k*xRNvH?+$r8e8I6eOWYuedfdhGp$v_7N4t|M4#m0OvEM0C;&jP^ zPM!FC+KpNaZ&JjByVQZdUR2w6Nx$T=mm{KIL$luoS4kV*6?4Q|Frg^V4znk|Ie_)NOYZQRS*h-hw7;flE0U7aq8 z(|0+`R2K>WLE(DZ+BR-vdTKlBNv-+%N@ZtA9@`%*t^w$|^yTAZ@mUlf@1EYUp{Piw zU2NwH{VHVdV5pvT2cP6ZE7A>B>k`_#u5{5zm)3QsOY9=G9b2|Cp4Mxr6&5bru31c( zg$=N<5U(X~TU&LtPBWJNjHy3k>d)l#XN305l?;t!w9K81n0Z)#ibY#Cavn4a>Fg6^ z<>|NTM(Zd|^J{d5%A_{67*CRPMOsUXB;A>&73m1tJ?Y-`{T+h-w7rG9TSF{wr`juW z-Zs#P@Cmi{fYMzwoWw9C&UDjIv3{-b0>MuRpk6OZ9h9e4W`!RRY$TnG>;LBM0IhlSSLnB zs#^qfi-2wt&~pUzh~BIB>5`)Nps`gLxb^XuxYn#5L^KQQ9|UAbsf=AvP8*{aph?wBww7K=u~#pp5mjFZL%!$yowbi}X` zGrBP{X52Ak!{lO^TnvkgVR11`E{4g)u(%ixap|akG%oUUG-6*ux;2j^QY95jwWm5$ zeJLADxzbb$nSt?jh{;$|Z09k$la#o#-_4q#$UJ4rg^NwuG@nb&SvplsYB;P(5}she zuY(TjK6of9V3Gloji+GHy9D*ps8+h9841D&AP{4Q*vnMz#9w&!$C1$3Wh2Wma)^$5XwkiTxbQTZ^h|eZ^%m((Hp9)w2#oQ z2dzTXorm|ETPPCU{sN}luc?q94Hf#Byl@Ji3xWYG(DF6nSNyog3q*hLfsN{5SQ)LW z5lWP+C{oIn-7aioB}s`g%FBL~Aj@v!X-i7NtgO3&`lVF)eI06pJE} z1QvY3UOoA#hjw8>vE4qMvfj*wXk7phZ@6OGp&(up9nP5vPcAjVV4Ce59% zc#2hzQV>#oBiTtmM>Zr*)-l~7;4z5Li8ufLj~A7Yv2{l;na z+we>zfnkxRSf-sDUbANQY<5f6ldzeY-fx_#2lJcR{GSakU8*P#=CcY2wGVmkN58(f z&f9d?F~vdHum9%E*-W1O%kURpy>tIrg*fuibz(kS0oWIeFDK0k`RbkVYQ@wu=_kJ; zTSK%lhm-WLWUaJ~_<$w$Ao+o91<9cHT1AhO7a7DL(WDb(E9M?YUx)k+TZ{SM0j>j0 zzzU$u8e0ae2U4t$xo6p0=;&d3xZFloIYOk{wjz5U_72!Cl8wM&wELx-lU|qy&JMFKLQYHZz z{oQDnfrkv~1uB7A^aN?7#pE1h82+y`{RS?QF6ML2C-Ap8JqnX!+hoAzd%$$sn7sw* zoW$*6?0yJK#3<>7+yqPk67)}Gv$T{5h}S{eEg~`??^v9!0rRB|WI6f*c&2Q_23lgUPCUfK}vJ?5$0{y#y!_fH&&xZ{p4g0l_ zQRx=Xp}oM5Ve7vWabmGSe;4*O30wErdBFM*?D0( z3oZlykZK&l>qcYV=}!&FX}h2x#AwyY{p(0wuYf5%_v>NJCvT(D7Q#o?{YY$tjf@=>19q z-A6Rm`&?JL-E>~OCu7`)xhrCOH8gXbdSlD$;UA08`34zv&K>b}+_MUO*69g!dbd{> z>+IDz@pzU0NnFl`cvWnY{oja2;jBx3Gt?mU+wqQ{2x9f|DspC(|7pC=_qop;6B8MG zou1(IkTSj!6oGRx&voW!7CLJ(3Y3+Q_JLn`dAc~BrwhDw*e9DjPb@HA5dW*zy0cW~ z)%iP|A{E8zRFaXcTVwOcX`B_SSFwTFA37n$kB;)Ws4s;y^w%ggIY02JPS6DLw<*9! z0lotJ@uR1mkY8-NIU$99Ofjj>dcIt{|T+w)y5uJ!Vm0>?p*Y2YSAne zySwNY%-Y^M+188x8jkE6>=-rGP%{=Eu0@Hx%JB-wwd*v_*vj0)$YX4ud9PYzW|JrC z)XRI0IoWE;yh^KsJT0+)Vb&H(Mi&{kDFdG!%p9}dLc1nUtpa^4wz{zE=|zlx8C|ev zB3nakKe1O&#S1i?7+RQ7q=ktBVlG=t+2a}36&P7q*WT9axf(@$m6DrE$vLwAKhi(w zR&k&E$?L!^LPu3<8!tkKh4$`OddVC+-NcW(OlKJ%Nz5e=n|@-h%DrpKN`Tby0SxLMoZ^fIPLF!7R+r`Cxg+Xu+XVEPo!cR$fWH(#ar z@nxBF(Ze+Lpk6rmUPsU?3Cm9kFf$1|mX)N=kKHUiXvcf2Hnz-dhTobR`ieJ2Kl6qu z$L*zd-pT6WZ6#I@Xo1^OqrG>vz+0o4hWA?QYS5QV zz{(mTB6I9o^p=lJk=Oh`N?v4bkTaC=81mVBntfSk=6DO#SMqm*Gn4f2kk~9$fy&rU zUEvPW1I|*v#(7*D_X*3ru70 z*PyG+yTBlJx%wE&*ppyBcrW~x3Uk)6##0gR;MW|*ucp=jXCHUicl0-V<`nw!TyUvh zV}LK_8zd&HO~!p{<921dBkLl3yaVyHT3yn~lMc>i^|U%nA}{rhp*^6ddS_?{f~@V$8e$GK@SDjIz|6JlTj**78@nJ@&3g?re9zSYgA~2?F?w|?lHWu7 zgm#JA2l?{6O}Ykp7W5+MjnMp%Hu!gtFOKs0AxVF4;7u<1I5Ou*OdN@g&8F5Id(ZzT z5IgUJx4~Qg>$4o;s~`&`cGHLSr;n_oKN+QB=@7Z(oAbf5u;u0Oa8+`<1Zz=Qn% zGxRm+eCB`3x~b6Dliv@GhQAN|0e&z1onQq2ABJW_yMxxC73=32n0}DS{^@8ucuO>mp+C$&BBK7U_-`+SO#h!;# z;T8CY=qa0y4c zjnv%g?9-DV3v>u*A#)DIy84@_O)bf(`{^|o8`#=r>KefBH{0*^{#r8!x)J^~=>D*# zg}Jp+j!je3erW!9Yvc*k)SLjLBlx!Q5Ellx#vodYj~D4`_X*eXZ>iC#b^81AVVw_= zt}kuW2c+TC?RUIKGK(jd=!noM}05sXWFZM10r#EyfAMIZ}pMhKa?RF#|`lo zz7ZyCKq|-sX9qQO5&5DgI1Nyv{5gzG%KSz-nJ*{@el?(O9{v|}ocRWQ%9$m_zVZ*j zKLnrUZM1Vo1Q?gjpQCt~b)( z?`;B+9xyG<)!pC)_?GZ3mHeF(LA~T~Z~{w@-EU9^fCju*FfaRFO{yP2f7X$UiY{(h&h888-#WTbI&17rJ=}k z6W@m2AdO(}pCH31_PhBj=@xpT(J|@P3TZ4o&bYUv+hZa8 zgY5VAkshd&e)Fa@iMth1Ca18+6xKY%84rCf6(e^sIw^i0pu?&3e^WVQ>LzI#^QUpw zY31O3siY%d{}RqB`HM6ie)<@IzNRC4DgIu{_fm9T%J;H1fc?tg%W9=^WGKgX%ei+s z`^{kg8IMXc+e@=q`&)GJ2)*4SYos~XNsl7eJY=6=Ej`9PDzIY(cV2+)pGZhgagR#u zv9KTD{6*a1X?o0Okmp(EEkSonh^wX8;yLCnqwlQZ{?C6TEoaS2`o~ozQZ@Z!^+ahk zwt0y)FQb<=-1!yO)L@4ide0hs=T&U)4NZ=t8RS@Sl2@DAe}xX*j6Lj`)DGv7zo8}Z34;{my13x2(oyKcoNx3az# zU#{icT4bt4uiMb$HuSR%e%lslJNDm>J-4Idx;#SZEP(ISbKVE10QC7G;~%1*9r)S~ zVreI`?IN%2;vT#3t^ZJ5@4;DBR~U!)+1?mbWE2qr5iJ!&L2N2ub7;AjS|wihca!H~G#v zd#}CLyWVxae5HC&ItBb%E>?vaDtNKNb)_>7d3H#zs+vMLoE<{7zSgL_*6bV^9>Oto z9PbU!j`PQHG3)42mxF>3PSEZIFP#wg6pc?g|I}_Yhfr@{z4-O&saHb-e>Cb-qx+3? zYou4Bo}K2W)Al!+w;v`#pMTivH-&Z0eACP$&2l|MuQT*HBiH_0t@jWT0(Np%ON@M=8#+vL(l0vriRr}hxLlRP^)uTxP-I?KItFId}oId+ER zs#X|?`>+uQL(-)k#$y@O(8c*z55-b=e)ZXqbd_sYnsrUboRC~2&u;4R{!F@y*WLZ@ z?spfX`+BIiM;AfZ9{&k)rMt8m7Dpz3ne%{|x9`e{uUage0{a+)H&Yl@6)y4RCLO zdjsS%NUejMGpITwgVlMw0`C})h~jZx2m zk4Ee37(E)Z3a-b>V=T|6_kp^{SvO8yBoEF)WEB52oKW?TUH$O{wdWiw=4N{rM1uM;q&re#Vap} z|HAN)tXAV{YyVse?}Zn6H3P#>%248$>TLT=Bqtl?fLS}7wh#~z|XI% z<8>OZr^g$#dZR8RZ}R^J`Ml*_@i%?nI65Tnl!WA6=f5YP59I!VGe0!ro9MLJtZe3q zEqtEaAy<0#3 zMbm$~-b074=%U8oY zuU!5WG^sQzm10$@;Sl|+c=E9GtDRdTw;DOu@{Uh|%A3&c{MDgm`XGEDiCz(I^S={7W$b zPoO@;3*JX{h^^Y=F3iUUSlim?)}FVv?m}@coQ|_0Uepxg#XayPnnP@JGnQd%h?h9K z?aLuvdTxl9-3zfUv!`8Zh?oBr-_Cr6k?Cu5U&@z z=kO43u&0+gdwG6iT8KBT$5&88A9ePzr*D@K`*jO3r47VSabC((_y`ptrcQ%eQ$K`S z2DCz7Oah$;ybJjaw11%e1MMFq?x15K4wnC5=MNqV^$pgq!P`R|k{RM{Y8Wbqp*unx zrsiS#b-U-kaNdZSA>N@!cZxrfp1-8+XxC%(WUQLUs&VYw*cYOIbz-{v=^5aGbegAs zgO(7-(R17w=s ztevX%sq&vHuc>@EjTfe=ZQ84F?)26n&T!@oXU=fu3}?=8=FDrMuQMOPTI`1NXVHI_ z-ptaoS!&EN5oXD~q04{4<+Yv+bX4|NZ)Wzy8h9 z>j!xG!9F3*6F<8H)b+5vkMM4e8s@9(_p4yf0?!uM_t;N}vrr!v%J&caut@K7^*C3) zx$?-R?_x0*>%|iLm)O753_Zc?PxitsAugkh-yiX*u8_mi6GP0?$7g8ujNUJ&`SK|t zuCRWE^()&!FP?S%tn23^%#gvuHPHt8$Q3uzZ>ZC7T(skjn3YvZ|{iv&XEw` zqw#xcecvp6V9h3bHhm6$*`x=Xd1Lc1n6HodU<Pqh+81;4ms{r&rbF3wC*!neZf;-^5Y)0eJ#KLn4|ylexdUU`MS`W zLY^tq*Fv!hd9qNiiY`KDsJ}>$io8dPmO~vybS>7~V!bW)&M2l|G5w0gDi*6)Ud3V+ z%gc95ED@`OmL+Dj#Jiz{9wq#--@9Qy4fcCC?5EX!Gq#^6O3iPnxTR*dlwV5CuHQki zj0R9hK&&l7A1Hql4z?Aa5Py(L=O5#6yQ@U8QeTdR28F z^t-A6`hQp-57Xu_za3tQZQ$o>eXQp7YVZGQeW|8XHJxhcR70m4I@QprhE6qfs@1nz zeW+F25o?aB`?wtI%!< zV&oxYD{@s#-a=%rm=67rWypWT;4ZhJ?=xuw+D6i0I#0p+>J~TZ! z*DDkGGD7TLPa(wYMUK6*5&ZNfx8CGg2Bu|TR0eisU{gl@eZZ{`YkgSjL+n1UBjD#F zSAHKF-^<8v#oU9hdqyI)$cxA+gk1U#L@E)m>I-*Y7>}$#&WY*AnSOBgMM3buU7z`if#2@k#F~hJO(FK8vuTbNC;Bh~D55UEP7^CQ) zQS{m9lVZkXh#5Op%s70G2bT%pJ%N~y#>Gqo&q?4s2^_vQSIlH;p3M0vYsE|@pJ`w= zotnQ+9enPa8Pq%zy9zk0ARfQH%q)6#7H4MBo3lqD=(CTDnFIE7W+UJ^mwe~aA9Ja5 zUO7^Qkl#FVn#Z~M?9Ydz`P&iVEhs~%Z2>$lAlFK8s-*5p&Q+3Y3Asz4`%!yld#88v20Wji!b^uYt!};)Pic<173ULSHS0 z$Hny2VlY~Q-z60Y*hI)70#6YzkI>H%`n!%^tJ{dcV?F!z^hZ6<_4sZWiZmnGHo|e^ zqX_&oa&9TPE+wa>)Ey1m2z?))UmSl3BEpnpbjeC3k-n>#N9N z6*;VCZ#6S(HSt#Ca}6A>*@KYFTISYTdS)#=e1qBZB=~-lyYm$9>#$o#|E{CH_0+na zI2-V_p&9{$jqtsZUfW1Kz6+U6+|f<=*z|WXt<=!UooFTA)7U+|Ud%Iv2zTdMaC{a{ zH{)wFb8s`YY^Eo+a7VX**A{wY3q7-y*x!QxZ^P|(;O;s6Jx}c~aOS(@^CH}Q5BqK0 z)$enEUZSQSfYHnJ?+>YaJL}uY{T1TB(umMkJD8t4xLZ5GX(xVn(o;L>&0YA}1^&CR z-%YRWhL7Fcm)-Eb2aNWB-yY8Fp`Ttwe-&SQ;czef?*+$w+=G4av7dh2PcQ5T>;2$( zfO&j?dv<_W2f*ndyc`6JgYbTcIESe95a(Z`uESt@nD|GyuSdAkN9e($%#Nea1dB<5{C6W)Q7cZv5d*q)(|Gt_kk`?K(P7Cg@q;~X5G z!{!`!oW7@3bFp%1-NR1L zkix7>PB*eJ>$uZ1(`>S&Th_-;&z8dMGN4j2R_^DT!{;laa!|ClLtK;9Co*_BKqn&PKNbzu|XQtU? zNq+G}r)OjDcY2Nliff&oE1f$RIlaA%E9vL-ybOQGvrg|I!%D(V&zBJ;+niot<`Xsv` zXQtU$j;wAuvbyES>Xsv`TaK)5IkLLt$m*6Ot6Pq&ZaMPwytH~dXe|>|&re$~)Y|8$ zUgXtMTBCYr^y1Pc)w`tGclG=@y(DeDyPn;kdQXjIefCbX>651SQ~T#tAEf$D)$djP zu&3vy<)51tD?e>LKT%7CESE+JNwxST$h%MWAr(@q`V?u9dL-_wd@_coD7yFRXFaSI zK2{=}FGm}z>;BK_X-G0NpUh+@B27t~7;6)GxABI_gZvMbd!061S4VRq!ut%))R045 zPtCwz42d#ZLQd~v9mh9`)W0;+|TGwhU5B0c<5Yq~SdN!{6_3FiY_i}2`9Kx=aM)mDw6x6I@8qM4B z?5p(M=HH~zd>SD=tFZcyvtO^zE$X}0MGraK2K8lQC)OkCJMIt(@??>@-7b#LkfIXi z-TDr?l_o{n<0{o94a!SY5sm11FH^5O>fEVBgrJ^pc2UEwQg6?qnL?o&OV68KP2n1L z=r*`Y!fM~7PbpSo+OZMM?(RL2xH++8E#6+8`b+tU5@(6a*6;8SYES!I-zPAu(%3b+ zYR|W@6LuVWHW9eDJ<`By4SUTFZR;U*m;K6>?GB$}7c4H0nLG-B_rKmB%-!TjGLJfaN_B7iws{k~t-hd(5l|0JigeX2y&00FtS6B5 zdOMh`uv&ZDr#-Mtv5jfp#g&bkB}X>js3#ax%A=8@g4Q%3xMdEGtRfNHJKv)FenlecVt9ARq8QiniHsB88?}e(bcQB!E5Bo|j=Y66 zZ{F2t|9k9?BB<%T7m_I03koRqie0f`S8S+& z3J5AHiVZ0$D5$7dwgtZd_SxHg{`0=)`@dWlnVDzSx}VjbHDjD9)&Dj>+eJMj8UKpT zY$Z+Z>PW(UVim8y{H)K(O4Q2-;FHzPJgQ-3-#vfI9^9m|mzHG=|2TkgW18M@*`N6IY2U+z#?SqF@AlAH%OdIo zXIkHTaoYw~ssb#fcOz~l$u)E0oe-|;{nH17lPIyJY_sI+#}VmUv->apG+TVwr#X9R z=&Y219Cp)%>dFZlo5uB{aqbT7Orc#G)KvTIP176H=}D&*;-m(*KK-oX7AS7H@*)XcU(6$kJs(nw6aKm)v%CJ$$Why zWb1(2BtCRaMg3air$-qx!v;+9q7Wx)g>S*%T%Aa?OS+=c4oI2d*_VxLMjI}2!^7`a z9Sl$1$ZZ3!nET&s!`b7p&lg9pswkN@uO zV+3|ijP^3$42%%gxW5{BJqJ!w^Ioi3`*Qzjf$zLSuM$rl{P3ad+08L_=UvN@;EH3p z0ZA8ShtH1}SgBA1s%$m5$ z_?@WbFWx^P{nR#k3h2F>fU=9^51ZiXZ(jn;8;VaKvJ+-YX1LVWK7P-6w_^7k%Gmdm z+349+L*31q4&I+~m zPY0nBLO!J4UH>eiak~aPMI3)&^t6d@Z%?hUmVTPCZ`-lkT-nZ{rI7N*nJI-aJFffo zN(mbM=rif^QLb!m+B2U8w;!$_+Pp<{c)^Zq@(V9MecD4wDUD5yz1IJSD{SP#9n%+1 z94gol_H^0m1L?ny?azp>bw)to6HnNu&2Q*qc-dpw?pW zm;(uDmw&59ru>|9Gu8kMT%1Wqr7<%0A6j6F&AyO*>15RC{$EBL;%(pKOEV$|im$H4 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 DGphXP diff --git a/mods/clean_file_storage/README b/mods/clean_file_storage/README deleted file mode 100644 index 52fec4433..000000000 --- a/mods/clean_file_storage/README +++ /dev/null @@ -1,3 +0,0 @@ -This is a module that cleans up the files and folders left over by removed courses and members from ATutor versions older than 1.6.3 in which when members or courses are deleted, their members' personal files and course assignment files stored in file storage are not deleted accordingly. This module is created for one-time clean-up of these files. - -After installation, this module creates admin tool -> User -> Clean Up File Storage. Clicking on "Clean Up File Storage" leads to the list of the files to be cleaned up and asks for user's approval on deletion. Once user approves, the listed files are permanently deleted from file storage. \ No newline at end of file diff --git a/mods/clean_file_storage/clean_file_storage.jpg b/mods/clean_file_storage/clean_file_storage.jpg deleted file mode 100644 index c6cf71b3be9da5b70601ca2f24e175ddb011b565..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1827 zcmbW!X;hO}8VB$<%S*@xWJ7|%C?XW5ku5TaHZcl8P!5}eEQ2Xq3bg2vMLO3KF!SkKKFjP%Xxn1>R#w3 z0TXYw7aM>;005#NfNlcV2f(1v_0k8fFVGMK;cyUzKo}TeP#6pvg+^nI@FrLzoDmvr zVrqgT5J@Bw#(0C7DbWm1BoWsifxz^4;2;tNkwh#SOZ=as>i}?ufGt3SK`a3%4g$kL zbX@>d-zNz9HNfwIK=nNuAPkWxwEjS|2>^w_U{E-0y=(pHO#MCp$AS1Qjw}O$e+0tv zIMFGmxXN(r-o{Q+z>|3^=g7oUNR;UYGqU+MYnxAO?dUsP{_48ZZJ)ab+jGB{ci^GF z1sx6!35|-5;eHVt7oU`zaw0V?{p9I0x!>gdBmZnk>9-fl$}28izFu8(<7Vxx+jp7- z!e&v+{nj6(54*a1dix&zI5PV5+4Hd%<1)EI`FiTjFK?%3R15$7*GKiDW@&ld1p#2c zvGnV2u>Wx3^e!kI4ud1sT@Yxhe!_5YaEqe>p5>2-I8Ly1$}uGFEv{$G2G{~heq|0Vka_NPk*U|P9gr{1nry(P z^>cKQK%Du=l(gtB!gwUYp;ZVdZRp3%hp&B(PxR7@Frz)@B z)dBNdUVD`G(-pQzED&?B9p!Oac6*^LTo@7GT247i> zijyYWQE6En%azv}VxRcldh6!#;A&BvOKk!;;6(R7r4l>2+9f(S=MCKPM<|2?XUCd-sU{`-6PDua=pe?Sy1w%8PyJH8VkD>V?8bG~r!K2leI) zU)I4L`d%Ma(Ao=mEUkk^r0l8Oq^c}c#QKblH(L-6JPm&=?VTzsaW7`ery9}p=2|^zb^3_q_xA~*92P~@o>&QOq}>8DTF|9jd|)=k2H)4D6x` z7>%nBGScP7`EHA+lHavXwUv60CJ2}6yB7LJeC$@QKMx9cKRW;ef=dfZdoTJR;Z6D$*-((bId?u;CIjZq;;g&oerQ z{6aQ#^75g97IoPjOiK{{_JN90*Cn;ZyS`mYR&lWZ@j~}E_s-STOgAIAX^)EvB-UxD z#fPu9sHo?~{)%J9K8}|&b|x2Eb*6HkRE$@D=_>x&iEP2O6F2RdAqv0-Q1e0Yff7Hq z+*6yb2-5)@(!zY6`#gJ46Xc)+V!Agr{WLxI#uL9ZV_AZ)8~L8g-Z|uZQ({g<^Mae^ zA1`IRjG4nMn)`)?n0uAEjBgVU^hJ5Z7K)sQUZJ`ml}YNtd1s!jCP6uomB+wl!n{>b zWw@lwmVDw?x_7m(!XwbCrY<&$w(G(Hvg4eGUv2(5f1ecJn0xP*U;R@0I4GG)=g+KM zTFO<~ciZn+R6i&QlPO}Hrq@FJk#J=^KI?>Mf9LM#P2#nD9nk5#;+ttdt2~Cu6}M%K zE6>>!Rz_|5EXV3=($cDm(6yY^WjiNy-A&GnQ0M@Gb$No?YnYWNm0w8;tGGCv{#CZ) z(Szxmqm>`4)s7mx4!}x~apv^f+PA~I>k!zjF;{iK&+cQ^48h&Npwx)XRal(*vzWBJ zJuPFiR-$XLy9J*=uP04e^!9}=c5uvj+f~^2g88AY!*2K^yB?+1xGgQGOgNBJTaLo6 z8do}<&uF9sxwI;aWSk?TZ$@w{7B_q8Ttu5_*gAbL?sN{VziP#=C|*kq(0Gwp}=LHTdqgH*9Q9xOTG=yF;kD@qYuuZZI+c diff --git a/mods/clean_file_storage/index.php b/mods/clean_file_storage/index.php deleted file mode 100644 index 111bd831f..000000000 --- a/mods/clean_file_storage/index.php +++ /dev/null @@ -1,12 +0,0 @@ - - -
    - Hello Student!! :) -
    - - \ No newline at end of file diff --git a/mods/clean_file_storage/index_admin.php b/mods/clean_file_storage/index_admin.php deleted file mode 100644 index 4d4ea45ef..000000000 --- a/mods/clean_file_storage/index_admin.php +++ /dev/null @@ -1,74 +0,0 @@ -addFeedback('CANCELLED'); - Header('Location: ../../admin/index.php'); - exit; -} -else if (isset($_POST['submit_yes'])) -{ - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - Header('Location: ../../admin/index.php'); - exit; -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -if (count($files_to_del) > 0) -{ - $msg_files = '
      '; - - foreach (array_unique($files_to_del) as $file) - $msg_files .= '
    • '.$file.'
    • '; - - $msg_files .= '
    '; - - $confirm = array('DELETE_FILES', $msg_files); - $msg->addConfirm($confirm); - $msg->printConfirm(); -} -else -{ - $msg->addInfo('NO_FILES'); - $msg->printInfos(); -} -?> - - - \ No newline at end of file diff --git a/mods/clean_file_storage/module.css b/mods/clean_file_storage/module.css deleted file mode 100644 index 15da01381..000000000 --- a/mods/clean_file_storage/module.css +++ /dev/null @@ -1,11 +0,0 @@ -div#helloworld { - border: 1px solid #ccc; - padding: 10px; - width: 50%; - margin-right: auto; - margin-left: auto; - background-color: #efefef; - color: #444; - margin-top: 30px; - margin-bottom: 30px; -} \ No newline at end of file diff --git a/mods/clean_file_storage/module.php b/mods/clean_file_storage/module.php deleted file mode 100644 index 748cab8b9..000000000 --- a/mods/clean_file_storage/module.php +++ /dev/null @@ -1,24 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_CLEAN_FILE_STORAGE', $this->getAdminPrivilege()); - -if (admin_authenticate(AT_ADMIN_PRIV_CLEAN_FILE_STORAGE, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages['admin/users.php']['children'] = array('mods/clean_file_storage/index_admin.php'); - $this->_pages['mods/clean_file_storage/index_admin.php']['title_var'] = 'clean_file_storage'; - $this->_pages['mods/clean_file_storage/index_admin.php']['parent'] = 'admin/users.php'; -} - -?> \ No newline at end of file diff --git a/mods/clean_file_storage/module.sql b/mods/clean_file_storage/module.sql deleted file mode 100644 index 124290b3a..000000000 --- a/mods/clean_file_storage/module.sql +++ /dev/null @@ -1,11 +0,0 @@ -# sql file for hello world module - -CREATE TABLE `hello_world` ( - `course_id` mediumint(8) unsigned NOT NULL, - `value` VARCHAR( 30 ) NOT NULL , - PRIMARY KEY ( `course_id` ) -); - -INSERT INTO `language_text` VALUES ('en', '_module','clean_file_storage','Clean Up File Storage',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_CONFIRM_DELETE_FILES','The listed files will be deleted. Are you sure you want to proceed?
    %s',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_INFOS_NO_FILES','There are no files need to be cleaned up.',NOW(),''); diff --git a/mods/clean_file_storage/module.xml b/mods/clean_file_storage/module.xml deleted file mode 100644 index 7046007a5..000000000 --- a/mods/clean_file_storage/module.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - Clean Up File Storage - This is a module that cleans up the files and folders left over by removed courses and members from ATutor versions older than 1.6.3 in which when members or courses are deleted, their members' personal files and course assignment files stored in file storage are not deleted accordingly. This module is created for one-time clean-up of these files. - - After installation, this module creates admin tool -> User -> Clean Up File Storage. Clicking on "Clean Up File Storage" leads to the list of the files to be cleaned up and asks for user's approval on deletion. Once user approves, the listed files are permanently deleted from file storage. - - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.1 - 2008-12-04 - stable - - - diff --git a/mods/clean_file_storage/module_install.php b/mods/clean_file_storage/module_install.php deleted file mode 100644 index e7dcaa886..000000000 --- a/mods/clean_file_storage/module_install.php +++ /dev/null @@ -1,67 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/clean_file_storage/module_uninstall.php b/mods/clean_file_storage/module_uninstall.php deleted file mode 100644 index b5f973153..000000000 --- a/mods/clean_file_storage/module_uninstall.php +++ /dev/null @@ -1,44 +0,0 @@ -addError(array('MODULE_UNINSTALL', '
  • '.$directory.' can not be removed. Please manually remove it.
  • ')); -//} - -/****** - * the following code checks if there are any errors (generated previously) - * then uses the SqlUtility to run reverted database queries of module.sql, - * ie. "create table" statement in module.sql is run as drop according table. - */ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/cmap/README b/mods/cmap/README deleted file mode 100644 index 03654347e..000000000 --- a/mods/cmap/README +++ /dev/null @@ -1,19 +0,0 @@ -# CMAP README - -CMAP is a collaborative concept mapping application. It is possible to the CMAP tools alone to generate concept maps and export them as images or Web pages, which can then be added to an ATutor course. Or, if the CMAP server is installed in a central location, and students have the CMAPTools installed, they can collaborate through the server to create concept maps. - -Web services for CMAP are currently under development, and in a future release will allow the authoring and storing of Maps from directly within ATutor. For now CMAP is a simple addon to an external application. - -See the CMAP web site for complete details about the system. -CMAP Home -http://cmap.ihmc.us/ - -Sample Concept Maps -http://cmapskm.ihmc.us/ - -CMAP Documentation -http://cmap.ihmc.us/Documentation/index.php - -**Installing the ATutor-CMAP module** -Once the CMAP server has been installed and is functioning properly, unpack the atutor_cmap.tar.gz file into your ATutor mods/ directory. Then login to ATutor as the administrator, choose the modules tab, then choose Install Modules from the Modules submenu. Follow the instructions to install the module, then when installed, enable it to make it avalable to courses on that ATutor server. Finally, access the CMAP tab that gets added to the Administrator main menu, and there enter the URL to the CMAP server. Done. - diff --git a/mods/cmap/cmap_logo.jpg b/mods/cmap/cmap_logo.jpg deleted file mode 100644 index 779a75b65f8093dafa0153eec5faf1aa8b884344..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1428 zcmb7^YdDk%6vy9pW?q8~UWP1V#$4nwQ7$ubnM$rRE*UGVrdmWsE}IgewsHxnVThi6 za!J%8gvk)k%7$5y808*OYC^SJEe$d|J^P_&Kkn~5=X^Qme=c8+Y)tkXP-nR^T>%gT z0e86pvROdeC6OBr0A5~zDF6V9a+f2U1e^c}i9(@}kUT&Tq<~gYM9Wdzv`I+?R@2ac z)nHgt8@E{#tE&aWIz$~^eSHFfpt+euA>k=FJOTf;2`HDM70{}RimG@ljK%+NWcLAB z5wHX-kst{`z#tL^WnBOc01ybI{EBZVAW$HLMk>m)baenkqCgNrDx?1`01-$O04cy4 zL`@4vb}*WB46CJ0wzS&gl-EG>4GBGdu3WCu0fGPa1c0wXdBy;i&y$1vHV;I=NDZO| z$ESmsSkf3}$Bn<2V)`-L1ca2xTd)`?_jMnbR7f>H6vC&6AOvqm-EHI9O;4<&b z>FW9Ak0+%)QPfcSlO{}BtD&^s1avsh^Fj`ymhxXSwH>BEs?I1(XVFnT(G}bKh2sU2 zs(FxKD??L-6o0d=Cy%E#wCxTj^Z6wX0^bs5 z!1v1;ck5RF5Si`Jzi1&c8|t&Dql;d3`4;-^>n<;Xo96PnR?}DgY-y%ko%f8|6mOw^ z*S!ZZw_3T%dVg0vJ$mF%$;{l|xBig?m8Am^mc4r*I*;uqC8S0+6AzYTJVATC+oSk9QGqJ^^7tu; zLl3v=bQb>6I}B-^O+OySej8#Gv3OQ%+4m*grbC|+)4X%^Qse7X4u^Llb80NdZYdtE z!3=;5-A7hGFil2l*&>TXW^a+MQ~~pQprG8NFFx%y`daRXQBkg)p513~zk?O7JFv^l zhN(@p@)p9kiim7Ih(f`K1xZp80vIu!E-ed>IZ2r57oq8NJeTHa_mE|ybm?-jXiDOC z3?H9!&K7fiqDCkVI6|_UG~fQom0zUckH`>%XlIF3oO&uVE0-l0k2$&KRXtbfdC~6W zj7&ejeb%dX7v^^^+No;~znMgQ1l;T}~ow5xCi3rid;@$2c| zZK-D5s7Sqo(Na%RrkdJq<&<(;cf}nL_r`}+t^^GNXu2F7`pW>&c=j0(S)JeN>F~o z!w9awqH(CiSff+g_SVdIjsmB!Li0Nup+nu+^`8R~{BdR0*-@u*wOX1{O9Pe!f9DCs0bet?oM)gesXF%zsM0AF)BAdQokX79)NOv3fh4wsxrH<-ApA z7APFd6-c!(`Uwfct5$j>^#a41t3U)8l{dUWWfxA*9$bnIiq11P?=NT`9P>l_l(sV| zRZRIWpybc8b!e2{MDZ*0(vG3$3CgC94C69Mxk1U1`t&g8#g2h&6YXGB!O8}C?Ux4( mAAVA?+C;YTr!Ag|erhw|mo3@G&P^hI$JGr1+XW)X#{U6~?mDsn diff --git a/mods/cmap/index.php b/mods/cmap/index.php deleted file mode 100644 index b044094fc..000000000 --- a/mods/cmap/index.php +++ /dev/null @@ -1,29 +0,0 @@ - -
    -
    -

    -
    -
    - -
    -
    -

    -
    -
    - -
    - - - - - \ No newline at end of file diff --git a/mods/cmap/index_admin.php b/mods/cmap/index_admin.php deleted file mode 100644 index ce369642e..000000000 --- a/mods/cmap/index_admin.php +++ /dev/null @@ -1,76 +0,0 @@ -addError('CMAPURL_ADD_EMPTY'); - } - - if (!$msg->containsErrors()) { - $_POST['uri'] = $addslashes($_POST['uri']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('cmap', '$_POST[uri]')"; - mysql_query($sql, $db); - $msg->addFeedback('CMAPURL_ADD_SAVED'); - - header('Location: '.$_SERVER['PHP_SELF']); - exit; - } -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> - - -
    -
    -

    -
    - -
    - -
    -
    -

    -
    -
    - - -
    -
    -
    -

    - - -
    - -
    - -
    -
    -
    - - -
    -| -| -|

    -
    - - -
    -

    -
    - - - - \ No newline at end of file diff --git a/mods/cmap/index_instructor.php b/mods/cmap/index_instructor.php deleted file mode 100644 index 44374c21b..000000000 --- a/mods/cmap/index_instructor.php +++ /dev/null @@ -1,30 +0,0 @@ - - - -
    -
    -

    -
    -
    - -
    -
    -

    -
    -
    - -
    -| -| -|

    -
    - - - - - \ No newline at end of file diff --git a/mods/cmap/module.php b/mods/cmap/module.php deleted file mode 100644 index 046c947cd..000000000 --- a/mods/cmap/module.php +++ /dev/null @@ -1,73 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_CMAP', $this->getAdminPrivilege()); -define('AT_CMAP_WSDL', 'http://greg-pc.atrc.utoronto.ca::8080/services/CmapWebService'); - -/******* - * create a side menu box/stack. - */ -//$this->_stacks['cmap'] = array('title_var'=>'cmap', 'file'=>'mods/cmap/side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('cmap', array('title_var' => 'cmap', 'file' => './side_menu.inc.php'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_student_tool = 'mods/cmap/index.php'; -// ** possible alternative: ** -// $this->addTool('./index.php'); - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_CMAP, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/cmap/index_admin.php'); - $this->_pages['mods/cmap/index_admin.php']['title_var'] = 'cmap'; - $this->_pages['mods/cmap/index_admin.php']['parent'] = AT_NAV_ADMIN; -} - -/******* - * instructor Manage section: - */ -$this->_pages['mods/cmap/index_instructor.php']['title_var'] = 'cmap'; -$this->_pages['mods/cmap/index_instructor.php']['parent'] = 'tools/index.php'; -// ** possible alternative: ** -// $this->pages['./index_instructor.php']['title_var'] = 'cmap'; -// $this->pages['./index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages['mods/cmap/index.php']['title_var'] = 'cmap'; -$this->_pages['mods/cmap/index.php']['img'] = 'mods/cmap/cmap_logo.jpg'; - - -/* public pages */ -// $this->_pages[AT_NAV_PUBLIC] = array('mods/cmap/index_public.php'); -// $this->_pages['mods/cmap/index_public.php']['title_var'] = 'cmap'; -// $this->_pages['mods/cmap/index_public.php']['parent'] = 'login.php'; -// $this->_pages['login.php']['children'] = array('mods/cmap/index_public.php'); - -/* my start page pages */ -// $this->_pages[AT_NAV_START] = array('mods/cmap/index_mystart.php'); -// $this->_pages['mods/cmap/index_mystart.php']['title_var'] = 'cmap'; -// $this->_pages['mods/cmap/index_mystart.php']['parent'] = 'users/index.php'; -// $this->_pages['users/index.php']['children'] = array('mods/cmap/index_mystart.php'); -?> \ No newline at end of file diff --git a/mods/cmap/module.sql b/mods/cmap/module.sql deleted file mode 100644 index b9adfa938..000000000 --- a/mods/cmap/module.sql +++ /dev/null @@ -1,15 +0,0 @@ -# sql file for Cmap module - -INSERT INTO `language_text` VALUES ('en', '_module', 'cmap_missing_url', 'You must supply the URL to your Cmap installation in the field below.', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_module','cmap','Cmap',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','cmap_admin_text',' The CMAP server admin can be found in the CmapTools client application, which can be downloaded from the CMAP Download Site. The URL entered below should appear something like http://www.mysite.com:8080/, adjusting the port number to the one choosen during installation. See the CMAP documention for installation and configuration instructions.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','cmap_help_window','Cmap Help Window',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','cmap','Cmap',NOW(),''); - -INSERT INTO `language_text` VALUES ('en', '_module','cmap_own_window','Open Cmap in its own Window',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','cmap_text','Use Cmap for collaborative authoring of concept maps, and to retrieve and create concept maps. For collaborative authoring download the latest CmapTools client application. The URL to your Cmap server is %s' ,NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','cmap_open','Open Cmap',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','cmap_location','The location of your Cmap installation:',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_CMAPURL_ADD_SAVED','Location of Cmap was successfully saved.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_CMAPURL_ADD_EMPTY','You must enter a URL to the location of your Cmap installation.',NOW(),''); - diff --git a/mods/cmap/module.xml b/mods/cmap/module.xml deleted file mode 100644 index 95109cd83..000000000 --- a/mods/cmap/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Cmap Concept Mapping Server - This module links the Cmap concept mapping server into ATutor. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - GPL - - 0.2 - 2010-10-25 - stable - A Cmap server must be running and functioning properly to make use of this module once installed. There is also a client CmapTools that can be installed on the users system so they to can interact with the server for collaborative concept map authoring. See the Cmap site for full details (http://cmap.ihmc.us/) Once the module is installed, go to the Cmap admin tool created in ATutor, and enter the URL to your Cmap server. - - \ No newline at end of file diff --git a/mods/cmap/module_install.php b/mods/cmap/module_install.php deleted file mode 100644 index 9168b4543..000000000 --- a/mods/cmap/module_install.php +++ /dev/null @@ -1,26 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/cmap/module_uninstall.php b/mods/cmap/module_uninstall.php deleted file mode 100644 index 52d8f8129..000000000 --- a/mods/cmap/module_uninstall.php +++ /dev/null @@ -1,31 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/cpref_switch/ajax_save.php b/mods/cpref_switch/ajax_save.php deleted file mode 100644 index e426e0173..000000000 --- a/mods/cpref_switch/ajax_save.php +++ /dev/null @@ -1,88 +0,0 @@ - \ No newline at end of file diff --git a/mods/cpref_switch/module.css b/mods/cpref_switch/module.css deleted file mode 100644 index 0afa399e9..000000000 --- a/mods/cpref_switch/module.css +++ /dev/null @@ -1,23 +0,0 @@ -/* Content preferences switcher styles */ -/* These styles need to be moved to styles.css */ -.cpref_switch div { - position: relative; - padding: 1em; - height: 15.5em; -} - -.cpref_switch label { - display: block; - margin-bottom: 0.25em; -} - -.cpref_switch select { - margin-bottom: 1em; - margin-left: 1em; -} - -.cpref_switch input { - position: absolute; - right: 2em; - bottom: 1em; -} \ No newline at end of file diff --git a/mods/cpref_switch/module.inc.php b/mods/cpref_switch/module.inc.php deleted file mode 100644 index 369d06cd2..000000000 --- a/mods/cpref_switch/module.inc.php +++ /dev/null @@ -1,16 +0,0 @@ - \ No newline at end of file diff --git a/mods/cpref_switch/module.php b/mods/cpref_switch/module.php deleted file mode 100644 index 983789b70..000000000 --- a/mods/cpref_switch/module.php +++ /dev/null @@ -1,21 +0,0 @@ -_stacks['cpref_switch'] = array('title_var'=>'cpref_switch', 'file'=>dirname(__FILE__).'/side_menu.inc.php'); - -global $_custom_css, $_base_path; - -$_custom_css = $_base_path . 'mods/cpref_switch/module.css'; // use a custom stylesheet - -?> \ No newline at end of file diff --git a/mods/cpref_switch/module.sql b/mods/cpref_switch/module.sql deleted file mode 100644 index fe276991b..000000000 --- a/mods/cpref_switch/module.sql +++ /dev/null @@ -1,3 +0,0 @@ -# sql file for preference switcher module - -INSERT INTO `language_text` VALUES ('en', '_module','cpref_switch','Content preferences switcher',NOW(),''); diff --git a/mods/cpref_switch/module.xml b/mods/cpref_switch/module.xml deleted file mode 100644 index 3d58daad4..000000000 --- a/mods/cpref_switch/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Content preferences switcher - This module provides users with a menu to switch between adapted content resources. For instance it allows a user to set a preference to view visual content alternatives to text content. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0 alpha - 2010-01-11 - - - - diff --git a/mods/cpref_switch/module_install.php b/mods/cpref_switch/module_install.php deleted file mode 100644 index 8f109fce8..000000000 --- a/mods/cpref_switch/module_install.php +++ /dev/null @@ -1,64 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/cpref_switch/module_uninstall.php b/mods/cpref_switch/module_uninstall.php deleted file mode 100644 index 7a8a35e11..000000000 --- a/mods/cpref_switch/module_uninstall.php +++ /dev/null @@ -1,27 +0,0 @@ -addError(array('MODULE_UNINSTALL', '
  • '.$directory.' can not be removed. Please manually remove it.
  • ')); -} - -?> \ No newline at end of file diff --git a/mods/cpref_switch/side_menu.inc.php b/mods/cpref_switch/side_menu.inc.php deleted file mode 100644 index 56e9608ee..000000000 --- a/mods/cpref_switch/side_menu.inc.php +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - -
    -
    - - - - - - - - - - - - - - -
    -
    - -assign('dropdown_contents', ob_get_contents()); -ob_end_clean(); - -$savant->assign('title', _AT('content_settings')); // the box title -$savant->display('include/box.tmpl.php'); -?> \ No newline at end of file diff --git a/mods/disclaimer/README b/mods/disclaimer/README deleted file mode 100644 index ab463a142..000000000 --- a/mods/disclaimer/README +++ /dev/null @@ -1,20 +0,0 @@ -Disclaimer ReadMe - -This module can be installed with ATutor to set up the legal disclaimer page as ATutor's initial page. Users must agree with the terms and consitions described before accessing ATutor. - -* How to install Disclaimer -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 disclaimer-0.1.tar.gz - -2. Login to ATutor as the administrator and run Install Module under the Modules tab, Select the Disclaimer module, which should be listed as available to be installed when the module has been unzipped into the mods directory - -3. Once the module has been installed, select it's associated radio button from the Module Manager screen, then click Enable. - -4. Go to "Patcher" tab, in section "Upload a zip file to install patch:", select the patch "disclaimer_supplement.zip" in the unzipped module folder "mods/disclaimer", then click "Install" button. - -4. Then to configure the module go to admin home page, and follow the "Legal Disclaimer" link listed with System Preferences, to configuration screen. Enter the text of the disclaimer in the text area, then enter a redirect URL to some location outside ATutor, then enable the disclaimer module by selecting the "Enable" radio button, then Save. diff --git a/mods/disclaimer/common.inc.php b/mods/disclaimer/common.inc.php deleted file mode 100644 index 47148bfd6..000000000 --- a/mods/disclaimer/common.inc.php +++ /dev/null @@ -1,43 +0,0 @@ - 1) { - return true; - } else { - // check whether the user has agreed with legal disclaimer - $sql = "SELECT * FROM ".TABLE_PREFIX."DS_agreed_logins - WHERE login = '".$_SESSION['login']."' "; - $result = mysql_query($sql, $db); - if (mysql_num_rows($result) > 0) { - return true; - } else { - return false; - } - } -} - -function save_agreed_login($login) { - global $db; - - if ($login == '') return; - - $sql = "INSERT INTO ".TABLE_PREFIX."DS_agreed_logins (login) - VALUES ('".$login."')"; - $result = mysql_query($sql, $db); -} -?> \ No newline at end of file diff --git a/mods/disclaimer/disclaimer.png b/mods/disclaimer/disclaimer.png deleted file mode 100644 index 2a56925df807e1256b84742a49800b870ad9b773..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6514 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 diff --git a/mods/disclaimer/disclaimer_supplement.zip b/mods/disclaimer/disclaimer_supplement.zip deleted file mode 100644 index 77101800a89f57f5afbfba3aba56a94c08951ca7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7851 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 - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_TERMS_AND_CONDITION, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages['admin/config_edit.php']['children'][] = 'mods/disclaimer/tac_edit.php'; - $this->_pages['mods/disclaimer/tac_edit.php']['title_var'] = 'disclaimer'; - $this->_pages['mods/disclaimer/tac_edit.php']['parent'] = 'admin/config_edit.php'; -} - -// The user cannot bypass the "terms and conditions" page -//if($_config['enable_terms_and_conditions']==1 && !isset($_SESSION['agree_terms_and_conditions']) && !strstr($_SERVER['PHP_SELF'], 'terms_and_conditions.php')){ -// header('Location: '.AT_BASE_HREF.'mods/disclaimer/terms_and_conditions.php'); -// exit; -//} -// -//// destroy the session var at logout -//if (strstr($_SERVER['PHP_SELF'], 'logout.php')) { -// unset($_SESSION['agree_terms_and_conditions']); -//} -?> \ No newline at end of file diff --git a/mods/disclaimer/module.sql b/mods/disclaimer/module.sql deleted file mode 100644 index 5aa911940..000000000 --- a/mods/disclaimer/module.sql +++ /dev/null @@ -1,13 +0,0 @@ -CREATE TABLE `DS_agreed_logins` ( - `login` varchar(30) NOT NULL, - PRIMARY KEY ( `login` ) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - -INSERT INTO `language_text` VALUES ('en', '_module','disclaimer','Legal Disclaimer',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','enable_terms_and_conditions','Enable Legal Disclaimer',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','tac_link','Where to redirect if users do not agree to the legal disclaimer',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','tac_attention','Before using this Online Learning System, please indicate that you agree with the following terms by clicking on the \"Yes, I Agree\" button located below.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','i_agree','Yes, I Agree',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','i_do_not_agree','No, I do not Agree',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_TAC_SAVED','Legal Disclaimer is saved successfully.',NOW(),''); \ No newline at end of file diff --git a/mods/disclaimer/module.xml b/mods/disclaimer/module.xml deleted file mode 100644 index 7fda4bda7..000000000 --- a/mods/disclaimer/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Legal Disclaimer - To enforce the users to agree to the legal disclaimer before they login. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.2 - 2010-07-20 - stable - - - diff --git a/mods/disclaimer/module_install.php b/mods/disclaimer/module_install.php deleted file mode 100644 index b8b2a9746..000000000 --- a/mods/disclaimer/module_install.php +++ /dev/null @@ -1,52 +0,0 @@ -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); -} -?> \ No newline at end of file diff --git a/mods/disclaimer/module_uninstall.php b/mods/disclaimer/module_uninstall.php deleted file mode 100644 index 0b7022e52..000000000 --- a/mods/disclaimer/module_uninstall.php +++ /dev/null @@ -1,30 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/disclaimer/tac_edit.php b/mods/disclaimer/tac_edit.php deleted file mode 100644 index 3f27259f2..000000000 --- a/mods/disclaimer/tac_edit.php +++ /dev/null @@ -1,117 +0,0 @@ -addFeedback('TAC_SAVED'); - } - header('Location: tac_edit.php'); - exit; -} - -//get config preferences -$_POST['body_text'] = htmlentities($_config['tac_body']); -$_POST['tac_link'] = htmlentities($_config['tac_link']); - -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; - } -} - -//template goes here -include(AT_INCLUDE_PATH.'header.inc.php'); -if (($_POST['setvisual'] && !$_POST['settext']) || $_GET['setvisual']) { - $_SESSION['prefs']['PREF_CONTENT_EDITOR'] = 2; - load_editor(); -} else if ($_POST['formatting']) { - $_SESSION['prefs']['PREF_CONTENT_EDITOR'] = 1; -} else { - $_SESSION['prefs']['PREF_CONTENT_EDITOR'] = 0; -} -?> -
    -
    -
    -
    -
    - /> /> -
    -
    -
    - -
    -
    -
    - onclick="javascript: document.form.setvisual.disabled=true;" /> - - - onclick="javascript: document.form.setvisual.disabled=false;"/> - - - '; - echo ''; - } else { - echo ''; - } - ?> -
    - -
    -
    - -
    - -
    - - -
    -
    -
    -
    - \ No newline at end of file diff --git a/mods/disclaimer/terms_and_conditions.php b/mods/disclaimer/terms_and_conditions.php deleted file mode 100644 index 51ffe94d9..000000000 --- a/mods/disclaimer/terms_and_conditions.php +++ /dev/null @@ -1,58 +0,0 @@ -addFeedback('LOGIN_SUCCESS'); - header('Location: '.AT_BASE_HREF.'bounce.php?course='.$_POST['form_course_id']); - exit; - } -} else if (isset($_POST['disagree'])) { - $_SESSION = array(); // destroy all session vars set in login.php - header('Location: '.$_config['tac_link']); - exit; -} - -$savant->assign('site_name', $_config['site_name']); -$savant->assign('theme', $_SESSION['prefs']['PREF_THEME']); -$savant->assign('base_href', $_base_href); -$savant->assign('body_text', $_config['tac_body']); -$savant->display('terms_and_conditions.tmpl.php'); -?> \ No newline at end of file diff --git a/mods/disclaimer/terms_and_conditions.tmpl.php b/mods/disclaimer/terms_and_conditions.tmpl.php deleted file mode 100644 index ced1c3425..000000000 --- a/mods/disclaimer/terms_and_conditions.tmpl.php +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - <?php echo $this->site_name . ' - ' . _AT('disclaimer'); ?> - - - -
    - -
    -
    -
    body_text; ?>
    -
    -
    -
    - - - - - - - - - - - -
    -
    - - diff --git a/mods/ecomm/datetimepicker.js b/mods/ecomm/datetimepicker.js deleted file mode 100644 index 95b53f827..000000000 --- a/mods/ecomm/datetimepicker.js +++ /dev/null @@ -1,487 +0,0 @@ -//Javascript name: My Date Time Picker -//Date created: 16-Nov-2003 23:19 -//Scripter: TengYong Ng -//Website: http://www.rainforestnet.com -//Copyright (c) 2003 TengYong Ng -//FileName: DateTimePicker.js -//Version: 0.8 -//Contact: contact@rainforestnet.com -// Note: Permission given to use this script in ANY kind of applications if -// header lines are left unchanged. - -//Global variables -var winCal; -var dtToday=new Date(); -var Cal; -var docCal; -var MonthName=["January", "February", "March", "April", "May", "June","July", - "August", "September", "October", "November", "December"]; -var WeekDayName=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]; -var exDateTime;//Existing Date and Time - -//Configurable parameters -var cnTop="200";//top coordinate of calendar window. -var cnLeft="500";//left coordinate of calendar window -var WindowTitle ="DateTime Picker";//Date Time Picker title. -var WeekChar=2;//number of character for week day. if 2 then Mo,Tu,We. if 3 then Mon,Tue,Wed. -var CellWidth=20;//Width of day cell. -var DateSeparator="-";//Date Separator, you can change it to "/" if you want. -var TimeMode=24;//default TimeMode value. 12 or 24 - -var ShowLongMonth=true;//Show long month name in Calendar header. example: "January". -var ShowMonthYear=true;//Show Month and Year in Calendar header. -var MonthYearColor="#cc0033";//Font Color of Month and Year in Calendar header. -var WeekHeadColor="#0099CC";//Background Color in Week header. -var SundayColor="#6699FF";//Background color of Sunday. -var SaturdayColor="#CCCCFF";//Background color of Saturday. -var WeekDayColor="white";//Background color of weekdays. -var FontColor="blue";//color of font in Calendar day cell. -var TodayColor="#FFFF33";//Background color of today. -var SelDateColor="#FFFF99";//Backgrond color of selected date in textbox. -var YrSelColor="#cc0033";//color of font of Year selector. -var ThemeBg="";//Background image of Calendar window. -//end Configurable parameters -//end Global variable - -function NewCal(pCtrl,pFormat,pShowTime,pTimeMode) -{ - Cal=new Calendar(dtToday); - if ((pShowTime!=null) && (pShowTime)) - { - Cal.ShowTime=true; - if ((pTimeMode!=null) &&((pTimeMode=='12')||(pTimeMode=='24'))) - { - TimeMode=pTimeMode; - } - } - if (pCtrl!=null) - Cal.Ctrl=pCtrl; - if (pFormat!=null) - Cal.Format=pFormat.toUpperCase(); - - exDateTime=document.getElementById(pCtrl).value; - if (exDateTime!="")//Parse Date String - { - var Sp1;//Index of Date Separator 1 - var Sp2;//Index of Date Separator 2 - var tSp1;//Index of Time Separator 1 - var tSp1;//Index of Time Separator 2 - var strMonth; - var strDate; - var strYear; - var intMonth; - var YearPattern; - var strHour; - var strMinute; - var strSecond; - //parse month - Sp1=exDateTime.indexOf(DateSeparator,0) - Sp2=exDateTime.indexOf(DateSeparator,(parseInt(Sp1)+1)); - - if ((Cal.Format.toUpperCase()=="DDMMYYYY") || (Cal.Format.toUpperCase()=="DDMMMYYYY")) - //if ((Cal.Format.toUpperCase()=="YYYYMMDD") || (Cal.Format.toUpperCase()=="YYYYMMMDD")) - { - strMonth=exDateTime.substring(Sp1+1,Sp2); - strDate=exDateTime.substring(0,Sp1); - } - else if ((Cal.Format.toUpperCase()=="MMDDYYYY") || (Cal.Format.toUpperCase()=="MMMDDYYYY")) - { - strMonth=exDateTime.substring(0,Sp1); - strDate=exDateTime.substring(Sp1+1,Sp2); - } - if (isNaN(strMonth)) - intMonth=Cal.GetMonthIndex(strMonth); - else - intMonth=parseInt(strMonth,10)-1; - if ((parseInt(intMonth,10)>=0) && (parseInt(intMonth,10)<12)) - Cal.Month="0"+intMonth; - //end parse month - //parse Date - if ((parseInt(strDate,10)<=Cal.GetMonDays()) && (parseInt(strDate,10)>=1)) - Cal.Date=strDate; - //end parse Date - //parse year - strYear=exDateTime.substring(Sp2+1,Sp2+5); - YearPattern=/^\d{4}$/; - if (YearPattern.test(strYear)) - Cal.Year=parseInt(strYear,10); - //end parse year - //parse time - if (Cal.ShowTime==true) - { - tSp1=exDateTime.indexOf(":",0) - tSp2=exDateTime.indexOf(":",(parseInt(tSp1)+1)); - strHour=exDateTime.substring(tSp1,(tSp1)-2); - Cal.SetHour(strHour); - strMinute=exDateTime.substring(tSp1+1,tSp2); - Cal.SetMinute(strMinute); - strSecond=exDateTime.substring(tSp2+1,tSp2+3); - Cal.SetSecond(strSecond); - } - } - winCal=window.open("","DateTimePicker","toolbar=0,status=0,menubar=0,fullscreen=no,width=195,height=245,resizable=0,top="+cnTop+",left="+cnLeft); - docCal=winCal.document; - RenderCal(); -} - -function RenderCal() -{ - var vCalHeader; - var vCalData; - var vCalTime; - var i; - var j; - var SelectStr; - var vDayCount=0; - var vFirstDay; - - docCal.open(); - docCal.writeln(""+WindowTitle+""); - docCal.writeln(""); - docCal.writeln("
    "); - - vCalHeader="\n"; - //Month Selector - vCalHeader+="\n\n"; - vCalHeader+=""; - //Calendar header shows Month and Year - if (ShowMonthYear) - vCalHeader+="\n"; - //Week day header - vCalHeader+=""; - for (i=0;i<7;i++) - { - vCalHeader+=""; - } - vCalHeader+=""; - docCal.write(vCalHeader); - - //Calendar detail - CalDate=new Date(Cal.Year,Cal.Month); - CalDate.setDate(1); - vFirstDay=CalDate.getDay(); - vCalData=""; - for (i=0;i\n"; - } - } - docCal.writeln(vCalData); - //Time picker - if (Cal.ShowTime) - { - var showHour; - showHour=Cal.getShowHour(); - vCalTime="\n\n"; - docCal.write(vCalTime); - } - //end time picker - docCal.writeln("\n
    "; - //Year selector - vCalHeader+="\n
    \n"; - vCalHeader+="< "+Cal.Year+" >
    "+Cal.GetMonthName(ShowLongMonth)+" "+Cal.Year+"
    "+WeekDayName[i].substr(0,WeekChar)+"
    "; - vCalTime+=""; - vCalTime+=" : "; - vCalTime+=""; - vCalTime+=" : "; - vCalTime+=""; - if (TimeMode==12) - { - var SelectAm =(parseInt(Cal.Hours,10)<12)? "Selected":""; - var SelectPm =(parseInt(Cal.Hours,10)>=12)? "Selected":""; - - vCalTime+=""; - } - vCalTime+="\n
    "); - docCal.writeln("
    "); - docCal.close(); -} - -function GenCell(pValue,pHighLight,pColor)//Generate table cell with value -{ - var PValue; - var PCellStr; - var vColor; - var vHLstr1;//HighLight string - var vHlstr2; - var vTimeStr; - - if (pValue==null) - PValue=""; - else - PValue=pValue; - - if (pColor!=null) - vColor="bgcolor=\""+pColor+"\""; - else - vColor=""; - if ((pHighLight!=null)&&(pHighLight)) - {vHLstr1="color='red'>";vHLstr2="";} - else - {vHLstr1=">";vHLstr2="";} - - if (Cal.ShowTime) - { - vTimeStr="winMain.document.getElementById('"+Cal.Ctrl+"').value+=' '+"+"winMain.Cal.getShowHour()"+"+':'+"+"winMain.Cal.Minutes"+"+':'+"+"winMain.Cal.Seconds"; - if (TimeMode==12) - vTimeStr+="+' '+winMain.Cal.AMorPM"; - } - else - vTimeStr=""; - PCellStr=""+PValue+""+vHLstr2+""; - return PCellStr; -} - -function Calendar(pDate,pCtrl) -{ - //Properties - this.Date=pDate.getDate();//selected date - this.Month=pDate.getMonth();//selected month number - this.Year=pDate.getFullYear();//selected year in 4 digits - this.Hours=pDate.getHours(); - - if (pDate.getMinutes()<10) - this.Minutes="0"+pDate.getMinutes(); - else - this.Minutes=pDate.getMinutes(); - - if (pDate.getSeconds()<10) - this.Seconds="0"+pDate.getSeconds(); - else - this.Seconds=pDate.getSeconds(); - - this.MyWindow=winCal; - this.Ctrl=pCtrl; - this.Format="ddMMyyyy"; - this.Separator=DateSeparator; - this.ShowTime=false; - - if (pDate.getHours()<12) - this.AMorPM="AM"; - else - this.AMorPM="PM"; -} - -function GetMonthIndex(shortMonthName) -{ - for (i=0;i<12;i++) - { - if (MonthName[i].substring(0,3).toUpperCase()==shortMonthName.toUpperCase()) - { return i;} - } -} -Calendar.prototype.GetMonthIndex=GetMonthIndex; - -function IncYear() -{ Cal.Year++;} -Calendar.prototype.IncYear=IncYear; - -function DecYear() -{ Cal.Year--;} -Calendar.prototype.DecYear=DecYear; - -function SwitchMth(intMth) -{ Cal.Month=intMth;} -Calendar.prototype.SwitchMth=SwitchMth; - -function SetHour(intHour) -{ - var MaxHour; - var MinHour; - if (TimeMode==24) - { MaxHour=23;MinHour=0} - else if (TimeMode==12) - { MaxHour=12;MinHour=1} - else - alert("TimeMode can only be 12 or 24"); - var HourExp=new RegExp("^\\d\\d$"); - if (HourExp.test(intHour) && (parseInt(intHour,10)<=MaxHour) && (parseInt(intHour,10)>=MinHour)) - { - if ((TimeMode==12) && (Cal.AMorPM=="PM")) - { - if (parseInt(intHour,10)==12) - Cal.Hours=12; - else - Cal.Hours=parseInt(intHour,10)+12; - } - else if ((TimeMode==12) && (Cal.AMorPM=="AM")) - { - if (intHour==12) - intHour-=12; - Cal.Hours=parseInt(intHour,10); - } - else if (TimeMode==24) - Cal.Hours=parseInt(intHour,10); - } -} -Calendar.prototype.SetHour=SetHour; - -function SetMinute(intMin) -{ - var MinExp=new RegExp("^\\d\\d$"); - if (MinExp.test(intMin) && (intMin<60)) - Cal.Minutes=intMin; -} -Calendar.prototype.SetMinute=SetMinute; - -function SetSecond(intSec) -{ - var SecExp=new RegExp("^\\d\\d$"); - if (SecExp.test(intSec) && (intSec<60)) - Cal.Seconds=intSec; -} -Calendar.prototype.SetSecond=SetSecond; - -function SetAmPm(pvalue) -{ - this.AMorPM=pvalue; - if (pvalue=="PM") - { - this.Hours=(parseInt(this.Hours,10))+12; - if (this.Hours==24) - this.Hours=12; - } - else if (pvalue=="AM") - this.Hours-=12; -} -Calendar.prototype.SetAmPm=SetAmPm; - -function getShowHour() -{ - var finalHour; - if (TimeMode==12) - { - if (parseInt(this.Hours,10)==0) - { - this.AMorPM="AM"; - finalHour=parseInt(this.Hours,10)+12; - } - else if (parseInt(this.Hours,10)==12) - { - this.AMorPM="PM"; - finalHour=12; - } - else if (this.Hours>12) - { - this.AMorPM="PM"; - if ((this.Hours-12)<10) - finalHour="0"+((parseInt(this.Hours,10))-12); - else - finalHour=parseInt(this.Hours,10)-12; - } - else - { - this.AMorPM="AM"; - if (this.Hours<10) - finalHour="0"+parseInt(this.Hours,10); - else - finalHour=this.Hours; - } - } - else if (TimeMode==24) - { - if (this.Hours<10) - finalHour="0"+parseInt(this.Hours,10); - else - finalHour=this.Hours; - } - return finalHour; -} -Calendar.prototype.getShowHour=getShowHour; - -function GetMonthName(IsLong) -{ - var Month=MonthName[this.Month]; - if (IsLong) - return Month; - else - return Month.substr(0,3); -} -Calendar.prototype.GetMonthName=GetMonthName; - -function GetMonDays()//Get number of days in a month -{ - var DaysInMonth=[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; - if (this.IsLeapYear()) - { - DaysInMonth[1]=29; - } - return DaysInMonth[this.Month]; -} -Calendar.prototype.GetMonDays=GetMonDays; - -function IsLeapYear() -{ - if ((this.Year%4)==0) - { - if ((this.Year%100==0) && (this.Year%400)!=0) - { - return false; - } - else - { - return true; - } - } - else - { - return false; - } -} -Calendar.prototype.IsLeapYear=IsLeapYear; - -function FormatDate(pDate) -{ - - if (this.Format.toUpperCase()=="DDMMYYYY") - return (this.Year+DateSeparator+(this.Month+1)+DateSeparator+pDate); - else if (this.Format.toUpperCase()=="DDMMMYYYY") - return (pDate+DateSeparator+this.GetMonthName(false)+DateSeparator+this.Year); - else if (this.Format.toUpperCase()=="MMDDYYYY") - return ((this.Month+1)+DateSeparator+pDate+DateSeparator+this.Year); - else if (this.Format.toUpperCase()=="MMMDDYYYY") - return (this.GetMonthName(false)+DateSeparator+pDate+DateSeparator+this.Year); - -} -Calendar.prototype.FormatDate=FormatDate; \ No newline at end of file diff --git a/mods/ecomm/error_beanstream.php b/mods/ecomm/error_beanstream.php deleted file mode 100644 index 0ae9ff732..000000000 --- a/mods/ecomm/error_beanstream.php +++ /dev/null @@ -1,28 +0,0 @@ - -



    -
    -printErrors('EC_PAYMENT_FAILED') ?>. -


    -
      - -
    - \ No newline at end of file diff --git a/mods/ecomm/failure_beanstream.php b/mods/ecomm/failure_beanstream.php deleted file mode 100644 index fa68b7e88..000000000 --- a/mods/ecomm/failure_beanstream.php +++ /dev/null @@ -1,38 +0,0 @@ - -



    -
    - -printErrors('EC_PAYMENT_FAILED') ?> - -
    - - -


    - - - - \ No newline at end of file diff --git a/mods/ecomm/images/cal.gif b/mods/ecomm/images/cal.gif deleted file mode 100644 index 8526cf5d19a915aa8073cf344873c4505491970d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 127 zcmZ?wbhEHb6krfwSj51v)Yr?)cd3`J*V1K6uU)?O9}E~67!-f9FfuT(G3WrDe9t*lRprYQvxW6oWoHk37|QIf^v%1qx=ep z5L56XgJ+HcLWS1t3Fmr7-Md5}AZiTg;OUlh!qgp0U-ehtsraxnJlz}LJWd12)0A;Gnj9OglK}$wqpb4 zv)clRFYb-ScBNTCk(Dd9Y)-bsD(ryB4v6ib$j;q8<|nm&o;{v+d_1d^Tp24O0TBU+ zNkB{iVtOUZNKip9R~#aUoSMbQ%yRio7q4nl*?V`Db1m)b?EML~*@Et9^b>*VEPYb61yLr?8%Y4({=dPd*6kWLfqZ7pm9Gbuo0*6TqA#sqzArfbHV1!UONZ}C0v^YXz z%rb}zL+nN&feBy!BqA)+b`h{Qz{#+YI&E+a76i=R>`OibY7DLi3rB+ia!KgEk2 zce9BnC8Q;b99EG-CFHYG4Ab}FZ8)aCXKXW@4HMQ&BwkP28l1+gg`qDfbFOo|keVo^ ziQ?IbivJPi^vH!JTN6dpFWFlbW^_xW);VQZe%pp(*mYAsienhohgvWUM=^#iXt!mB zP@HLS3}=|RvtYOd$5!4l7G^QyIBvby_tuQfnFrrEexN9ndTXAgNs@MwE{b%~6cf1d z!}#5$xqmFp7?;iCwAD&mCzdA(nlid5Y}sjEc0Q(Q`$vkPUG}9Vhl`+G@7~dr(?wA( zil%9b8M9IuqFprYVqC^zkaD?bmn#Bb&dOf^z)wK0m)q@>D^kTkowO$FymhCdx7zE= zmXy|;d27BvGinR?x2nvSHb-%|t)gS5pZ_y`nrgd$cK*Ylu+-sZh$*)|{C4=_%iBe> zgWqpBRPem_;17d+2hSG!J<5Ol=f8Zr{%MZEb6sW^+=L8p)~^3#Smx;0_oN)Wks{y; zZM^+=Y`F8^I|Vn}UQR6;53mxwHn<;vY?X+H1Loc6c8eD_T^`Qlq>r6cr*@~_e^K;L zzl-FaKdcKogLMqldU$MrxJ0|DswcW0O793>wjo;&b=?r``ii&bZq}H3^NfBD)Od_{DB~cBdN_$! z8J8Zv?sB>)o}V3*u`g^EcJmTB*4nxwk=?9gm;ZDEtPb2NP8 z;ra7oD95JrUtN-|UocyZX5QLPUSiDbFyao@HKLo)cvb zc+;x11k6m1ofr6Mrahux+?{IJjVi8PsA$zJHthIiKG?bg&5Lc=lnY-?>_0kk;>nL? z`jA9%S*7xc-$Z8A+UR?g9i!W?#;G1g{HnV4DD*e&r8PU+Zp!Q2D;_ITcc0EVxE4M& ziLl`D_sY~Thrv4mEpA%?fpt;Z)Dx7{@?J`8HNsXVtE6g~+7`CoVEvxVyR>a6hR0E_Ll z*Hq^n%Qc7j>Q%qK`NXSNcVq?W52)C}9&S`3TQCW)Vj-GJDJLYaL{hM)t54&b8nY1B zZ9L=fwfK9(}@4P36kbju!CzPS@G1iWM%N?&K_TFi=}tvf+&^<- z?G?S*EwFyT|D)t`(bogQMR0U$T6#n0{VD#mBGH>_{%adpBM4>HMP^=Us*TjF-6*IJ hukq&QgV*38347Opjz^l58Now!LcB(Lz7hcT{2yxN&AI>p diff --git a/mods/ecomm/images/visa_42x27.gif b/mods/ecomm/images/visa_42x27.gif deleted file mode 100644 index a2e6bb67c1dea1bd9fb75048af0c5b0c2ce25d1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1493 zcmd6m|4-C*7{@Ez;3HpV1A-L{Pz86#x3jP;-ZXO*BT~R&5zRU?k#m!+Y!MqX^f2K| z`Q~oh!5X6G=HO;0FuN#F#K}cGT|GV5iIAI4Q{B0x%XBL&Ce5BPn1i&aTmSG!!2^c0}1cMP9jNmXrA_#$?Bx1o43xQZj1S3$?hN3u% zk|;`{796z@sKsb#)QB+Bf>RhqV>TSK5txm#;iL_>+i(WQNu03b1dS68oM3U1!bzG~ zfF%tmhNKMVNV|hFpjo@!X{Q;x(a=tsW@wtDX*bOn@U+88J2=|mW*ClP4CfgK#~5D+ z&#)ZBx*3*tuuhicSf`tH@~l%}Il;-fogDAvM9$4~ZqY4>JTLIP_@7C<*UL)+FNp$2 z32sIZL_zQhg0%38vfwpP1j#FUMbRsZvM9=uD9c`1@+y+#q$G}zI7$*7k|Y}?1%pyh zkyNjwD>7%7B~}h9vf`B$!&O<)WL1&1psX7xLCG03q^LpFKnrSeP*Z}MsyJXpq7{iz zf^J1ojZ##@HAM|8MyhFwrYm7xWf4`PRf$m*aUnOP>8h@(x~A$z6IR2j8rIaXt~r2_ zXu789x~7MyTL)U3qvFk#&84GX zRveFe|D}DdnU=PgME6t+I@Q`1m26)6^iDrMb85@pmp_XUEmfb#XRbY1Y^ z|6^~&o#8DX96C@_^e8nMNL!BnHG{XCDiX`z>ps`oela=aS7B~O+ZtK@;3(|s^W7VY ze75Q1d;4E)_dmaK)q&<8zApDgWNvGiseU^$ig;~FCAFyKexU8rc+=q>@3fwetE7_# zpCgiUcJ%L@uFWdz%cchR%vbCz>$7b4>>UW*ok%iIpMB#}Z%5TIHP-lS`nT#p-|07x z!xh6>IZ2sS-P?}grqV>m>s{q%PgS32vhEt0#TREy%oYUlM`t}5jmK{`x8#lI&KD;y z?^;wG{mN}uSKeEDAXECVKNQs!>p9j*ky@h*p-ByiOMTTdOh5+dbFvCjWct%PWHrxMnKjm zH(1jh8Zt{!B{v`Vmz(!&EnA*f4|S}{F%3k-o_t(e+wFa_GA*CWO-QrGq+B=WjT~Jx z6|>79YL7nP>Lt=vJaCy}*Ppyul=)K&lC~e za{k@=;Ukmyjc=}<4&-CM`yTx$cDjQ-8_*yT2M|GZ?1^oPZq - -
    - - - - - - - - - - - - - - - <?php echo _AT('ec_acceptvisa'); ?> <?php echo _AT('ec_acceptmastercard'); ?> -
    - - -
    - - - - - - - - - <?php echo _AT('ec_acceptvisa'); ?> <?php echo _AT('ec_acceptmastercard'); ?> -
    - addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - } else { - $msg->addError('EC_PAYMENT_FAILED'); - } - } -} - -function beanstream_print_form($payment_id, $amount, $course_id) { - - global $_config, $db, $addslashes; - if($_config['ec_gateway'] == 'BeanStream'){ - $mtid = mysql_insert_id($db); - $mkey = md5($mtid.$amount.$password); - $sql = "SELECT * from ".TABLE_PREFIX."members WHERE member_id = $_SESSION[member_id]"; - - $result = mysql_query($sql, $db); - - while($row = mysql_fetch_assoc($result)){ - $member['firstname'] = $row['first_name']; - $member['lastname'] = $row['last_name']; - $member['email'] = $row['email']; - //$member['organization'] = $row['organization']; - $member['address'] = $row['address']; - $member['postal'] = $row['postal']; - $member['province'] = $row['province']; - $member['city'] = $row['city']; - $member['telephone'] = $row['phone']; - $member['country'] = $row['country']; - } - - $firstname = $addslashes($member['firstname']); - $lastname = $addslashes( $member['lastname']); - $email = $addslashes( $member['email']); - $address = $addslashes($member['address']); - $postal = $addslashes($member['postal']); - $telephone = $addslashes($member['telephone']); - $country = $addslashes($member['country']); - $province = $addslashes($member['province']); - $city = $addslashes($member['city']); - $payment_id = $_SESSION['course_title']; - ?> -
    -
    - - - - - - - - - '._AT('street_address').':

    '; - }else{ ?> - - - - '._AT('city').':

    '; - }else{ ?> - - - - '._AT('ec_province').':
    -
    '; - - ?> - - '._AT('ec_postal').':

    '; - }else{ ?> - - - - '._AT('ec_telephone').':

    '; - }else{ ?> - - - - Country:
    -
    - -
    '; -?> - - - - - - - - - - - - - - - - - - - - - - - - - - -

    - - - -

    - -

    - - - - - <?php echo _AT('ec_acceptvisa'); ?> <?php echo _AT('ec_acceptmastercard'); ?> - - -

    - addFeedback($auto_link_login); - } else { - $msg->addFeedback('EC_PAYMENT_CONFIRMED_MANUAL'); - } - /// Get the course title - $course_title = $system_courses[$course_id]['title']; - - require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php'); - // If auto email when payment is made, send an email to the instructor (maybe this should be an admin option) - if ($course_fee_row['auto_email']) { - - /// Get the instructor's email address - $sql = "SELECT email FROM ".TABLE_PREFIX."members WHERE member_id=".$system_courses[$course_id]['member_id']; - $result = mysql_query($sql,$db); - $row = mysql_fetch_assoc($result); - $instructor_email = $row['email']; - - $mail = new ATutorMailer; - $mail->From = $_config['contact_email']; - $mail->AddAddress($instructor_email); - $mail->Subject = _AT('ec_payment_made'); - $mail->Body = _AT('ec_payment_mail_instruction', $course_title); - - if(!$mail->Send()) { - $msg->printErrors('SENDING_ERROR'); - return; - } - $mail->ClearAddresses(); - } - - if ($_config['ec_email_admin']) { - /// Email Administrator if set - if ($_config['ec_email_admin']){ - if ($_config['ec_contact_email']){ - $contact_admin_email = $_config['ec_contact_email']; - } else { - $contact_admin_email = $_config['contact_email']; - } - $mail = new ATutorMailer; - $mail->From = $_config['contact_email']; - $mail->AddAddress($contact_admin_email); - $mail->Subject = _AT('ec_payment_made'); - $mail->Body = _AT('ec_admin_payment_mail_instruction', $course_title); - - if (!$mail->Send()) { - $msg->printErrors('SENDING_ERROR'); - return; - } - } - } -} - -function check_payment_print_form($payment_id, $amount, $course_id){ - global $db, $system_courses, $_config, $payment_id; - - if (!$_config['ec_contact_address']) { - return; - } - echo _AT('or'); - ?> -
    - - - -


    - \ No newline at end of file diff --git a/mods/ecomm/index.php b/mods/ecomm/index.php deleted file mode 100644 index dc092e32b..000000000 --- a/mods/ecomm/index.php +++ /dev/null @@ -1,87 +0,0 @@ -'n'"; - $result = mysql_query($sql, $db); - return (boolean) mysql_fetch_assoc($result); -} - -/// Get a list of enrolled courses or pending enrollments, and display their fee payment status - -$payment_count = 0; // num listed courses - -$sql = "SELECT course_id, approved FROM ".TABLE_PREFIX."course_enrollment WHERE member_id=$_SESSION[member_id]"; -$result = mysql_query($sql,$db); - - -if (mysql_num_rows($result)) { ?> - - - - - - - - - - - 0"; - $result2 = mysql_query($sql2,$db); - if ($this_course_fee = mysql_fetch_assoc($result2)) { - $this_course_fee = $this_course_fee['course_fee']; - } else { - continue; - } - - $payment_count++; - - echo ''; - if(is_enrolled($_SESSION['member_id'], $row['course_id'])){ - echo ''; - - }else{ - echo ''; - } - echo ''; - - $sql4 = "SELECT SUM(amount) AS total_amount FROM ".TABLE_PREFIX."payments WHERE course_id='$row[course_id]' AND member_id = '$_SESSION[member_id]' AND approved=1"; - $result4 = mysql_query($sql4,$db); - - $row4 = mysql_fetch_assoc($result4); - $amount_paid = $row4['total_amount']; - - echo ''; - - if ($row['approved'] == 'y'){ - echo ''; - } else { - echo ''; - } - if ($amount_paid >= $this_course_fee){ - echo ''; - }else{ - echo ''; - } - } - echo '
    '.$system_courses[$row['course_id']]['title'].''.$system_courses[$row['course_id']]['title'].''.$_config['ec_currency_symbol'].number_format($this_course_fee, 2).' '.$_config['ec_currency'].''.$_config['ec_currency_symbol'].number_format($amount_paid, 2).''._AT('yes').''._AT('no').''._AT('ec_full_payment_recieved').''._AT('ec_make_payment').'
    '; - if($payment_count == 0){ - $msg->printInfos('EC_NO_PAID_COURSES'); - } -} else { - $msg->printInfos('EC_NO_PAID_COURSES'); -} - -require (AT_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file diff --git a/mods/ecomm/index_admin.php b/mods/ecomm/index_admin.php deleted file mode 100644 index 834438eee..000000000 --- a/mods/ecomm/index_admin.php +++ /dev/null @@ -1,195 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: payments_admin.php'); - exit; -} else if (isset($_POST['submit'])) { - - $_POST['ec_uri'] = trim($_POST['ec_uri']); - $_POST['ec_vendor_id'] = trim($_POST['ec_vendor_id']); - $_POST['ec_password'] = trim($_POST['ec_password']); - $_POST['ec_contact_email'] = trim($_POST['ec_contact_email']); - $_POST['ec_contact_address'] = trim($_POST['ec_contact_address']); - $_POST['ec_allow_instructors'] = intval($_POST['ec_allow_instructors']); - $_POST['ec_email_admin'] = intval($_POST['ec_email_admin']); - $_POST['ec_email_admin'] = intval($_POST['ec_email_admin']); - $_POST['ec_log_file'] = $addslashes($_POST['ec_log_file']); - $_POST['ec_store_log'] = intval($_POST['ec_store_log']); - - - if (!$_POST['ec_uri']){ - $msg->addError('EC_URL_EMPTY'); - } - if (!$_POST['ec_vendor_id']){ - $msg->addError('EC_ID_EMPTY'); - } - //if (!$_POST['ec_password']){ - //$msg->addError('EC_PASSWORD_EMPTY'); - //} - if (!$msg->containsErrors()) { - $_POST['ec_gateway'] = $addslashes($_POST['ec_gateway']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_gateway', '$_POST[ec_gateway]')"; - mysql_query($sql, $db); - - $_POST['ec_uri'] = $addslashes($_POST['ec_uri']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_uri', '$_POST[ec_uri]')"; - mysql_query($sql, $db); - - $_POST['ec_vendor_id'] = $addslashes($_POST['ec_vendor_id']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_vendor_id', '$_POST[ec_vendor_id]')"; - mysql_query($sql, $db); - - $_POST['ec_password'] = $addslashes($_POST['ec_password']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_password', '$_POST[ec_password]')"; - mysql_query($sql, $db); - - $_POST['ec_currency'] = $addslashes($_POST['ec_currency']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_currency', '$_POST[ec_currency]')"; - mysql_query($sql, $db); - - $_POST['ec_currency_other'] = $addslashes($_POST['ec_currency_other']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_currency_other', '$_POST[ec_currency_other]')"; - mysql_query($sql, $db); - - if($_POST['ec_currency_other']){ - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_currency', '')"; - mysql_query($sql, $db); - } - - $_POST['ec_currency_symbol'] = $_POST['ec_currency_symbol']; - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_currency_symbol', '$_POST[ec_currency_symbol]')"; - mysql_query($sql, $db); - - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_allow_instructors', '{$_POST['ec_allow_instructors']}')"; - mysql_query($sql, $db); - - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_email_admin', '{$_POST['ec_email_admin']}')"; - mysql_query($sql, $db); - - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_store_log', '{$_POST['ec_store_log']}')"; - mysql_query($sql, $db); - - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_log_file', '{$_POST['ec_log_file']}')"; - mysql_query($sql, $db); - - $_POST['ec_contact_email'] = $addslashes($_POST['ec_contact_email']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_contact_email', '$_POST[ec_contact_email]')"; - mysql_query($sql, $db); - - $_POST['ec_contact_address'] = $addslashes($_POST['ec_contact_address']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('ec_contact_address', '$_POST[ec_contact_address]')"; - mysql_query($sql, $db); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - - header('Location: '.$_SERVER['PHP_SELF']); - exit; - } -} - -$_config['ec_allow_instructors'] = isset($_config['ec_allow_instructors']) ? $_config['ec_allow_instructors'] : 0; -$_config['ec_email_admin'] = isset($_config['ec_email_admin']) ? $_config['ec_email_admin'] : 0; -$_config['ec_uri'] = isset($_config['ec_uri']) ? $_config['ec_uri'] : ''; -$_config['ec_currency'] = isset($_config['ec_currency']) ? $_config['ec_currency'] : 'USD'; -$_config['ec_currency_symbol'] = isset($_config['ec_currency_symbol']) ? $_config['ec_currency_symbol'] : '$'; - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> - -
    -
    - -
    -

    -
    -
    -
    *

    - -
    - -
    -
    *

    - -
    -
    -
    *

    - -
    -
    -
    - -
    -
    -
    - > - > - >   - - - - - -
    -
    -
    - -
    -
    -
    - -
    - -
    -
    - -
    - -
    -
    - /> - - /> -
    -
    -
    - /> - - /> -
    -
    -
    - /> - - /> -
    -
    -
    - -
    -
    - - -
    -
    -
    - - \ No newline at end of file diff --git a/mods/ecomm/index_admin_approve.php b/mods/ecomm/index_admin_approve.php deleted file mode 100644 index e2ff4eee8..000000000 --- a/mods/ecomm/index_admin_approve.php +++ /dev/null @@ -1,96 +0,0 @@ -addError('EC_INVOICE_NOT_FOUND'); - } else if ($invoice_row['approved']) { - // already approved - $msg->addError('EC_INVOICE_APPROVED'); - $invoice_row = false; - } -} else if (isset($_POST['id'], $_POST['submit'])) { - $_POST['id'] = intval($_POST['id']); - $_POST['txid'] = $addslashes($_POST['txid']); - approve_payment($_POST['id'], $_POST['txid']); - - $msg->deleteFeedback('EC_PAYMENT_CONFIRMED_AUTO'); - $msg->deleteFeedback('EC_PAYMENT_CONFIRMED_MANUAL'); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: payments_admin.php'); - exit; -} else if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - header('Location: '.$_SERVER['PHP_SELF']); - exit; -} - - -require (AT_INCLUDE_PATH.'header.inc.php'); -?> - - -
    -
    -
    -
    *

    - -
    - -
    - -
    -
    -
    - -
    - -
    -
    - #
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - - -
    - - -
    -
    -
    - - \ No newline at end of file diff --git a/mods/ecomm/index_instructor.php b/mods/ecomm/index_instructor.php deleted file mode 100644 index e175400a6..000000000 --- a/mods/ecomm/index_instructor.php +++ /dev/null @@ -1,121 +0,0 @@ -printInfos('EC_PAYMENTS_TURNED_OFF'); - require (AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -if (isset($_POST['submit'])) { - $_POST['ec_course_fee'] = floatval($_POST['ec_course_fee']); - $_POST['ec_auto_approve'] = intval($_POST['ec_auto_approve']); - $_POST['ec_auto_email'] = intval($_POST['ec_auto_email']); - - $sql = "REPLACE INTO ".TABLE_PREFIX."ec_course_fees VALUES ($_SESSION[course_id], '{$_POST['ec_course_fee']}', {$_POST['ec_auto_approve']}, {$_POST['ec_auto_email']})"; - if ($result = mysql_query($sql,$db)) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - }else{ - $msg->addError('EC_COURSE_PAYMENT_SETTINGS_NOT_SAVED'); - } - - header('Location: '.$_SERVER['PHP_SELF']); - exit; -} - -if($_GET['func'] == 'enroll'){ - $_GET['func'] = $addslashes($_GET['func']); - $sql = "REPLACE INTO ".TABLE_PREFIX."course_enrollment SET approved = 'y' WHERE course_id= '$_GET[course_id]' AND member_id = '$_GET[id0]'"; - $result = mysql_query($sql,$db); -}else if($_GET['func'] == 'unenroll'){ - - $_GET['func'] = $addslashes($_GET['func']); - $sql = "REPLACE INTO ".TABLE_PREFIX."course_enrollment SET approved = 'n' WHERE course_id= '$_GET[course_id]' AND member_id = '$_GET[id0]'"; - $result = mysql_query($sql,$db); -} - - -$sql = "SELECT * from ".TABLE_PREFIX."ec_course_fees WHERE course_id='$_SESSION[course_id]'"; -$result = mysql_query($sql,$db); -if ($row = mysql_fetch_assoc($result)){ - $this_course_fee = $row['course_fee']; - $this_auto_approve = $row['auto_approve']; - $this_auto_email = $row['auto_email']; -} - -require (AT_INCLUDE_PATH.'header.inc.php'); -?> - -
    -
    -
    -
    - () -
    -
    -
    - /> - /> -
    -
    -
    - /> - /> -
    - -
    - -
    -
    -
    - - - - - - - - - - - '; - echo ''; - - echo ''; - - $sql4 = "SELECT * from ".TABLE_PREFIX."course_enrollment WHERE course_id = '$_SESSION[course_id]' AND member_id = '$row[member_id]'"; - if($result4 = mysql_query($sql4, $db)){ - if(mysql_num_rows($result4) >= '1'){ - while($row4 = mysql_fetch_assoc($result4)){ - - if($row4['approved'] == 'y'){ - echo ''; - }else{ - echo ''; - } - } else { - echo ''; - } - } - echo '
    '.$row['login'].''.$_config['ec_currency_symbol'].number_format($row['amount'],2).' '.$_config['ec_currency'].''._AT('yes').' ('._AT('unenroll').')'._AT('no').' ( '._AT('enroll').')'; - } - } - }else{ - echo ''._AT('no').' ('._AT('enroll').')'._AT('no').'
    '; -} else { - $msg->printInfos('EC_NO_STUDENTS_ENROLLED'); -} - -require (AT_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file diff --git a/mods/ecomm/invoice.php b/mods/ecomm/invoice.php deleted file mode 100644 index 6d9d157d9..000000000 --- a/mods/ecomm/invoice.php +++ /dev/null @@ -1,79 +0,0 @@ - - -

    - - - - - - - - - - - -

    #
    - :
    '; - } - if($row['organization']){ - $contribinfo .= ''.$row['organization'].'
    '; - } - if($row['email']){ - $contribinfo .= ''.$row['email'].'
    '; - } - if($row['address']){ - $contribinfo .= ''.$row['address'].'
    '; - } - if($row['city']){ - $contribinfo .= ''.$row['city'].'
    '; - } - if($row['province']){ - $contribinfo .= ''.$row['province'].'
    '; - } - if($row['postal']){ - $contribinfo .= ''.$row['postal'].'
    '; - } - if($row['phone']){ - $contribinfo .= ''.$row['phone'].'
    '; - } - if($row['country']){ - $contribinfo .= ''.$row['country'].'
    '; - } - - echo $contribinfo; - ?> - -
    - :
    - -
    - - - '; - echo ''; - echo ''; - echo ''; - ?> -
    '. htmlspecialchars($stripslashes($_GET['course_title'])).''.$_config['ec_currency_symbol'].$amount.'

    '._AT('total').':'.$_config['ec_currency_symbol'].$amount.' '.$_config['ec_currency'].'
    - - -
    -
    - \ No newline at end of file diff --git a/mods/ecomm/module.php b/mods/ecomm/module.php deleted file mode 100644 index 846c38cc8..000000000 --- a/mods/ecomm/module.php +++ /dev/null @@ -1,60 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_ECOMM', $this->getAdminPrivilege()); - - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_ECOMM, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/ecomm/payments_admin.php'); - $this->_pages['mods/ecomm/payments_admin.php']['title_var'] = 'ec_payments'; - $this->_pages['mods/ecomm/payments_admin.php']['parent'] = AT_NAV_ADMIN; - $this->_pages['mods/ecomm/payments_admin.php']['children'] = array('mods/ecomm/index_admin.php','mods/ecomm/index_admin_approve.php', 'mods/_core/enrolment/admin/index.php'); - - $this->_pages['mods/ecomm/index_admin.php']['title_var'] = 'ec_settings'; - $this->_pages['mods/ecomm/index_admin.php']['parent'] = 'mods/ecomm/payments_admin.php'; - - $this->_pages['mods/ecomm/index_admin_approve.php']['title_var'] = 'ec_approve_manually'; - $this->_pages['mods/ecomm/index_admin_approve.php']['parent'] = 'mods/ecomm/payments_admin.php'; -} - -/******* - * instructor Manage section: - */ -$this->_pages['mods/ecomm/response_ipn.php']['title_var'] = 'ec_payments'; -$this->_pages['mods/ecomm/response_user.php']['title_var'] = 'ec_payments'; -$this->_pages['mods/ecomm/error_beanstream.php']['title_var'] = 'ec_payments'; -$this->_pages['mods/ecomm/success_beanstream.php']['title_var'] = 'ec_payments'; -$this->_pages['mods/ecomm/failure_beanstream.php']['title_var'] = 'ec_payments'; -$this->_pages['mods/ecomm/index_instructor.php']['title_var'] = 'ec_payments'; -$this->_pages['mods/ecomm/index_instructor.php']['parent'] = 'tools/index.php'; -$this->_pages['mods/ecomm/index_instructor.php']['children'] = array('mods/_core/enrolment/index.php'); -$this->_pages['tools/enrollment/index.php']['children'] = array('mods/ecomm/index_instructor.php'); - - -/* my start page pages */ -$this->_pages[AT_NAV_START] = array('mods/ecomm/index.php'); -$this->_pages['mods/ecomm/index.php']['title_var'] = 'ec_payments'; -$this->_pages['mods/ecomm/index.php']['parent'] = AT_NAV_START; - -$this->_pages['mods/ecomm/payment.php']['title_var'] = 'ec_payments'; -$this->_pages['mods/ecomm/payment.php']['parent'] = 'mods/ecomm/index.php'; -$this->_pages['mods/ecomm/index.php']['children'] = array('users/index.php','users/browse.php'); - -$this->_pages['mods/ecomm/failure.php']['title_var'] = 'ec_payments'; -$this->_pages['mods/ecomm/invoice.php']['title_var'] = 'ec_payments'; -?> \ No newline at end of file diff --git a/mods/ecomm/module.sql b/mods/ecomm/module.sql deleted file mode 100644 index 4420257fd..000000000 --- a/mods/ecomm/module.sql +++ /dev/null @@ -1,140 +0,0 @@ -# sql file for ATutor Ecommerce module - -CREATE TABLE `payments` ( -`payment_id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , -`timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , -`approved` TINYINT NOT NULL DEFAULT '0', -`transaction_id` CHAR( 100 ) NOT NULL , -`member_id` MEDIUMINT UNSIGNED NOT NULL , -`course_id` MEDIUMINT UNSIGNED NOT NULL , -`amount` DECIMAL( 7, 2 ) NOT NULL DEFAULT '0' -) ENGINE=MYISAM ; - - -CREATE TABLE `ec_course_fees` ( - `course_id` smallint( 8 ) NOT NULL , - `course_fee` DECIMAL( 7, 2 ) NOT NULL DEFAULT '0', - `auto_approve` tinyint( 1 ) default NULL , - `auto_email` tinyint( 1 ) default NULL , - PRIMARY KEY ( `course_id` ) -) ENGINE=MyISAM; - - - -INSERT INTO `language_text` VALUES ('en', '_module','ec_transaction_id','Transaction ID',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_settings','Settings',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payments','Payments',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_approve_manually','Approve Manually',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ecomm','Payments',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_confirm_info','Review the following information before proceeding. If the information is correct, click the Pay by Credit Card button (or Pay by Cheque if enabled) to move on to the next step.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_course','Course',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_amount','Amount',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_firstname','First Name',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_lastname','Last Name',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_organization','Organization',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_email','Email',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_address','Address',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_postal','Postal/Zip Code',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_telephone','Telephone',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_country','Country',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_comments','Comments',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payment_message','%s has registered in the course %s. To review the payment, login to ATutor as an Administrator then click on the Payments tab.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_invalid_fields','The following fields are invalid',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_requirements','Requirements to proceed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_requirements_ssl','SSL enabled, with 128-bit encryption. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_requirements_cookies','Cookies enabled.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_requirements_javascript','Javascript enabled.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_requirements_comment','Note that most current browsers will have these enabled by default. If you are unable to complete the transaction, check these settings in your browser to be sure they are enabled.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_modify','Modify ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_select_creditcard','Select the Pay by Credit Card button below to move to the secure credit card payment site. Following a payment, a printable receipt will be generated and email will be sent to the payee with details of the transaction. Or, select Pay by Cheque to send payment by regular mail.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_paybycredit','Pay by Credit Card',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_paybycheque','Pay by Cheque',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_date','Date Paid',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_acceptvisa','Accepting Visa',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_acceptmastercard','Accepting Master Card',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payfeesfor','Pay Fees',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_fees','Fees',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_complete_thisinfo','Complete the information below. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_next_toproceed','Use the Next Step button to review your information before proceding to the secure credit card payment site.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_purchaser_info','Purchaser Information',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_required','Required ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_next_step','Next Step ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_location_text','Enter the following settings for your credit card processing service. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_location','Credit card processing location URL ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payments','ATutor Payments ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payment_confirmation','Payment Confirmation ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payment_received','An ATutor Payment Received ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payment_retrieve_admin','An ATutor payment has been received. To review the payment login to ATutor as the administrator, choose the Payments tab, then select Review Payments ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_this_course_fee','Course Fee ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_vendor_id','Vendor ID assigned by credit card payment service ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_password','Password assigned by credit card payment service ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_currency','Currency ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_currency_symbol','Currency Symbol ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_currency_other','Other Currency ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_gateway','Payment Gateway ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_course_fee','Fee to charge for this course ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_auto_approve','Auto approve enrollment when fee has been paid ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payment_made','Course Fees Received ',NOW(),''); - -INSERT INTO `language_text` VALUES ('en', '_module','ec_enrollpay_confirmed_manual','Your payment has been received, and you have been enrolled in %s. You should receive confirmation by email, and access to the course, once approved by the instructor. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_enrollpay_confirmed_auto','Your payment has been received, and you have been enrolled in %s. You can now login to the course. ',NOW(),''); - -INSERT INTO `language_text` VALUES ('en', '_module','ec_payment_mail_instruction','Course fees have been received for the course: %s. Login as the course instructor and review the payment through the Manage tab, then choose Payments. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payment_mail_instruction','Course fees have been recieved for course %. Login to the Payments utility to review the payment, and to approved the enrollment if Auto Approve Enrollment has not been set. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payment_made','Fees Received ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_allow_instructors','Allow instructors to manage payments ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_cancel','Cancel',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_auto_email','Email instructor when a payment has been received',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_requirements_comments','Note that most current browsers will have these enabled by default. If you are unable to complete the transaction, check these settings in your browser to be sure they are enabled.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_remove','Remove/Un-Enroll',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_this_course_fee','Course Fee',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payment_made','Payment Received',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_enroll_approved','Enrollment Approved',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_action','Action',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_full_payment_recieved','Fees Paid',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_make_payment','Make Payment',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_student_name','Name',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payment_failed','Payment Failed/Cancelled',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_course_name','Course Title',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_balance_due','Balance Due',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_amount_recieved','Amount Received',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_email_admin','Email payment notices to the administrator',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_admin_payment_mail_instruction','A payment has been made for course: %s. To review the payment login to ATutor as an administrator and select the Payments tab.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_login','login',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payments_settings','Payment Settings',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_payments_received','Payments Received',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_return_to_payments','Return to Payments',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_start_date','Start Date',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_end_date','End Date',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_set_date','Set Dates',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_invoice','Invoice',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_print_invoice','Print_invoice',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_paybypaypal','Pay by PayPal',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_store_log','Keep transaction log ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_log_file','Full path to writable transaction log file. (required if log is enable, create writable file manually if necessary) ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_export_data','Export Data Displayed Below',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_date_picker','Select a date range to display. (e.g. 2007-2-6)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_contact_email','EMail notification of payments to: (if different from the ATutor contact email, set in System Preferences)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_contact_address','Address where cheques should be sent. (leave empty to disabled cheque payments)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_date_picker','The table below shows by default the past 30 payments. Use the date selectors to select a specific date range.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_cc_number','Credit Card Number',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_cc_expiry_month','Expiry Month',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_cc_expiry_year','Expiry Year',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_more_info_required','The following additional information is needed to complete your payment request:
    ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_province','State/Province',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_cc_cvd_number','Card CVD Number',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_cc_cvd_info','(3 or 4 digit number on the back of the card)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','ec_cc_cvd_number','Card CVD Number',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_INFOS_EC_NO_PAID_COURSES','You have not enrolled in any courses that require fees to be paid. Browse courses. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_EC_ADD_SAVED','Payment settings were successfully saved. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_INFOS_EC_NO_STUDENTS_ENROLLED','No students have requested enrollment. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_EC_PAYMENT_CONFIRMED_AUTO','Your payment has been received, and your course enrollment has been approved. You may now login to the course. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_EC_PAYMENT_CONFIRMED_MANUAL','Your payment has been received. You will receive a notice by email when your enrollment in the course has been manually approved. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_EC_COURSE_PAYMENT_SETTINGS_SAVED','Course payment settings have been saved.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_EC_COURSE_PAYMENT_SETTINGS_NOT_SAVED','Unable to save course payment settings. Contact your system administrator to report the problem',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_EC_PAYMENT_FAILED','The payment was cancelled or failed.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_INFOS_EC_PAYMENTS_TURNED_OFF','Course fees are being managed by the systems administrator.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_EC_INVOICE_NOT_FOUND','Invoice number cannot be found.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_EC_INVOICE_APPROVED','Invoice number has already been approved.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_ACTION_PENDING_CC_CONFIRM','Your enrollment is conditional on your credit card payment being approved',NOW(),''); -REPLACE INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_APPROVAL_PENDING','Your enrolment request has been made. To complete your enrolment, open the Payments tab above, then click on Make Payment next to the listing for the course you enrolled in.',NOW(),''); diff --git a/mods/ecomm/module.xml b/mods/ecomm/module.xml deleted file mode 100644 index 06faea2b3..000000000 --- a/mods/ecomm/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Payments - This module can be used to connect to a payment service to collect fees for course enrollment. By default it comes with PayPal, Beanstream, and MiraPay configurations, but can be adapted without too much effort to work with other credit card payment services. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 1.1 - 2010-10-25 - Stable - See the readme file included with the source code for details about setting up either a Paypal, Beanstream, or MiraPay merchant account. - - \ No newline at end of file diff --git a/mods/ecomm/module_install.php b/mods/ecomm/module_install.php deleted file mode 100644 index 3a161f0e5..000000000 --- a/mods/ecomm/module_install.php +++ /dev/null @@ -1,51 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/ecomm/module_uninstall.php b/mods/ecomm/module_uninstall.php deleted file mode 100644 index ee13969a0..000000000 --- a/mods/ecomm/module_uninstall.php +++ /dev/null @@ -1,26 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/ecomm/payment.php b/mods/ecomm/payment.php deleted file mode 100644 index 81665767d..000000000 --- a/mods/ecomm/payment.php +++ /dev/null @@ -1,102 +0,0 @@ - 0){ - $amount_paid = $row4['total_amount']; - } else { - $amount_paid = 0.00; - } -} -$balance_course_fee = $this_course_fee - $amount_paid; -$this_course_fee = $balance_course_fee; - -$sql = "INSERT INTO ".TABLE_PREFIX."payments VALUES (NULL, NULL, 0, '', '{$_SESSION['member_id']}', '$course_id', '$balance_course_fee')"; -$result = mysql_query($sql, $db); - -$payment_id = mysql_insert_id($db); -?> -
    -
    -

    - -

    - -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    - -

    -
      -
    • -
    • -
    • -
    • -
    -
    - - - -
    - - - - - -
    -
    - - \ No newline at end of file diff --git a/mods/ecomm/payments.png b/mods/ecomm/payments.png deleted file mode 100644 index 244973e43bb25e885adf42cc4e55b2b15861acb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6525 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'n'"; - $result = mysql_query($sql, $db); - return (boolean) mysql_fetch_assoc($result); -} - -$sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."payments"; -//$sql = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."course_enrollment"; -$result = mysql_query($sql, $db); -if (($row = mysql_fetch_assoc($result)) && $row['cnt']) { - $num_results = $row['cnt']; -} else { - require(AT_INCLUDE_PATH.'header.inc.php'); - $msg->printInfos('EC_NO_STUDENTS_ENROLLED'); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -$results_per_page = 25; -$num_pages = max(ceil($num_results / $results_per_page), 1); -$page = abs($_GET['p']); - -if (!$page) { - $page = 1; -} - -$count = (($page-1) * $results_per_page) + 1; -$offset = ($page-1)*$results_per_page; - -// enroll/unenroll students - -if($_GET['func'] == 'enroll'){ - $_GET['func'] = $addslashes($_GET['func']); - $sql = "REPLACE INTO ".TABLE_PREFIX."course_enrollment SET approved = 'y' WHERE course_id= '$_GET[course_id]' AND member_id = '$_GET[id0]'"; - $result = mysql_query($sql,$db); -}else if($_GET['func'] == 'unenroll'){ - - $_GET['func'] = $addslashes($_GET['func']); - $sql = "REPLACE INTO ".TABLE_PREFIX."course_enrollment SET approved = 'n' WHERE course_id= '$_GET[course_id]' AND member_id = '$_GET[id0]'"; - $result = mysql_query($sql,$db); -} - -/// Get a list of those who have made payments -if ($_GET['reset_filter']) { - unset($_GET); -} - -$page_string = ''; - -//$sql = "SELECT P.*, M.login FROM ".TABLE_PREFIX."payments P INNER JOIN ".TABLE_PREFIX."members M USING (member_id) WHERE P.approved=1 ORDER BY timestamp desc LIMIT $offset, $results_per_page"; -$sql = "SELECT P.*, M.login FROM ".TABLE_PREFIX."payments P INNER JOIN ".TABLE_PREFIX."members M USING (member_id) ORDER BY timestamp desc LIMIT $offset, $results_per_page"; - -//$sql ="SELECT C.*, P.*,M.login FROM ".TABLE_PREFIX."course_enrollment C, ".TABLE_PREFIX."payments P, ".TABLE_PREFIX."members M WHERE M.member_id = E.member_id"; - -$result = mysql_query($sql,$db); - -require (AT_INCLUDE_PATH.'header.inc.php'); ?> - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - -
    - - \ No newline at end of file diff --git a/mods/ecomm/payments_export_csv.php b/mods/ecomm/payments_export_csv.php deleted file mode 100644 index 9e5648ea3..000000000 --- a/mods/ecomm/payments_export_csv.php +++ /dev/null @@ -1,52 +0,0 @@ - \ No newline at end of file diff --git a/mods/ecomm/readme b/mods/ecomm/readme deleted file mode 100644 index e8ce8c238..000000000 --- a/mods/ecomm/readme +++ /dev/null @@ -1,135 +0,0 @@ -# ATutor Ecommerce Module Readme - -##This moldule is intended for use with ATutor 1.5.4+, though it should work with -## older versions except for the admin enrollment functions, which were added in 1.5.4. - -This module allows for payment of course fees, and automated enrollment when payments are recieved. It can be used with one (and only one at a time) of the following payment gateways. - -Payment Gateways Supported -It is currently setup to run with the MiraPay credit card processing service: -https://ws1.eigendev.com/mira/ - -Or - -It can be used with your PayPal account -https://www.paypal.com/cgi-bin/webscr - -Or - -You can connect to a Beamstream server -https://www.beanstream.com/scripts/process_transaction.asp - ---------------- -MiraPay Test Account -#A test account is available. Enter the following information into the admin payments settings screen. You will need to setup a proper merchant account with Mirapay to actually use the system for collecting your own payments, but to test the module the test account works well enough. MiraPay has the advantage over PayPal of not requiring the customer to have an account on their system. - -Test Location: -https://staging.eigendev.com/mirapay/secure_credit.php -Test Vendor ID: -e911ca205ec7c2a9436af9102c497fd4 - -Test Password: -test - -# Use the following credit card info to make fake payments through the test account. - -Test Credit Card # -4444333322221111 - -Test Expiry Date -2222 - ------------------- -PayPal Merchant Account Setup -See the details for setting up a PayPal account at: -http://www.paypal.com/cgi-bin/webscr?cmd=_merchant-outside - -The ATutor Payments module is written to run with PayPal "Buy Now Buttons" which allows customers to purchase one item at a time, in the case of ATutor, a single course at a time. Note that payees will have to setup their own PayPal customer account before they can make payments through PayPal. Also note that after a payment is made through PayPal, there is a 10 second delay before the payee is redirected back to ATutor, and the payments table updated with the transaction ID from PayPal. If a users decides to go off to some other web site before being redirected back to ATutor, the payments table may not be updated. In such a case the admin, or the instructor of a course if instructors are given payment management privileges, will need to manually update the payments table, and if auto enroll is turned on, also update the enrolment for the course, manually enrolling the person in the course. This problem is less likely to occur when using MiraPay, which automatically redirectls back to ATutor without any delay during which the users can go off somewhere else on the Internet. - -Once you have your paypal account setup, enter the URL to the PayPal Credit Card processing in the Payments>Settings screen, followed theVendor ID (leave the password field empty) - -PayPal Location -(for production) -https://www.paypal.com/cgi-bin/webscr -or -(for testing) -https://www.sandbox.paypal.com/cgi-bin/webscr - -See details on setting up a sandbox for testing the modules at: -https://www.paypal.com/en_US/ebook/PP_Sandbox_UserGuide/wwhelp/wwhimpl/js/html/wwhelp.htm - -PayPal IPN Setup -For security purpose Instant Payment Notification (IPN) must be setup with your PayPal merchant account. You will be asked to provide a URL to the IPN notification verification script, included with the EComm module. While logged into your PayPal account, slect the Profile tab, then choose "Instant Payment Notification Preferences". Turn "ON" the service, and provide the URL. The URL should also include the password you entered when setting up the module Settings in ATutor. The URL would look something like this: - - -http://www.mysite.com/ATutor/mods/ecomm/response_ipn.php?secret=payment01 - - --------------------- -Beanstream Setup -You will need to setup a Beanstream sandbox and merchant account at: -https://www.beanstream.com/public/index.asp - -1. Once your Beanstream account is setup, in the administrator's Settings area of the Payments module enter the beanstream credit card processing location. This location is the same for your production system and sandbox. - -https://www.beanstream.com/scripts/process_transaction.asp - -2. Enter the 9 digit Mercant ID assigned by Beanstrem into the "Vendor ID" field of the Payment Settings - -3. Enter the password assigned by Beanstream in the filed below the Vendor ID field. - -4. Set the other configuration options according to your requirements, described in more detail in the Installation & Setup instructions below. - -Use your sandbox account to setup the module and do you testing, and once everything is functioning as it should, switch the Vendor ID and password to those for you production beanstream account. - -In most cases Beanstream will create a sandbook area first, and when your ready, switch the account to live, using the same information previously used for the sandbox. You might however, request that another sandbox account be created once the initial account becomes live. - -The following credit card num,bers can be used for testing. Note that the expiry date for any of these is any time into the future. - -Visa - Use CVD/CVV code 123 -Approved 4030000010001234 -Approved $100 Limit 4504481742333 -Approved VBV 4123450131003312 with VBV passcode 12345 -Declined 4003050500040005 - -MasterCard - Use CVD/CVV code 123 -Approved 5100000010001004 -Approved 5194930004875020 -Approved 5123450000002889 -Approved 3D Secure 5123450000000000 passcode 12345 -Declined 5100000020002000 - -For additional information, contact Beanstream for a copy of the Beanstream API documentation. - - - --------------------- -Installation & Setup -1. Unpack the downloaded module into the ATutor mods directory. This will create an ecomm/ directory which contains all the module files. - -2. As the ATutor administrator, under the Modules tab choose Install Module, and choose the Payments module from the list of available modules. If you do not see the module available, make sure you have unpacked it into to right place ( /ATutor/mods/ecomm/) - -3. After installed, on the main admin modules screen enable the module. - -4. Once enabled, go to the admin's Payments tab and enter the Test information listed above into the appropriate fields, along with the currency and curreny symbol, and save those setting. - -5.Optionally, the admin can enter a mailing address to which cheques can be sent, if that is to be one of the payment method. Leave this field empty to disabled cheques as a method of payment. - -6. Optionally, the admin can allow instructors to manage their own payments by selecting the associated checkbox in the payments settings. - -7. Optionally, the administrator can receive an email notification when new payments are made by selecting the associated checkbox in the payments settings - - -How the module works -Payments are course fees associated with an enrollment in a Private course. When a student attempts to enroll in a private course that has a fee associated with it, an entry will be added to the student's Payments screen, accessed through a tab in MyStart page. If the student clicks on Make Payment, and confirms the information as correct, they are redirectled to the secure payment site, where they enter their visa or master card number (availability of either depending on what the merchant account supports), and submit the payment. Just before being redirected to the secure site the information entered by the student is stored in the ec_shop table in ATutor, and it is updated when the payment service has confirmed the payment. Payments that have been completed will be updated with a confirmation code from the payment gateway. - -If the course has been set to auto-enroll students, they will immediately be given access to the course. If manual enrollment is set, they will receive a notice of their pending enrolment, which the instructor, or administrator must approve. - -Administrators can manage individual course payments and settings by logging into a specific course, then managing the course payment settings as describe below for Instructors. - -If instrutors are allowed to manage their payments, set by the administrator in step 6 above, they can access Payments through the Manage screen, where they can set the price for the course, and set whether to auto-enroll students, and whether to send an email to the instructor when a payment has been received. These settings are saved in the ec_course_fees table. - -To make a payment students must first click on Enter Course in the Browse Course listing, then choose to enroll in the course. Then under the Payments Tab, click on Make Payment next to the course that is pending enrollment. - - - diff --git a/mods/ecomm/response_ipn.php b/mods/ecomm/response_ipn.php deleted file mode 100644 index f4c0c753b..000000000 --- a/mods/ecomm/response_ipn.php +++ /dev/null @@ -1,73 +0,0 @@ - $value) { - $value = urlencode($stripslashes($value)); - $req .= "&$key=$value"; -} - -$host = parse_url($_config['ec_uri']); -$host = $host['host']; // either www.sandbox.paypal.com or just www.paypal.com -if (strcasecmp($host, 'www.sandbox.paypal.com') && strcasecmp($host, 'www.paypal.com')) { - // don't want to post this to the wrong URI - exit; -} - -// post back to PayPal system to validate -$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n"; -$header .= "Content-Type: application/x-www-form-urlencoded\r\n"; -$header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; -$fp = fsockopen($host, 80, $errno, $errstr, 30); -if (!$fp) { exit; } - -$result = ''; -fputs($fp, $header . $req); -while (!feof($fp)) { - $result .= fgets($fp, 1024); -} - -if (strpos($result, 'VERIFIED') === FALSE) { - // Error: not VERIFIED by PayPal - log_paypal_ipn_requests('INVALID (1)' . $result); - return; -} else if (strcasecmp($_POST['payment_status'], 'Completed')) { - // Error: not completed - log_paypal_ipn_requests('INCOMPLETE (2)'); - return; -} - -$error = false; -$_POST['item_number'] = $addslashes($_POST['item_number']); -$_POST['txn_id'] = $addslashes($_POST['txn_id']); - -// check that txn_id has not been previously processed -$sql = "SELECT transaction_id, amount FROM ".TABLE_PREFIX."payments WHERE payment_id='$_POST[item_number]'"; -$result = mysql_query($sql, $db); -if (!($row = mysql_fetch_assoc($result))) { - // Error: no valid payment_id - $error = 3; -} else if ($row['transaction_id']) { - // Error: this transaction has already been processed - $error = 4; -} else if ($row['amount'] != $_POST['mc_gross']) { - // Error: wrong amount sent - $error = 5; -} else if ($_config['ec_currency'] != $_POST['mc_currency']) { - // Error: wrong currency - $error = 6; -} - -if (!$error) { - approve_payment($_POST['item_number'], $_POST['txn_id']); - $status = 'VALID'; -} else { - $status = "INVALID ($error)"; -} -log_paypal_ipn_requests($status); -?> \ No newline at end of file diff --git a/mods/ecomm/response_paypal_user.php b/mods/ecomm/response_paypal_user.php deleted file mode 100644 index 045bbfaf7..000000000 --- a/mods/ecomm/response_paypal_user.php +++ /dev/null @@ -1,26 +0,0 @@ -addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - -} else if ($_GET['st'] == "Pending"){ - approve_payment($payment_id, $transaction_id); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - $msg->addFeedback('ACTION_PENDING_CC_CONFIRM'); - -}else { - $msg->addError('EC_PAYMENT_FAILED'); -} - -//print_r($_GET); -header('Location: index.php'); -exit; -?> \ No newline at end of file diff --git a/mods/ecomm/response_user.php b/mods/ecomm/response_user.php deleted file mode 100644 index 02c844bca..000000000 --- a/mods/ecomm/response_user.php +++ /dev/null @@ -1,11 +0,0 @@ - \ No newline at end of file diff --git a/mods/ecomm/success_beanstream.php b/mods/ecomm/success_beanstream.php deleted file mode 100644 index 16a4d87ec..000000000 --- a/mods/ecomm/success_beanstream.php +++ /dev/null @@ -1,37 +0,0 @@ - diff --git a/mods/elluminate/elluminate.php b/mods/elluminate/elluminate.php deleted file mode 100644 index 15c9fa0d4..000000000 --- a/mods/elluminate/elluminate.php +++ /dev/null @@ -1,75 +0,0 @@ -addError('ELLUMINATEURL_ADD_EMPTY'); - } - - if (!$msg->containsErrors()) { - $_POST['uri'] = $addslashes($_POST['uri']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('elluminate', '$_POST[uri]')"; - mysql_query($sql, $db); - $_POST['pw'] = $addslashes($_POST['pw']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('elluminate_pw', '$_POST[pw]')"; - mysql_query($sql, $db); - $msg->addFeedback('ELLUMINATEURL_ADD_SAVED'); - - header('Location: '.$_SERVER['PHP_SELF']); - exit; - } -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> - - -
    -
    -

    -
    -
    -
    - - - -
    -
    -
    - -
    -
    -

    -
    -
    - - -
    -
    -
    -

    - - -
    -
    -

    - - -
    -
    - -
    -
    -
    - - \ No newline at end of file diff --git a/mods/elluminate/elluminate_logo.gif b/mods/elluminate/elluminate_logo.gif deleted file mode 100644 index f75fc0a782d698d9711288fb7feb42d5fdf32e46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1917 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 DDfeyV diff --git a/mods/elluminate/index.php b/mods/elluminate/index.php deleted file mode 100644 index fc0f937d7..000000000 --- a/mods/elluminate/index.php +++ /dev/null @@ -1,57 +0,0 @@ - -
    - - - - - -
    -


    - - - - -
    -
    -

    - -

    -

    - -

    - - - -
    -
    - - - - - -
    -



    - - - - -
    -
    - -

    - -

    - - -
    - -
    -
    - -
    - \ No newline at end of file diff --git a/mods/elluminate/module.css b/mods/elluminate/module.css deleted file mode 100644 index e13c8a801..000000000 --- a/mods/elluminate/module.css +++ /dev/null @@ -1,24 +0,0 @@ -.normalbody { - font-family: "Trebuchet MS", Verdana, Tahoma, Arial, sans-serif; - font-size: 12px; - line-height: 13pt; - color: Black; - - font-weight: normal; -} -.logintable { -border:1px #99CCCC solid; - padding: 2px; -} -.field0ff -{ - background: #ffffff; - font-size: 11px; - color: #000000; - font-family: Verdana,Arial,sans-serif; -} -.sideIndent1 { - font-family: "Trebuchet MS", Verdana, Tahoma, Arial, sans-serif; - font-size: 8pt; - padding-left: 10px; -} diff --git a/mods/elluminate/module.php b/mods/elluminate/module.php deleted file mode 100644 index 1399cd450..000000000 --- a/mods/elluminate/module.php +++ /dev/null @@ -1,48 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_ELLUMINATE', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -$this->_stacks['elluminate'] = array('title_var'=>'elluminate', 'file'=>AT_INCLUDE_PATH.'../mods/elluminate/side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('elluminate', array('title_var' => 'elluminate', 'file' => './side_menu.inc.php'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_student_tool = 'mods/elluminate/index.php'; -// ** possible alternative: ** -// $this->addTool('./index.php'); - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_ELLUMINATE, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/elluminate/elluminate.php'); - $this->_pages['mods/elluminate/elluminate.php']['title_var'] = 'elluminate'; - $this->_pages['mods/elluminate/elluminate.php']['parent'] = AT_NAV_ADMIN; -} - -/******* - * student page. - */ -$this->_pages['mods/elluminate/index.php']['title_var'] = 'elluminate'; -$this->_pages['mods/elluminate/index.php']['img'] = 'mods/elluminate/elluminate_logo.gif'; - - -?> \ No newline at end of file diff --git a/mods/elluminate/module.sql b/mods/elluminate/module.sql deleted file mode 100644 index 39dbb766f..000000000 --- a/mods/elluminate/module.sql +++ /dev/null @@ -1,16 +0,0 @@ -# sql file for Elluminate module - -INSERT INTO `language_text` VALUES ('en', '_module', 'elluminate_missing_url', 'You must supply the URL to your Elluminate installation in the field below.', NOW(), ''); - -INSERT INTO `language_text` VALUES ('en', '_module','elluminate','Elluminate',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','elluminate_text','Use Elluminate to conduct live collaborative activities.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','elluminate_pw','Optional guest password.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','elluminate_open','Open Elluminate',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','elluminate_loginname','Please enter your name for the session.
    (Note: The Name may not exceed 32 characters) ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','elluminate_passwordln',' (Note: Passwords are case sensitive)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','elluminate_password','Password',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','elluminate_name','Name',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','elluminate_location','The location of your Elluminate installation:',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','elluminate_guest','Login as a guest:',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_ELLUMINATEURL_ADD_SAVED','Elluminate configuration options were successfully saved.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_ELLUMINATEURL_ADD_EMPTY','You must enter a URL to the location of your Elluminate installation.',NOW(),''); diff --git a/mods/elluminate/module.xml b/mods/elluminate/module.xml deleted file mode 100644 index 6fa9c8cf6..000000000 --- a/mods/elluminate/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Elluminate - Elluminate is a leading provider of live Web conferencing and eLearning solutions for the real-time organization. Serving corporate and academic sectors, the company ensures the best user experience through superior quality VoIP, communications that are in-sync regardless of connection speed, broad cross-platform support, and advanced yet easy-to-use moderator tools. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.3 - 2010-10-25 - stable - Requires Sun Java WebStart on the client's computer. Elluminate must be installed before installing this module. Once the module is installed and enabled, open the Administrator's Elluminate screen to enter the URL, and optional guest password. See the readme file included with the module for further details. If you are using the free 3 room version (vRoom) add the line "header( 'Location: your url here to elluminate' ) ;" (changing the words to a URL of course) somewhere near the top of the index.php file. - - \ No newline at end of file diff --git a/mods/elluminate/module_install.php b/mods/elluminate/module_install.php deleted file mode 100644 index bff949cac..000000000 --- a/mods/elluminate/module_install.php +++ /dev/null @@ -1,25 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/elluminate/module_uninstall.php b/mods/elluminate/module_uninstall.php deleted file mode 100644 index 52d8f8129..000000000 --- a/mods/elluminate/module_uninstall.php +++ /dev/null @@ -1,31 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/elluminate/readme b/mods/elluminate/readme deleted file mode 100644 index 332d78536..000000000 --- a/mods/elluminate/readme +++ /dev/null @@ -1,20 +0,0 @@ -#Elluminate module for ATutor readme - -Be sure Ellumniate is installed and functioning properly before attempting to install this module. If you do not have an Elliminate installation, you might instead use the elluminate.com demo server as a temporary installation location to test the module - -Elluminate Demo server: -https://sas.elluminate.com/site/external/launch/migration/meeting.jnlp - -The guest password for the demo server is "configuration". - -Requires Sun Java WebStart on the client's computer, included with the JDK 5.0. -http://java.sun.com/javase/downloads/index.jsp - -Installation -1. Unzip the module into the ATutor mods/ directory. -2. Login to ATutor as the administrator and run the ATutor administrator's Install Module tool. Select Elluminate to install. -3. Once installed, on the administrator modules screen, enabled to module. -4. Open the administrator's Elluminate screen and enter the ULR to the Elluminate installion you will be using. -5. Enter an optional guest password, which allows users to login to Elluminate without having to create an account. - -See http://www.elluminate.com for Elluminate licensing information diff --git a/mods/elluminate/side_menu.inc.php b/mods/elluminate/side_menu.inc.php deleted file mode 100644 index e8c00f530..000000000 --- a/mods/elluminate/side_menu.inc.php +++ /dev/null @@ -1,33 +0,0 @@ - - - -
    -

    -

    -

    - -

    - - Login as a guest - - -
    -
    -

    - -

    - - -
    - - -assign('dropdown_contents', ob_get_contents()); -ob_end_clean(); - -$savant->assign('title', _AT('elluminate')); // the box title -$savant->display('include/box.tmpl.php'); -?> \ No newline at end of file diff --git a/mods/epresence/epresence_logo.gif b/mods/epresence/epresence_logo.gif deleted file mode 100644 index b2e39c10bc3dff4b81cc1758d770eac5b835e8ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 529 zcmZ?wbhEHbG+;1bSjxyyTwMJB|Np&v_xAMk+`D%#Ep6t~rAyzxe}Cr8nVBM`>^;#n+ZFAAC^qlFIN?p6%*$v zmygscQ@+10J>;`Ev-rLsP+?;WFRqW|$IRXsU09msk A0ssI2 diff --git a/mods/epresence/index.php b/mods/epresence/index.php deleted file mode 100644 index 387f2fd24..000000000 --- a/mods/epresence/index.php +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/mods/epresence/index_admin.php b/mods/epresence/index_admin.php deleted file mode 100644 index c6b4ca1f8..000000000 --- a/mods/epresence/index_admin.php +++ /dev/null @@ -1,58 +0,0 @@ -addError('EPRESENCEURL_ADD_EMPTY'); - } - - if (!$msg->containsErrors()) { - $_POST['uri'] = $addslashes($_POST['uri']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('epresence', '$_POST[uri]')"; - mysql_query($sql, $db); - $msg->addFeedback('EPRESENCEURL_ADD_SAVED'); - - header('Location: '.$_SERVER['PHP_SELF']); - exit; - } -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> - - - - -
    -
    -

    -
    -
    - - -
    -
    -
    -

    - - -
    - -
    - -
    -
    -
    - - - - - \ No newline at end of file diff --git a/mods/epresence/index_instructor.php b/mods/epresence/index_instructor.php deleted file mode 100644 index f5323af5b..000000000 --- a/mods/epresence/index_instructor.php +++ /dev/null @@ -1,15 +0,0 @@ - - - - \ No newline at end of file diff --git a/mods/epresence/module.php b/mods/epresence/module.php deleted file mode 100644 index 8ebd950c8..000000000 --- a/mods/epresence/module.php +++ /dev/null @@ -1,54 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_EPRESENCE', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -//$this->_stacks['epresence'] = array('title_var'=>'epresence', 'file'=>'mods/epresence/side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('epresence', array('title_var' => 'epresence', 'file' => './side_menu.inc.php'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_student_tool = 'mods/epresence/index.php'; -// ** possible alternative: ** -// $this->addTool('./index.php'); - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_EPRESENCE, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/epresence/index_admin.php'); - $this->_pages['mods/epresence/index_admin.php']['parent'] = AT_NAV_ADMIN; - $this->_pages['mods/epresence/index_admin.php']['title_var'] = 'epresence'; -} -/******* - * instructor Manage section: **Not needed for now** - */ -$this->_pages['mods/epresence/index_instructor.php']['title_var'] = 'epresence'; -$this->_pages['mods/epresence/index_instructor.php']['parent'] = 'tools/index.php'; -// ** possible alternative: ** -// $this->pages['./index_instructor.php']['title_var'] = 'epresence'; -// $this->pages['./index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages['mods/epresence/index.php']['title_var'] = 'epresence'; -$this->_pages['mods/epresence/index.php']['img'] = 'mods/epresence/epresence_logo.gif'; -?> \ No newline at end of file diff --git a/mods/epresence/module.sql b/mods/epresence/module.sql deleted file mode 100644 index 7657d53a2..000000000 --- a/mods/epresence/module.sql +++ /dev/null @@ -1,10 +0,0 @@ -# sql file for ePresence module - -INSERT INTO `language_text` VALUES ('en', '_module', 'epresence_missing_url', 'You must supply the URL to your ePresence installation in the field below.', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_module','epresence','ePresence',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','epresence_text','Use ePresence to access the web casting and video archives. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','epresence_own_window','Open ePresence in its own window. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','epresence_open','Open ePresence',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','epresence_location','The location of your ePresence installation:',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_EPRESENCEURL_ADD_SAVED','Location of ePresence was successfully saved.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_EPRESENCEURL_ADD_EMPTY','You must enter a URL to the location of your ePresence installation.',NOW(),''); diff --git a/mods/epresence/module.xml b/mods/epresence/module.xml deleted file mode 100644 index 7978a6aa2..000000000 --- a/mods/epresence/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - ePresence - This module links ePresence into ATutor student, instructor, and administrator tools. ePresence Interactive Media software is a content capturing, archiving, and webcasting system that delivers video and presentation media over the internet using multiple streaming formats for multiple platforms. ePresence also supports text and voice interaction among event participants. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - GPL - - 0.3 - 2010-10-25 - stable - After installating the module, provide the URL to your ePresence server. See the ePresence Web site for further details, downloads, installation instructions, and other documentation. ( http://epresence.tv/ ) - - \ No newline at end of file diff --git a/mods/epresence/module_install.php b/mods/epresence/module_install.php deleted file mode 100644 index 43e079eff..000000000 --- a/mods/epresence/module_install.php +++ /dev/null @@ -1,25 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/epresence/module_uninstall.php b/mods/epresence/module_uninstall.php deleted file mode 100644 index 60ce25da8..000000000 --- a/mods/epresence/module_uninstall.php +++ /dev/null @@ -1,26 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/fha_refresher/index.php b/mods/fha_refresher/index.php deleted file mode 100644 index c47527c99..000000000 --- a/mods/fha_refresher/index.php +++ /dev/null @@ -1,111 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: '.$_base_href.'tools/index.php'); - exit; -} else if (isset($_POST['submit'])) { - $_POST['enabled'] = abs($_POST['enabled']); - $_POST['test_id'] = abs($_POST['test_id']); - $_POST['score'] = abs(intval($_POST['score'])); - $_POST['refresher_period'] = abs($_POST['refresher_period']); - $_POST['reminder_period'] = abs($_POST['reminder_period']); - $_POST['max_refresh_period'] = abs($_POST['max_refresh_period']); - - if (!$_POST['test_id']) { - $msg->addError('FHA_REF_MISSING_TEST'); - } - - if (!$_POST['refresher_period']) { - $msg->addError('FHA_REF_MISSING_REF_PERIOD'); - } - if (!$_POST['reminder_period']) { - $msg->addError('FHA_REF_MISSING_REMINDER_PERIOD'); - } - - if (!$_POST['max_refresh_period']) { - $msg->addError('FHA_REF_MISSING_MAX_PERIOD'); - } - - if (!$msg->containsErrors()) { - $sql = "REPLACE INTO ".TABLE_PREFIX."fha_refresher VALUES ($_SESSION[course_id], $_POST[test_id], $_POST[enabled], $_POST[score], $_POST[refresher_period], $_POST[reminder_period], $_POST[max_refresh_period])"; - mysql_query($sql, $db); - - $msg->addFeedback('FHA_REF_SAVED'); - header('Location: index.php'); - exit; - } -} - -require (AT_INCLUDE_PATH.'header.inc.php'); -if (!isset($_POST['submit'])) { - $sql = "SELECT * FROM ".TABLE_PREFIX."fha_refresher WHERE course_id=$_SESSION[course_id]"; - $result = mysql_query($sql, $db); - if ($row = mysql_fetch_assoc($result)) { - $_POST['enabled'] = $row['enabled']; - $_POST['test_id'] = $row['test_id']; - $_POST['score'] = $row['pass_score']; - $_POST['refresher_period'] = $row['refresh_period']; - $_POST['reminder_period'] = $row['reminder_period']; - $_POST['max_refresh_period'] = $row['max_refresh_period']; - } else { - $_POST['enabled'] = 0; - $_POST['test_id'] = 0; - $_POST['score'] = 0; - $_POST['refresher_period'] = 60; - $_POST['reminder_period'] = 7; - $_POST['max_refresh_period'] = 365; - } -} -?> - -
    -
    -
    - /> -
    - -
    -
    *

    - - -
    - -
    -
    *

    - -
    - -
    -
    *

    - -
    - -
    -
    *

    - -
    - -
    -
    *

    - -
    - -
    - - -
    -
    -
    - - \ No newline at end of file diff --git a/mods/fha_refresher/module.php b/mods/fha_refresher/module.php deleted file mode 100644 index 163014c47..000000000 --- a/mods/fha_refresher/module.php +++ /dev/null @@ -1,23 +0,0 @@ -getPrivilege()); - -/******* - * instructor Manage section: - */ -$this->_pages['mods/fha_refresher/index.php']['title_var'] = 'fha_refresher'; -$this->_pages['mods/fha_refresher/index.php']['parent'] = 'tools/index.php'; - -?> \ No newline at end of file diff --git a/mods/fha_refresher/module.sql b/mods/fha_refresher/module.sql deleted file mode 100644 index 6833304c8..000000000 --- a/mods/fha_refresher/module.sql +++ /dev/null @@ -1,38 +0,0 @@ - -CREATE TABLE `fha_refresher` ( - `course_id` mediumint(8) unsigned NOT NULL, - `test_id` mediumint(8) unsigned NOT NULL, - `enabled` TINYINT DEFAULT '0' NOT NULL, - `pass_score` VARCHAR( 5 ) NOT NULL , - `refresh_period` mediumint(8) unsigned NOT NULL, - `reminder_period` mediumint(8) unsigned NOT NULL, - `max_refresh_period` mediumint(8) unsigned NOT NULL, - PRIMARY KEY ( `course_id` ) -); - - -# refresh_period (number of days since the last successful pass) - -# reminder_period (number of days between reminders within refresher_period) - -# max_refresh_period (number of days since the last successful pass. not sent if greater than period) - - -INSERT INTO `language_text` VALUES ('en', '_module','fha_refresher','Test Refresher',NOW(),''); - -INSERT INTO `language_text` VALUES ('en', '_module','fha_ref_test','Test',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','fha_ref_pass_score','Pass Score',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','fha_ref_refresher_period','Refresher Period (Days)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','fha_ref_reminder_period','Reminder Period (Days)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','fha_ref_max_refresh_period','Maximum Refresh Period (Days)',NOW(),''); - -INSERT INTO `language_text` VALUES ('en', '_module','fha_ref_automatic_email_reminder','Automatic Email Reminder',NOW(),''); -INSERT INTO `language_text` VALUES ('en' ,'_module', 'fha_ref_automatic_email_body', 'Greetings!\n\nCourse Refresher:\n\nThis is an automatic e-mail reminder from the FHA Online Learning System. Please do not reply to this message.\n\nAccording to our records you are due for a course refresher for the following topic:\n\n%s\n\nPlease visit https://fhaol.primesignal.com and take the course at your earliest convenience. If the link does not open your browser automatically, please copy and paste the link into your Internet browser\'s address bar.\n\nYour Login Name is: %s\n\nIf you have forgotten your password, please use the Password Reminder feature on the Login Page and an email will be sent to your account prompting you to create a new password.\n\nYou will continue to receive these automatic reminders periodically until you take the refresher.\n\nThanks.\n\nOnline Learning Initiatives\nFraser Health Authority', NOW(), ''); - -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_FHA_REF_MISSING_TEST','You must select a test.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_FHA_REF_MISSING_SCORE','You must enter a pass score.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_FHA_REF_MISSING_REF_PERIOD','You must enter a refresher period.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_FHA_REF_MISSING_REMINDER_PERIOD','You must enter a reminder period.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_FHA_REF_MISSING_MAX_PERIOD','You must enter a maximum refresher period.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_FHA_REF_SAVED','Test refresher saved successuflly.',NOW(),''); - diff --git a/mods/fha_refresher/module.xml b/mods/fha_refresher/module.xml deleted file mode 100644 index 5ddb27ff4..000000000 --- a/mods/fha_refresher/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - FHA Refresher - Enables an automatic email to alumni about taking a course refresher test. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.1 - 2005-08-22 - stable - - - \ No newline at end of file diff --git a/mods/fha_refresher/module_cron.php b/mods/fha_refresher/module_cron.php deleted file mode 100644 index 789ac1170..000000000 --- a/mods/fha_refresher/module_cron.php +++ /dev/null @@ -1,49 +0,0 @@ -= $row[pass_score] GROUP BY member_id"; - $test_result = mysql_query($sql, $db); - - while ($test_row = mysql_fetch_assoc($test_result)) { - $refresh_difference = $test_row['date_taken'] - $refresh_period_seconds; - if ((abs($refresh_difference) < $max_refresh_period) && ($refresh_difference < 0)) { - $refresh_difference = abs($refresh_difference); - if ((round($refresh_difference / 24 / 60 / 60) % $row['reminder_period']) == 0) { - $sql = "SELECT login, email FROM ".TABLE_PREFIX."members WHERE member_id=$test_row[member_id]"; - $member_result = mysql_query($sql, $db); - $member_row = mysql_fetch_assoc($member_result); - - $mail->From = $_config['contact_email']; - $mail->AddAddress($member_row['email']); - $mail->Subject = $subject; - $mail->Body = _AT('fha_ref_automatic_email_body',$_SESSION['course_title'], $member_row['login']); - - $mail->Send(); - - $mail->ClearAllRecipients(); - } - } - } - } -} -?> \ No newline at end of file diff --git a/mods/fha_refresher/module_delete.php b/mods/fha_refresher/module_delete.php deleted file mode 100644 index 594715007..000000000 --- a/mods/fha_refresher/module_delete.php +++ /dev/null @@ -1,17 +0,0 @@ - \ No newline at end of file diff --git a/mods/fha_refresher/module_install.php b/mods/fha_refresher/module_install.php deleted file mode 100644 index c53a941de..000000000 --- a/mods/fha_refresher/module_install.php +++ /dev/null @@ -1,16 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/fha_student_tools/icon.gif b/mods/fha_student_tools/icon.gif deleted file mode 100644 index e5cb651a41446f63e000d8eb7bb54450c3b73a0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 373 zcmZ?wbhEHb)Mij&IKsg2cd^Ic6I1{H|NrmbzdwKe{QC9l$B!RhzkdDr@#DL9?_Rxn z_4Mh}hYug#yLa#A&70S*UAuVk;;B=oPM$n@?AS2|B7hD^4ahDA)?W)0`cf>_7#Uc4 zUhXUKT#_X#Q@HN(*4P&g!TAw~S^JMX5u7Qb*X;W|Sp2Q;%20+!v$Q`VBg}Pg;oPtl v6BhfNIKaR!ARuws#Ywonu!3a<+Y$bQ1-fT+IIb%v&*+s2wYVV2#9$2ok1Uu+ diff --git a/mods/fha_student_tools/index.php b/mods/fha_student_tools/index.php deleted file mode 100644 index 84face079..000000000 --- a/mods/fha_student_tools/index.php +++ /dev/null @@ -1,36 +0,0 @@ - $_base_path . $child, 'title' => $title, 'img' => $_base_path.$_pages[$child]['img']); - } -} - -$savant->assign('home_links', $home_links); - -$savant->assign('announcements', array()); -$savant->assign('num_pages', 0); -$savant->assign('current_page', 0); -$savant->display('index.tmpl.php'); - -?> - - - \ No newline at end of file diff --git a/mods/fha_student_tools/instructor_index.php b/mods/fha_student_tools/instructor_index.php deleted file mode 100644 index 3b4f7f112..000000000 --- a/mods/fha_student_tools/instructor_index.php +++ /dev/null @@ -1,134 +0,0 @@ -addFeedback('SECTIONS_SAVED'); - header('Location: '.$_SERVER['PHP_SELF']); - exit; -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -$fha_student_tools = array(); - -$sql = "SELECT links FROM ".TABLE_PREFIX."fha_student_tools WHERE course_id=$_SESSION[course_id]"; -$result = mysql_query($sql, $db); -if ($row = mysql_fetch_assoc($result)) { - $fha_student_tools = explode('|', $row['links']); -} - -$_current_modules = array_merge($fha_student_tools, array_diff($_modules, $fha_student_tools)); - -$num_modules = count($fha_student_tools); -?> -
    - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - -   - - 1)): ?> - - - - - - - - - - -
    -
    - - - \ No newline at end of file diff --git a/mods/fha_student_tools/module.php b/mods/fha_student_tools/module.php deleted file mode 100644 index c4c6a18f8..000000000 --- a/mods/fha_student_tools/module.php +++ /dev/null @@ -1,23 +0,0 @@ -_pages['mods/fha_student_tools/instructor_index.php']['title_var'] = 'fha_student_tools'; -$this->_pages['mods/fha_student_tools/instructor_index.php']['parent'] = 'tools/index.php'; - -$this->_pages['mods/fha_student_tools/index.php']['title_var'] = 'fha_student_tools'; -$this->_pages['mods/fha_student_tools/index.php']['img'] = 'mods/fha_student_tools/icon.gif'; -?> \ No newline at end of file diff --git a/mods/fha_student_tools/module.sql b/mods/fha_student_tools/module.sql deleted file mode 100644 index 5250649ad..000000000 --- a/mods/fha_student_tools/module.sql +++ /dev/null @@ -1,10 +0,0 @@ -# sql file for hello world module - -CREATE TABLE `fha_student_tools` ( - `course_id` mediumint(8) unsigned NOT NULL, - `links` text NOT NULL , - PRIMARY KEY ( `course_id` ) -); - - -INSERT INTO `language_text` VALUES ('en', '_module','fha_student_tools','FHA Student Tools',NOW(),''); diff --git a/mods/fha_student_tools/module.xml b/mods/fha_student_tools/module.xml deleted file mode 100644 index e8be8b66a..000000000 --- a/mods/fha_student_tools/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - FHA Student Tools - Creates a page that links to other student tools. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.1 - 2005-08-22 - stable - - - \ No newline at end of file diff --git a/mods/fha_student_tools/module_delete.php b/mods/fha_student_tools/module_delete.php deleted file mode 100644 index 0c6d210ae..000000000 --- a/mods/fha_student_tools/module_delete.php +++ /dev/null @@ -1,17 +0,0 @@ - \ No newline at end of file diff --git a/mods/fha_student_tools/module_install.php b/mods/fha_student_tools/module_install.php deleted file mode 100644 index 104ffda62..000000000 --- a/mods/fha_student_tools/module_install.php +++ /dev/null @@ -1,16 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/flowplayer/LICENSE.txt b/mods/flowplayer/LICENSE.txt deleted file mode 100644 index 2a00962f2..000000000 --- a/mods/flowplayer/LICENSE.txt +++ /dev/null @@ -1,721 +0,0 @@ -The Flowplayer Free version is released under the -GNU GENERAL PUBLIC LICENSE Version 3 (GPL). - -The GPL requires that you not remove the Flowplayer copyright notices -from the user interface. See section 5.d below. - -Commercial licenses are available. The commercial player version -does not require any Flowplayer notices or texts and also provides -some additional features. - -======================================================================== - -ADDITIONAL TERM per GPL Section 7 -If you convey this program (or any modifications of it) and assume -contractual liability for the program to recipients of it, you agree -to indemnify Flowplayer, Ltd. for any liability that those contractual -assumptions impose on Flowplayer, Ltd. - -Except as expressly provided herein, no trademark rights are granted in -any trademarks of Flowplayer, Ltd. Licensees are granted a limited, -non-exclusive right to use the mark Flowplayer and the Flowplayer logos -in connection with unmodified copies of the Program and the copyright -notices required by section 5.d of the GPL license. For the purposes -of this limited trademark license grant, customizing the Flowplayer -by skinning, scripting, or including PlugIns provided by Flowplayer, Ltd. -is not considered modifying the Program. - -Licensees that do modify the Program, taking advantage of the open-source -license, may not use the Flowplayer mark or Flowplayer logos and must -change the fullscreen notice (and the non-fullscreen notice, if that -option is enabled), the copyright notice in the dialog box, and the -notice on the Canvas as follows: - -the full screen (and non-fullscreen equivalent, if activated) notice -should read: "Based on Flowplayer source code"; in the context menu -(right-click menu), the link to "About Flowplayer free version #.#.#" -can remain. The copyright notice can remain, but must be supplemented with -an additional notice, stating that the licensee modified the Flowplayer. -A suitable notice might read "Flowplayer Source code modified by ModOrg 2009"; -for the canvas, the notice should read "Based on Flowplayer source code". -In addition, licensees that modify the Program must give the modified -Program a new name that is not confusingly similar to Flowplayer and -may not distribute it under the name Flowplayer. - -======================================================================== - - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. 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 -them 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 prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. 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. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey 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; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If 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 convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU 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 that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - 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. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -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. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: 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 3 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, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/mods/flowplayer/README.txt b/mods/flowplayer/README.txt deleted file mode 100644 index 5e2913b05..000000000 --- a/mods/flowplayer/README.txt +++ /dev/null @@ -1,222 +0,0 @@ -Version history: - -3.1.2 ------ -- The domain of the logo url must the same domain from where the player SWF is loaded from. -- Fullscreen can be toggled by doublclick on the video area. -Fixes: -- Player was not initialized correctly when instream playlists were used and the provider used in the instream clips was defined in the common clip. -- A separator in the Context Menu made the callbacks in the following menu items out of order. Related forum post: http://flowplayer.org/forum/8/22541 -- the width and height settings of a logo were ignored if the logo was a sWF file -- volume control and mute/unmute were not working after an instream clip had been played -- now possible to use RTMP for mp3 files -- Issue 12: cuepointMultiplier was undefined in the clip object set to JS event listeners -- Issue 14: onBeforeStop was unnecessarily fired when calling setPlaylist() and the player was not playing, - additionally onStop was never fired even if onBeforeStop was -- fixed screen vertical placement problems that reappeared with 3.1.1 -- The rotating animation now has the same size and position as it has after initialized - -3.1.1 ------ -- External configuration files -- Instream playback -- Added toggleFullscreen() the API -- Possibility to specify controls configuration in clips -- Seek target position is now sent in the onBeforeSeek event -Fixes: -- The screen size was initially too small on Firefox (Mac) -- Did not persist a zero volume value: http://www.flowplayer.org/forum/8/18413 - -3.1.0 ------ -New features: -- clip's can have urlResolvers and connectionProviders -- Added new configuration options 'connectionCallbacks' and 'streamCallbacks'. Both accept an Array of event names as a value. - When these events get fired on the connection or stream object, corresponding Clip events will be fired by the player. - This can be used for example when firing custom events from RTMP server apps -- Added new clip event types: 'onConnectionEvent' and 'onStreamEvent' these get fired when the predefined events happen on the connection and stream objects. -- Added Security.allowDomain() to allow loaded plugins to script the player -- Added addClip(clip, index) to the API, index is optional -- Possibility to view videos without metadata, using clip.metaData: false -- Now the player's preloader uses the rotating animation instead of a percent text to indicate the progress - of loading the player SWF. You can disable the aninamtion by setting buffering: false -- calling close() now does not send the onStop event -- Clip's custom properties are now present in the root of the clip argument in all clip events that are sent to JS. - -Bug fixes: -- The preloader sometimes failed to initialize the player -- Allow seeking while in buffering state: http://flowplayer.org/forum/8/16505 -- Replay of a RTMP stream was failing after the connection had expired -- Security error when clicking on the screen if there is an image in the playlist loaded from a foreign domain -- loadPlugin() was not working -- now fullscreen works with Flash versions older than 9.0.115, in versions that do not support hardware scaling -- replaying a RTMP stream with an image in front of the stream in the playlist was not working (video stayed hidden). Happened - because the server does not send metadata if replaying the same stream. -- the scrubber is disabled if the clip is not seekable in the first frame: http://flowplayer.org/forum/8/16526 - By default if the clip has one of following extensions (the typical flash video extensions) it is seekable - in the first frame: 'f4b', 'f4p', 'f4v', 'flv'. Added new clip property seekableOnBegin that can be used to override the default. - -3.0.6 ------ -- added possibility to associate a linkUrl and linkWindow to the canvas -Fixes: -- fix for entering fullscreen for Flash versions that don't support the hardware scaled fullscreen-mode -- when showing images the duration tracking starts only after the image has been completely loaded: http://flowplayer.org/forum/2/15301 -- fix for verifying license keys for domains that have more than 4 labels in them -- if plugin loading failis because of a IO error, the plugin will be discarded and the player initialization continues: - -3.0.4 ------ -- The "play" pseudo-plugin now supports fadeIn(), fadeOut(), showPlugin(), hidePlugin() and - additionally you can configure it like this: - // make only the play button invisible (buffering animation is still used) - play: { display: 'none' } - // disable the play button and the buffering animation - play: null - // disable the buffering animation - buffering: null -- Added possibility to seek when in the buffering state: http://flowplayer.org/forum/3/13896 -- Added copyright notices and other GPL required entries to the user interface - -Fixes: -- clip urls were not resolved correctly if the HTML page URL had a query string starting with a question mark (http://flowplayer.org/forum/8/14016#post-14016) -- Fixed context menu for with IE (commercial version) -- a cuepoint at time zero was fired several times -- screen is now arranged correctly even when only bottom or top is defined for it in the configuration -- Fixed context menu for with IE (commercial version) -- a cuepoint at time zero was fired several times -- screen is now arranged correctly even when only bottom or top is defined for it in the configuration -- Now possible to call play() in an onError handler: http://flowplayer.org/forum/8/12939 -- Does not throw an error if the player cannot persist the volume on the client computer: http://flowplayer.org/forum/8/13286#post-13495 -- Triggering fullscreen does not pause the player in IE -- The play button overlay no longer has a gap between it's pieces when a label is used: http://flowplayer.org/forum/8/14250 -- clip.update() JS call now resets the duration -- a label configured for the play button overlay did not work in the commercial version - -3.0.3 ------ -- fixed cuepoint firing: Does not skip cuepoints any more -- Plugins can now be loaded from a different domain to the flowplayer.swf -- Specifying a clip to play by just using the 'clip' node in the configuration was not working, a playlist definition was required. This is now fixed. -- Fixed: A playlist with different providers caused the onMetadata event to fire events with metadata from the previous clip in the playlist. Occurred when moving in the playlist with next() and prev() -- the opacity setting now works with the logo -- fadeOut() call to the "screen" plugin was sending the listenerId and pluginName arguments in wrong order -- stop(), pause(), resume(), close() no longer return the flowplayer object to JS -- changing the size of the screen in a onFullscreen listener now always works, there was a bug that caused this to fail occasionally -- fixed using arbitrary SWFs as plugins -- the API method setPlaylist() no longer starts playing if autoPlay: true, neither it starts buffering if autoBuffering: true -- the API method play() now accepts an array of clip objects as an argument, the playlist is replaced with the specified clips and playback starts from the 1st clip - -3.0.2 ------ -- setting play: null now works again -- pressing the play again button overlay does not open a linkUrl associated with a clip -- now displays a live feed even when the RTMP server does not send any metadata and the onStart method is not therefore dispatched -- added onMetaData clip event -- fixed 'orig' scaling: the player went to 'fit' scaling after coming back from fullscreen. This is now fixed and the original dimensions are preserved in non-fullscreen mode. -- cuepoint times are now given in milliseconds, the firing precision is 100 ms. All cuepoint times are rounded to the nearest 100 ms value (for example 1120 rounds to 1100) -- backgroundGradient was drawn over the background image in the canvas and in the content and controlbar plugins. Now it's drawn below the image. -- added cuepointMultiplier property to clips. This can be used to multiply the time values read from cuepoint metadata embedded into video files. -- the player's framerate was increased to 24 FPS, makes all animations smoother - -3.0.1 ------ -- Fixed negative cuepoints from common clip. Now these are properly propagated to the clips in playlist. -- buffering animation is now the same size as the play button overlay -- commercial version now supports license keys that allows the use of subdomains -- error messages are now automatically hidden after a 4 second delay. They are also hidden when a new clips - starts playing (when onBeforeBegin is fired) -- added possibility to disable the buffering animation like so: buffering: false -- pressing the play button overlay does not open a linkUrl associated with a clip -- license key verification failed if a port number was used in the URL (like in this url: http://mydomain.com:8080/video.html) -- added audio support, clip has a new "image" property -- workaround for missing "NetStream.Play.Start" notfication that was happending with Red5. Because of this issue the video was not shown. -- commercial version has the possibility to change the zIndex of the logo - -3.0.0 ------ -- Removed security errors that happened when loading images from foreign domains (domains other than the domain of the core SWF). - Using a backgroundImage on canvas, in the content plugin, and for the controls is also possible to be loaded - from a foreign domain - BUT backgroundRepeat cannot be used for foreign images. -- Now allows the embedding HTML to script the player even if the player is loaded from another domain. -- Added a 'live' property to Clips, used for live streams. -- A player embedded to a foreign domain now loads images, css files and other resources from the domain where the palyer SWF was loaded from. This is to generate shorter embed-codes. -- Added linkUrl and linkWindow properties to the logo, in commercial version you can set these to point to a linked page. The linked page gets opened - when the logo is clicked. Possible values for linkWindow: - * "_self" specifies the current frame in the current window. - * "_blank" specifies a new window. - * "_parent" specifies the parent of the current frame. - * "_top" specifies the top-level frame in the current window. -- Added linkUrl and linkWindow properties to clips. The linked page is opened when the video are is clicked and the corresponding clip has a linkUrl specified. -- Made the play button overlay and the "Play again" button slightly bigger. - -RC4 ---- -- Now shows a "Play again" button at the end of the video/playlist -- Commercial version shows a Flowplayer logo if invalidKey was supplied, but the otherwise the player works -- setting play: null in configuration will disable the play button overlay -- setting opacity for "play" also sets it for the buffering animation -- Fixed firing of cuepoints too early. Cuepoint firing is now based on stream time and does not rely on timers -- added onXMPData event listener -- Should not stop playback too early before the clip is really completed -- The START event is now delayed so that the metadata is available when the event is fired, METADATA event was removed, - new event BEGIN that is dispatched when the playback has been successfully started. Metadata is not normally - available when BEGIN is fired. - -RC3 ---- -- stopBuffering() now dispatches the onStop event first if the player is playing/paused/buffering at the time of calling it -- fixed detection of images based on file extensions -- fixed some issues with having images in the playlist -- made it possible to autoBuffer next video while showing an image (image without a duration) - -RC2 ---- -- fixed: setting the screen height in configuration did not have any effect - -RC1 ------ -- better error message if plugin loading fails, shows the URL used -- validates our redesigned multidomain license key correctly -- fix to prevent the play button going visible when the onBufferEmpty event occurs -- the commercial swf now correctly loads the controls using version information -- fixed: the play button overlay became invisible with long fadeOutSpeeds - -beta6 ------ -- removed the onFirstFramePause event -- playing a clip for the second time caused a doubled sound -- pausing on first frame did not work on some FLV files - -beta5 ------ -- logo only uses percentage scaling if it's a SWF file (there is ".swf" in it's url) -- context menu now correctly builds up from string entries in configuration --always closes the previous connection before starting a new clip - -beta4 ------ -- now it's possible to load a plugin into the panel without specifying any position/dimensions - information, the plugin is placed to left: "50%", top: "50%" and using the plugin DisplayObject's width & height -- The Flowplayer API was not fully initialized when onLoad was invoked on Flash plugins - -beta3 ------ -- tweaking logo placement -- "play" did not show up after repeated pause/resume -- player now loads the latest controls SWF version, right now the latest SWF is called 'flowplayer.controls-3.0.0-beta2.swf' - -beta2 ------ -- fixed support for RTMP stream groups -- changed to loop through available fonts in order to find a suitable font also in IE -- Preloader was broken on IE: When the player SWf was in browser's cache it did not initialize properly -- Context menu now correctly handles menu items that are configured by their string labels only (not using json objects) -- fixed custom logo positioning (was moved to the left edge of screen in fullscreen) -- "play" now always follows the position and size of the screen -- video was stretched below the controls in fullscreen when autoHide: 'never' -- logo now takes 6.5% of the screen height, width is scaled so that the aspect ratio is preserved - -beta1 ------ -- First public beta release diff --git a/mods/flowplayer/flowplayer-3.1.2.min.js b/mods/flowplayer/flowplayer-3.1.2.min.js deleted file mode 100644 index 0d202cb5f..000000000 --- a/mods/flowplayer/flowplayer-3.1.2.min.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * flowplayer.js 3.1.2. The Flowplayer API - * - * Copyright 2009 Flowplayer Oy - * - * This file is part of Flowplayer. - * - * Flowplayer is free software: 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 3 of the License, or - * (at your option) any later version. - * - * Flowplayer 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 Flowplayer. If not, see . - * - * Date: 2009-02-25 16:24:29 -0500 (Wed, 25 Feb 2009) - * Revision: 166 - */ -(function(){function g(o){console.log("$f.fireEvent",[].slice.call(o))}function k(q){if(!q||typeof q!="object"){return q}var o=new q.constructor();for(var p in q){if(q.hasOwnProperty(p)){o[p]=k(q[p])}}return o}function m(t,q){if(!t){return}var o,p=0,r=t.length;if(r===undefined){for(o in t){if(q.call(t[o],o,t[o])===false){break}}}else{for(var s=t[0];p1){var r=arguments[1];var q=(arguments.length==3)?arguments[2]:{};if(typeof o=="string"){if(o.indexOf(".")!=-1){var t=[];m(n(o),function(){t.push(new b(this,k(r),k(q)))});return new d(t)}else{var s=c(o);return new b(s!==null?s:o,r,q)}}else{if(o){return new b(o,r,q)}}}return null};i(window.$f,{fireEvent:function(){var o=[].slice.call(arguments);var q=$f(o[0]);return q?q._fireEvent(o.slice(1)):null},addPlugin:function(o,p){b.prototype[o]=p;return $f},each:m,extend:i});if(typeof jQuery=="function"){jQuery.prototype.flowplayer=function(q,p){if(!arguments.length||typeof arguments[0]=="number"){var o=[];this.each(function(){var r=$f(this);if(r){o.push(r)}});return arguments.length?o[arguments[0]]:new d(o)}return this.each(function(){$f(this,k(q),p?k(p):{})})}}})();(function(){var e=typeof jQuery=="function";function i(){if(c.done){return false}var k=document;if(k&&k.getElementsByTagName&&k.getElementById&&k.body){clearInterval(c.timer);c.timer=null;for(var j=0;j'}o.width=o.height=o.id=o.w3c=o.src=null;for(var j in o){if(o[j]!==null){m+=''}}var n="";if(s){for(var l in s){if(s[l]!==null){n+=l+"="+(typeof s[l]=="object"?g(s[l]):s[l])+"&"}}n=n.substring(0,n.length-1);m+='"}m+="";return m}function d(l,o,k){var j=flashembed.getVersion();f(this,{getContainer:function(){return l},getConf:function(){return o},getVersion:function(){return j},getFlashvars:function(){return k},getApi:function(){return l.firstChild},getHTML:function(){return a(o,k)}});var p=o.version;var q=o.expressInstall;var n=!p||flashembed.isSupported(p);if(n){o.onFail=o.version=o.expressInstall=null;l.innerHTML=a(o,k)}else{if(p&&q&&flashembed.isSupported([6,65])){f(o,{src:q});k={MMredirectURL:location.href,MMplayerType:"PlugIn",MMdoctitle:document.title};l.innerHTML=a(o,k)}else{if(l.innerHTML.replace(/\s/g,"")!==""){}else{l.innerHTML="

    Flash version "+p+" or greater is required

    "+(j[0]>0?"Your version is "+j:"You have no flash plugin installed")+"

    "+(l.tagName=="A"?"

    Click here to download latest version

    ":"

    Download latest version from here

    ");if(l.tagName=="A"){l.onclick=function(){location.href="http://www.adobe.com/go/getflashplayer"}}}}}if(!n&&o.onFail){var m=o.onFail.call(this);if(typeof m=="string"){l.innerHTML=m}}if(document.all){window[o.id]=document.getElementById(o.id)}}window.flashembed=function(k,l,j){if(typeof k=="string"){var m=document.getElementById(k);if(m){k=m}else{c(function(){flashembed(k,l,j)});return}}if(!k){return}var n={width:"100%",height:"100%",allowfullscreen:true,allowscriptaccess:"always",quality:"high",version:null,onFail:null,expressInstall:null,w3c:false};if(typeof l=="string"){l={src:l}}f(n,l);return new d(k,n,j)};f(window.flashembed,{getVersion:function(){var l=[0,0];if(navigator.plugins&&typeof navigator.plugins["Shockwave Flash"]=="object"){var k=navigator.plugins["Shockwave Flash"].description;if(typeof k!="undefined"){k=k.replace(/^.*\s+(\S+\s+\S+$)/,"$1");var m=parseInt(k.replace(/^(.*)\..*$/,"$1"),10);var q=/r/.test(k)?parseInt(k.replace(/^.*r(.*)$/,"$1"),10):0;l=[m,q]}}else{if(window.ActiveXObject){try{var o=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7")}catch(p){try{o=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");l=[6,0];o.AllowScriptAccess="always"}catch(j){if(l[0]==6){return l}}try{o=new ActiveXObject("ShockwaveFlash.ShockwaveFlash")}catch(n){}}if(typeof o=="object"){k=o.GetVariable("$version");if(typeof k!="undefined"){k=k.replace(/^\S+\s+(.*)$/,"$1").split(",");l=[parseInt(k[0],10),parseInt(k[2],10)]}}}}return l},isSupported:function(j){var l=flashembed.getVersion();var k=(l[0]>j[0])||(l[0]==j[0]&&l[1]>=j[1]);return k},domReady:c,asString:g,getHTML:a});if(e){jQuery.tools=jQuery.tools||{version:{}};jQuery.tools.version.flashembed="1.0.3";jQuery.fn.flashembed=function(k,j){var l=null;this.each(function(){l=flashembed(this,k,j)});return k.api===false?this:l}}})(); \ No newline at end of file diff --git a/mods/flowplayer/flowplayer-3.1.2.swf b/mods/flowplayer/flowplayer-3.1.2.swf deleted file mode 100644 index 40b9647b1fd84a428e0a46ec8317f6da17bffd01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 107779 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%0A9EUcxVUAi-nh0e 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⁢KzX`F+{)TKP<%yfYPJ+4YMUHTf) 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ɀu&83*d|Bhqo6gTP)I(7P{r^W4Uarn$m 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 diff --git a/mods/flowplayer/flowplayer.controls-3.1.2.swf b/mods/flowplayer/flowplayer.controls-3.1.2.swf deleted file mode 100644 index 82c03fd29e63d7973977cb30f899b9ddc17c3d0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26349 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 AegFUf diff --git a/mods/flowplayer/module.php b/mods/flowplayer/module.php deleted file mode 100644 index a9622ce3e..000000000 --- a/mods/flowplayer/module.php +++ /dev/null @@ -1,20 +0,0 @@ -getAdminPrivilege()); - -global $_custom_head; -$_custom_head .=''; - -?> \ No newline at end of file diff --git a/mods/flowplayer/module.sql b/mods/flowplayer/module.sql deleted file mode 100644 index bd2f799f3..000000000 --- a/mods/flowplayer/module.sql +++ /dev/null @@ -1 +0,0 @@ -INSERT INTO `language_text` VALUES ('en', '_module','flowplayer','FlowPlayer',NOW(),''); \ No newline at end of file diff --git a/mods/flowplayer/module.xml b/mods/flowplayer/module.xml deleted file mode 100644 index 58e221fc7..000000000 --- a/mods/flowplayer/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - FlowPlayer - This module extends ATutor [media] tag to display .flv file with the built in flowplayer Flash player. No special permissions, tools tabs or icons are defined. Once installed just enter the path to a local flv file or URL to a remote flv file in between media tags. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.1 - 2009-08-22 - stable - The browser on linux OS may have problem accessing remote flv file. This module is only for ATutor 1.6.3+. For 1.6.3, please install patch 04 before enabling this module. - - diff --git a/mods/flowplayer/module_format_content.php b/mods/flowplayer/module_format_content.php deleted file mode 100644 index f295d2110..000000000 --- a/mods/flowplayer/module_format_content.php +++ /dev/null @@ -1,67 +0,0 @@ - -"; - -// .flv - uses Flowplayer 3.0 from flowplayer.org (playing file from AT_content_dir) -preg_match_all("#\[media[0-9a-z\|]*\]([\w\./-]+)\.flv\[/media\]#i",$_input,$media_matches[1],PREG_SET_ORDER); -$media_replace[1] =" -"; - -$has_flv = false; -// Executing the replace -for ($i=0;$i - '; -} -?> \ No newline at end of file diff --git a/mods/flowplayer/module_install.php b/mods/flowplayer/module_install.php deleted file mode 100644 index d49503347..000000000 --- a/mods/flowplayer/module_install.php +++ /dev/null @@ -1,24 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/flowplayer/module_uninstall.php b/mods/flowplayer/module_uninstall.php deleted file mode 100644 index b30362032..000000000 --- a/mods/flowplayer/module_uninstall.php +++ /dev/null @@ -1,44 +0,0 @@ -addError(array('MODULE_UNINSTALL', '
  • '.$directory.' can not be removed. Please manually remove it.
  • ')); -} - -/****** - * the following code checks if there are any errors (generated previously) - * then uses the SqlUtility to run reverted database queries of module.sql, - * ie. "create table" statement in module.sql is run as drop according table. - */ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/google_calendar/get_google_user.php b/mods/google_calendar/get_google_user.php deleted file mode 100644 index e79ca57d9..000000000 --- a/mods/google_calendar/get_google_user.php +++ /dev/null @@ -1,55 +0,0 @@ -addFeedback('GOOGLE_CAL_UPDATED'); - }else{ - $msg->addError('GOOGLE_CAL_UPDATE_FAILED'); - } -} - - -$sql = "SELECT email from ".TABLE_PREFIX."members WHERE member_id = '$_SESSION[member_id]'"; -$result=mysql_query($sql, $db); - -while($row = mysql_fetch_array($result)){ - $my_email_address = $row[0]; -} - - -$sql="SELECT * from ".TABLE_PREFIX."google_prefs WHERE member_id = '$_SESSION[member_id]'"; -$result=mysql_query($sql, $db); - -while($row = mysql_fetch_assoc($result)){ - $private_xml = $row['private_xml']; - $private_html= $row['private_html']; - $timezone = $row['timezone']; -} - -if($private_xml){ - $calendar_xml = $private_xml; -}else{ - $calendar_xml = "http://www.google.com/calendar/feeds/".$my_email_address."/public/basic"; - $private_message = ''._AT('google_calendar_permission').' '; -} - -$calendar_xml = str_replace('%40','%2540',$calendar_xml); - -if($private_html){ - $calendar_html = $private_html; -}else{ - $calendar_html = "http://www.google.com/calendar/feeds/".$my_email_address."/public/basic"; -} - - -if($timezone == ''){ - $timezone = date_default_timezone_get(); -} -?> \ No newline at end of file diff --git a/mods/google_calendar/google_cal.gif b/mods/google_calendar/google_cal.gif deleted file mode 100644 index 7f9dc5a790c807a4f96f940198724faeb675f708..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2455 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 V-~t;sz-Ix - -
    -
    -
    diff --git a/mods/google_calendar/index.php b/mods/google_calendar/index.php deleted file mode 100644 index c1ffd9679..000000000 --- a/mods/google_calendar/index.php +++ /dev/null @@ -1,40 +0,0 @@ - -
    -

    -
    - -
    - - - - - - - - - - - -
    - -

    -
    - -
    - -

    - \ No newline at end of file diff --git a/mods/google_calendar/index_admin.php b/mods/google_calendar/index_admin.php deleted file mode 100644 index 4e8fcaede..000000000 --- a/mods/google_calendar/index_admin.php +++ /dev/null @@ -1,38 +0,0 @@ - -
    -

    -
    - -
    - - - - - - - - -
    - - - -

    -
    - -
    - -

    - \ No newline at end of file diff --git a/mods/google_calendar/index_instructor.php b/mods/google_calendar/index_instructor.php deleted file mode 100644 index aca1d0e50..000000000 --- a/mods/google_calendar/index_instructor.php +++ /dev/null @@ -1,38 +0,0 @@ - -
    -

    -
    -
    - - - - - - - - - - -
    - - - -

    -
    - -
    - -

    -php require (AT_INCLUDE_PATH.'footer.inc.php'); ?> \ No newline at end of file diff --git a/mods/google_calendar/index_mystart.php b/mods/google_calendar/index_mystart.php deleted file mode 100644 index 34375f50b..000000000 --- a/mods/google_calendar/index_mystart.php +++ /dev/null @@ -1,43 +0,0 @@ - -
    -

    -
    - -
    - - - - - - - - - - - -
    - -

    -
    - -
    - -

    - \ No newline at end of file diff --git a/mods/google_calendar/module.php b/mods/google_calendar/module.php deleted file mode 100644 index 20f2917c6..000000000 --- a/mods/google_calendar/module.php +++ /dev/null @@ -1,50 +0,0 @@ -getPrivilege()); - -/******* - * create a side menu box/stack. - */ -$menu_path =AT_INCLUDE_PATH.'../mods/google_calendar/side_menu.inc.php'; - -$this->_stacks['google_calendar'] = array('title_var'=>'google_calendar', 'file'=>''.$menu_path.''); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_group_tool = $_student_tool = 'mods/google_calendar/index.php'; - - -/******* - * instructor Manage section: - */ -$this->_pages['mods/google_calendar/index_instructor.php']['title_var'] = 'google_calendar'; -$this->_pages['mods/google_calendar/index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages['mods/google_calendar/index.php']['title_var'] = 'google_calendar'; -$this->_pages['mods/google_calendar/index.php']['img'] = 'mods/google_calendar/google_cal.gif'; - -/* my start page pages */ -$this->_pages[AT_NAV_START] = array('mods/google_calendar/index_mystart.php'); -$this->_pages['mods/google_calendar/index_mystart.php']['title_var'] = 'google_calendar'; -$this->_pages['mods/google_calendar/index_mystart.php']['parent'] = AT_NAV_START; - -function google_calendar_get_group_url($group_id) { - return 'mods/google_calendar/index.php'; -} -?> \ No newline at end of file diff --git a/mods/google_calendar/module.sql b/mods/google_calendar/module.sql deleted file mode 100644 index 1c2cbb07a..000000000 --- a/mods/google_calendar/module.sql +++ /dev/null @@ -1,37 +0,0 @@ -# sql file for Google Calendar module - -CREATE TABLE `google_prefs` ( - `member_id` mediumint(8) NOT NULL, - `private_xml` varchar(150) NOT NULL, - `private_html` varchar(255) character set utf8 collate utf8_unicode_ci NOT NULL, - `timezone` varchar(50) NOT NULL, - PRIMARY KEY (`member_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - -INSERT INTO `language_text` VALUES ('en', '_module','google_calendar','Google Calendar',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','google_howto','To use the Google Calendar module with ATutor, you need to register a google account. If your google calendar is a shared calendar, you don\'t need to do anything to get your calendar to display in ATutor, provided the email address you used in ATutor is the same as the one used in your google account. If you have a Private calendar, follow these steps once you have your Google account setup: -

    Private Calendar Setup

    -
      -
    1. Sign in to your google account, and click on My Account
    2. -
    3. Click on "Calendar" under My Products
    4. -
    5. Click on the calendar "Settings" link
    6. -
    7. Click on the Calendars tab under Calendar Settings
    8. -
    9. Click on the name in the first column for the calandar you wish to make available through ATutor
    10. -
    11. Scroll down to "Private Address" and click on the XML button
    12. -
    13. Copy the URL generated into the Private Calendar XML URL field below.
    14. -
    15. Click on the HTML button
    16. -
    17. Copy the URL generated into the Private Calendar HTML URL field below. -
    18. Press Save.
    19. -
    -

    For additional details about Google Calendar setup and features, See Google Calendar Help.

    ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','google_private_xml','Private Calendar XML URL',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','google_private_html','Private Calendar HTML URL',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','google_private_calendar_prefs','Set Private Calendar Preferences',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','google_private_calendar','Private Calendar',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','google_setup','How to setup your Google calendar',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','google_timzone','Select Timezoner',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','google_calendar_permission','You do not have permission to view all events in this calendar. See details on setting up your Calendar below the main Google Calendar tool.',NOW(),''); - -INSERT INTO `language_text` VALUES ('en', '_c_msgs','AT_FEEDBACK_GOOGLE_CAL_UPDATED','Google calendar preferences were successfully updated',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_c_msgs','AT_FEEDBACK_GOOGLE_CAL_UPDATE_FAILED','Google calendar preferences update failed for some undetermined reason.',NOW(),''); diff --git a/mods/google_calendar/module.xml b/mods/google_calendar/module.xml deleted file mode 100644 index 6c2c589b1..000000000 --- a/mods/google_calendar/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Google Calendar - Adds Student and Instructor access to Google Calendars, as well as a calendar thumbnail side menu block while within courses. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.2 - 2010-10-25 - stable - Users require their own Google account inorder to use the calendar module. This module is intended to add users' personal calendars to ATutor. See the google calendar help page (http://www.google.com/support/calendar?hl=en) for details on creating a shared calendar, and the HTML generated by the Calendar that can be copied into an ATutor content page. - - \ No newline at end of file diff --git a/mods/google_calendar/module_install.php b/mods/google_calendar/module_install.php deleted file mode 100644 index 3bbed4b95..000000000 --- a/mods/google_calendar/module_install.php +++ /dev/null @@ -1,68 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} -*/ - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/google_calendar/module_uninstall.php b/mods/google_calendar/module_uninstall.php deleted file mode 100644 index 60ce25da8..000000000 --- a/mods/google_calendar/module_uninstall.php +++ /dev/null @@ -1,26 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/google_calendar/readme b/mods/google_calendar/readme deleted file mode 100644 index 49119f947..000000000 --- a/mods/google_calendar/readme +++ /dev/null @@ -1,14 +0,0 @@ -Google Calendar ReadMe - - -This module allows users on an ATutor system to integrate their personal Google Calendar into the ATutor environment. Details to setup your calendar are presented in the main page pages of the module once installed (mods/google_calendar/index.php). - -Calendars can be shared or private. In most cases users will want to keep their canlendar private, in which case they will need to copy the approriate URLs to their private calendar, and save those values into ATutor. - -It is possible create a shared calendar, but not via this module. It is intended to allow users to integrate their personal calendars into ATutor. If you wish to create a shared calendar that can be accessed, and used at various levels by class members, you can copy the HTML like that below (generated on the Calendar Details screen) into an ATutor content page, replacing the email address with the one associated with the shared calendar and setting the timezome, to create a shared course calendar for your courses. See the Google Calendar Help page for additional details on setting up shared calendars. - -Embed Calendar HTML - - -Installation -Unzip the module file into the ATutor mods/ directory, then as the ATutor administrator, install the module through the Module tab, then Install Module in the sub-menu, the Calendar module should be listed as available to install. After installing. enable the module on the main Module screen in ATutor to make it available to users. diff --git a/mods/google_calendar/side_menu.inc.php b/mods/google_calendar/side_menu.inc.php deleted file mode 100644 index 79df8ea76..000000000 --- a/mods/google_calendar/side_menu.inc.php +++ /dev/null @@ -1,22 +0,0 @@ - - - - -assign('dropdown_contents', ob_get_contents()); -ob_end_clean(); - -$savant->assign('title', _AT('google_calendar')); // the box title -$savant->display('include/box.tmpl.php'); - -?> \ No newline at end of file diff --git a/mods/google_talk/google_talk.png b/mods/google_talk/google_talk.png deleted file mode 100644 index 3bd53918c8f98e57a79b5ed2bda9d3464e64aae0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9774 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 diff --git a/mods/google_talk/index.php b/mods/google_talk/index.php deleted file mode 100644 index 562f9a3cd..000000000 --- a/mods/google_talk/index.php +++ /dev/null @@ -1,12 +0,0 @@ - - -
    - -
    - - \ No newline at end of file diff --git a/mods/google_talk/module.php b/mods/google_talk/module.php deleted file mode 100644 index 6336396b9..000000000 --- a/mods/google_talk/module.php +++ /dev/null @@ -1,68 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_GOOGLE_TALK', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -#$this->_stacks['google_talk'] = array('title_var'=>'google_talk', 'file'=>'mods/google_talk/side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('google_talk', array('title_var' => 'google_talk', 'file' => './side_menu.inc.php'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_group_tool = $_student_tool = 'mods/google_talk/index.php'; - -/******* - * add the admin pages when needed. - */ -#if (admin_authenticate(AT_ADMIN_PRIV_google_talk, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { -# $this->_pages[AT_NAV_ADMIN] = array('mods/google_talk/index_admin.php'); -# $this->_pages['mods/google_talk/index_admin.php']['title_var'] = 'google_talk'; -# $this->_pages['mods/google_talk/index_admin.php']['parent'] = AT_NAV_ADMIN; -#} - -/******* - * instructor Manage section: - */ -$this->_pages['mods/google_talk/index_instructor.php']['title_var'] = 'google_talk'; -$this->_pages['mods/google_talk/index_instructor.php']['parent'] = 'tools/index.php'; -// ** possible alternative: ** -// $this->pages['./index_instructor.php']['title_var'] = 'google_talk'; -// $this->pages['./index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages['mods/google_talk/index.php']['title_var'] = 'google_talk'; -$this->_pages['mods/google_talk/index.php']['img'] = 'mods/google_talk/google_talk.png'; - - -/* public pages */ -#$this->_pages[AT_NAV_PUBLIC] = array('mods/google_talk/index_public.php'); -#$this->_pages['mods/google_talk/index_public.php']['title_var'] = 'google_talk'; -#$this->_pages['mods/google_talk/index_public.php']['parent'] = AT_NAV_PUBLIC; - -/* my start page pages */ -#$this->_pages[AT_NAV_START] = array('mods/google_talk/index_mystart.php'); -#$this->_pages['mods/google_talk/index_mystart.php']['title_var'] = 'google_talk'; -#$this->_pages['mods/google_talk/index_mystart.php']['parent'] = AT_NAV_START; - -function google_talk_get_group_url($group_id) { - return 'mods/google_talk/index.php'; -} -?> \ No newline at end of file diff --git a/mods/google_talk/module.sql b/mods/google_talk/module.sql deleted file mode 100644 index f1672a30a..000000000 --- a/mods/google_talk/module.sql +++ /dev/null @@ -1,5 +0,0 @@ -# sql file for hello world module - - - -INSERT INTO `language_text` VALUES ('en', '_module','google_talk','Google Talk',NOW(),''); diff --git a/mods/google_talk/module.xml b/mods/google_talk/module.xml deleted file mode 100644 index f8fc00dec..000000000 --- a/mods/google_talk/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Google Talk - Adds Google Talk Instant messaging to an ATutor system. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.3 - 2010-10-25 - stable - Users must setup a google talk account before they can use this module. - - \ No newline at end of file diff --git a/mods/google_talk/module_install.php b/mods/google_talk/module_install.php deleted file mode 100644 index 9a828118f..000000000 --- a/mods/google_talk/module_install.php +++ /dev/null @@ -1,67 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/google_talk/module_uninstall.php b/mods/google_talk/module_uninstall.php deleted file mode 100644 index 60ce25da8..000000000 --- a/mods/google_talk/module_uninstall.php +++ /dev/null @@ -1,26 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/gradebook/README b/mods/gradebook/README deleted file mode 100644 index aa8aa0b5b..000000000 --- a/mods/gradebook/README +++ /dev/null @@ -1,51 +0,0 @@ -Gradebook ReadMe - -This module can be installed with ATutor for: -1) instructors 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. -2) students to view their marks for completed tests or assignments, list tests or assignments yet to be completed or yet to be marked, and print out a report of their marks. - -For additional documentation see: http://wiki.atutor.ca/display/atutorwiki/Gradebook - -* 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 gradebook-0.1.tar.gz - -2. Login to ATutor as the administrator and run Install Module under the Modules tab, Select the Gradebook 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, login as instructor, click on tab "Manage", "Gradebook" line is there. Instructors can grant access on gradebook to students through "Student Tools". - -* How to use gradebook (for instructors) -1. Gradebook Scales - 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. - -2. Add ATutor Test/Assignment to Gradebook - -2.1 Add ATutor Assignment - Assignments that have been created using the ATutor Assignment Manager can be added to the gradebook. Select the "Title" 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 "External Marks". 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. - -2.2 Add ATutor Test - Tests that are created using the ATutor Test & Survey Manager can be added to the gradebook if the test's "Attempts Allowed" property has been set to 1 attempt. Select the test "Title" 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. - -3. Update ATutor Marks - -3.1 Update ATutor Marks - 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. - -3.2 Combine ATutor Tests - 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 "Combine Into" menu. Select the test to be combined from the "Combined From" select menu, then press the "Combine" button to import the marks from that test. Be sure to run "Update ATutor Marks" on the "Combined Into" 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. - -4. External Marks - -4.1 Export - 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. - -4.2 Import - Marks from an external assignment or test can be imported in a Comma Separated Values (CSV) file in the form ""firstname", "lastname", "email", "grade"" with one student per line. The mark can either be a scale mark such ""A"" or ""Pass"", or a percentage mark such as "78%". Select the test or assignment previously defined through "Add Tests/Assignment" The first line of the imported file should contain the field names ""First Name, Last Name, Email, Grade" " If it is not included the first line will be removed when the marks are imported. - -5. Edit Marks - 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 "edit" link, editing either marks for a single student, or editing marks for a single test. To edit marks from ATutor based tests, use the "Test & Surveys Manager". When editing ATutor based marks, be sure to run "Update ATutor Marks" to have the changes take affect in the Gradebook.. diff --git a/mods/gradebook/edit_marks.php b/mods/gradebook/edit_marks.php deleted file mode 100644 index 132ec4b9c..000000000 --- a/mods/gradebook/edit_marks.php +++ /dev/null @@ -1,421 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: gradebook_tests.php'); - exit; -} -else if (isset($_GET['save'])) -{ - foreach($_GET as $key => $value) - { - $value = $addslashes($value); - if (preg_match('/^grade_(.*)_(.*)$/', $key, $matches) > 0) - { - $sql = "SELECT grade_scale_id FROM ".TABLE_PREFIX."gradebook_tests WHERE gradebook_test_id = ". $matches[1]; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - $sql = "REPLACE ".TABLE_PREFIX."gradebook_detail SET gradebook_test_id = ". $matches[1].", member_id=". $matches[2].", grade='".get_mark_by_grade($row["grade_scale_id"], $value)."'"; - $result = mysql_query($sql, $db) or die(mysql_error()); - } - } -} - -$orders = array('asc' => 'desc', 'desc' => 'asc'); - -if (isset($_GET['asc'])) -{ - $order = 'asc'; - $order_col = $_GET['asc']; -} -else if (isset($_GET['desc'])) { - $order = 'desc'; - $order_col = $_GET['desc']; -} else { - // no order set - $order = 'asc'; - $order_col = 'name'; -} - -if ($_GET['reset_filter']) { - unset($_GET); -} - -// Initialize all applicable tests array and all enrolled students array -$all_tests = array(); -$all_students = array(); - -// generate test array -$sql = "(SELECT g.gradebook_test_id, g.id, g.type, t.title". - " FROM ".TABLE_PREFIX."gradebook_tests g, ".TABLE_PREFIX."tests t". - " WHERE g.type='ATutor Test'". - " AND g.id = t.test_id". - " AND t.course_id=".$_SESSION["course_id"]." ORDER BY title)". - " UNION (SELECT g.gradebook_test_id, g.id, g.type, a.title". - " FROM ".TABLE_PREFIX."gradebook_tests g, ".TABLE_PREFIX."assignments a". - " WHERE g.type='ATutor Assignment'". - " AND g.id = a.assignment_id". - " AND a.course_id=".$_SESSION["course_id"]." ORDER BY title)". - " UNION (SELECT gradebook_test_id, id, type, title". - " FROM ".TABLE_PREFIX."gradebook_tests". - " WHERE course_id=".$_SESSION["course_id"]." ORDER BY title)"; -$result = mysql_query($sql, $db) or die(mysql_error()); - -while ($row = mysql_fetch_assoc($result)) -{ - $no_error = true; - - if($row["type"]=="ATutor Test") - { - $studs_take_num = get_studs_take_more_than_once($_SESSION["course_id"], $row["id"]); - - foreach ($studs_take_num as $student => $num) - { - if ($no_error) $no_error = false; - $error_msg .= $student . ": " . $num . " times
    "; - } - - if (!$no_error) - { - $f = array('ADD_TEST_INTO_GRADEBOOK', - $row['title'], - $error_msg); - $msg->addFeedback($f); - } - } - - if ($no_error) array_push($all_tests, $row); -} - -// generate students array -$sql_students = "SELECT m.first_name, m.last_name, e.member_id FROM ".TABLE_PREFIX."members m, ".TABLE_PREFIX."course_enrollment e WHERE m.member_id = e.member_id AND e.course_id=".$_SESSION["course_id"]." AND e.approved='y' AND e.role!='Instructor'"; -if ($order_col == "name") -{ - $sql_students .= " ORDER BY m.first_name ".$order.",m.last_name ".$order; -} -$result = mysql_query($sql_students, $db) or die(mysql_error()); - -while ($row = mysql_fetch_assoc($result)) - array_push($all_students, $row); -// end of initialization - -// Creates arrays for filtered test/student -$selected_tests = array(); -$selected_students = array(); -$grades = array(); - -// generate test array -if (($_GET["filter"] || $_GET["download"]) && $_GET["gradebook_test_id"]<>0) -{ - foreach ($all_tests as $test) - { - if ($test["gradebook_test_id"] == $_GET["gradebook_test_id"]) - { - $selected_tests[0]["gradebook_test_id"] = $test["gradebook_test_id"]; - $selected_tests[0]["title"] = $test["title"]; - $selected_tests[0]["type"] = $test["type"]; - } - } -} -else - $selected_tests = $all_tests; - -// generate students array -if (($_GET["filter"] || $_GET["download"]) && $_GET["member_id"]<>0) -{ - foreach ($all_students as $student) - { - if ($student["member_id"] == $_GET["member_id"]) - { - $selected_students[0]["member_id"] = $student["member_id"]; - $selected_students[0]["first_name"] = $student["first_name"]; - $selected_students[0]["last_name"] = $student["last_name"]; - } - } - - $sql_students = "SELECT first_name, last_name, member_id FROM ".TABLE_PREFIX."members WHERE member_id=" . $_GET["member_id"]; -} -else - $selected_students = $all_students; - -// generate grade 2-dimentional array -foreach ($selected_tests as $selected_test) - foreach($selected_students as $selected_student) - { - $sql = "SELECT grade FROM ".TABLE_PREFIX."gradebook_detail WHERE gradebook_test_id=".$selected_test["gradebook_test_id"]." AND member_id=".$selected_student["member_id"]; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - $grades[$selected_test["gradebook_test_id"]][$selected_student["member_id"]] = $row["grade"]; - } - -// sort grade -if ((isset($_GET["asc"]) || isset($_GET["desc"])) && $order_col <> "name") -{ - $sort = '$grades['.$order_col.'], SORT_'.strtoupper($order).', $selected_students, SORT_'.strtoupper($order); - - foreach($selected_tests as $test) - { - if ($test["gradebook_test_id"] <> $order_col) - $sort .= ', $grades['.$test["gradebook_test_id"].'], SORT_'.strtoupper($order); - } - $sort='array_multisort('.$sort.');'; - eval($sort); -} -// end of initialization - -$num_students = count($selected_students); -$results_per_page = 50; -$num_pages = max(ceil($num_students / $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; - -// generate table & csv head -$table_head = "\n\r"; -$table_head .= "\n\r"; - -if ($_GET[filter] <> "") - $query_str = '&filter='.$_GET[filter]; - -if ($_GET[member_id] <> "") - $query_str .= '&member_id='.$_GET[member_id]; - -if ($_GET[gradebook_test_id] <> "") - $query_str .= '&gradebook_test_id='.$_GET[gradebook_test_id]; - -$table_head .= " ". _AT('name')."\n\r"; - -$csv_content = _AT('name'); - -foreach ($selected_tests as $selected_test) -{ - $table_head .= " ". $selected_test[title]."\n\r"; - $csv_content .= ",".$selected_test[title]; -} -$table_head .= " \n\r"; -$table_head .= "\n\r"; - -$csv_content .= "\n"; - -$table_head .= "\n\r"; -$table_head .= " \n\r"; - -$has_edit_button = false; -foreach ($selected_tests as $selected_test) -{ - if ($selected_test["type"] == "External" || $selected_test["type"] == "ATutor Assignment") - { - $has_edit_button = true; - $table_head .= " ". _AT("edit")."\n\r"; - } - else - { - $table_head .= " \n\r"; - } -} -if ($has_edit_button) $table_head .= " "; -$table_head .= "\n\r"; -$table_head .= "\n\r"; - -// generate table & csv content -if ($num_students > 0) -{ - $table_content = " \n\r"; - if ($offset + $results_per_page > $num_students) $end_pos = $num_students; - else $end_pos = $offset + $results_per_page; - - $tabindex_input = 1; - $tabindex_edit = 2; - - for ($i=$offset; $i < $end_pos; $i++) - { - $table_content .= " \n\r"; - $table_content .= " ".$selected_students[$i]["first_name"]." " . $selected_students[$i]["last_name"]."\n\r"; - - $csv_content .= $selected_students[$i]["first_name"]." " . $selected_students[$i]["last_name"]; - - foreach ($selected_tests as $selected_test) - { - $sql = "SELECT grade FROM ".TABLE_PREFIX."gradebook_detail WHERE gradebook_test_id=".$selected_test["gradebook_test_id"]." AND member_id=".$selected_students[$i]["member_id"]; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - $row["grade"] = htmlspecialchars($row["grade"]); // handle html special chars - - if ($_GET["edit"]=="c_".$selected_test["gradebook_test_id"] || $_GET["edit"]=="r_".$selected_students[$i]["member_id"] && ($selected_test["type"]=="External" || $selected_test["type"]=="ATutor Assignment")) - { - $table_content .= " \n\r"; - $csv_content .= ",".$row["grade"]; - } - else - { - if ($row["grade"]=="") - { - $table_content .= " "._AT("na")."\n\r"; - $csv_content .= ",". _AT("na"); - } - else - { - $table_content .= " ".$row["grade"]."\n\r"; - $csv_content .= ",".$row["grade"]; - } - } - } - - if ($has_edit_button) - $table_content .= " ". _AT("edit") ."\n\r"; - - $table_content .= " \n\r"; - $csv_content .= "\n"; - } - - $table_content .= " \n\r"; -} - -// download csv file -if ($_GET['download']) -{ - if ($num_students == 0) - { - 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="grades.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->printFeedbacks(); - -if (count($selected_tests)==0) -{ - echo _AT('empty_gradebook'); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} -?> -
    -
    - -
    -
    -
    - -
    - -
    -
    - -
    - -
    - - - -
    -
    -
    - -
    - -
    - - - - - - - - - - - - - - - - - - - - - -
    -
    - -
    -
    - -
    - - \ No newline at end of file diff --git a/mods/gradebook/grade_scale.php b/mods/gradebook/grade_scale.php deleted file mode 100644 index 7e44dd2e9..000000000 --- a/mods/gradebook/grade_scale.php +++ /dev/null @@ -1,186 +0,0 @@ - - - - /> - - - - - - - -addError('NO_ITEM_SELECTED'); -} - -require(AT_INCLUDE_PATH.'header.inc.php'); -?> - -
    - -

    - - - - - - - - - - - - - - - - - - - - - - - - - $prev_row['grade_scale_id']) - { - // print row - if ($prev_row['grade_scale_id'] <> 0) print_row($prev_row['grade_scale_id'], $prev_row['scale_name'], $whole_scale_value, $prev_row['created_date'], $_POST['grade_scale_id']); - - // initialize next $whole_scale_value - $whole_scale_value = $row['scale_value'] . ' = ' . $row['percentage_from'] . ' to ' . $row['percentage_to'] . '%'; - $prev_row = $row; - } - else - { - $whole_scale_value .= '
    '.$row['scale_value'] . ' = ' . $row['percentage_from'] . ' to ' . $row['percentage_to'] . '%'; - } - } - // print last row - if ($prev_row['grade_scale_id'] <> 0) print_row($prev_row['grade_scale_id'], $prev_row['scale_name'], $whole_scale_value, $prev_row['created_date'], $_POST['grade_scale_id']); -} -?> - - -
     
    -
    - - -
    -
    -
    - -

    - - - - - - - - - - - - - - - $prev_row['grade_scale_id']) - { - // print row - if ($prev_row['grade_scale_id'] <> 0) print_row($prev_row['grade_scale_id'], $prev_row['scale_name'], $whole_scale_value, $prev_row['created_date'], $_POST['grade_scale_id'], false); - - // initialize next $whole_scale_value - $whole_scale_value = $row['scale_value'] . ' = ' . $row['percentage_from'] . ' to ' . $row['percentage_to'] . '%'; - $prev_row = $row; - } - else - { - $whole_scale_value .= '
    '.$row['scale_value'] . ' = ' . $row['percentage_from'] . ' to ' . $row['percentage_to'] . '%'; - } - } - // print last row - if ($prev_row['grade_scale_id'] <> 0) print_row($prev_row['grade_scale_id'], $prev_row['scale_name'], $whole_scale_value, $prev_row['created_date'], $_POST['grade_scale_id'], false); -} -?> - - -
    - - diff --git a/mods/gradebook/grade_scale_add.php b/mods/gradebook/grade_scale_add.php deleted file mode 100644 index 73526cf49..000000000 --- a/mods/gradebook/grade_scale_add.php +++ /dev/null @@ -1,17 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: grade_scale.php'); - exit; -} else if (isset($_POST['submit_yes'])) { - /* delete has been confirmed, delete this category */ - $grade_scale_id = intval($_POST['grade_scale_id']); - - $sql = "DELETE FROM ".TABLE_PREFIX."grade_scales WHERE grade_scale_id=$grade_scale_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - $sql = "DELETE FROM ".TABLE_PREFIX."grade_scales_detail WHERE grade_scale_id=$grade_scale_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - $sql = "UPDATE ".TABLE_PREFIX."gradebook_tests SET grade_scale_id=0 WHERE grade_scale_id=$grade_scale_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: grade_scale.php'); - exit; -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -$_GET['grade_scale_id'] = intval($_GET['grade_scale_id']); - -$sql = "SELECT grade_scale_id, scale_name FROM ".TABLE_PREFIX."grade_scales g WHERE g.grade_scale_id=$_GET[grade_scale_id]"; -$result = mysql_query($sql,$db) or die(mysql_error()); - -if (mysql_num_rows($result) == 0) { - $msg->printErrors('ITEM_NOT_FOUND'); -} else { - $row = mysql_fetch_assoc($result); - - $hidden_vars['scale_name']= $row['scale_name']; - $hidden_vars['grade_scale_id'] = $row['grade_scale_id']; - - $confirm = array('DELETE_GRADE_SCALE', $row['scale_name']); - $msg->addConfirm($confirm, $hidden_vars); - - $msg->printConfirm(); -} - -require(AT_INCLUDE_PATH.'footer.inc.php'); - -?> \ No newline at end of file diff --git a/mods/gradebook/grade_scale_edit.php b/mods/gradebook/grade_scale_edit.php deleted file mode 100644 index 799316614..000000000 --- a/mods/gradebook/grade_scale_edit.php +++ /dev/null @@ -1,17 +0,0 @@ -^@RCt{2nO#g<_Zf#@I%(3j3wAMWyDE3Pn#x_It&*LaU1U-c z?P8OvX=vJRCN12w(ryx*Y0@qhEvc$?nHEgCq-~P6kTz+T1rnE!7$`9*C1CIuU@-mw z+ZZ3)_~RV>?BX07jthh(CdJbJ(j&{Vef&OtfA9Ys+amv8d#)xC;Q(oRULpr6QQ^Q> zlZaroTAA|BF&hZtUsz&(Da>Lx%5rp-$ZCR>#2WFn6vHXKg)ADxD#n$&$(D z$nGYgs;H`ls%g(vIhYVY-);*(?Hlnm^7q&^Lns%Ta>EB5}L>L$t zz&SizmncF?3LHf&Po6YMRHEb!%riLj zpe|9WN@$yCnuhbXp!kJyL`Zq7B4?jTL`1ea5nCk|PqLC&BQPIi=z-G|rIFFkxZB%D zzEGsEua7flI_R|9ak*S{clU7q{CV!*chF(8;cz$@AAf|y;h?9drz)jt8qOX;nGwoC zfyF0x#VWfDaxE2!XgtY}Uw)aty?K%O;35y4!=@;mK7EGc$B%RBR67=n1&hT(b8|Bm zixrF2N?ThSEiElrtyWH)ILUe!W_Vmy4E`7CLM;Iy!8q znnq7g53Q}OG&eWna5!jgZpLP_(bCdV-MLg%qok@hFAK^8p*+4-<93k`MTChf0;4+R zVPVrLWF3P4u9Yco0MA^Iz~VBC;V4Uy7?aa8sH#RHwXW|>nJh{sODG&+WMtITg%c-E zuo{nJ@9M(d)m4>fYiq-5wUS6C>AHLwtJR9lX2Tx{n7UR{Rf;7Q=RXC-A(Th9YTYh^ zh*0hqw0lDFj*!14WV?mDB^rwP;Lq3UV%QHibzUCDBcjluM30i!h5d>i#G*=0xJS(fr7xM0LE=e zU_)Ttc+R50te#o-onLVE>QxfSWc8EX?F3i5E7eA+P^?H4$mI(-&k4%=Lix79$2t`e zM1<&h;orY8+BI$z^^_tE3Vb5C#>d&%$nVmH{Y5EXD6)|+klVs82`Xulh0G71D~bW0bnOx^|4xmPCL3v9k zUlX{lV-n%Iz?y(I3!9PpuqK2;A&SKk@k9c9R~Igqi}v<*>~=dJboXGl+p*j2^xeBh zU*A2vUN6yDjJv(PWVZ>Vl?t)vCWoFicduEnt_Y70hZlCu*k4}~t?;fuw-MWW0z(300uusm0lzVeVPn=30x4tmV#Z@0y;UnRCy+edc-*QL@e8b;YCQb4 zA|8RruNn_et%zG->1U0D??t_4cdf`{f%%^tZXU~ym_;T8d_Ou|Ony_Z>j{`e9tq5} zezmxNX!@GHU(6y81s?z4`SVbo8MDZ!z~?U>JmcT1e%G!SW)Y{r*mn;GryM9|kwJms zZ`TLsH}vB@C(I)K0z=<=div!n!z^-N;M1?~pZhQ9uQ>#mMS2DLzP2~Lawsv2+!46b zRD(1GW|2=C7qiH%#-$>1Rz%4C>-!Ch>9^mrKNt9*@u(!KDk36qqwz3mUyyAJ5uyK# xz_r6q%Xjwv|8QS_yB#w2Twir@Polq8;J+s~ND-Ui@2UU*002ovPDHLkV1g}bkzfD- diff --git a/mods/gradebook/gradebook_add_tests.php b/mods/gradebook/gradebook_add_tests.php deleted file mode 100644 index cabbaf7b8..000000000 --- a/mods/gradebook/gradebook_add_tests.php +++ /dev/null @@ -1,305 +0,0 @@ - $num) - { - if ($no_error) $no_error = false; - $error_msg .= $student . ": " . $num . " times
    "; - } - - if (!$no_error) - { - $f = array('ADD_TEST_INTO_GRADEBOOK', - $title, - $error_msg); - $msg->addFeedback($f); - } - - if ($no_error) // add into gradebook - { - $sql_insert = "INSERT INTO ".TABLE_PREFIX."gradebook_tests (id, type, grade_scale_id) - VALUES (". $test_id. ", 'ATutor Test', ".$_POST["selected_grade_scale_id"].")"; - $result_insert = mysql_query($sql_insert, $db) or die(mysql_error()); - } -} - -function add_assignment($assignment_id) -{ - global $db; - - $sql_insert = "INSERT INTO ".TABLE_PREFIX."gradebook_tests (id, type, grade_scale_id) - VALUES (". $assignment_id. ", 'ATutor Assignment', ".$_POST["selected_grade_scale_id"].")"; - $result_insert = mysql_query($sql_insert, $db) or die(mysql_error()); -} - -if (isset($_POST['cancel'])) -{ - $msg->addFeedback('CANCELLED'); - header('Location: gradebook_tests.php'); - exit; -} -else if (isset($_POST['addATutorTest'])) -{ - if (preg_match('/^at_(.*)$/', $_POST["id"], $matches) > 0) // add atutor test - { - if ($matches[1] == 0) // add all applicable tests - { - $sql = "SELECT * FROM ".TABLE_PREFIX."tests t". - " WHERE course_id=".$_SESSION["course_id"]. - " AND num_takes = 1". - " AND NOT EXISTS (SELECT 1". - " FROM ".TABLE_PREFIX."gradebook_tests g". - " WHERE g.id = t.test_id". - " AND g.type='ATutor Test')"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - while ($row = mysql_fetch_assoc($result)) - { - add_test($row["test_id"], $row["title"]); - } - } - else // add one atutor test - { - $sql = "SELECT * FROM ".TABLE_PREFIX."tests t". - " WHERE test_id=".$matches[1]; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - add_test($matches[1], $row["title"]); - } - } - else if (preg_match('/^aa_(.*)$/', $_POST["id"], $matches) > 0) // add atutor test - { - if ($matches[1] == 0) // add all applicable tests - { - $sql = "SELECT * FROM ".TABLE_PREFIX."assignments a". - " WHERE course_id=".$_SESSION["course_id"]. - " AND NOT EXISTS (SELECT 1". - " FROM ".TABLE_PREFIX."gradebook_tests g". - " WHERE g.id = a.assignment_id". - " AND g.type='ATutor Assignment')"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - while ($row = mysql_fetch_assoc($result)) - { - add_assignment($row["assignment_id"]); - } - } - else // add one test_id - { - add_assignment($matches[1]); - } - } - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: gradebook_tests.php'); - exit; -} -else if (isset($_POST['addExternalTest'])) -{ - $missing_fields = array(); - - if ($_POST['title'] == '') { - $missing_fields[] = _AT('title'); - } - - if ($missing_fields) { - $missing_fields = implode(', ', $missing_fields); - $msg->addError(array('EMPTY_FIELDS', $missing_fields)); - } - - if (!$msg->containsErrors()) - { - if ($_POST["has_due_date"] == 'true') - $date_due = $_POST["year_due"]. '-' .str_pad ($_POST["month_due"], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST["day_due"], 2, "0", STR_PAD_LEFT). ' '.str_pad ($_POST["hour_due"], 2, "0", STR_PAD_LEFT). ':' .str_pad ($_POST["min_due"], 2, "0", STR_PAD_LEFT) . ':00'; - - $sql_insert = "INSERT INTO ".TABLE_PREFIX."gradebook_tests (course_id, type, title, due_date, grade_scale_id) - VALUES (".$_SESSION["course_id"].", 'External', '". $_POST["title"]. "', '".$date_due . "', ".$_POST["selected_grade_scale_id"].")"; - $result_insert = mysql_query($sql_insert, $db) or die(mysql_error()); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: gradebook_tests.php'); - exit; - } -} - -$onload .= ' disable_dates (true, \'_due\');'; -require(AT_INCLUDE_PATH.'header.inc.php'); - -?> -
    -
    -
    - -
    -

    -
    - - 0 ". - " GROUP BY test_id ". - " HAVING count(*) > 0) ". - " ORDER BY title"; -$result_at = mysql_query($sql_at, $db) or die(mysql_error()); - -$sql_aa = "SELECT * FROM ".TABLE_PREFIX."assignments a". - " WHERE course_id=".$_SESSION["course_id"]. - " AND NOT EXISTS (SELECT 1". - " FROM ".TABLE_PREFIX."gradebook_tests g". - " WHERE g.id = a.assignment_id". - " AND g.type='ATutor Assignment')". - " ORDER BY title"; -$result_aa = mysql_query($sql_aa, $db) or die(mysql_error()); - -if (mysql_num_rows($result_at) == 0 && mysql_num_rows($result_aa) == 0) -{ - echo _AT('none_found'); -} -else -{ - echo '
    '."\n\r"; - echo '
    '."\n\r"; - echo ' '."\n\r"; - echo '
    '."\n\r"; - -?> -
    -
    - -
    - -
    - - -
    - -
    - -
    -
    - -
    -
    -
    - -
    -
    *

    - -
    - -
    -
    - -
    - -
    -
    - -
    - - - - - -
    - -
    - - -
    - -
    - -
    -
    - - - - diff --git a/mods/gradebook/gradebook_delete_tests.php b/mods/gradebook/gradebook_delete_tests.php deleted file mode 100644 index 7f7ff6efa..000000000 --- a/mods/gradebook/gradebook_delete_tests.php +++ /dev/null @@ -1,77 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: gradebook_tests.php'); - exit; -} else if (isset($_POST['submit_yes'])) { - /* delete has been confirmed, delete this category */ - $gradebook_test_id = intval($_POST['gradebook_test_id']); - - $sql = "DELETE FROM ".TABLE_PREFIX."gradebook_tests WHERE gradebook_test_id=$gradebook_test_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - $sql = "DELETE FROM ".TABLE_PREFIX."gradebook_detail WHERE gradebook_test_id=$gradebook_test_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: gradebook_tests.php'); - exit; -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -$_GET['gradebook_test_id'] = intval($_GET['gradebook_test_id']); - -$sql = "(SELECT g.gradebook_test_id, t.title". - " FROM ".TABLE_PREFIX."gradebook_tests g, ".TABLE_PREFIX."tests t". - " WHERE g.type='ATutor Test'". - " AND g.id = t.test_id". - " AND g.gradebook_test_id=".$_GET['gradebook_test_id'].")". - " UNION (SELECT g.gradebook_test_id, a.title". - " FROM ".TABLE_PREFIX."gradebook_tests g, ".TABLE_PREFIX."assignments a". - " WHERE g.type='ATutor Assignment'". - " AND g.id = a.assignment_id". - " AND g.gradebook_test_id=".$_GET['gradebook_test_id'].")". - " UNION (SELECT gradebook_test_id, title ". - " FROM ".TABLE_PREFIX."gradebook_tests". - " WHERE type='External'". - " AND gradebook_test_id=".$_GET['gradebook_test_id'].")"; - -$result = mysql_query($sql,$db) or die(mysql_error()); - -if (mysql_num_rows($result) == 0) { - $msg->printErrors('ITEM_NOT_FOUND'); -} else { - $row = mysql_fetch_assoc($result); - - $hidden_vars['title']= $row["title"]; - $hidden_vars['gradebook_test_id'] = $row['gradebook_test_id']; - - $confirm = array('DELETE_TEST_FROM_GRADEBOOK', $row["title"]); - $msg->addConfirm($confirm, $hidden_vars); - - $msg->printConfirm(); -} - -require(AT_INCLUDE_PATH.'footer.inc.php'); - -?> \ No newline at end of file diff --git a/mods/gradebook/gradebook_edit_tests.php b/mods/gradebook/gradebook_edit_tests.php deleted file mode 100644 index 8593b5674..000000000 --- a/mods/gradebook/gradebook_edit_tests.php +++ /dev/null @@ -1,195 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: gradebook_tests.php'); - exit; -} -else if (isset($_POST['save'])) -{ - $missing_fields = array(); - - if (isset($_POST['title']) && $_POST['title'] == '') { - $missing_fields[] = _AT('title'); - } - - if ($missing_fields) { - $missing_fields = implode(', ', $missing_fields); - $msg->addError(array('EMPTY_FIELDS', $missing_fields)); - } - - if (!$msg->containsErrors()) - { - $sql = "UPDATE ".TABLE_PREFIX."gradebook_tests SET "; - - if (isset($_POST["title"])) $sql .= "title = '".$_POST["title"]. "', "; - if ($_POST["has_due_date"] == 'true') - { - $due_date = $_POST["year_due"]. '-' .str_pad ($_POST["month_due"], 2, "0", STR_PAD_LEFT). '-' .str_pad ($_POST["day_due"], 2, "0", STR_PAD_LEFT). ' '.str_pad ($_POST["hour_due"], 2, "0", STR_PAD_LEFT). ':' .str_pad ($_POST["min_due"], 2, "0", STR_PAD_LEFT) . ':00'; - $sql .= "due_date = '".$due_date. "', "; - } - else - $sql .= "due_date = '', "; - - $sql .= "grade_scale_id=".$_POST["selected_grade_scale_id"]." WHERE gradebook_test_id = ". $_REQUEST["gradebook_test_id"]; - $result = mysql_query($sql, $db) or die(mysql_error()); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: gradebook_tests.php'); - exit; - } -} - -$sql = "SELECT * FROM ".TABLE_PREFIX."gradebook_tests WHERE gradebook_test_id=" . $_REQUEST["gradebook_test_id"]; -$result = mysql_query($sql, $db) or die(mysql_error()); - -$sql = "(SELECT g.gradebook_test_id, g.type, t.title, DATE_FORMAT(end_date, '%Y-%m-%d %H:%i:00') AS due_date, g.grade_scale_id". - " FROM ".TABLE_PREFIX."gradebook_tests g, ".TABLE_PREFIX."tests t". - " WHERE g.type='ATutor Test'". - " AND g.id = t.test_id". - " AND g.gradebook_test_id=".$_GET['gradebook_test_id'].")". - " UNION (SELECT g.gradebook_test_id, g.type, a.title, DATE_FORMAT(date_due, '%Y-%m-%d %H:%i:00') AS due_date, g.grade_scale_id". - " FROM ".TABLE_PREFIX."gradebook_tests g, ".TABLE_PREFIX."assignments a". - " WHERE g.type='ATutor Assignment'". - " AND g.id = a.assignment_id". - " AND g.gradebook_test_id=".$_GET['gradebook_test_id'].")". - " UNION (SELECT gradebook_test_id, type, title, DATE_FORMAT(due_date, '%Y-%m-%d %H:%i:00') AS due_date,grade_scale_id ". - " FROM ".TABLE_PREFIX."gradebook_tests". - " WHERE type='External'". - " AND gradebook_test_id=".$_GET['gradebook_test_id'].")"; -$result = mysql_query($sql, $db) or die(mysql_error()); -$row_this = mysql_fetch_assoc($result); - -if ($row_this["type"] == "External") -{ - $array1 = explode (' ', $row_this['due_date'], 2); - $array_date_due = explode ('-', $array1[0],3); - $array_time_due = explode (':', $array1[1]); - $today_year = $array_date_due[0]; - $today_mon = $array_date_due[1]; - $today_day = $array_date_due[2]; - $today_hour = $array_time_due[0]; - $today_min = $array_time_due[1]; - - if ($today_year == '0000') - { - $has_due_date = 'false'; - - // if due date is not set, use today's date as default - $today = getdate(); - $today_day = $today['mday']; - $today_mon = $today['mon']; - $today_year = $today['year']; - $today_hour = $today['hours']; - $today_min = $today['minutes']; - // round the minute to the next highest multiple of 5 - $today_min = round($today_min / '5' ) * '5' + '5'; - if ($today_min > '55') $today_min = '55'; - } - else - $has_due_date = 'true'; -} - -if ($has_due_date == 'false') $onload .= ' disable_dates (true, \'_due\');'; -require(AT_INCLUDE_PATH.'header.inc.php'); - -?> -
    -
    -
    - - -
    -
    *

    - " /> -
    - - -
    -
    - -
    - - -
    -
    - -
    - -
    -
    - - - - onfocus="disable_dates (true, '_due');" /> -
    - - onfocus="disable_dates (false, '_due');" /> - - - -
    - -
    - - -
    - -
    - -
    -
    - - - - diff --git a/mods/gradebook/gradebook_tests.php b/mods/gradebook/gradebook_tests.php deleted file mode 100644 index 6a6bac3c2..000000000 --- a/mods/gradebook/gradebook_tests.php +++ /dev/null @@ -1,129 +0,0 @@ -addError('NO_ITEM_SELECTED'); -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -?> - -
    - - - - - - - - - - - - - - - - - - - - - -'; - } - - if ($whole_scale_value <> '') $scale_content[$row_scale_ids["grade_scale_id"]] = $whole_scale_value; - } - // End of initialize scale content array - - while ($row = mysql_fetch_assoc($result)) - { -?> - '].checked = true; rowselect(this);" id="r_"> - - - - - - - - -
     
    -
    - - -
    -
    " id="m" />
    -
    - - diff --git a/mods/gradebook/html/grade_scale_add_edit.inc.php b/mods/gradebook/html/grade_scale_add_edit.inc.php deleted file mode 100644 index 7b03703c5..000000000 --- a/mods/gradebook/html/grade_scale_add_edit.inc.php +++ /dev/null @@ -1,227 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: grade_scale.php'); - exit; -} -else if (isset($_POST['submit'])) -{ - $_POST['scale_name'] = trim($_POST['scale_name']); - - $empty_fields = array(); - if ($_POST['scale_value'][0] == '') - { - $empty_fields[] = _AT('scale_value').' at line 1'; - } - - if ($_POST['percentage_from'][0] == '') - { - $empty_fields[] = _AT('percentage_from').' at line 1'; - } - - if ($_POST['percentage_to'][0] == '') - { - $empty_fields[] = _AT('percentage_to').' at line 1'; - } - - if (!empty($empty_fields)) - { - $msg->addError(array('EMPTY_FIELDS', implode(', ', $empty_fields))); - } - - if (!$msg->containsErrors()) - { - $_POST['scale_name'] = $addslashes($_POST['scale_name']); - - if ($action == "add") - { - $sql = "INSERT INTO ".TABLE_PREFIX."grade_scales - (member_id, scale_name, created_date) - VALUES (" . $_SESSION["member_id"] . ", '". $_POST["scale_name"] ."', now())"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - $grade_scale_id = mysql_insert_id(); - } - else if ($action == "edit" && isset($_POST["grade_scale_id"])) - { - $grade_scale_id = $_POST["grade_scale_id"]; - - $sql = "UPDATE ".TABLE_PREFIX."grade_scales - SET scale_name = '".$_POST["scale_name"]."' - WHERE grade_scale_id = ". $grade_scale_id; - $result = mysql_query($sql, $db) or die(mysql_error()); - - // clean up scale details for new insertions - $sql = "DELETE FROM ".TABLE_PREFIX."grade_scales_detail WHERE grade_scale_id = ". $grade_scale_id; - $result = mysql_query($sql, $db) or die(mysql_error()); - } - - for ($i=0; $i<10; $i++) - { - if ($_POST['scale_value'][$i] <> "") - { - $_POST['scale_value'][$i] = $addslashes(trim($_POST['scale_value'][$i])); - $_POST['percentage_from'][$i] = intval($_POST['percentage_from'][$i]); - $_POST['percentage_to'][$i] = intval($_POST['percentage_to'][$i]); - - $sql = "INSERT INTO ".TABLE_PREFIX."grade_scales_detail - (grade_scale_id, scale_value, percentage_from, percentage_to) - VALUES (" . $grade_scale_id . ", '". $_POST['scale_value'][$i] ."', ".$_POST['percentage_from'][$i].", ".$_POST['percentage_to'][$i].")"; - -// print $sql; - $result = mysql_query($sql, $db) or die(mysql_error()); - } - } - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: grade_scale.php'); - exit; - } -} -else if (isset($_POST['preset']) || ($action == 'edit' && isset($_REQUEST['grade_scale_id']))) -{ - if (isset($_POST['selected_grade_scale_id'])) - { - // clean up values preset previously - unset($_POST["scale_value"]); - unset($_POST["percentage_from"]); - unset($_POST["percentage_to"]); - } - - if (!$msg->containsErrors() && $_POST['selected_grade_scale_id'] > 0) - { - // load preset - $_POST['selected_grade_scale_id'] = intval($_POST['selected_grade_scale_id']); - $sql = "SELECT * FROM ".TABLE_PREFIX."grade_scales_detail d, ".TABLE_PREFIX."grade_scales g WHERE d.grade_scale_id = g.grade_scale_id AND d.grade_scale_id=".$_POST[selected_grade_scale_id]." ORDER BY percentage_to DESC"; - } - else if ($action == 'edit' && isset($_REQUEST['grade_scale_id'])) - { - // edit existing - $sql = "SELECT * FROM ".TABLE_PREFIX."grade_scales_detail d, ".TABLE_PREFIX."grade_scales g WHERE d.grade_scale_id = g.grade_scale_id AND d.grade_scale_id=".$_REQUEST['grade_scale_id']." ORDER BY percentage_to DESC"; - } - - $result = mysql_query($sql, $db) or die(mysql_error()); - - $i = 0; - while ($row = mysql_fetch_assoc($result)) - { - $_POST["scale_name"] = $row["scale_name"]; - $_POST["scale_value"][$i] = $row["scale_value"]; - $_POST["percentage_from"][$i] = $row["percentage_from"]; - $_POST["percentage_to"][$i] = $row["percentage_to"]; - - $i++; - } -} - -$onload = 'document.form.selected_grade_scale_id.focus();'; - -require(AT_INCLUDE_PATH.'header.inc.php'); -?> - -
    " method="post" name="form"> - - - -
    -
    - -
    - -
    - -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    - -
    - -
    - - - - - - - - - - - - - - - - - - -
    - - -
    *
    - - -
    - -
    *
    - - -
    - -
    *
    - - -
    %%
    -
    - -
    - - -
    -
    -
    -
    - - \ No newline at end of file diff --git a/mods/gradebook/import_export_external_marks.php b/mods/gradebook/import_export_external_marks.php deleted file mode 100644 index e62ba50c6..000000000 --- a/mods/gradebook/import_export_external_marks.php +++ /dev/null @@ -1,277 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: gradebook_tests.php'); - exit; -} -else if (isset($_POST['export'])) -{ - // generate students array - $sql = "SELECT m.first_name, m.last_name, m.email, e.member_id FROM ".TABLE_PREFIX."members m, ".TABLE_PREFIX."course_enrollment e WHERE m.member_id = e.member_id AND e.course_id=".$_SESSION["course_id"]." AND e.approved='y' AND e.role<>'Instructor' ORDER BY m.first_name,m.last_name,m.email"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - if (mysql_num_rows($result)==0) - { - // nothing to send. empty file - $msg->addError('ENROLLMENT_NONE_FOUND'); - } - else - { - $this_row = "First Name, Last Name, Email, Grade\n"; - while ($row = mysql_fetch_assoc($result)) - { - // retrieve title - $sql_title = "(SELECT g.gradebook_test_id, t.title". - " FROM ".TABLE_PREFIX."gradebook_tests g, ".TABLE_PREFIX."tests t". - " WHERE g.type='ATutor Test'". - " AND g.id = t.test_id". - " AND g.gradebook_test_id=".$_POST['gradebook_test_id'].")". - " UNION (SELECT g.gradebook_test_id, a.title". - " FROM ".TABLE_PREFIX."gradebook_tests g, ".TABLE_PREFIX."assignments a". - " WHERE g.type='ATutor Assignment'". - " AND g.id = a.assignment_id". - " AND g.gradebook_test_id=".$_POST['gradebook_test_id'].")". - " UNION (SELECT gradebook_test_id, title ". - " FROM ".TABLE_PREFIX."gradebook_tests". - " WHERE type='External'". - " AND gradebook_test_id=".$_POST['gradebook_test_id'].")"; - $result_title = mysql_query($sql_title, $db) or die(mysql_error()); - $row_title = mysql_fetch_assoc($result_title); - - // retrieve grade - $sql_grade = "SELECT grade FROM ".TABLE_PREFIX."gradebook_detail WHERE gradebook_test_id=".$_POST["gradebook_test_id"]." AND member_id=".$row["member_id"]; - $result_grade = mysql_query($sql_grade, $db) or die(mysql_error()); - $row_grade = mysql_fetch_assoc($result_grade); - $grade=$row_grade["grade"]; - - $this_row .= quote_csv($row['first_name']).","; - $this_row .= quote_csv($row['last_name']).","; - $this_row .= quote_csv($row['email']).","; - $this_row .= quote_csv($grade)."\n"; - } - header('Content-Type: text/csv'); - header('Content-transfer-encoding: binary'); - header('Content-Disposition: attachment; filename="grade_'.$row_title["title"].'.csv"'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Pragma: public'); - - echo $this_row; - exit; - } -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -?> -
    -
    -
    -
    -

    -
    - -
    - -
    - -
    -
    - -
    - -
    - - -
    - -
    -
    -
    - -

    - -
    -
    -
    -
    -

    -
    - - -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    - - -
    - -
    -
    -
    - - \ No newline at end of file diff --git a/mods/gradebook/lib/gradebook.inc.php b/mods/gradebook/lib/gradebook.inc.php deleted file mode 100644 index 0bf306350..000000000 --- a/mods/gradebook/lib/gradebook.inc.php +++ /dev/null @@ -1,489 +0,0 @@ - A+ - E -// [2] => Pass - Fail -// [3] => Excellent - Inadequate -// [grade_scale_id] => scale_value_max - scale_value_min (Value Explanation) -//) -define ('USE_HIGHER_GRADE', 1); -define ('USE_LOWER_GRADE', 2); -define ('NOT_OVERWRITE', 3); -define ('OVERWRITE', 4); - -function get_grade_scales_array($member_id = 0) -{ - global $db; - - $sql = "SELECT d.grade_scale_id, MIN(percentage_to) min, MAX(percentage_to) max FROM ".TABLE_PREFIX."grade_scales_detail d, ".TABLE_PREFIX."grade_scales g WHERE d.grade_scale_id = g.grade_scale_id AND g.member_id = ". $member_id ." GROUP BY d.grade_scale_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - $preset_grade_scales = array(); - while ($row = mysql_fetch_assoc($result)) - { - $sql_min = "SELECT scale_value FROM ".TABLE_PREFIX."grade_scales_detail WHERE grade_scale_id=".$row["grade_scale_id"]." AND percentage_to=".$row["min"]; - $result_min = mysql_query($sql_min, $db) or die(mysql_error()); - $row_min = mysql_fetch_assoc($result_min); - $min_value = $row_min['scale_value']; - - $sql_max = "SELECT scale_value FROM ".TABLE_PREFIX."grade_scales_detail WHERE grade_scale_id=".$row["grade_scale_id"]." AND percentage_to=".$row["max"]; - $result_max = mysql_query($sql_max, $db) or die(mysql_error()); - $row_max = mysql_fetch_assoc($result_max); - $max_value = $row_max['scale_value']; - - $preset_grade_scales[$row["grade_scale_id"]] = $max_value . " - ". $min_value; - } - - return $preset_grade_scales; -} - -// generate html of dropdown list box on preset grade scales and grade scales created by current member Id -// parameter: $selected_grade_scale_id: the grade_scale_id that need to set to be selected. -// return: html text -function print_grade_scale_selectbox($selected_grade_scale_id = 0, $id_name="selected_grade_scale_id") -{ -?> - - - '' && $out_of <> 0) // raw final score - $mark_in_percentage = $score / $out_of * 100; - - mysql_data_seek($result_grade, 0); - while ($row_grade = mysql_fetch_assoc($result_grade)) - { - if ($mark_in_percentage <= $row_grade['percentage_to'] && $mark_in_percentage >= $row_grade['percentage_from']) - $mark = $row_grade['scale_value']; - } - } - } - - // in case grade definition does not cover all scores - if ($mark == '') $mark = $default_mark; - - return $mark; -} - -function get_member_grade($test_id, $member_id, $grade_scale_id) -{ - global $db; - - require_once(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php'); - - $grade = ""; - - // find out final_score, out_of - $sql = "SELECT t.random, t.out_of, r.result_id, r.final_score FROM ".TABLE_PREFIX."tests t, ".TABLE_PREFIX."tests_results r WHERE t.test_id=".$test_id." AND t.test_id=r.test_id AND r.member_id=".$member_id; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - if (mysql_num_rows($result) > 0 && $row["final_score"] <> "") - { - if ($row['random']) { - $out_of = get_random_outof($test_id, $row['result_id']); - } else { - $out_of = $row['out_of']; - } - $grade = get_mark_by_grade($grade_scale_id, $row["final_score"], $out_of); - } - - return $grade; -} - -// Return array of students in the given course who take the given test more than once -// Parameter: $member_id, $test_id -// Return: an empty array or -//Array -//( -// [member_id1] => [num_takes1] -// [member_id2] => [num_takes2] -// ... -//) -function get_studs_take_more_than_once($course_id, $test_id) -{ - global $db; - - $rtn_array = array(); - - $sql = "SELECT m.first_name, m.last_name, count(result_id) num FROM ".TABLE_PREFIX."members m, ".TABLE_PREFIX."course_enrollment e, ".TABLE_PREFIX."tests_results t WHERE m.member_id = e.member_id AND e.course_id = ".$course_id." AND e.approved='y' AND e.role <> 'Instructor' AND e.member_id=t.member_id AND t.test_id=".$test_id." GROUP BY m.first_name, m.last_name having count(*) > 1"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - while ($row = mysql_fetch_assoc($result)) - $rtn_array[$row["first_name"]. " " . $row["last_name"]] = $row["num"]; - - return $rtn_array; -} - -// compare grades -// parameters: 2 grades to compare, grade_scale_id, "higher"/"lower": return higher or lower grade -// grade can be percentage like 70% or grade defined in grade_scale_id, like "A", "B"... -// return: higher or lower grade depending on 4th parameter -// or, -1 if grades are comparable -function compare_grades($grade1, $grade2, $gradebook_test_id, $mode = "higher") -{ - global $db; - - // get grade scale id - $sql = "SELECT grade_scale_id FROM ".TABLE_PREFIX."gradebook_tests WHERE gradebook_test_id = ".$gradebook_test_id; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - $grade_scale_id = $row["grade_scale_id"]; - - if ($grade_scale_id == 0) // compare raw scores - { - // retrieve raw score - $grade1 = trim(str_replace("%", "", $grade1)); - $grade2 = trim(str_replace("%", "", $grade2)); - - if ($grade1 > $grade2) return 1; - else if ($grade1 < $grade2) return -1; - else return 0; - } - else - { - $grade1 = get_mark_by_grade($grade_scale_id, $grade1); - $grade2 = get_mark_by_grade($grade_scale_id, $grade2); - - $grades = array(); - - $sql_grade = "SELECT scale_value from ".TABLE_PREFIX."grade_scales_detail WHERE grade_scale_id = ". $grade_scale_id. " ORDER BY percentage_to DESC"; - $result_grade = mysql_query($sql_grade, $db) or die(mysql_error()); - while ($row_grade = mysql_fetch_assoc($result_grade)) - { - $grades[] = $row_grade["scale_value"]; - } - - if (!in_array($grade1, $grades) || !in_array($grade2, $grades)) - return -1; // uncomparable - else - { - $grade1_key = array_search($grade1, $grades); - $grade2_key = array_search($grade2, $grades); - - if ($grade1_key > $grade2_key) - { - $higher_grade = $grade2; - $lower_grade = $grade1; - } - else if ($grade1_key < $grade2_key) - { - $higher_grade = $grade1; - $lower_grade = $grade2; - } - else $higher_grade = $lower_grade = $grade1; - } - } - - if ($mode == "higher") return $higher_grade; - else return $lower_grade; -} - -// check imported students and grades: -// 1. if the student exists in the class, if not, report error -// 2. if the grade already exists, if it is, report conflict -// parameter: an array of student/grade info -// Array -//( -// [member_id] => 1 -// [fname] => angelo (could be empty if [member_id] is given) -// [lname] => yuan (could be empty if [member_id] is given) -// [email] => angelo@hotmail.com (could be empty if [member_id] is given) -// [grade] => 70% -// [gradebook_test_id] => 4 -// [solve_conflict] => 0 -//) -// return: an array of processed student/grade/error info -// Array -//( -// [member_id] => 1 -// [fname] => angelo (could be empty if [member_id] is given) -// [lname] => yuan (could be empty if [member_id] is given) -// [email] => angelo@hotmail.com (could be empty if [member_id] is given) -// [grade] => 70% -// [gradebook_test_id] => 4 -// [solve_conflict] => 0 -// [error] => "Student not exists" -// [has_conflict] => 1 -//) -function check_user_info($record) -{ - global $db; - - $record['fname'] = htmlspecialchars(stripslashes(trim($record['fname']))); - $record['lname'] = htmlspecialchars(stripslashes(trim($record['lname']))); - $record['member_id'] = htmlspecialchars(stripslashes(trim($record['member_id']))); - $record['email'] = htmlspecialchars(stripslashes(trim($record['email']))); - $record['grade'] = htmlspecialchars(stripslashes(trim($record['grade']))); - - if (empty($record['remove'])) { - $record['remove'] = FALSE; - } - - if ($record['member_id'] == '') - { - $sql = "SELECT * FROM ".TABLE_PREFIX."members m, ".TABLE_PREFIX."course_enrollment e WHERE m.first_name='".$record['fname']."' AND m.last_name='".$record['lname']."' AND m.email='".$record['email']."' AND m.member_id = e.member_id AND e.course_id=".$_SESSION["course_id"]." AND e.approved='y' AND e.role<>'Instructor'"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - if (mysql_num_rows($result) == 0) - $record['error'] = _AT("student_not_exists"); - else - { - $row = mysql_fetch_assoc($result); - $record['member_id'] = $row["member_id"]; - } - } - - if ($record['error'] == "" && $record['member_id'] > 0) - { - $sql = "SELECT grade FROM ".TABLE_PREFIX."gradebook_detail WHERE gradebook_test_id=".$record['gradebook_test_id']. " AND member_id=".$record["member_id"]; - $result = mysql_query($sql, $db) or die(mysql_error()); - - if (mysql_num_rows($result) > 0 && $record['solve_conflict'] == 0) - { - $row = mysql_fetch_assoc($result); - $record['error'] = _AT("grade_already_exists", $row["grade"]); - $record['conflict'] = 1; - } - - if (mysql_num_rows($result) > 0 && $record['solve_conflict'] > 0) - { - $row = mysql_fetch_assoc($result); - - if ($record['solve_conflict'] == USE_HIGHER_GRADE || $record['solve_conflict'] == USE_LOWER_GRADE) - { - if ($record['solve_conflict'] == USE_HIGHER_GRADE) - $grade = compare_grades($record['grade'], $row['grade'], $record['gradebook_test_id'], "higher"); - - if ($record['solve_conflict'] == USE_LOWER_GRADE) - $grade = compare_grades($record['grade'], $row['grade'], $record['gradebook_test_id'], "lower"); - - if ($grade == -1) - { - $record["error"] = _AT("grades_uncomparable"); - $record['conflict'] = 1; - } - else - $record['grade'] = $grade; - } - - if ($record['solve_conflict'] == NOT_OVERWRITE) $record['grade'] = $row['grade']; - if ($record['solve_conflict'] == OVERWRITE) $record['grade'] = $record['grade']; - } - } - - if ($record['remove']) { - //unset errors - $record['error'] = ''; - } - - return $record; -} - -// update gradebook -function update_gradebook_external_test($students, $gradebook_test_id) -{ - global $db, $msg; - - foreach($students as $student) - { - if (!$student['remove']) - { - // retrieve member id - $sql = "SELECT member_id FROM ".TABLE_PREFIX."members m WHERE m.first_name='".$student['fname']."' AND m.last_name='".$student['lname']."' AND m.email='".$student['email']."'"; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - $member_id = $row["member_id"]; - - // retrieve grade scale id - $sql = "SELECT grade_scale_id FROM ".TABLE_PREFIX."gradebook_tests WHERE gradebook_test_id=".$gradebook_test_id; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - $grade_scale_id = $row["grade_scale_id"]; - - $grade = get_mark_by_grade($grade_scale_id, $student["grade"]); - $sql = "REPLACE INTO ".TABLE_PREFIX."gradebook_detail(gradebook_test_id, member_id, grade) VALUES(".$gradebook_test_id.", ".$member_id.", '".$grade."')"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - $updated_list .= '
  • ' . $student['fname'] . ', '. $student['lname']. ': '. $grade. '
  • '; - } - } - - if ($updated_list) - { - $feedback = array('GRADEBOOK_UPDATED', $updated_list); - $msg->addFeedback($feedback); - } -} - -// return median value of the given array -function median($grade_array) -{ - $oe_value = count($grade_array); - - if ($oe_value % 2 == 0 ) - $position = 1; - else - $position = 2; - - if ($position == 2 ) - $median = $grade_array[(count($grade_array)/2)]; - else - $median= $grade_array[(count($grade_array)/2)-1]; - - return $median; -} - -// return class average of the given test_id -function get_class_avg($gradebook_test_id) -{ - global $db; - - $sql = "SELECT * FROM ".TABLE_PREFIX."gradebook_tests WHERE gradebook_test_id=".$gradebook_test_id; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - if ($row["id"]<>0) // internal atutor test - { - require_once (AT_INCLUDE_PATH.'lib/test_result_functions.inc.php'); - - $sql_test = "SELECT * FROM ".TABLE_PREFIX."tests WHERE test_id=".$row["id"]; - $result_test = mysql_query($sql_test, $db) or die(mysql_error()); - $row_test = mysql_fetch_assoc($result_test); - - if ($row_test['out_of'] == 0 || $row_test['result_release']==AT_RELEASE_NEVER) - return _AT("na"); - - $sql_marks = "SELECT * FROM ".TABLE_PREFIX."tests_results WHERE test_id=".$row["id"]. " AND status=1"; - $result_marks = mysql_query($sql_marks, $db) or die(mysql_error()); - - $num_students = 0; - $total_final_score = 0; - $total_out_of = 0; - while ($row_marks = mysql_fetch_assoc($result_marks)) - { - if ($row_marks['final_score'] == '' ) continue; - - $num_students++; - $total_final_score += $row_marks["final_score"]; - - if ($row_test['random']) - $total_out_of += get_random_outof($row_marks['test_id'], $row_marks['result_id']); - else - $total_out_of += $row_test['out_of']; - } - - if ($num_students > 0) - { - $avg_final_score = round($total_final_score / $num_students); - $avg_out_of = round($total_out_of / $num_students); - } - - if ($avg_final_score <> "") - $avg_grade = get_mark_by_grade($row["grade_scale_id"], $avg_final_score, $avg_out_of); - else - $avg_grade = ""; - } - else // external test - { - $sql_grades = "SELECT * FROM ".TABLE_PREFIX."gradebook_detail WHERE gradebook_test_id=".$gradebook_test_id." ORDER BY grade"; - $result_grades = mysql_query($sql_grades, $db) or die(mysql_error()); - - $grade_array = array(); - while ($row_grades = mysql_fetch_assoc($result_grades)) - $grade_array[] = $row_grades["grade"]; - - $avg_grade = median($grade_array); - } - - if ($avg_grade == "") return _AT("na"); - else return $avg_grade; -} -?> diff --git a/mods/gradebook/module.php b/mods/gradebook/module.php deleted file mode 100644 index b776ba3d1..000000000 --- a/mods/gradebook/module.php +++ /dev/null @@ -1,100 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_GRADEBOOK', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -//$this->_stacks['gradebook'] = array('title_var'=>'gradebook', 'file'=>'mods/gradebook/side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('gradebook', array('title_var' => 'gradebook', 'file' => './side_menu.inc.php'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_student_tool = 'mods/gradebook/my_gradebook.php'; - -/******* - * add the admin pages when needed. - */ -//if (admin_authenticate(AT_ADMIN_PRIV_GRADEBOOK, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { -// $this->_pages[AT_NAV_ADMIN] = array('mods/gradebook/index_admin.php'); -// $this->_pages['mods/gradebook/index_admin.php']['title_var'] = 'gradebook'; -// $this->_pages['mods/gradebook/index_admin.php']['parent'] = AT_NAV_ADMIN; -//} - -/******* - * instructor Manage section: - */ -$this->_pages['mods/gradebook/gradebook_tests.php']['title_var'] = 'gradebook'; -$this->_pages['mods/gradebook/gradebook_tests.php']['parent'] = 'tools/index.php'; -$this->_pages['mods/gradebook/gradebook_tests.php']['guide'] = 'instructor/?p=gradebook.php'; -$this->_pages['mods/gradebook/gradebook_tests.php']['children'] = array('mods/gradebook/gradebook_add_tests.php', 'mods/gradebook/update_gradebook.php', 'mods/gradebook/import_export_external_marks.php', 'mods/gradebook/edit_marks.php', 'mods/gradebook/grade_scale.php'); - -$this->_pages['mods/gradebook/gradebook_add_tests.php']['title_var'] = 'add_tests'; -$this->_pages['mods/gradebook/gradebook_add_tests.php']['parent'] = 'mods/gradebook/gradebook_tests.php'; -$this->_pages['mods/gradebook/gradebook_add_tests.php']['guide'] = 'instructor/?p=gradebook_add.php'; - -$this->_pages['mods/gradebook/gradebook_edit_tests.php']['title_var'] = 'edit_tests'; -$this->_pages['mods/gradebook/gradebook_edit_tests.php']['parent'] = 'mods/gradebook/gradebook_tests.php'; - -$this->_pages['mods/gradebook/gradebook_delete_tests.php']['title_var'] = 'delete_test'; -$this->_pages['mods/gradebook/gradebook_delete_tests.php']['parent'] = 'mods/gradebook/gradebook_tests.php'; - -$this->_pages['mods/gradebook/update_gradebook.php']['title_var'] = 'update_gradebook'; -$this->_pages['mods/gradebook/update_gradebook.php']['parent'] = 'mods/gradebook/gradebook_tests.php'; -$this->_pages['mods/gradebook/update_gradebook.php']['guide'] = 'instructor/?p=gradebook_update.php'; - -$this->_pages['mods/gradebook/verify_tests.php']['title_var'] = 'update_list'; -$this->_pages['mods/gradebook/verify_tests.php']['parent'] = 'mods/gradebook/update_gradebook.php'; - -$this->_pages['mods/gradebook/import_export_external_marks.php']['title_var'] = 'import_export_external_marks'; -$this->_pages['mods/gradebook/import_export_external_marks.php']['parent'] = 'mods/gradebook/gradebook_tests.php'; -$this->_pages['mods/gradebook/import_export_external_marks.php']['guide'] = 'instructor/?p=gradebook_external_marks.php'; - -$this->_pages['mods/gradebook/verify_list.php']['title_var'] = 'update_list'; -$this->_pages['mods/gradebook/verify_list.php']['parent'] = 'mods/gradebook/import_export_external_marks.php'; - -$this->_pages['mods/gradebook/edit_marks.php']['title_var'] = 'edit_marks'; -$this->_pages['mods/gradebook/edit_marks.php']['parent'] = 'mods/gradebook/gradebook_tests.php'; -$this->_pages['mods/gradebook/edit_marks.php']['guide'] = 'instructor/?p=gradebook_edit_marks.php'; - -$this->_pages['mods/gradebook/grade_scale.php']['title_var'] = 'grade_scale'; -$this->_pages['mods/gradebook/grade_scale.php']['parent'] = 'mods/gradebook/gradebook_tests.php'; -$this->_pages['mods/gradebook/grade_scale.php']['guide'] = 'instructor/?p=gradebook_scales.php'; -$this->_pages['mods/gradebook/grade_scale.php']['children'] = array('mods/gradebook/grade_scale_add.php'); - -$this->_pages['mods/gradebook/grade_scale_add.php']['title_var'] = 'add_grade_scale'; -$this->_pages['mods/gradebook/grade_scale_add.php']['parent'] = 'mods/gradebook/grade_scale.php'; -$this->_pages['mods/gradebook/grade_scale_add.php']['guide'] = 'instructor/?p=gradebook_scales.php'; - -$this->_pages['mods/gradebook/grade_scale_edit.php']['title_var'] = 'edit_grade_scale'; -$this->_pages['mods/gradebook/grade_scale_edit.php']['parent'] = 'mods/gradebook/grade_scale.php'; - -$this->_pages['mods/gradebook/grade_scale_delete.php']['title_var'] = 'delete_grade_scale'; -$this->_pages['mods/gradebook/grade_scale_delete.php']['parent'] = 'mods/gradebook/grade_scale.php'; - -/******* - * student page. - */ -$this->_pages['mods/gradebook/my_gradebook.php']['title_var'] = 'gradebook'; -$this->_pages['mods/gradebook/my_gradebook.php']['img'] = 'mods/gradebook/gradebook.png'; - - -function gradebook_get_group_url($group_id) { - return 'mods/gradebook/index.php'; -} -?> \ No newline at end of file diff --git a/mods/gradebook/module.sql b/mods/gradebook/module.sql deleted file mode 100644 index 555afead4..000000000 --- a/mods/gradebook/module.sql +++ /dev/null @@ -1,108 +0,0 @@ -# sql file for gradebook module - -CREATE TABLE `grade_scales` ( - `grade_scale_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, - `member_id` mediumint(8) unsigned NOT NULL default '0', - `scale_name` VARCHAR(255) NOT NULL , - `created_date` datetime NOT NULL default '0000-00-00 00:00:00', - PRIMARY KEY ( `grade_scale_id` ) -); - -CREATE TABLE `grade_scales_detail` ( - `grade_scale_id` mediumint(8) unsigned NOT NULL, - `scale_value` VARCHAR(50) NOT NULL , - `percentage_from` MEDIUMINT NOT NULL default '0', - `percentage_to` MEDIUMINT NOT NULL default '0', - PRIMARY KEY (`grade_scale_id`, `scale_value`) -); - -CREATE TABLE `gradebook_tests` ( - `gradebook_test_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, - `id` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Values: 0, tests.test_id or assignments.assignment_id. 0 for external tests/assignments. tests.test_id for ATutor tests, assignments.assignment_id for ATutor assignments.', - `type` VARCHAR(50) NOT NULL default '' COMMENT 'Values: ATutor Test, ATutor Assignment, External', - `course_id` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Values: 0 or courses.course_id. Only has value for external tests/assignments. When ATutor internal assignments/tests/surveys, always 0.', - `title` VARCHAR(255) NOT NULL COMMENT 'Values: Null or test name. Always null if ATutor internal assignments/tests/surveys.', - `due_date` datetime NOT NULL default '0000-00-00 00:00:00', - `grade_scale_id` mediumint(8) unsigned NOT NULL default '0', - PRIMARY KEY ( `gradebook_test_id` ) -); - -CREATE TABLE `gradebook_detail` ( - `gradebook_test_id` mediumint(8) unsigned NOT NULL, - `member_id` mediumint(8) unsigned NOT NULL default '0', - `grade` VARCHAR(255) NOT NULL, - PRIMARY KEY (`gradebook_test_id`, `member_id`) -); - -INSERT INTO `grade_scales` (grade_scale_id, member_id, scale_name, created_date) values (1, 0, 'Letter Grade', now()); -INSERT INTO `grade_scales` (grade_scale_id, member_id, scale_name, created_date) values (2, 0, 'Competency 1', now()); -INSERT INTO `grade_scales` (grade_scale_id, member_id, scale_name, created_date) values (3, 0, 'Competency 2', now()); - -INSERT INTO `grade_scales_detail` (grade_scale_id, scale_value, percentage_from, percentage_to) values (1, 'A+', 90, 100); -INSERT INTO `grade_scales_detail` (grade_scale_id, scale_value, percentage_from, percentage_to) values (1, 'A', 80, 89); -INSERT INTO `grade_scales_detail` (grade_scale_id, scale_value, percentage_from, percentage_to) values (1, 'B', 70, 79); -INSERT INTO `grade_scales_detail` (grade_scale_id, scale_value, percentage_from, percentage_to) values (1, 'C', 60, 69); -INSERT INTO `grade_scales_detail` (grade_scale_id, scale_value, percentage_from, percentage_to) values (1, 'D', 50, 59); -INSERT INTO `grade_scales_detail` (grade_scale_id, scale_value, percentage_from, percentage_to) values (1, 'E', 0, 49); - -INSERT INTO `grade_scales_detail` (grade_scale_id, scale_value, percentage_from, percentage_to) values (2, 'Pass', 75, 100); -INSERT INTO `grade_scales_detail` (grade_scale_id, scale_value, percentage_from, percentage_to) values (2, 'Fail', 0, 74); - -INSERT INTO `grade_scales_detail` (grade_scale_id, scale_value, percentage_from, percentage_to) values (3, 'Excellent', 80, 100); -INSERT INTO `grade_scales_detail` (grade_scale_id, scale_value, percentage_from, percentage_to) values (3, 'Good', 70, 79); -INSERT INTO `grade_scales_detail` (grade_scale_id, scale_value, percentage_from, percentage_to) values (3, 'Adequate', 60, 69); -INSERT INTO `grade_scales_detail` (grade_scale_id, scale_value, percentage_from, percentage_to) values (3, 'Inadequate', 0, 59); - - -INSERT INTO `language_text` VALUES ('en', '_module','gradebook','Gradebook',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','grade_scale','Grade Scale',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','add_grade_scale','Add Grade Scale',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','edit_grade_scale','Edit Grade Scale',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','delete_grade_scale','Delete Grade Scale',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','custom_grade_scale','Custom Grade Scale',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','preset_grade_scale','Preset Grade Scale',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','custom','Custom',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','scale','Scale',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','scale_value','Scale Value',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','percentage_from','Percentage From',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','percentage_to','Percentage To',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','scale','Scale',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','grade','Grade',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','edit_marks','Edit Marks',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','add_tests','Add Tests/Assignments',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','edit_tests','Edit Tests/Assignments',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','add_atutor_test','Add ATutor Assignments/Test/Surveys',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','add_external_test','Add External Assignments/Tests',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','all_atutor_tests','All Applicable ATutor Tests & Surveys',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','all_atutor_assignments','All ATutor Assignments',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','add_atutor_test_info','Select from the available test and assignment titles, then optionally choose a "Grade Scale", to add a test or assignment to the gradebook. . If "Grade Scale" is set to none, the raw final score will be used in place of a grade scale. Only tests with the test property "Attempts Allowed" set to 1 can be added to the Gradebook. Create tests using the ATutor Tests & Surveys Manager',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','raw_final_score','Raw Final Score',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','update_gradebook','Update ATutor Marks',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','import_export_external_marks','External Marks',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','export_marks_info','To simplify the import process, you can export an empty csv file on the test you want to import, fill in the marks, import back into ATutor.',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','import_marks_info','A mark list may be imported into ATutor. Create the mark list in a comma separated values (CSV) format as follows: "firstname", "lastname", "email", "mark" with one student per line. Please leave the first line as title. The mark in CSV file can be grade or percentage like 50%%. To simplify the process, you can export the CSV file with export functionality, update the marks into exported file and import back into ATutor.',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','student_not_exists','Student not exists',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','empty_gradebook','Gradebook is empty.',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','completed_date','Completed Date',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','your_mark','Your Mark',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','class_avg','Class Avg',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','completed','Completed',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','external_tests','External Tests',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','grade_already_exists','Conflict: Grade already exists - %s',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','how_to_solve_conflict','How to solve conflict',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','use_higher_grade','Use higher grade',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','use_lower_grade','Use lower grade',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','not_overwrite','Not overwrite',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','grades_uncomparable','Grades are uncomparable. Choose another way to solve conflict',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','combine_tests','Combine ATutor Tests',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','combine','Combine',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','combine_into','Combine Into',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','combine_from','Combine From',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','combine_tests_info','Before combining tests, please run section above to update marks of "Combine Into Test/Survey."',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_template','grade_info','Note: "Grade" field can be grade defined in "Grade Scale" or percentage like 50%%.',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_CONFIRM_DELETE_GRADE_SCALE','Are you sure you want to delete grade scale %s?',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_CONFIRM_DELETE_TEST_FROM_GRADEBOOK','Are you sure you want to delete test %s from gradebook?',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_ADD_TEST_INTO_GRADEBOOK', '"%1$s" cannot be added into gradebook because the following students have taken it more than once:
    \r\n%2$s.',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_COMBINE_TESTS', '"%1$s" cannot be combined because the following students have taken it more than once:
    \r\n%2$s.',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_UPDATE_GRADEBOOK', '"%1$s" cannot be updated into gradebook because the following students have taken it more than once:
    \r\n%2$s.',NOW(),'gradebook'); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_GRADEBOOK_UPDATED', 'The following grades have been successfully updated into gradebook:
      %s
    ',NOW(),'gradebook'); diff --git a/mods/gradebook/module.xml b/mods/gradebook/module.xml deleted file mode 100644 index 8c2daab37..000000000 --- a/mods/gradebook/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Gradebook - The Gradebook allows instructors to automatically gather scores from tests and quizzes taken through the ATutor Test Manager, and allows them to define external tests or assignments and manually record marks for those. It will allow students to view their marks for completed tests or assignments, list tests or assignments yet to be completed or yet to be marked, and print out a report of their marks. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.1 - 2008-05-27 - stable - - - \ No newline at end of file diff --git a/mods/gradebook/module_install.php b/mods/gradebook/module_install.php deleted file mode 100644 index 1f9e34a54..000000000 --- a/mods/gradebook/module_install.php +++ /dev/null @@ -1,67 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -//} else if (!is_writable($directory) && @chmod($directory, 0666)) { -// $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -//} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/gradebook/my_gradebook.php b/mods/gradebook/my_gradebook.php deleted file mode 100644 index b067d70b4..000000000 --- a/mods/gradebook/my_gradebook.php +++ /dev/null @@ -1,131 +0,0 @@ - - -
    - - - - - - - - - - - - - - - - - - - - "") - { - $sql_tr = "SELECT R.result_id, R.date_taken, (UNIX_TIMESTAMP(R.end_time) - UNIX_TIMESTAMP(R.date_taken)) AS diff FROM ".TABLE_PREFIX."tests_results R WHERE R.status=1 AND R.test_id=".$row["id"]." AND R.member_id=".$_SESSION[member_id]; - $result_tr = mysql_query($sql_tr, $db) or die(mysql_error()); - $row_tr = mysql_fetch_assoc($result_tr); - } -?> - -'.$row["title"].''."\n\r"; - else - echo ' '."\n\r"; -?> - - - - - - - - - - - - - - - - - - -
    '.$row["title"].'
    -
    - - diff --git a/mods/gradebook/update_gradebook.php b/mods/gradebook/update_gradebook.php deleted file mode 100644 index 241991185..000000000 --- a/mods/gradebook/update_gradebook.php +++ /dev/null @@ -1,294 +0,0 @@ - $num) - { - if ($no_error) $no_error = false; - $error_msg .= $student . ": " . $num . " times
    "; - } - - if (!$no_error) - { - $f = array('UPDATE_GRADEBOOK', - $row['title'], - $error_msg); - $msg->addFeedback($f); - } - - if ($no_error) - return true; - else - return false; -} - -function update_gradebook($gradebook_test_id, $member_id) -{ - global $db; - - $sql = "SELECT id, grade_scale_id FROM ".TABLE_PREFIX."gradebook_tests WHERE gradebook_test_id = ". $gradebook_test_id; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - $test_id = $row["id"]; - $grade_scale_id = $row["grade_scale_id"]; - - // get grade - $grade = get_member_grade($test_id, $member_id, $grade_scale_id); - - if ($grade <> "") - { - $sql = "REPLACE INTO ".TABLE_PREFIX."gradebook_detail(gradebook_test_id, member_id, grade) VALUES (".$gradebook_test_id.", ".$member_id.", '".$grade."')"; - $result = mysql_query($sql, $db) or die(mysql_error()); - } -} - -// Initialize all applicable tests array and all enrolled students array -$tests = array(); -$students = array(); - -// generate gradebook test array -$sql = "SELECT *, t.title FROM ".TABLE_PREFIX."gradebook_tests g, ".TABLE_PREFIX."tests t WHERE g.id = t.test_id AND g.type='ATutor Test' AND t.course_id=".$_SESSION["course_id"]; -$result = mysql_query($sql, $db) or die(mysql_error()); -while ($row = mysql_fetch_assoc($result)) -{ - $test["gradebook_test_id"] = $row["gradebook_test_id"]; - $test["title"] = $row["title"]; - - array_push($tests, $test); -} - -// generate students array -$sql = "SELECT m.first_name, m.last_name, e.member_id FROM ".TABLE_PREFIX."members m, ".TABLE_PREFIX."course_enrollment e WHERE m.member_id = e.member_id AND e.course_id=".$_SESSION["course_id"]." AND e.approved='y' AND e.role<>'Instructor' ORDER BY m.first_name,m.last_name"; -$result = mysql_query($sql, $db) or die(mysql_error()); - -while ($row = mysql_fetch_assoc($result)) -{ - $student["first_name"] = $row["first_name"]; - $student["last_name"] = $row["last_name"]; - $student["member_id"] = $row["member_id"]; - - array_push($students, $student); -} -// end of initialization - -if (isset($_POST['cancel'])) -{ - $msg->addFeedback('CANCELLED'); - header('Location: gradebook_tests.php'); - exit; -} -else if (isset($_POST['update'])) -{ - if (!$msg->containsErrors()) - { - if ($_POST["gradebook_test_id"] == 0) - { - foreach($tests as $test) - { - if (is_test_updatable($test["gradebook_test_id"])) - { - if ($_POST["member_id"]==0) - { - // delete old data for this test - $sql = "DELETE from ".TABLE_PREFIX."gradebook_detail WHERE gradebook_test_id = ".$test["gradebook_test_id"]; - $result = mysql_query($sql, $db) or die(mysql_error()); - - foreach($students as $student) - update_gradebook($test["gradebook_test_id"], $student["member_id"]); - } - else - update_gradebook($test["gradebook_test_id"], $_POST["member_id"]); - } - } - } - else - { - if (is_test_updatable($_POST["gradebook_test_id"])) - { - if ($_POST["member_id"]==0) - { - // delete old data for this test - $sql = "DELETE from ".TABLE_PREFIX."gradebook_detail WHERE gradebook_test_id = ".$_POST["gradebook_test_id"]; - $result = mysql_query($sql, $db) or die(mysql_error()); - - foreach($students as $student) - update_gradebook($_POST["gradebook_test_id"], $student["member_id"]); - } - else - update_gradebook($_POST["gradebook_test_id"], $_POST["member_id"]); - } - } - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - } -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -?> -
    -
    -
    - - -
    - -
    -'."\n\r"; - echo '
    '."\n\r"; - echo ' '."\n\r"; - echo '
    '."\n\r"; - - // list of students - echo '
    '."\n\r"; - echo '
    '."\n\r"; - echo ' '."\n\r"; - echo '
    '."\n\r"; -?> - -
    - - -
    - -
    -| -| -|

    -

    &o=(`@N*Ykn>KkSp9&AnFMVs#xx*)J27Z3h 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≪Ktt{ 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 cW=@#p#qC^@ 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

    - -
    - - -
    -
    -
    -
    -

    -
    - - -
    - -
    -'."\n\r"; - echo '
    '."\n\r"; - echo ' '."\n\r"; - echo '
    '."\n\r"; - - // list of atutor tests that can be combined. - // These tests can only be taken once and are not in gradebook yet - // note: surveys are excluded by checking if question weights are defined - $sql_at = "SELECT * FROM ".TABLE_PREFIX."tests t". - " WHERE course_id=".$_SESSION["course_id"]. - " AND num_takes = 1". - " AND NOT EXISTS (SELECT 1". - " FROM ".TABLE_PREFIX."gradebook_tests g". - " WHERE g.id = t.test_id". - " AND g.type='ATutor Test')". - " AND test_id IN (SELECT test_id FROM ".TABLE_PREFIX."tests_questions_assoc ". - " WHERE weight > 0 ". - " GROUP BY test_id ". - " HAVING count(*) > 1) ". - " ORDER BY title"; - $result_at = mysql_query($sql_at, $db) or die(mysql_error()); - - if (mysql_num_rows($result_at) == 0) - echo _AT('none_found'); - else - { - echo '
    '."\n\r"; - echo '
    '."\n\r"; - echo ' '."\n\r"; - echo '
    '."\n\r"; - } -?> - -
    - - -
    - - - - -
    - - diff --git a/mods/gradebook/verify_list.php b/mods/gradebook/verify_list.php deleted file mode 100644 index 97ae62048..000000000 --- a/mods/gradebook/verify_list.php +++ /dev/null @@ -1,201 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: import_export_external_marks.php'); - exit; -} -else if (isset($_POST['import'])) -{ - //IMPORT - if ($_FILES['file']['size'] < 1) - { - $msg->addError('FILE_EMPTY'); - header('Location: import_course_list.php'); - exit; - } - else - { - $fp = fopen($_FILES['file']['tmp_name'],'r'); - $line_number=0; - while ($data = fgetcsv($fp, 100000, ',')) { - $line_number++; - if ($line_number > 1) - { - $num_fields = count($data); - if ($num_fields == 4) - { - $students[] = check_user_info(array('fname' => $data[0], 'lname' => $data[1], 'email' => $data[2], 'grade' => $data[3], 'gradebook_test_id' => $_POST['gradebook_test_id'])); - } - else if ($num_fields != 1) - { - $errors = array('INCORRECT_FILE_FORMAT', $line_number); - $msg->addError($errors); - header('Location: import_course_list.php'); - exit; - } - else if (($num_fields == 1) && (trim($data[0]) != '')) - { - $errors = array('INCORRECT_FILE_FORMAT', $line_number); - $msg->addError($errors); - header('Location: import_course_list.php'); - exit; - } - } - } - } -} -/************* INFO GATHERED **************/ - -if ($_POST['verify']) { - for ($i=0; $i < $_POST['count']; $i++) - { - $info = array('fname' => $_POST['fname'.$i], 'lname' => $_POST['lname'.$i], 'email' => $_POST['email'.$i], 'grade' => $_POST['grade'.$i], 'remove' => $_POST['remove'.$i], 'gradebook_test_id' => $_POST["gradebook_test_id"], 'solve_conflict' => $_POST["solve_conflict"]); - $students[] = check_user_info($info); - - if (!empty($students[$i]['error'])) - $still_errors = TRUE; - } - - /**************************************************************************/ - // !!!!!!STEP 3 - INSERT INTO DB !!!!!!! - if (!$still_errors && isset($_POST['update'])) - { - update_gradebook_external_test($students, $_POST["gradebook_test_id"]); - header('Location: import_export_external_marks.php'); - exit; - } -} - -require(AT_INCLUDE_PATH.'header.inc.php'); -// STEP 2 - INTERNAL VERIFICATION -if ($still_errors || !isset($_POST['verify']) || isset($_POST['resubmit'])) { -?> - -
    -
    -
    -

    -
    -
    - - - " /> - " /> - - - - - - - - - - - - - -'."\n\r"; - foreach ($students as $student) { - - if (!empty($student['conflict'])) - $has_conflict = TRUE; - - echo ' '."\n\r"; - echo ' '."\n\r"; - - echo ' '."\n\r"; - echo ' '."\n\r"; - echo ' '."\n\r"; - echo ' '."\n\r"; - echo ' '."\n\r"; - - $i++; - echo ' '."\n\r"; - } - echo ' '."\n\r"; - } - - $dsbld = ''; - if ($still_errors || $err_count>0) { - $dsbld = 'disabled="disabled"'; - } -?> - - - - - - - -
    '."\n\r"; - - //give status - if(!empty($student['error'])) { - echo ''.$student['error']; - } - - if (empty($student['error'])) - { - if ($student['remove']) - echo ''._AT('removed'); - else - echo ''._AT('ok'); - } - else - $err_count++; - - echo '
    - - /> - - | - - - -
    -
    \ No newline at end of file diff --git a/mods/gradebook/verify_tests.php b/mods/gradebook/verify_tests.php deleted file mode 100644 index f84a9257e..000000000 --- a/mods/gradebook/verify_tests.php +++ /dev/null @@ -1,225 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: update_gradebook.php'); - exit; -} -else if (isset($_POST['combine'])) -{ - //Check if the "combine from test" has students taking it more than once - $no_error = true; - - $sql = "SELECT title FROM ".TABLE_PREFIX."tests WHERE test_id=".$_POST["test_id"]; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - $studs_take_num = get_studs_take_more_than_once($_SESSION["course_id"], $_POST["test_id"]); - - foreach ($studs_take_num as $student => $num) - { - if ($no_error) $no_error = false; - $error_msg .= $student . ": " . $num . " times
    "; - } - - if (!$no_error) - { - $error = array('COMBINE_TESTS', - $row["title"], - $error_msg); - $msg->addError($error); - } - - if (!$msg->containsErrors()) - { - $sql = "SELECT id, grade_scale_id FROM ".TABLE_PREFIX."gradebook_tests WHERE gradebook_test_id = ". $_POST["gradebook_test_id"]; - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result) or die(mysql_error()); - $grade_scale_id = $row["grade_scale_id"]; - - $sql = "SELECT m.first_name, m.last_name, m.email, e.member_id FROM ".TABLE_PREFIX."members m, ".TABLE_PREFIX."course_enrollment e WHERE m.member_id = e.member_id AND e.course_id=".$_SESSION["course_id"]." AND e.approved='y' AND e.role<>'Instructor' ORDER BY m.first_name,m.last_name"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - while ($row = mysql_fetch_assoc($result)) - { - $grade = get_member_grade($_POST["test_id"], $row["member_id"], $grade_scale_id); - - if ($grade <> "") - $students[] = check_user_info(array('member_id' => $row["member_id"], 'fname' => $row["first_name"], 'lname' => $row["last_name"], 'email' => $row["email"], 'grade' => $grade, 'gradebook_test_id' => $_POST['gradebook_test_id'])); - } - - if (count($students) == 0) - { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: update_gradebook.php'); - exit; - } - - } - else - { - header('Location: update_gradebook.php'); - exit; - } -} - -/************* INFO GATHERED **************/ - -if ($_POST['verify']) { - for ($i=0; $i < $_POST['count']; $i++) - { - $info = array('fname' => $_POST['fname'.$i], 'lname' => $_POST['lname'.$i], 'email' => $_POST['email'.$i], 'grade' => $_POST['grade'.$i], 'remove' => $_POST['remove'.$i], 'gradebook_test_id' => $_POST["gradebook_test_id"], 'solve_conflict' => $_POST["solve_conflict"]); - $students[] = check_user_info($info); - - if (!empty($students[$i]['error'])) - $still_errors = TRUE; - } - - /**************************************************************************/ - // !!!!!!STEP 3 - INSERT INTO DB !!!!!!! - - if (!$still_errors && isset($_POST['update'])) - { - update_gradebook_external_test($students, $_POST["gradebook_test_id"]); - header('Location: update_gradebook.php'); - exit; - } -} - -require(AT_INCLUDE_PATH.'header.inc.php'); -// STEP 2 - INTERNAL VERIFICATION -if ($still_errors || !isset($_POST['verify']) || isset($_POST['resubmit'])) { -?> - -
    -
    -
    -

    -
    -
    - - - " /> - " /> - " /> - - - - - - - - - - - - - -'."\n\r"; - foreach ($students as $student) { - - if (!empty($student['conflict'])) - $has_conflict = TRUE; - - echo ' '."\n\r"; - echo ' '."\n\r"; - - echo ' '."\n\r"; - echo ' '."\n\r"; - echo ' '."\n\r"; - echo ' '."\n\r"; - echo ' '."\n\r"; - - echo ' '."\n\r"; - echo ' '."\n\r"; - echo ' '."\n\r"; - - $i++; - echo ' '."\n\r"; - } - echo ' '."\n\r"; - } - - $dsbld = ''; - if ($still_errors || $err_count>0) { - $dsbld = 'disabled="disabled"'; - } -?> - - - - - - - -
    '."\n\r"; - - //give status - if(!empty($student['error'])) { - echo ''.$student['error']; - } - - if (empty($student['error'])) - { - if ($student['remove']) - echo ''._AT('removed'); - else - echo ''._AT('ok'); - } - else - $err_count++; - - echo ''.$student['fname'].''.$student['lname'].''.$student['email'].'
    - - /> - - | - - - -
    -
    \ No newline at end of file diff --git a/mods/hello_world/ModuleCallbacks.class.php b/mods/hello_world/ModuleCallbacks.class.php deleted file mode 100644 index 5e1437d4a..000000000 --- a/mods/hello_world/ModuleCallbacks.class.php +++ /dev/null @@ -1,27 +0,0 @@ - \ No newline at end of file diff --git a/mods/hello_world/content_tool_action.js b/mods/hello_world/content_tool_action.js deleted file mode 100644 index 01f11d011..000000000 --- a/mods/hello_world/content_tool_action.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * This javascript is to perform the functionalities that are required to implement - * the add-on content tool. - * - * Register this javascript @ module.php => $this->_content_tools["js"] - */ - -/*global jQuery*/ -/*global ATutor */ -/*global tinyMCE */ -/*global window */ - -ATutor = ATutor || {}; -ATutor.mods = ATutor.mods || {}; -ATutor.mods.hello_world = ATutor.mods.hello_world || {}; - -(function () { - var helloWorldOnClick = function () { - alert("Clicked on hello world tool icon!"); - } - - //set up click handlers and show/hide appropriate tools - var initialize = function () { - jQuery("#helloworld_tool").click(helloWorldOnClick); - }; - - jQuery(document).ready(initialize); -})(); \ No newline at end of file diff --git a/mods/hello_world/hello_world.jpg b/mods/hello_world/hello_world.jpg deleted file mode 100644 index c6cf71b3be9da5b70601ca2f24e175ddb011b565..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1827 zcmbW!X;hO}8VB$<%S*@xWJ7|%C?XW5ku5TaHZcl8P!5}eEQ2Xq3bg2vMLO3KF!SkKKFjP%Xxn1>R#w3 z0TXYw7aM>;005#NfNlcV2f(1v_0k8fFVGMK;cyUzKo}TeP#6pvg+^nI@FrLzoDmvr zVrqgT5J@Bw#(0C7DbWm1BoWsifxz^4;2;tNkwh#SOZ=as>i}?ufGt3SK`a3%4g$kL zbX@>d-zNz9HNfwIK=nNuAPkWxwEjS|2>^w_U{E-0y=(pHO#MCp$AS1Qjw}O$e+0tv zIMFGmxXN(r-o{Q+z>|3^=g7oUNR;UYGqU+MYnxAO?dUsP{_48ZZJ)ab+jGB{ci^GF z1sx6!35|-5;eHVt7oU`zaw0V?{p9I0x!>gdBmZnk>9-fl$}28izFu8(<7Vxx+jp7- z!e&v+{nj6(54*a1dix&zI5PV5+4Hd%<1)EI`FiTjFK?%3R15$7*GKiDW@&ld1p#2c zvGnV2u>Wx3^e!kI4ud1sT@Yxhe!_5YaEqe>p5>2-I8Ly1$}uGFEv{$G2G{~heq|0Vka_NPk*U|P9gr{1nry(P z^>cKQK%Du=l(gtB!gwUYp;ZVdZRp3%hp&B(PxR7@Frz)@B z)dBNdUVD`G(-pQzED&?B9p!Oac6*^LTo@7GT247i> zijyYWQE6En%azv}VxRcldh6!#;A&BvOKk!;;6(R7r4l>2+9f(S=MCKPM<|2?XUCd-sU{`-6PDua=pe?Sy1w%8PyJH8VkD>V?8bG~r!K2leI) zU)I4L`d%Ma(Ao=mEUkk^r0l8Oq^c}c#QKblH(L-6JPm&=?VTzsaW7`ery9}p=2|^zb^3_q_xA~*92P~@o>&QOq}>8DTF|9jd|)=k2H)4D6x` z7>%nBGScP7`EHA+lHavXwUv60CJ2}6yB7LJeC$@QKMx9cKRW;ef=dfZdoTJR;Z6D$*-((bId?u;CIjZq;;g&oerQ z{6aQ#^75g97IoPjOiK{{_JN90*Cn;ZyS`mYR&lWZ@j~}E_s-STOgAIAX^)EvB-UxD z#fPu9sHo?~{)%J9K8}|&b|x2Eb*6HkRE$@D=_>x&iEP2O6F2RdAqv0-Q1e0Yff7Hq z+*6yb2-5)@(!zY6`#gJ46Xc)+V!Agr{WLxI#uL9ZV_AZ)8~L8g-Z|uZQ({g<^Mae^ zA1`IRjG4nMn)`)?n0uAEjBgVU^hJ5Z7K)sQUZJ`ml}YNtd1s!jCP6uomB+wl!n{>b zWw@lwmVDw?x_7m(!XwbCrY<&$w(G(Hvg4eGUv2(5f1ecJn0xP*U;R@0I4GG)=g+KM zTFO<~ciZn+R6i&QlPO}Hrq@FJk#J=^KI?>Mf9LM#P2#nD9nk5#;+ttdt2~Cu6}M%K zE6>>!Rz_|5EXV3=($cDm(6yY^WjiNy-A&GnQ0M@Gb$No?YnYWNm0w8;tGGCv{#CZ) z(Szxmqm>`4)s7mx4!}x~apv^f+PA~I>k!zjF;{iK&+cQ^48h&Npwx)XRal(*vzWBJ zJuPFiR-$XLy9J*=uP04e^!9}=c5uvj+f~^2g88AY!*2K^yB?+1xGgQGOgNBJTaLo6 z8do}<&uF9sxwI;aWSk?TZ$@w{7B_q8Ttu5_*gAbL?sN{VziP#=C|*kq(0Gwp}=LHTdqgH*9Q9xOTG=yF;kD@qYuuZZI+c diff --git a/mods/hello_world/index.php b/mods/hello_world/index.php deleted file mode 100644 index 111bd831f..000000000 --- a/mods/hello_world/index.php +++ /dev/null @@ -1,12 +0,0 @@ - - -
    - Hello Student!! :) -
    - - \ No newline at end of file diff --git a/mods/hello_world/index_admin.php b/mods/hello_world/index_admin.php deleted file mode 100644 index f8f43bda9..000000000 --- a/mods/hello_world/index_admin.php +++ /dev/null @@ -1,10 +0,0 @@ - - -Hello Administrator!! :) - - \ No newline at end of file diff --git a/mods/hello_world/index_instructor.php b/mods/hello_world/index_instructor.php deleted file mode 100644 index bf2d484c8..000000000 --- a/mods/hello_world/index_instructor.php +++ /dev/null @@ -1,10 +0,0 @@ - - -Hello Instructor!! :) - - \ No newline at end of file diff --git a/mods/hello_world/index_mystart.php b/mods/hello_world/index_mystart.php deleted file mode 100644 index c3f7b7bba..000000000 --- a/mods/hello_world/index_mystart.php +++ /dev/null @@ -1,13 +0,0 @@ - - -
    - 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 :) -
    - - \ No newline at end of file diff --git a/mods/hello_world/index_public.php b/mods/hello_world/index_public.php deleted file mode 100644 index fa3f2e63f..000000000 --- a/mods/hello_world/index_public.php +++ /dev/null @@ -1,15 +0,0 @@ - - -
    - This is a public page from the Hello World module, that does not require a login session to view. :) -
    - - \ No newline at end of file diff --git a/mods/hello_world/module.css b/mods/hello_world/module.css deleted file mode 100644 index 15da01381..000000000 --- a/mods/hello_world/module.css +++ /dev/null @@ -1,11 +0,0 @@ -div#helloworld { - border: 1px solid #ccc; - padding: 10px; - width: 50%; - margin-right: auto; - margin-left: auto; - background-color: #efefef; - color: #444; - margin-top: 30px; - margin-bottom: 30px; -} \ No newline at end of file diff --git a/mods/hello_world/module.php b/mods/hello_world/module.php deleted file mode 100644 index 48b46f9cf..000000000 --- a/mods/hello_world/module.php +++ /dev/null @@ -1,110 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_HELLO_WORLD', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -$this->_stacks['hello_world'] = array('title_var'=>'hello_world', 'file'=>'mods/hello_world/side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('hello_world', array('title_var' => 'hello_world', 'file' => './side_menu.inc.php'); - -/******* - * create optional sublinks for module "detail view" on course home page - * when this line is uncommented, "mods/hello_world/sublinks.php" need to be created to return an array of content to be displayed - */ -//$this->_list['hello_world'] = array('title_var'=>'hello_world','file'=>'mods/hello_world/sublinks.php'); - -// Uncomment for tiny list bullet icon for module sublinks "icon view" on course home page -//$this->_pages['mods/hello_world/index.php']['icon'] = 'mods/hello_world/hello_world_sm.jpg'; - -// Uncomment for big icon for module sublinks "detail view" on course home page -//$this->_pages['mods/hello_world/index.php']['img'] = 'mods/hello_world/hello_world.jpg'; - -// ** possible alternative: ** -// the text to display on module "detail view" when sublinks are not available -$this->_pages['mods/hello_world/index.php']['text'] = _AT('hello_world_text'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_group_tool = $_student_tool = 'mods/hello_world/index.php'; - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_HELLO_WORLD, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/hello_world/index_admin.php'); - $this->_pages['mods/hello_world/index_admin.php']['title_var'] = 'hello_world'; - $this->_pages['mods/hello_world/index_admin.php']['parent'] = AT_NAV_ADMIN; -} - -/******* - * instructor Manage section: - */ -$this->_pages['mods/hello_world/index_instructor.php']['title_var'] = 'hello_world'; -$this->_pages['mods/hello_world/index_instructor.php']['parent'] = 'tools/index.php'; -// ** possible alternative: ** -// $this->pages['./index_instructor.php']['title_var'] = 'hello_world'; -// $this->pages['./index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages['mods/hello_world/index.php']['title_var'] = 'hello_world'; -$this->_pages['mods/hello_world/index.php']['img'] = 'mods/hello_world/hello_world.jpg'; - -/* public pages */ -$this->_pages[AT_NAV_PUBLIC] = array('mods/hello_world/index_public.php'); -$this->_pages['mods/hello_world/index_public.php']['title_var'] = 'hello_world'; -$this->_pages['mods/hello_world/index_public.php']['parent'] = AT_NAV_PUBLIC; - -/* my start page pages */ -$this->_pages[AT_NAV_START] = array('mods/hello_world/index_mystart.php'); -$this->_pages['mods/hello_world/index_mystart.php']['title_var'] = 'hello_world'; -$this->_pages['mods/hello_world/index_mystart.php']['parent'] = AT_NAV_START; - -/******* - * Use the following array to define a tool to be added to the Content Editor's icon toolbar. - * id = a unique identifier to be referenced by javascript or css, prefix with the module name - * class = reference to a css class in the module.css or the primary theme styles.css to style the tool icon etc - * src = the src attribute for an HTML img element, referring to the icon to be embedded in the Content Editor toolbar - * title = reference to a language token rendered as an HTML img title attribute - * alt = reference to a language token rendered as an HTML img alt attribute - * text = reference to a language token rendered as the text of a link that appears below the tool icon - * js = reference to the script that provides the tool's functionality - */ - -$this->_content_tools[] = array("id"=>"helloworld_tool", - "class"=>"fl-col clickable", - "src"=>AT_BASE_HREF."mods/hello_world/hello_world.jpg", - "title"=>_AT('hello_world_tool'), - "alt"=>_AT('hello_world_tool'), - "text"=>_AT('hello_world'), - "js"=>AT_BASE_HREF."mods/hello_world/content_tool_action.js"); - -/******* - * Register the entry of the callback class. Make sure the class name is properly namespaced, - * for instance, prefixed with the module name, to enforce its uniqueness. - * This class must be defined in "ModuleCallbacks.class.php". - * This class is an API that contains the static methods to act on core functions. - */ -$this->_callbacks['hello_world'] = 'HelloWorldCallbacks'; - -function hello_world_get_group_url($group_id) { - return 'mods/hello_world/index.php'; -} -?> \ No newline at end of file diff --git a/mods/hello_world/module.sql b/mods/hello_world/module.sql deleted file mode 100644 index b55f655ab..000000000 --- a/mods/hello_world/module.sql +++ /dev/null @@ -1,12 +0,0 @@ -# sql file for hello world module - -CREATE TABLE `hello_world` ( - `hello_world_id` mediumint(8) unsigned NOT NULL, - `course_id` mediumint(8) unsigned NOT NULL, - `value` VARCHAR( 30 ) NOT NULL , - PRIMARY KEY ( `hello_world_id` ) -); - -INSERT INTO `language_text` VALUES ('en', '_module','hello_world','Hello World',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','hello_world_tool','Hello World Content Tool',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','hello_world_text','A sample Hello World text for detailed homepage.',NOW(),''); \ No newline at end of file diff --git a/mods/hello_world/module.xml b/mods/hello_world/module.xml deleted file mode 100644 index 6749b308a..000000000 --- a/mods/hello_world/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Hello World - 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. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.6 - 2010-12-06 - stable - - - diff --git a/mods/hello_world/module_backup.php b/mods/hello_world/module_backup.php deleted file mode 100644 index 7a65f7ac3..000000000 --- a/mods/hello_world/module_backup.php +++ /dev/null @@ -1,18 +0,0 @@ - \ No newline at end of file diff --git a/mods/hello_world/module_cron.php b/mods/hello_world/module_cron.php deleted file mode 100644 index 6e1460046..000000000 --- a/mods/hello_world/module_cron.php +++ /dev/null @@ -1,13 +0,0 @@ - \ No newline at end of file diff --git a/mods/hello_world/module_delete.php b/mods/hello_world/module_delete.php deleted file mode 100644 index 322d3a611..000000000 --- a/mods/hello_world/module_delete.php +++ /dev/null @@ -1,21 +0,0 @@ - \ No newline at end of file diff --git a/mods/hello_world/module_format_content.php b/mods/hello_world/module_format_content.php deleted file mode 100644 index eb6d3f032..000000000 --- a/mods/hello_world/module_format_content.php +++ /dev/null @@ -1,21 +0,0 @@ -',$_input); -$_input = str_replace('[/black]','',$_input); - -?> \ No newline at end of file diff --git a/mods/hello_world/module_install.php b/mods/hello_world/module_install.php deleted file mode 100644 index 9a828118f..000000000 --- a/mods/hello_world/module_install.php +++ /dev/null @@ -1,67 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/hello_world/module_news.php b/mods/hello_world/module_news.php deleted file mode 100644 index 471b3d2f6..000000000 --- a/mods/hello_world/module_news.php +++ /dev/null @@ -1,18 +0,0 @@ - diff --git a/mods/hello_world/module_uninstall.php b/mods/hello_world/module_uninstall.php deleted file mode 100644 index 9ed6969e7..000000000 --- a/mods/hello_world/module_uninstall.php +++ /dev/null @@ -1,44 +0,0 @@ -addError(array('MODULE_UNINSTALL', '
  • '.$directory.' can not be removed. Please manually remove it.
  • ')); -} - -/****** - * the following code checks if there are any errors (generated previously) - * then uses the SqlUtility to run reverted database queries of module.sql, - * ie. "create table" statement in module.sql is run as drop according table. - */ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/hello_world/side_menu.inc.php b/mods/hello_world/side_menu.inc.php deleted file mode 100644 index 94e91e82f..000000000 --- a/mods/hello_world/side_menu.inc.php +++ /dev/null @@ -1,13 +0,0 @@ - - -hello world - -assign('dropdown_contents', ob_get_contents()); -ob_end_clean(); - -$savant->assign('title', _AT('hello_world')); // the box title -$savant->display('include/box.tmpl.php'); -?> \ No newline at end of file diff --git a/mods/hello_world/sublinks.php b/mods/hello_world/sublinks.php deleted file mode 100644 index c0d631091..000000000 --- a/mods/hello_world/sublinks.php +++ /dev/null @@ -1,34 +0,0 @@ - 0) { - while ($row = mysql_fetch_assoc($result)) { - /**** - * SUBLINK_TEXT_LEN, VALIDATE_LENGTH_FOR_DISPLAY are defined in include/lib/constance.lib.inc - * SUBLINK_TEXT_LEN determins the maxium length of the string to be displayed on "detail view" box. - *****/ - $list[] = ' SUBLINK_TEXT_LEN ? ' title="'.$row['value'].'"' : '') .'>'. - validate_length($row['value'], SUBLINK_TEXT_LEN, VALIDATE_LENGTH_FOR_DISPLAY) .''; - } - return $list; -} else { - return 0; -} - -?> \ No newline at end of file diff --git a/mods/job_board/README b/mods/job_board/README deleted file mode 100644 index 48482cde5..000000000 --- a/mods/job_board/README +++ /dev/null @@ -1,138 +0,0 @@ -MODULE DETAILS: ---------------- -Description: -Allow users to add job postings to the board. - -Version: -1.0 - -License: -GPL/ATutor - - -------------------------------------------------------------------- -TABLE OF CONTENT -------------------------------------------------------------------- -1. Job board - 1.1. Job Listing - 1.2. Simple Search - 1.3. Advanced Search - 1.4. View Posting - 1.5. Job Cart - -2. Employers - 2.1. Registration - 2.2. Adding a job posting - 2.3. Update employer profile - 2.4. Edit/Delete Postings -3. Administrator - 3.1. Edit/Delete Posting - 3.1.1. Approving Postings - 3.2. Preference Settings - 3.3. Job Categories - 3.4. Employers - 3.4.1. Approving Employers - - -------------------------------------------------------------------- -1.1. Job Listing -------------------------------------------------------------------- -- Job listing can be sorted by clicking the column headers. Not all columns can be sorted, only the ones with an up/down arrows can be sorted. Namely, job title, created, closing date. -- Clicking on the column header again will change the sorting from ascending order to descending order. Vice versa. - -------------------------------------------------------------------- -1.2. Simple Search -------------------------------------------------------------------- -- Search box allow users to search for any job post that matches your search query. Specifically, it will genereate a list that matches its title, and description. - -------------------------------------------------------------------- -1.3. Advanced Search -------------------------------------------------------------------- -- Advanced search allow users to add specific parameters to refine their search. -- If bookmark is checked, it will filter out all entries that are bookmarked by the ATutor user. -- If archive is checked, it will generate all postings even if its closing date is expired. - -------------------------------------------------------------------- -1.4. View Posting -------------------------------------------------------------------- -- Click on any entries and you will be brought to another page that shows the content of the posting -- Users have the option to bookmark this entry by clicking "Add to job cart" on the right floating box. - -------------------------------------------------------------------- -1.5. Job Cart -------------------------------------------------------------------- -- "Job cart" is a bookmarking system. It is made to allow users to track the posting they like. -- Bookmarked entries will have a '*' in the job listing. - - -------------------------------------------------------------------- -2.1. Registration -------------------------------------------------------------------- -- Only employers have the privilege to post jobs -- To allow third party users to post jobs within ATutor. ie. you do not have to be registered in ATutor to post a job. -- Email need to be valid in order to activate your account. -- Registration is needed to filter out spammers. - -------------------------------------------------------------------- -2.2. Adding a job posting -------------------------------------------------------------------- -1. Register as an Employer by clicking on "Register as Employer"; or if you already have an Job board account, log in with your username. Note: this username is different than the ATutor ID. -2. Click on "Add a job posting" on the submenu on top. -3. -- Title, is the title of your Job Post. Should always include the position in the title. -- Category, is used for ATutor users to get subscription and search for. If there is no matching category, you may suggest it to the ATutor admin so they can add it in. -- Closing date, is the deadline of the job post. Once the post expired, it will no longer show up in the job board unless the user search for archives in the advanced search box. -- Description, should always include Job Title, Brief Description, Requirements, Contacts. -4. Once ready, click submit and it will be posted. (Might not show up if the post requires administrator approval) - -------------------------------------------------------------------- -2.3. Update Employer profile -------------------------------------------------------------------- -1. Log in -2. Click on "Update Profile" on the submenu. -3. Make your changes and click save. - -------------------------------------------------------------------- -2.4. Edit/Delete Posting -------------------------------------------------------------------- -1. On the listing page, click on edit/delete. - - -------------------------------------------------------------------- -3.1. Edit/Delete Posting -------------------------------------------------------------------- -- Refer to 2.4. - -------------------------------------------------------------------- -3.1.1. Approving Posting -------------------------------------------------------------------- -- From listing, click on Edit. -- Within Admin mode, there is an option called "Approval State". "Confirmed" will allow the posting to show up publicly. "Unconfirmed" will hide it from the public listing. - -------------------------------------------------------------------- -3.2. Preference Settings -------------------------------------------------------------------- -- if required posting approval is set to "Yes", all posting will needed to be approved. -- To know how to approve a posting, check 3.1.1. - -------------------------------------------------------------------- -3.3. Job Categories -------------------------------------------------------------------- -- Admin has the ability to add more category by entering the new category name in the textbox. -- To delete any categories, click "Delete" beside the desired category. -- Note: Categories are always sorted alphanumerically. - -------------------------------------------------------------------- -3.4. Employers -------------------------------------------------------------------- -- Admin has the ability to edit employers. Click on 'Edit'. - -------------------------------------------------------------------- -3.4.1. Approving Employer -------------------------------------------------------------------- -- Employers can be disabled by clicking on 'Edit' as mentioned in 3.4. -- Under "Approval State" - "Unconfirmed" means the employer has not been confirmed and cannot post any job posting. - "Confirmed" means the employer is evaludated and has the right to post any job posting they want. - "Suspended" means the employer has violated the job board rules and can no longer post or login. - diff --git a/mods/job_board/admin/categories.php b/mods/job_board/admin/categories.php deleted file mode 100644 index b6cd0da67..000000000 --- a/mods/job_board/admin/categories.php +++ /dev/null @@ -1,65 +0,0 @@ -getCategories(); - -//handle submit -if (isset($_REQUEST['submit'])){ - if($_POST['submit']=='ajax' && $_POST['action']=='edit'){ - //handle edit. - $cid = intval($_POST['cid']); //category id - $name = $_POST['category_name']; //category name - $job->updateCategory($cid, $name); - exit; //ajax exit; - } elseif($_POST['action']=='add'){ - //handle add - $name = $_POST['category_name']; //category name - $job->addCategory($name); - $categories = $job->getCategories(); //refresh the list. - } elseif ($_GET['action']=='delete'){ - //handle delete - $cid = intval($_GET['cid']); //category id - $hidden_vars['cid'] = $cid; - $this_category_name = $job->getCategoryNameById($cid); - $msg->addConfirm(array('DELETE', $this_category_name), $hidden_vars); - } -} - -//handle delete confirmation -if (isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - header('Location: categories.php'); - exit; -} else if (isset($_POST['submit_yes'])) { - $cid = intval($_POST['cid']); - $job->removeCategory($cid); - $msg->addFeedback('JB_CATEGORY_DELETED'); - header('Location: categories.php'); - exit; -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$msg->printConfirm(); -$savant->assign('categories', $categories); -$savant->display('admin/jb_categories.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/job_board/admin/edit_employer.php b/mods/job_board/admin/edit_employer.php deleted file mode 100644 index 410c9f4ad..000000000 --- a/mods/job_board/admin/edit_employer.php +++ /dev/null @@ -1,90 +0,0 @@ -getEmail()){ - if ($email!=$email2){ - $msg->addError('EMAIL_MISMATCH'); - header('Location: edit_employer.php'); - exit; - } - } - - //check js errors - if ($_POST['jb_employer_password_error'] != ''){ - $errors = explode(',', $_POST['jb_employer_password_error']); - if(sizeof($errors) > 0){ - foreach($errors as $err){ - $msg->addError($err); - } - } - header('Location: edit_employer.php?eid='.intval($_GET['eid'])); - exit; - } - - //update password - if ($pass!='' && strlen($pass)==40){ - $employer->updatePassword($pass); - } - - //set approval state - $employer->setApprovalState($approval_state); - - if ($employer->updateProfile($name, $company, $email, $website, $description)){ - $msg->addFeedback('JB_PROFILE_UPDATED'); - } else { - $msg->addError('DB_NOT_UPDATED'); - } - header('Location: employers.php'); - exit; -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->assign('name', $employer->getName()); -$savant->assign('company', $employer->getCompany()); -$savant->assign('email', $employer->getEmail()); -$savant->assign('website', $employer->getWebsite()); -$savant->assign('description', $employer->getDescription()); -$savant->assign('approval_state', $employer->getApprovalState()); -$savant->display('admin/jb_edit_employer.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/admin/edit_post.php b/mods/job_board/admin/edit_post.php deleted file mode 100644 index 85cb73f75..000000000 --- a/mods/job_board/admin/edit_post.php +++ /dev/null @@ -1,89 +0,0 @@ - - - - '; - -/* - * Add the submenu on this page so that user can go back to the listing. - * Reason why this is not included in module.php is because we don't want the - * 'edit_post' submenu to show on job_board/index.php - */ -$_pages[AT_JB_BASENAME.'index_admin.php']['children'] = array(AT_JB_BASENAME.'admin/edit_post.php'); - -$jid = intval($_GET['jid']); -$job = new Job(); -$job_post = $job->getJob($jid); - -//visual editor -if ((!$_POST['setvisual'] && $_POST['settext']) || !$_GET['setvisual']){ - $onload = 'document.form.title.focus();'; -} - -//handle edit -if(isset($_POST['submit'])){ - //concat the closing date values - $year = intval($_POST['year_jb_closing_date']); - $month = intval($_POST['month_jb_closing_date']); - $month = ($month < 10)?'0'.$month:$month; - $day = intval($_POST['day_jb_closing_date']); - $day = ($day < 10)?'0'.$day:$day; - $hour = intval($_POST['hour_jb_closing_date']); - $hour = ($hour < 10)?'0'.$hour:$hour; - $min = intval($_POST['min_jb_closing_date']); - $min = ($min < 10)?'0'.$min:$min; - $jb_closing_date = $year.'-'.$month.'-'.$day.' '.$hour.':'.$min.':00'; - - $job->updateJob($jid, $_POST['title'], $_POST['jb_description'], $_POST['jb_categories'], $_POST['jb_is_public'], $jb_closing_date, $_POST['jb_approval_state']); - $msg->addFeedback('JB_POST_UPDATED_SUCCESS'); - header('Location: ../index_admin.php'); - exit; -} - -//load visual editor base on personal preferences -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; - } -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->assign('job', $job); -$savant->assign('categories', $job->getCategories()); -$savant->assign('job_post', $job_post); -$savant->display('admin/jb_edit_post.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/admin/employers.php b/mods/job_board/admin/employers.php deleted file mode 100644 index 199b64dca..000000000 --- a/mods/job_board/admin/employers.php +++ /dev/null @@ -1,34 +0,0 @@ -assign('employers', $employers); -$savant->display('admin/jb_employers.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/admin/preferences.php b/mods/job_board/admin/preferences.php deleted file mode 100644 index 6479e8998..000000000 --- a/mods/job_board/admin/preferences.php +++ /dev/null @@ -1,40 +0,0 @@ - 1){ - $posting_approval = 1; - } - $sql = 'REPLACE INTO '.TABLE_PREFIX."config SET value='$posting_approval', name='jb_posting_approval'"; - $result = mysql_query($sql, $db); - if ($reuslt===false){ - $msg->addError('DB_NOT_UPDATED'); - } else { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: preferences.php'); - exit; - } -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('admin/jb_preferences.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/admin/view_post.php b/mods/job_board/admin/view_post.php deleted file mode 100644 index e0ce8af90..000000000 --- a/mods/job_board/admin/view_post.php +++ /dev/null @@ -1,56 +0,0 @@ -getJob($jid); - -if($_GET['action']=='delete'){ - $hidden_vars['jid'] = $jid; - $job_post = $job->getJob($jid); - $msg->addConfirm(array('DELETE', $job_post['title']), $hidden_vars); -} -//handle delete -if (isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - header('Location: ../index_admin.php'); - exit; -} else if (isset($_POST['submit_yes'])) { - $job->removeJob($jid); - $msg->addFeedback('JB_POST_DELETED'); - header('Location: ../index_admin.php'); - exit; -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$msg->printConfirm(); -$savant->assign('job_obj', $job); -$savant->assign('job_post', $job_post); -$savant->display('jb_view_post.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/confirm.php b/mods/job_board/confirm.php deleted file mode 100644 index 5ba19c4d6..000000000 --- a/mods/job_board/confirm.php +++ /dev/null @@ -1,42 +0,0 @@ -addFeedback('CONFIRM_GOOD'); - - } else { - //not confirmed - $msg->addError('CONFIRM_BAD'); - } - } -} - -header('Location: index.php'); -exit; -?> \ No newline at end of file diff --git a/mods/job_board/employer/add_new_post.php b/mods/job_board/employer/add_new_post.php deleted file mode 100644 index 0cf5cc6fd..000000000 --- a/mods/job_board/employer/add_new_post.php +++ /dev/null @@ -1,93 +0,0 @@ - - - - '; - -if (!Employer::authenticate()){ - $msg->addError('ACCESS_DENIED'); - header('Location: ../index.php'); - exit; -} - -$job = new Job(); -$all_categories = $job->getCategories(); - -//visual editor -if ((!$_POST['setvisual'] && $_POST['settext']) || !$_GET['setvisual']){ - $onload = 'document.form.title.focus();'; -} - -//on submit -if(isset($_POST['submit'])){ - //concat the closing date values - $year = intval($_POST['year_jb_closing_date']); - $month = intval($_POST['month_jb_closing_date']); - $month = ($month < 10)?'0'.$month:$month; - $day = intval($_POST['day_jb_closing_date']); - $day = ($day < 10)?'0'.$day:$day; - $hour = intval($_POST['hour_jb_closing_date']); - $hour = ($hour < 10)?'0'.$hour:$hour; - $min = intval($_POST['min_jb_closing_date']); - $min = ($min < 10)?'0'.$min:$min; - $jb_closing_date = $year.'-'.$month.'-'.$day.' '.$hour.':'.$min.':00'; - - $job->addJob($_POST['title'], $_POST['jb_description'], $_POST['jb_categories'], $_POST['jb_is_public'], $jb_closing_date); - - if ($_config['jb_posting_approval']==1){ - //if the post require approval. - $msg->addFeedback('JB_POST_PENDING'); - } else { - $msg->addFeedback('JB_POST_ADDED_SUCCESSFULLY'); - } - header('Location: home.php'); - exit; -} - -//load visual editor base on personal preferences -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; - } -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -echo '
    '; -$savant->display('employer/jb_employer_header.tmpl.php'); -echo '
    '; -$savant->assign('categories', $all_categories); -$savant->display('employer/jb_add_new_post.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/employer/edit_post.php b/mods/job_board/employer/edit_post.php deleted file mode 100644 index 437b95833..000000000 --- a/mods/job_board/employer/edit_post.php +++ /dev/null @@ -1,98 +0,0 @@ - - - - '; - -if (!Employer::authenticate()){ - $msg->addError('ACCESS_DENIED'); - header('Location: ../index.php'); - exit; -} - -/* - * Add the submenu on this page so that user can go back to the listing. - * Reason why this is not included in module.php is because we don't want the - * 'edit_post' submenu to show on job_board/index.php - */ -$_pages[AT_JB_BASENAME.'index_admin.php']['children'] = array(AT_JB_BASENAME.'admin/edit_post.php'); - -$jid = intval($_GET['jid']); -$job = new Job(); -$job_post = $job->getJob($jid); - -//visual editor -if ((!$_POST['setvisual'] && $_POST['settext']) || !$_GET['setvisual']){ - $onload = 'document.form.title.focus();'; -} - -//handle edit -if(isset($_POST['submit'])){ - //concat the closing date values - $year = intval($_POST['year_jb_closing_date']); - $month = intval($_POST['month_jb_closing_date']); - $month = ($month < 10)?'0'.$month:$month; - $day = intval($_POST['day_jb_closing_date']); - $day = ($day < 10)?'0'.$day:$day; - $hour = intval($_POST['hour_jb_closing_date']); - $hour = ($hour < 10)?'0'.$hour:$hour; - $min = intval($_POST['min_jb_closing_date']); - $min = ($min < 10)?'0'.$min:$min; - $jb_closing_date = $year.'-'.$month.'-'.$day.' '.$hour.':'.$min.':00'; - - //approval state. - $approval_state = ($_config['jb_posting_approval']==1)?AT_JB_POSTING_STATUS_UNCONFIRMED:AT_JB_POSTING_STATUS_CONFIRMED; - - $job->updateJob($jid, $_POST['title'], $_POST['jb_description'], $_POST['jb_categories'], $_POST['jb_is_public'], $jb_closing_date, $approval_state); - $msg->addFeedback('JB_POST_UPDATED_SUCCESS'); - header('Location: home.php'); - exit; -} - -//load visual editor base on personal preferences -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; - } -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('employer/jb_employer_header.tmpl.php'); -$savant->assign('job', $job); -$savant->assign('categories', $job->getCategories()); -$savant->assign('job_post', $job_post); -$savant->display('employer/jb_edit_post.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/employer/home.php b/mods/job_board/employer/home.php deleted file mode 100644 index 4304872b2..000000000 --- a/mods/job_board/employer/home.php +++ /dev/null @@ -1,63 +0,0 @@ -addError('ACCESS_DENIED'); - header('Location: ../index.php'); - exit; -} - -//init -$job = new Job(); -$page = intval($_GET['p']); -$page = ($page==0)?1:$page; -$all_job_posts = $job->getMyJobs($_GET['col'], $_GET['order']); - -//handle pages -if ($page > 0){ - $offset = ($page - 1) * AT_JB_ROWS_PER_PAGE; -} else { - $offset = 0; -} -if (sizeof($all_job_posts) > 0){ - $current_job_posts = array_slice($all_job_posts, $offset, AT_JB_ROWS_PER_PAGE); -} - -//handle order -if ($_GET['order']==''){ - $order = 'DESC'; -} else { - //flip the ordre - $order = ($_GET['order']=='ASC')?'DESC':'ASC'; - $page_string = 'col='.$_GET['col'].SEP.'order='.$_GET['order']; -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -echo '
    '; -$savant->display('employer/jb_employer_header.tmpl.php'); -print_paginator($page, sizeof($all_job_posts), $page_string, AT_JB_ROWS_PER_PAGE); -echo '
    '; -$savant->assign('job_obj', $job); -$savant->assign('job_posts', $current_job_posts); -$savant->display('employer/jb_home.tmpl.php'); -print_paginator($page, sizeof($all_job_posts), $page_string, AT_JB_ROWS_PER_PAGE); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/employer/login.php b/mods/job_board/employer/login.php deleted file mode 100644 index 197883078..000000000 --- a/mods/job_board/employer/login.php +++ /dev/null @@ -1,48 +0,0 @@ -addError('INVALID_LOGIN'); - } else { - //check login + password - //if enc(a x s) = enc(b x s), then valid - if (sha1($addslashes($row['password']).$_SESSION['token']) == $_POST['form_password_hidden']){ - $_SESSION['jb_employer_id'] = $row['id']; - //if succeeded - $msg->addFeedback('LOGIN_SUCCESS'); - header('Location: home.php'); - exit; - } else { - $msg->addError('INVALID_LOGIN'); - } - } -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('employer/jb_login.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/employer/logout.php b/mods/job_board/employer/logout.php deleted file mode 100644 index 09cb594b6..000000000 --- a/mods/job_board/employer/logout.php +++ /dev/null @@ -1,23 +0,0 @@ -addFeedback('LOGOUT'); - -header('Location: ../index.php'); -exit; -?> diff --git a/mods/job_board/employer/password_reminder.php b/mods/job_board/employer/password_reminder.php deleted file mode 100644 index 800c10e95..000000000 --- a/mods/job_board/employer/password_reminder.php +++ /dev/null @@ -1,167 +0,0 @@ -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 id, username, employer_name, password, email FROM ".TABLE_PREFIX."jb_employers 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['id'] + $gen + $row['password']); - $hash_bit = substr($hash, 5, 15); - - $change_link = $_base_href.AT_JB_BASENAME.'employer/password_reminder.php?id='.$row['id'].'&g='.$gen.'&h='.$hash_bit; - if($row['employer_name'] != ''){ - $reply_name = $row['employer_name']; - }else{ - $reply_name = $row['employer_name']; - } - $tmp_message = _AT(array('password_request2',$reply_name, $row['employer_name'], 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('job_board') . ': ' . _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."jb_employers WHERE 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('employer/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."jb_employers SET password='".$password."', last_login=last_login WHERE 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'].': '._AT('job_board'), $_base_href.AT_JB_BASENAME.'employer/login.php'))."\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:login.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/mods/job_board/employer/profile.php b/mods/job_board/employer/profile.php deleted file mode 100644 index a11de83db..000000000 --- a/mods/job_board/employer/profile.php +++ /dev/null @@ -1,87 +0,0 @@ -addError('ACCESS_DENIED'); - header('Location: ../index.php'); - exit; -} - -//init -$employer = new Employer($_SESSION['jb_employer_id']); - -//save profile changes -if ($_POST['submit']){ - $name = $_POST['jb_employer_name']; - $pass = $_POST['jb_employer_password_hidden']; - $company = $_POST['jb_employer_company']; - $email = $_POST['jb_employer_email']; - $email2 = $_POST['jb_employer_email2']; - $website = $_POST['jb_employer_website']; - $description = $_POST['jb_employer_description']; - - //check if email has been changed. If it's been changed, check the 2 emails. - if ($email!=$employer->getEmail()){ - if ($email!=$email2){ - $msg->addError('EMAIL_MISMATCH'); - header('Location: profile.php'); - exit; - } - } - - //check js errors - if ($_POST['jb_employer_password_error'] != ''){ - $errors = explode(',', $_POST['jb_employer_password_error']); - if(sizeof($errors) > 0){ - foreach($errors as $err){ - $msg->addError($err); - } - } - header('Location: profile.php'); - exit; - } - - //update password - if ($pass!='' && strlen($pass)==40){ - $employer->updatePassword($pass); - } - - if ($employer->updateProfile($name, $company, $email, $website, $description)){ - $msg->addFeedback('JB_PROFILE_UPDATED'); - } else { - $msg->addFeedback('DB_NOT_UPDATED'); - } - header('Location: profile.php'); - exit; -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$msg->printConfirm(); -echo '
    '; -$savant->display('employer/jb_employer_header.tmpl.php'); -echo '
    '; -$savant->assign('name', $employer->getName()); -$savant->assign('company', $employer->getCompany()); -$savant->assign('email', $employer->getEmail()); -$savant->assign('website', $employer->getWebsite()); -$savant->assign('description', $employer->getDescription()); -$savant->display('employer/jb_profile.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/employer/registration.php b/mods/job_board/employer/registration.php deleted file mode 100644 index decd476dd..000000000 --- a/mods/job_board/employer/registration.php +++ /dev/null @@ -1,91 +0,0 @@ - 0){ - foreach($errors as $err){ - $msg->addError($err); - } - } - $noerror = false; - } - - // these fields cannot be empty - if($email=='' || $username=='' || $company=='' || $employer_name==''){ - $msg->addError('JB_MISSING_FIELDS'); - $noerror = false; - } - - // email, username taken - $sql = 'SELECT COUNT(*) FROM '.TABLE_PREFIX."jb_employers WHERE username='$username' OR email='$email'"; - $result = mysql_query($sql, $db); - if ($result){ - $row = mysql_fetch_row($result); - if ($row[0] > 0){ - $msg->addError('JB_EXISTING_INFO'); - $noerror = false; - } - } - - if ($noerror){ - //no error - $now = date('Y-m-d H:i:s'); // we use this later for the email confirmation. - $e_id = $job->addEmployerRequest($username, $password, $employer_name, $email, $company, $description, $now, $website); - - //sends out confirmation email. - $code = substr(md5($email . $now . $e_id), 0, 10); - $confirmation_link = $_base_href . AT_JB_BASENAME . 'confirm.php?id='.$e_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($email); - $mail->Subject = SITE_NAME . ' - ' . _AT('jb_email_confirmation_subject'); - $mail->Body = _AT('jb_email_confirmation_message', SITE_NAME, $confirmation_link); - $mail->Send(); - - $msg->addFeedback('REG_THANKS_CONFIRM'); - header('Location: ../index.php'); - exit; - } - - -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('employer/jb_registration.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/employer/view_post.php b/mods/job_board/employer/view_post.php deleted file mode 100644 index dbd5196db..000000000 --- a/mods/job_board/employer/view_post.php +++ /dev/null @@ -1,64 +0,0 @@ -addError('ACCESS_DENIED'); - header('Location: ../index.php'); - exit; -} - -/* - * Add the submenu on this page so that user can go back to the listing. - * Reason why this is not included in module.php is because we don't want the - * 'view_post' submenu to show on job_board/index.php - */ -$_pages[AT_JB_BASENAME.'employer/home.php']['children'] = array(AT_JB_BASENAME.'employer/view_post.php'); - -$jid = intval($_REQUEST['jid']); -$job = new Job(); -$job_post = $job->getJob($jid); - -if($_GET['action']=='delete'){ - $hidden_vars['jid'] = $jid; - $job_post = $job->getJob($jid); - $msg->addConfirm(array('DELETE', $job_post['title']), $hidden_vars); -} -//handle delete -if (isset($_POST['submit_no'])) { - $msg->addFeedback('CANCELLED'); - header('Location: home.php'); - exit; -} else if (isset($_POST['submit_yes'])) { - $job->removeJob($jid); - $msg->addFeedback('JB_POST_DELETED'); - header('Location: home.php'); - exit; -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$msg->printConfirm(); -echo '
    '; -$savant->display('employer/jb_employer_header.tmpl.php'); -echo '
    '; -$savant->assign('job_obj', $job); -$savant->assign('job_post', $job_post); -$savant->display('jb_view_post.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/images/bookmark.png b/mods/job_board/images/bookmark.png deleted file mode 100644 index f0f0ad52649be63c135f13b3ac41f23ccba677c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 459 zcmV;+0W|)JP)O#>-}JVAy5e z?7R2oc8Qb{{KzLJmT;lJX^I@?(RTIw#V-#*m{P6%bsP30zyQk5_T0>CoYMdR002ovPDHLkV1lcC B!rK4< diff --git a/mods/job_board/images/jb_icon.png b/mods/job_board/images/jb_icon.png deleted file mode 100644 index b07eeca86c3d6eb800067fea01bb81caec87ea81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6864 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 KMNUMnLSTYPT{WWs diff --git a/mods/job_board/images/jb_icon_tiny.png b/mods/job_board/images/jb_icon_tiny.png deleted file mode 100644 index a60aeecf2bba0c6d7adf28689d641614fde7fb23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3700 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 S#Y~F;0000id = $id; - - $sql = 'SELECT username, employer_name, email, company, description, website, last_login, approval_state FROM '.TABLE_PREFIX."jb_employers WHERE id=$id"; - $result = mysql_query($sql, $db); - if ($result){ - $row = mysql_fetch_assoc($result); - - $this->name = $row['employer_name']; - $this->username = $row['username']; - $this->company = $row['company']; - $this->description = $row['description']; - $this->email = $row['email']; - $this->website = $row['website']; - $this->last_login = $row['last_login']; - $this->approval_state = $row['approval_state']; - } - } - - function getId(){ - return $this->id; - } - - function getUsername(){ - return $this->username; - } - - function getName(){ - return $this->name; - } - - function getEmail(){ - return $this->email; - } - - function getCompany(){ - return $this->company; - } - - function getDescription(){ - return $this->description; - } - - function getWebsite(){ - return $this->website; - } - - function getLastLogin(){ - return $this->last_login; - } - - function getApprovalState(){ - return $this->approval_state; - } - - /** - * Set the approval state value - * @param int Approval state, check constants.inc.php - * @return null - */ - function setApprovalState($state){ - global $addslashes, $db; - - //change this if the approval_state has more than 3 values in the constant file - $state = (intval($state) > 2)?AT_JB_STATUS_UNCONFIRMED:intval($state); - - $sql = 'UPDATE '.TABLE_PREFIX."jb_employers SET approval_state='$state' WHERE id=".$this->id; - mysql_query($sql, $db); - } - - - /** - * Update the employer profile. - * - * @param string employer's name - * @param string company's name - * @param string employer's email - * @param string employer's website. - * @param string employer's description - * @return null - */ - function updateProfile($name, $company, $email, $website, $description){ - global $addslashes, $db; - $name = $addslashes($name); - $company = $addslashes($company); - $email = $addslashes($email); - $website = $addslashes($website); - $description = $addslashes($description); - - $sql = 'UPDATE '.TABLE_PREFIX."jb_employers SET employer_name='$name', company='$company', email='$email', website='$website', description='$description' WHERE id=".$this->id; - $result = mysql_query($sql, $db); - if ($result){ - return true; - } - return false; - } - - /** - * Update password - * @pass string SHA1 encrpted password, length=40 - */ - function updatePassword($pass){ - global $addslashes, $db; - $pass = $addslashes($pass); - - //if password is empty, or not encrypted, quit - if ($pass=='' || strlen($pass)!=40){ - return; - } - - $sql = 'UPDATE '.TABLE_PREFIX."jb_employers SET password='$pass' WHERE id=".$this->id; - mysql_query($sql, $db); - } - - /** - * Simple authentication. - * - * @return Boolean True if is an employer with the valid id. False otherwise. - * @precondition User has been authenticated via the login page. - * @access public - */ - function authenticate(){ - if(isset($_SESSION['jb_employer_id']) && $_SESSION['jb_employer_id'] > 0){ - return true; - } - return false; - } -} -?> diff --git a/mods/job_board/include/classes/Job.class.php b/mods/job_board/include/classes/Job.class.php deleted file mode 100644 index b01efa2fc..000000000 --- a/mods/job_board/include/classes/Job.class.php +++ /dev/null @@ -1,642 +0,0 @@ -categories = $this->getCategories(); - - $cols['title'] = 'title'; - $cols['created_date'] = 'created_date'; - $cols['closing_date'] = 'closing_date'; - $this->cols = $cols; - } - - /** - * Add a job posting to the database. - * @param string job title - * @param string description - * @param Array categories id - * @param int 1 if public; 0 otherwise. - * @param string Closing date for this job post, mysql TIMESTAMP format - * @precondition ATutor Mailer class imported. - */ - function addJob($title, $description, $categories, $is_public, $closing_date){ - require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php'); - global $addslashes, $db, $msg, $_config, $_base_href; - - if($_SESSION['jb_employer_id']<1){ - $msg->addError(); //authentication error - exit; - } else { - include(AT_JB_INCLUDE.'Employer.class.php'); - $employer = new Employer($_SESSION['jb_employer_id']); - $employer_id = $employer->getId(); - } - - $title = $addslashes($title); - $description = $addslashes($description); - $is_public = (isset($is_public))?1:0; - $closing_date = $addslashes($closing_date); - $approval_state = ($_config['jb_posting_approval']==1)?AT_JB_POSTING_STATUS_UNCONFIRMED:AT_JB_POSTING_STATUS_CONFIRMED; - $sql = 'INSERT INTO '.TABLE_PREFIX."jb_postings (employer_id, title, description, is_public, closing_date, created_date, revised_date, approval_state) VALUES ($employer_id, '$title', '$description', $is_public, '$closing_date', NOW(), NOW(), $approval_state)"; - $result = mysql_query($sql, $db); - $posting_id = mysql_insert_id(); - - //add to posting category table - if (!empty($categories)){ - foreach($categories as $id => $category){ - $category = intval($category); - $sql = 'INSERT INTO '.TABLE_PREFIX."jb_posting_categories (posting_id, category_id) VALUES ($posting_id, $category)"; - mysql_query($sql, $db); - - //send out notification if the person is subscribed to the category. - $sql = 'SELECT m.member_id, m.email FROM '.TABLE_PREFIX.'jb_category_subscribes cs LEFT JOIN '.TABLE_PREFIX."members m ON cs.member_id=m.member_id WHERE category_id=$category"; - $result = mysql_query($sql, $db); - $post_link = $_base_href . AT_JB_BASENAME . 'view_post.php?jid='.$posting_id; - if($result){ - while($row = mysql_fetch_assoc($result)){ - $mail = new ATutorMailer; - $mail->AddAddress($row['email'], get_display_name($row['member_id'])); - $body = _AT('jb_subscription_msg', $title, $this->getCategoryNameById($category), $post_link); - $body .= "\n\n"; - $body .= _AT('jb_posted_by').": ".htmlentities_utf8($employer->getCompany())."\n"; - $mail->FromName = $_config['site_name']; - $mail->From = $_config['contact_email']; - $mail->Subject = _AT('jb_subscription_mail_subject'); - $mail->Body = $body; - - if(!$mail->Send()) { - $msg->addError('SENDING_ERROR'); - } - unset($mail); - } - } - - } - } - - if (!$result){ - //TODO: db error message - $msg->addError(); - } - } - - /** - * Add a category, used by Admin only. - * @param string name of the category - */ - function addCategory($name){ - global $addslashes, $db, $msg; - - $name = $addslashes(trim($name)); - - //don't update if it's empty. - if ($name==''){ - $msg->addError('JB_CATEGORY_NAME_CANNOT_BE_EMPTY'); - return; - } - - $sql = 'INSERT INTO '.TABLE_PREFIX."jb_categories (name) VALUES ('$name')"; - $result = mysql_query($sql, $db); - - if (!$result){ - //TODO: db error message - $msg->addError(); - } - - //add this category to the category list. - $row['id'] = mysql_insert_id();; - $row['name'] = $name; - $this->categories[] = $row; - $msg->addFeedback('JB_CATEGORY_ADDED_SUCCESSFULLY'); - } - - /** - * Add an employer from the registration page. - * @param string username - * @param string password for the login - * @param string employer name - * @param string employer's email - * @param string the company that this employer represents - * @param string a brief description of the company, useful for admin approval. - * @param string Requested date in the format of mysql TIMESTAMP, (yyyy-mm-dd hh:mm:ss) - * @param string company main website. - * @return the ID of this employer. - */ - function addEmployerRequest ($username, $password, $employer_name, $email, $company, $description, $requested_date, $website=""){ - global $addslashes, $db, $msg; - - $username = $addslashes($username); - $password = $addslashes($password); - $employer_name = $addslashes($employer_name); - $email = $addslashes($email); - $company = $addslashes($company); - $description = $addslashes($description); - $requested_date = $addslashes($requested_date); - $website = $addslashes($website); - $approval_status = AT_JB_STATUS_UNCONFIRMED; - - $sql = 'INSERT INTO '.TABLE_PREFIX."jb_employers (username, password, employer_name, email, company, description, website, requested_date, approval_state) VALUES ('$username', '$password', '$employer_name', '$email', '$company', '$description', '$website', '$requested_date', $approval_status)"; - $result = mysql_query($sql, $db); - if (!$result){ - //TODO: db error message - $msg->addError(); - } - return mysql_insert_id(); - } - - - /** - * Bookmark this job. - * @param int ATutor's member_id - * @param int Job id - * @return null - */ - function addToJobCart($member_id, $job_id){ - global $db, $msg; - - $member_id = intval($member_id); - $job_id = intval($job_id); - - $sql = 'INSERT INTO '.TABLE_PREFIX."jb_jobcart (member_id, job_id, created_date) VALUES ($member_id, $job_id, NOW())"; - $result = mysql_query($sql, $db); - - if (!$result){ - //TODO: db error message - $msg->addError(); - } - } - - /** - * Update the job posting - * @param int Job's id - * @param string job title - * @param string description - * @param Array categories id - * @param int 1 if public; 0 otherwise. - * @param string Closing date for this job post, mysql TIMESTAMP format - * @param int Check job_board/include/constants.inc.php - */ - function updateJob($id, $title, $description, $categories, $is_public, $closing_date, $approval_state){ - global $addslashes, $db, $msg; - - $id = intval($id); - $title = $addslashes($title); - $description = $addslashes($description); - $is_public = (isset($is_public))?1:0; - $closing_date = $addslashes($closing_date); - $approval_state = intval($approval_state); - - $sql = 'UPDATE '.TABLE_PREFIX."jb_postings SET title='$title', description='$description', is_public=$is_public, closing_date='$closing_date', approval_state=$approval_state WHERE id=$id"; - mysql_query($sql, $db); - - //update to posting category table - if (!empty($categories)){ - //remove all - $sql = 'DELETE FROM '.TABLE_PREFIX."jb_posting_categories WHERE posting_id=$id"; - mysql_query($sql, $db); - - foreach($categories as $category){ - $category = intval($category); - //add all the categories back. - $sql = 'INSERT INTO '.TABLE_PREFIX."jb_posting_categories (posting_id, category_id) VALUES ($id, $category)"; - mysql_query($sql, $db); - } - } - } - - /** - * Update category name, used by admin only. - * @param int category id - * @param string category name - * @return null - */ - function updateCategory($id, $name){ - global $addslashes, $db, $msg; - - $id = intval($id); - $name = $addslashes(trim($name)); - - //don't update if it's empty. - if ($name==''){ - $msg->addError('JB_CATEGORY_NAME_CANNOT_BE_EMPTY'); - return; - } - - $sql = 'UPDATE '.TABLE_PREFIX."jb_categories SET name='$name' WHERE id=$id"; - $result = mysql_query($sql, $db); - - if (!$result){ - $msg->addError(); - } - } - - function updateEmployer($employer_id, $company, $note){} - - /** - * Remove this job posting entry from the database - * @param int job posting id - */ - function removeJob($job_id){ - global $db; - $job_id = intval($job_id); - - //Delete all associated posting_categories - $sql = 'DELETE FROM '.TABLE_PREFIX."jb_posting_categories WHERE posting_id=$job_id"; - mysql_query($sql, $db); - - //Delete job cart posting entries - $sql = 'DELETE FROM '.TABLE_PREFIX."jb_jobcart WHERE job_id=$job_id"; - mysql_query($sql, $db); - - //Delete job post - $sql = 'DELETE FROM '.TABLE_PREFIX."jb_postings WHERE id=$job_id"; - mysql_query($sql, $db); - } - - /** - * Remove the category - * @param int category id. - */ - function removeCategory($cat_id){ - global $db; - - $cat_id = intval($cat_id); - if($cat_id < 1){ - return; - } - - //Remove all categories entries with this category id - $sql = 'DELETE FROM '.TABLE_PREFIX."jb_posting_categories WHERE category_id=$cat_id"; - mysql_query($sql, $db); - - //Remove category - $sql = 'DELETE FROM '.TABLE_PREFIX."jb_categories WHERE id=$cat_id"; - mysql_query($sql, $db); - } - - function removeEmployer($member_id){} - - /** - * Remove the job bookmark - * @param int member id - * @param int job posting id - * @return null - */ - function removeFromJobCart($member_id, $job_id){ - global $db; - $member_id = intval($member_id); - $job_id = intval($job_id); - - $sql = 'DELETE FROM '.TABLE_PREFIX."jb_jobcart WHERE member_id=$member_id AND job_id=$job_id"; - mysql_query($sql, $db); - } - - - /** - * Return all the values of a single job - * @param int The id of the job - * @return Array row value of the job entry. - */ - function getJob($job_id){ - global $addslashes, $db, $msg; - $job_id = intval($job_id); - - $sql = 'SELECT * FROM '.TABLE_PREFIX."jb_postings WHERE id=$job_id"; - $rs = mysql_query($sql, $db); - if ($rs){ - $row = mysql_fetch_assoc($rs); - $row['categories'] = $this->getPostingCategories($row['id']); - } - return $row; - } - - - /** - * Return all jobs - * @param string sortable columns: title, created_date, closing_date - * @param string asc for ascending, else descending - * @param boolean true if this is an admin. If set to true. will return all - * entries even if it's not approved. Default is false - * @return Array job posts that will be shown on the given page. - * Return empty array if no entries. - */ - function getAllJobs($col, $order, $is_admin=false){ - global $addslashes, $db, $msg; - $result = array(); - - //if not admin, filter only the ones that's approved. - if(!$is_admin){ - $now = date('Y-m-d H:i:s'); - $filter_sql = "WHERE closing_date >= '$now' AND approval_state=".AT_JB_POSTING_STATUS_CONFIRMED; - } else { - $filter_sql = ''; - } - - //order - $col = isset($this->cols[$col])?$this->cols[$col]:$this->cols['created_date']; - $order = ($order=='ASC')?'ASC':'DESC'; - - $sql = 'SELECT * FROM '.TABLE_PREFIX."jb_postings $filter_sql ORDER BY $col $order"; - $rs = mysql_query($sql, $db); - if ($rs){ - while($row = mysql_fetch_assoc($rs)){ - $row['categories'] = $this->getPostingCategories($row['id']); - $result[$row['id']] = $row; - } - } - return $result; - } - - /** - * Returns a list of jobs that's created by the currented logged in employer - * @param string sortable columns: title, created_date, closing_date - * @param string asc for ascending, else descending - * @return Array job posts that will be shown on the given page. - */ - function getMyJobs($col, $order){ - global $addslashes, $db, $msg; - $result = array(); - - //order - $col = isset($this->cols[$col])?$this->cols[$col]:$this->cols['created_date']; - $order = ($order=='ASC')?'ASC':'DESC'; - - $sql = 'SELECT * FROM '.TABLE_PREFIX.'jb_postings WHERE employer_id='.$_SESSION['jb_employer_id']." ORDER BY $col $order"; - $rs = mysql_query($sql, $db); - if ($rs){ - while($row = mysql_fetch_assoc($rs)){ - $row['categories'] = $this->getPostingCategories($row['id']); - $result[$row['id']] = $row; - } - } - - return $result; - } - - /** - * Returns a list of jobs that are bookmarked. - * @return Array job posts that are bookmarked by the ATutor user - */ - function getBookmarkJobs(){ - global $db; - $member_id = $_SESSION['member_id']; - $result = array(); - - $sql = 'SELECT * FROM '.TABLE_PREFIX."jb_jobcart WHERE member_id=$member_id"; - $rs = mysql_query($sql, $db); - if($rs){ - while($row=mysql_fetch_assoc($rs)){ - $result[] = $row['job_id']; - } - } - return $result; - } - - //returns the list of categories. - function getCategories(){ - global $addslashes, $db, $msg; - $result = array(); - - //If this instance already have the categories, don't run the query. - if(!empty($this->categories)){ - return $this->categories; - } - $sql = 'SELECT * FROM '.TABLE_PREFIX.'jb_categories order by name'; - $rs = mysql_query($sql, $db); - - if ($rs){ - while($row = mysql_fetch_assoc($rs)){ - $result[$row['id']] = $row; - } - } - return $result; - } - - /** - * Match the category id to its name - * @param int Category ID - * @return string the name of the category. - */ - function getCategoryNameById($id){ - foreach($this->categories as $category){ - if ($category['id']==$id){ - return $category['name']; - } - } - //if it can't find any category, then return 'no category' - return _AT('jb_no_category'); - } - - /** - * Get the categories by the given posting id - * @param int posting id - * @return Array Array of categories integers. Null if input is an empty string. - * @private - */ - function getPostingCategories($pid){ - global $addslashes, $db; - $pid = intval($pid); - - $sql = 'SELECT * FROM '.TABLE_PREFIX."jb_posting_categories WHERE posting_id=$pid"; - $rs = mysql_query($sql, $db); - - if($rs){ - while($row = mysql_fetch_assoc($rs)){ - $result[] = $row['category_id']; - } - } - return $result; - } - - /** - * Get the list of categories that this member is subscribed to. - * @param int member id - * @return Array list of categories - */ - function getSubscribedCategories($member_id){ - global $db; - - $member_id = intval($member_id); - $result = array(); - - $sql = 'SELECT category_id FROM '.TABLE_PREFIX."jb_category_subscribes WHERE member_id=$member_id"; - $rs = mysql_query($sql, $db); - - if ($rs){ - while($row = mysql_fetch_array($rs)){ - $result[] = $row[0]; - } - } - return $result; - } - - /** - * Perform a search with the given filters. - * @param Array [field]=>[input]. Format must be the following: - * [title] =>[string] *no longer in use - * [categories] =>Array(integer) - * [email] =>[string] *no longer in use - * [description]=>[string] *no longer in use - * [bookmark] =>[string] (on/off) - * [archive] =>[string] (on/off) - * @param string sortable columns: title, created_date, closing_date - * @param string asc for ascending, else descending - * @return Array matched entries - */ - function search($input, $col, $order){ - global $addslashes, $db; - $result = array(); - //If input is not an array, quit right away. - if (!is_array($input)){ - return; - } - - //get the search fields - $general = $addslashes($input['general']); -// $title = $addslashes($input['title']); -// $email = $addslashes($input['email']); -// $description = $addslashes($input['description']); - $categories = $input['categories']; - $bookmark = $input['bookmark']; - $archive = $input['archive']; - - //create sub sql for general search - if ($general!=''){ - $general_sql = "`title` LIKE '%$general%' OR `description` LIKE '%$general%' OR "; - } - - //create sub sql for the search fields. - //*merged with general search -/* if ($title!=''){ - $title_bits = explode(' ', $input['title']); - $title_sql = ''; - //concat all the title search fields together. - foreach($title_bits as $v){ - $title_sql .= "`title` LIKE '%$v%' OR "; - } - } -*/ -/* - * Not sure if this is actually useful. - if ($email!=''){ - $email_bits = explode(' ', $input['email']); - $email_sql = ''; - //concat all the email search fields together. - foreach($email_bits as $v){ - $email_sql .= "`email` LIKE '%$v%' OR "; - } - } -*/ -/* - if ($description!=''){ - $description_bits = explode(' ', $input['description']); - $description_sql = ''; - //concat all the description search fields together. - foreach($description_bits as $v){ - $description_sql .= "`description` LIKE '%$v%' OR "; - } - } -*/ - if (is_array($categories) && !empty($categories)){ - foreach($categories as $k=>$category_id){ - //if 'any' is selected, use all category - if ($category_id==0){ - $categories = $this->getCategories(); - foreach ($categories as $k2=>$v2){ - $categories[$k2] = intval($v2['id']); - } - break; - } - $categories[$k] = intval($category_id); - } - $categories = '('. implode(',', $categories) . ')'; - $categories_sql = 'RIGHT JOIN (SELECT DISTINCT posting_id FROM '.TABLE_PREFIX."jb_posting_categories WHERE category_id IN $categories) AS pc ON p.id=pc.posting_id "; - } - - if($bookmark!=''){ - $bookmark_jobs = $this->getBookmarkJobs(); - $bookmarks = '('. implode(',', $bookmark_jobs) . ')'; - $bookmark_sql = "`id` IN $bookmarks OR "; - } - - //load entries with expired closing date - if ($archive==''){ - $now = date('Y-m-d H:i:s'); - $closing_sql = "closing_date >= '$now' AND "; - } - - //only closed time and approved state - //this sql must go first - $approval_closing_sql = "($closing_sql approval_state=".AT_JB_POSTING_STATUS_CONFIRMED.')'; - - $sql_wc = $general_sql . $title_sql . $email_sql . $description_sql . $bookmark_sql; //where clause - if ($sql_wc!=''){ - $sql_wc = substr($sql_wc, 0, -3); - $sql_wc = ' AND ('. $sql_wc . ')'; - } - - //order - $col = isset($this->cols[$col])?$this->cols[$col]:$this->cols['created_date']; - $order = ($order=='ASC')?'ASC':'DESC'; - - //compose the search query - $sql = 'SELECT p.* FROM '.TABLE_PREFIX."jb_postings AS p $categories_sql WHERE $approval_closing_sql $sql_wc ORDER BY $col $order"; - $rs = mysql_query($sql, $db); - if ($rs){ - while ($row = mysql_fetch_assoc($rs)){ - $row['categories'] = $this->getPostingCategories($row['id']); - $result[] = $row; - } - } - return $result; - } - - function approveEmployer($member_id){} - - function disapproveEmployer($member_id){} - - - /** - * Update subscription for the categories. Remove existing entries first, then re-insert new ones. - * @param int Member id - * @param Array Categories IDs. [index]=>[category_id] - */ - function subscribeCategories ($member_id, $categories){ - global $db; - - $member_id = intval($member_id); - - //remove old subscriptions - $sql = 'DELETE FROM '.TABLE_PREFIX."jb_category_subscribes WHERE member_id=$member_id"; - mysql_query($sql, $db); - - if (!empty($categories)){ - foreach($categories as $category){ - $category = intval($category); - if($category < 1){ - continue; - } - - //add new subscription - $sql = 'INSERT INTO '.TABLE_PREFIX."jb_category_subscribes (member_id, category_id) VALUES ($member_id, $category)"; - mysql_query($sql, $db); - } - } - } -} -?> diff --git a/mods/job_board/include/constants.inc.php b/mods/job_board/include/constants.inc.php deleted file mode 100644 index 995e0c42a..000000000 --- a/mods/job_board/include/constants.inc.php +++ /dev/null @@ -1,32 +0,0 @@ - diff --git a/mods/job_board/include/html/admin/jb_categories.tmpl.php b/mods/job_board/include/html/admin/jb_categories.tmpl.php deleted file mode 100644 index d1ad09ed9..000000000 --- a/mods/job_board/include/html/admin/jb_categories.tmpl.php +++ /dev/null @@ -1,88 +0,0 @@ -
    -
    -

    -
    -
    - - - - " /> -
    -
    -
    - -
    -

    - categories)): ?> - categories as $category): ?> -
    -
    -
    -
    -
    -
    - - -
    -
    -
    - -
    -
    - - - diff --git a/mods/job_board/include/html/admin/jb_edit_employer.tmpl.php b/mods/job_board/include/html/admin/jb_edit_employer.tmpl.php deleted file mode 100644 index b7a3e5766..000000000 --- a/mods/job_board/include/html/admin/jb_edit_employer.tmpl.php +++ /dev/null @@ -1,83 +0,0 @@ - - -
    -
    -
    -
    - -
    - -
    -
    -
    - ·
    - ·
    -
    - -
    -
    - -
    - -
    -
    - - approval_state==AT_JB_STATUS_UNCONFIRMED)?'checked="checked"':''; ?> /> - - approval_state==AT_JB_STATUS_CONFIRMED)?'checked="checked"':''; ?> /> - - approval_state==AT_JB_STATUS_SUSPENDED)?'checked="checked"':''; ?> /> -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    - - - -
    -
    -
    diff --git a/mods/job_board/include/html/admin/jb_edit_post.tmpl.php b/mods/job_board/include/html/admin/jb_edit_post.tmpl.php deleted file mode 100644 index 91735d810..000000000 --- a/mods/job_board/include/html/admin/jb_edit_post.tmpl.php +++ /dev/null @@ -1,77 +0,0 @@ - -
    -
    -
    - - -
    -
    -
    - categories)): ?> - categories as $category): ?> -
    - job_post['categories'] && in_array($category['id'], $this->job_post['categories']))?'checked="checked"':''; ?> /> - -
    - -
    -
    -
    - - job_post['is_public']==1)?'checked="checked"':''; ?>/> -
    -
    - - - job_post['approval_state']==AT_JB_POSTING_STATUS_CONFIRMED)?'checked="checked"':''; ?> /> - - job_post['approval_state']==AT_JB_POSTING_STATUS_UNCONFIRMED)?'checked="checked"':''; ?> /> -
    -
    - - job_post['closing_date'])) { - $today_day = substr($this->job_post['closing_date'], 8, 2); - $today_mon = substr($this->job_post['closing_date'], 5, 2); - $today_year = substr($this->job_post['closing_date'], 0, 4); - - $today_hour = substr($this->job_post['closing_date'], 11, 2); - $today_min = substr($this->job_post['closing_date'], 14, 2); - } else { - $today_year = date('Y'); - } - - //load the release_date template. - $name = '_jb_closing_date'; - require(AT_INCLUDE_PATH.'html/release_date.inc.php'); - ?> -
    -
    - - - - /> - - - /> - - - -
    -
    - *
    - ·
    - -
    -
    - -
    -
    -
    diff --git a/mods/job_board/include/html/admin/jb_employers.tmpl.php b/mods/job_board/include/html/admin/jb_employers.tmpl.php deleted file mode 100644 index 5f2a224f4..000000000 --- a/mods/job_board/include/html/admin/jb_employers.tmpl.php +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - employers)): ?> - employers as $employer): ?> - - - - - - - - - getApprovalState()){ - case AT_JB_STATUS_UNCONFIRMED: - $approval_state = _AT('jb_employer_status_unconfirmed'); - break; - case AT_JB_STATUS_CONFIRMED: - $approval_state = _AT('jb_employer_status_confirmed'); - break; - case AT_JB_STATUS_SUSPENDED: - $approval_state = _AT('jb_employer_status_suspended'); - break; - } - ?> - - - - - - - -
    getUsername()); ?>getName()); ?>getEmail()); ?>getCompany()); ?>getDescription()); ?>getWebsite()); ?>getLastLogin()); ?>
    diff --git a/mods/job_board/include/html/admin/jb_index.tmpl.php b/mods/job_board/include/html/admin/jb_index.tmpl.php deleted file mode 100644 index 9e429560e..000000000 --- a/mods/job_board/include/html/admin/jb_index.tmpl.php +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - job_posts)): - foreach ($this->job_posts as $id=>$row): - ?> - - - - - - - - - - - - - - - -
    ">">">
    getCompany()); - ?> - - job_obj->getCategoryNameById($category).', '; - } - $category_str = substr($category_str, 0, -2); - ?> - - - job_obj->getCategoryNameById($row['categories']);?> - - |
    diff --git a/mods/job_board/include/html/admin/jb_preferences.tmpl.php b/mods/job_board/include/html/admin/jb_preferences.tmpl.php deleted file mode 100644 index b827c5075..000000000 --- a/mods/job_board/include/html/admin/jb_preferences.tmpl.php +++ /dev/null @@ -1,16 +0,0 @@ - -
    -
    -
    - - - /> - - /> -
    - -
    - -
    -
    -
    diff --git a/mods/job_board/include/html/employer/jb_add_new_post.tmpl.php b/mods/job_board/include/html/employer/jb_add_new_post.tmpl.php deleted file mode 100644 index 84891e149..000000000 --- a/mods/job_board/include/html/employer/jb_add_new_post.tmpl.php +++ /dev/null @@ -1,67 +0,0 @@ - -
    -
    -
    - - -
    -
    -
    - categories)): ?> - categories as $category): ?> -
    - - -
    - -
    -
    -
    - - -
    -
    - - -
    -
    - - - - /> - - - /> - - - -
    -
    - *
    - ·
    - -
    -
    - -
    -
    -
    diff --git a/mods/job_board/include/html/employer/jb_edit_post.tmpl.php b/mods/job_board/include/html/employer/jb_edit_post.tmpl.php deleted file mode 100644 index 9b13c3fda..000000000 --- a/mods/job_board/include/html/employer/jb_edit_post.tmpl.php +++ /dev/null @@ -1,73 +0,0 @@ - - -
    -
    -
    - - -
    -
    -
    - categories)): ?> - categories as $category): ?> -
    - job_post['categories'] && in_array($category['id'], $this->job_post['categories']))?'checked="checked"':''; ?> /> - -
    - -
    -
    -
    - - job_post['is_public']==1)?'checked="checked"':''; ?>/> -
    -
    - - job_post['closing_date'])) { - $today_day = substr($this->job_post['closing_date'], 8, 2); - $today_mon = substr($this->job_post['closing_date'], 5, 2); - $today_year = substr($this->job_post['closing_date'], 0, 4); - - $today_hour = substr($this->job_post['closing_date'], 11, 2); - $today_min = substr($this->job_post['closing_date'], 14, 2); - } else { - $today_year = date('Y'); - } - - //load the release_date template. - $name = '_jb_closing_date'; - require(AT_INCLUDE_PATH.'html/release_date.inc.php'); - ?> -
    - -
    - - - - /> - - - /> - - - -
    -
    - *
    - ·
    - -
    - -
    - -
    -
    -
    diff --git a/mods/job_board/include/html/employer/jb_employer_header.tmpl.php b/mods/job_board/include/html/employer/jb_employer_header.tmpl.php deleted file mode 100644 index f8ac06792..000000000 --- a/mods/job_board/include/html/employer/jb_employer_header.tmpl.php +++ /dev/null @@ -1,10 +0,0 @@ -
    - 0): ?> - | - - - | - - -
    -
    diff --git a/mods/job_board/include/html/employer/jb_home.tmpl.php b/mods/job_board/include/html/employer/jb_home.tmpl.php deleted file mode 100644 index f5f05e487..000000000 --- a/mods/job_board/include/html/employer/jb_home.tmpl.php +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - job_posts)): - foreach ($this->job_posts as $id=>$row): - ?> - - - - - - - - - - - - - - -
    ">">">
    getCompany()); - ?> - - job_obj->getCategoryNameById($category).', '; - } - $category_str = substr($category_str, 0, -2); - ?> - - - job_obj->getCategoryNameById($row['categories']);?> - - |
    -
    diff --git a/mods/job_board/include/html/employer/jb_login.tmpl.php b/mods/job_board/include/html/employer/jb_login.tmpl.php deleted file mode 100644 index cdfdd012c..000000000 --- a/mods/job_board/include/html/employer/jb_login.tmpl.php +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/mods/job_board/include/html/employer/jb_profile.tmpl.php b/mods/job_board/include/html/employer/jb_profile.tmpl.php deleted file mode 100644 index 2577e2a4d..000000000 --- a/mods/job_board/include/html/employer/jb_profile.tmpl.php +++ /dev/null @@ -1,73 +0,0 @@ - - -
    -
    -
    -
    - -
    - -
    -
    -
    - ·
    - ·
    -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    - - - -
    -
    -
    diff --git a/mods/job_board/include/html/employer/jb_registration.tmpl.php b/mods/job_board/include/html/employer/jb_registration.tmpl.php deleted file mode 100644 index 041562c8f..000000000 --- a/mods/job_board/include/html/employer/jb_registration.tmpl.php +++ /dev/null @@ -1,79 +0,0 @@ - - - -
    -
    -
    - * -
    -
    - ·
    - ·
    -
    - -
    - * -
    -
    - ·
    - ·
    -
    - -
    - * -
    - -
    - -
    - * -
    - -
    - -
    - * -
    - -
    - -
    - * -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    - - - -
    -
    -
    diff --git a/mods/job_board/include/html/employer/password_change.tmpl.php b/mods/job_board/include/html/employer/password_change.tmpl.php deleted file mode 100644 index 789ac3c84..000000000 --- a/mods/job_board/include/html/employer/password_change.tmpl.php +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - -
    - - - - - - - -
    -
    - -
    - -
    - *
    -
    - ·
    - ·
    -
    - -
    - *
    - -
    - -
    - - -
    -
    -
    - - \ No newline at end of file diff --git a/mods/job_board/include/html/jb_advance_search_table.tmpl.php b/mods/job_board/include/html/jb_advance_search_table.tmpl.php deleted file mode 100644 index ffbe33f5f..000000000 --- a/mods/job_board/include/html/jb_advance_search_table.tmpl.php +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - -
    -
    - /> - -
    - job_obj->getCategories() as $category): ?> -
    - - /> - -
    - -
    />
    />
    diff --git a/mods/job_board/include/html/jb_index.tmpl.php b/mods/job_board/include/html/jb_index.tmpl.php deleted file mode 100644 index 2eaa752d3..000000000 --- a/mods/job_board/include/html/jb_index.tmpl.php +++ /dev/null @@ -1,58 +0,0 @@ - -
    - - - - - - - - - - - - job_posts)): - foreach ($this->job_posts as $row): - if (!empty($this->bookmark_posts) && in_array($row['id'], $this->bookmark_posts)){ - $bookmark_icon = '*'; - } else { - $bookmark_icon = ''; - } - ?> - - - - - - - - - - - - - -
    ">">">
    getCompany()); - ?> - - job_obj->getCategoryNameById($category).', '; - } - $category_str = substr($category_str, 0, -2); - ?> - - - job_obj->getCategoryNameById($row['categories']);?> - -
    -
    -
    diff --git a/mods/job_board/include/html/jb_subscribe.tmpl.php b/mods/job_board/include/html/jb_subscribe.tmpl.php deleted file mode 100644 index e9f384b54..000000000 --- a/mods/job_board/include/html/jb_subscribe.tmpl.php +++ /dev/null @@ -1,16 +0,0 @@ -
    -
    -
    -
    - categories as $category): ?> - subscribed))?'checked="checked"':''; ?>/> -
    - -
    -
    - - - -
    -
    -
    \ No newline at end of file diff --git a/mods/job_board/include/html/jb_view_post.tmpl.php b/mods/job_board/include/html/jb_view_post.tmpl.php deleted file mode 100644 index ffea01521..000000000 --- a/mods/job_board/include/html/jb_view_post.tmpl.php +++ /dev/null @@ -1,38 +0,0 @@ -
    -

    job_post['title'];?>

    - - - -
    - - job_post['categories'])): - $category_str = ''; - foreach($this->job_post['categories'] as $category){ - $category_str .= $this->job_obj->getCategoryNameById($category).', '; - } - $category_str = substr($category_str, 0, -2); - ?> - - - job_obj->getCategoryNameById($this->job_post['categories']);?> - -
    - -
    - - job_post['company']; ?> -
    - -
    - - job_post['closing_date']; ?> -
    - -
    - -

    job_post['description']; ?>

    -
    - -
    diff --git a/mods/job_board/include/jb_add_to_cart.inc.php b/mods/job_board/include/jb_add_to_cart.inc.php deleted file mode 100644 index f470d620e..000000000 --- a/mods/job_board/include/jb_add_to_cart.inc.php +++ /dev/null @@ -1,46 +0,0 @@ - - - -
    - -
    - -
    - -
    - \ No newline at end of file diff --git a/mods/job_board/include/js/edit.js b/mods/job_board/include/js/edit.js deleted file mode 100644 index 17536ecf6..000000000 --- a/mods/job_board/include/js/edit.js +++ /dev/null @@ -1,48 +0,0 @@ -/***********************************************************************/ -/* ATutor */ -/***********************************************************************/ -/* Copyright (c) 2002-2010 */ -/* Inclusive Design Institute */ -/* http://atutor.ca */ -/* */ -/* This program is free software. You can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation. */ -/***********************************************************************/ -// $Id$ - -/*global jQuery*/ -/*global ATutor */ -/*global tinyMCE */ -/*global window */ - -ATutor = ATutor || {}; -ATutor.mods = ATutor.mods || {}; -ATutor.mods.editor = ATutor.mods.editor || {}; - -(function () { - //initialises values to show or hide them - var setupPage = function () { - var textArea = jQuery("#textSpan"); - var textAreaId = "jb_description"; - if (jQuery("#html").attr("checked")) { - if (ATutor.mods.editor.editor_pref !== '1' && !tinyMCE.get(textAreaId)) { - tinyMCE.execCommand('mceAddControl', false, textAreaId); - } - textArea.show(); - } else { - if (tinyMCE.get(textAreaId)) { - tinyMCE.execCommand('mceRemoveControl', false, textAreaId); - } - textArea.show(); - } - }; - - //set up click handlers and show/hide appropriate tools via setupPage - var initialize = function () { - jQuery("#formatting_radios > input").click(setupPage); - setupPage(); - }; - - jQuery(document).ready(initialize); -})(); \ No newline at end of file diff --git a/mods/job_board/index.php b/mods/job_board/index.php deleted file mode 100644 index 7f0ef5e09..000000000 --- a/mods/job_board/index.php +++ /dev/null @@ -1,135 +0,0 @@ -getAllJobs($_GET['col'], $_GET['order']); -$bookmark_posts = $job->getBookmarkJobs(); - -//handle order -if ($_GET['order']==''){ - $order = 'DESC'; -} else { - //flip the ordre - $order = ($_GET['order']=='ASC')?'DESC':'ASC'; - $page_string = 'col='.$_GET['col'].SEP.'order='.$_GET['order']; -} - -//handle search -if (isset($_GET['jb_submit'])){ - $search_input['general'] = trim($_GET['jb_search_general']); -// $search_input['title'] = trim($_GET['jb_search_title']); -// $search_input['email'] = $_GET['jb_search_email']; -// $search_input['description'] = trim($_GET['jb_search_description']); - $search_input['categories'] = $_GET['jb_search_categories']; - $search_input['bookmark'] = $_GET['jb_search_bookmark']; - $search_input['archive'] = $_GET['jb_search_archive']; - $all_job_posts = $job->search($search_input, $_GET['col'], $_GET['order']); - - if(!empty($_GET['jb_search_categories'])){ - foreach($_GET['jb_search_categories'] as $category_id){ - $category_string .= 'jb_search_categories[]='.intval($category_id).SEP; - } - } - $search_string = 'jb_submit=search'.SEP. - 'jb_search_general='.$_GET['jb_search_general'].SEP. - 'jb_search_title='.$_GET['jb_search_title'].SEP. - 'jb_search_description='.$_GET['jb_search_description'].SEP. - $category_string. - 'jb_search_bookmark='.$_GET['jb_search_bookmark'].SEP. - 'jb_search_archive='.$_GET['jb_search_archive']; -} - -//handle page -if ($page > 0){ - $offset = ($page - 1) * AT_JB_ROWS_PER_PAGE; -} else { - $offset = 0; -} -$current_job_posts = array_slice($all_job_posts, $offset, AT_JB_ROWS_PER_PAGE); - -include(AT_INCLUDE_PATH.'header.inc.php');?> - -
    -
    - -
    - 0): ?> - | - - - | - - -
    -
    -
    -
    -
    -
    -0): ?> -
    - -
    - - -
    -assign('job_posts', $current_job_posts); -$savant->assign('bookmark_posts', $bookmark_posts); -$savant->assign('job_obj', $job); -$savant->display('jb_index.tmpl.php'); -print_paginator($page, sizeof($all_job_posts), $search_string.SEP.$page_string, AT_JB_ROWS_PER_PAGE); -?> -
    - - - - diff --git a/mods/job_board/index_admin.php b/mods/job_board/index_admin.php deleted file mode 100644 index 3f8264e0f..000000000 --- a/mods/job_board/index_admin.php +++ /dev/null @@ -1,54 +0,0 @@ -getAllJobs($_GET['col'], $_GET['order'], true); - -//handle pages -if ($page > 0){ - $offset = ($page - 1) * AT_JB_ROWS_PER_PAGE; -} else { - $offset = 0; -} -$current_job_posts = array_slice($all_job_posts, $offset, AT_JB_ROWS_PER_PAGE); - -//handle order -if ($_GET['order']==''){ - $order = 'DESC'; -} else { - //flip the ordre - $order = ($_GET['order']=='ASC')?'DESC':'ASC'; - $page_string = 'col='.$_GET['col'].SEP.'order='.$_GET['order']; -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -echo '
    '; -print_paginator($page, sizeof($all_job_posts), $page_string, AT_JB_ROWS_PER_PAGE); -echo '
    '; -$savant->assign('job_obj', $job); -$savant->assign('job_posts', $current_job_posts); -$savant->display('admin/jb_index.tmpl.php'); -print_paginator($page, sizeof($all_job_posts), $page_string, AT_JB_ROWS_PER_PAGE); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/job_board/module.css b/mods/job_board/module.css deleted file mode 100644 index 7b167419d..000000000 --- a/mods/job_board/module.css +++ /dev/null @@ -1,111 +0,0 @@ -div.jb_head{ - float: left; - width: 99%; -} -div.jb_add_posting{ - float: right; - padding-right: 2em; -} -div.jb_search{ - width: 70%; - float: left; -} - -div.jb_login{ - width: 60%; - margin-left:auto; - margin-right:auto; - border: 1px #CCCCCC solid; - margin-bottom: 20px; - line-height:150%; - background-color: #F8F8F8; - border-radius:.5em; - -moz-border-radius: .5em .5em .5em .5em; - -moz-box-shadow:.1em .1em .2em #999999; - box-shadow: .1em .1em .2em #999999; - padding:.2em; -} - -fieldset.group_form{ - width:90%; - margin:.5em; - border:1px #6D7B8D solid; - min-height: 170px; - padding:.5em; - -} -legend.group_form{ - border:1px #6D7B8D solid; - background-color: #EEEEEE; - font-weight: 600; - color: black; - padding-left: 1em; - padding-right: 1em; - border-radius:.2em; - -moz-border-radius: .2em .2em .2em .2em; - -moz-box-shadow:.1em .1em .1em #999999; - box-shadow: .1em .1em .1em #999999; -} - -textarea#jb_description{ - width: 99%; - height: 600px; -} - -div.jb_view_container{ - border:1px solid #cccccc; - background-color:#eeffff; - padding:1em; - line-height:1.5em; - margin-bottom:1em; - border-radius: .5em .5em .5em .5em; - -moz-border-radius: .5em .5em .5em .5em; - -moz-box-shadow:.1em .1em .1em #999999; - box-shadow: .1em .1em .1em #999999; -} -div.jb_view_container label{ - font-weight: bold; - -} -div.jb_advance_search{ - margin-left: 5em; - background: #eeeeee; -} -div.category_box{ - width: 40%; - float: left; -} - -/* add to cart template style */ -div.add_to_cart{ - padding: 1em; - background-color: #eeeeee; - float:right; -} - -/* admin styles */ -div.admin_categories_container{ - width: 95%; - margin: auto; -} -div.admin_categories{ - float: left; - width: 100%; -} -div.admin_categories div.left{ - width: 40%; - float: left; -} -div.admin_categories div.right{ - float: left; -} - -/* overriders */ -div.paging { - margin:0em auto; -} -div.pageinator_box{ - width: 94%; - margin-bottom: 0em; - border-width: 1px; -} \ No newline at end of file diff --git a/mods/job_board/module.php b/mods/job_board/module.php deleted file mode 100644 index a5c6c7242..000000000 --- a/mods/job_board/module.php +++ /dev/null @@ -1,125 +0,0 @@ -addPath('template', AT_JB_INCLUDE.'html/'); - -/****** - * 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_JOB_BOARD', $this->getPrivilege()); -define('AT_ADMIN_PRIV_JOB_BOARD', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -//$this->_stacks['pa_photo_gallery'] = array('title_var'=>'pa_photo_gallery', 'file'=>AT_PA_BASE.'side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('social', array('title_var' => 'social', 'file' => './side_menu.inc.php'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_group_tool = $_student_tool = AT_JB_BASENAME.'index.php'; - -$this->_list['job_board'] = array('title_var'=>'job_board','file'=>AT_JB_BASENAME.'sublinks.php'); -$this->_pages[AT_JB_BASENAME.'index.php']['icon'] = 'images/pin.png'; - -/******* - * add the admin pages when needed. - */ - if (admin_authenticate(AT_ADMIN_PRIV_JOB_BOARD, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array(AT_JB_BASENAME.'index_admin.php'); - $this->_pages[AT_JB_BASENAME.'index_admin.php']['title_var'] = 'job_board'; - $this->_pages[AT_JB_BASENAME.'index_admin.php']['parent'] = AT_NAV_ADMIN; - $this->_pages[AT_JB_BASENAME.'index_admin.php']['children'] = array(AT_JB_BASENAME.'admin/preferences.php', AT_JB_BASENAME.'admin/categories.php', AT_JB_BASENAME.'admin/employers.php'); - $this->_pages[AT_JB_BASENAME.'admin/preferences.php']['title_var'] = 'jb_preferences'; - $this->_pages[AT_JB_BASENAME.'admin/preferences.php']['parent'] = AT_JB_BASENAME.'index_admin.php'; - $this->_pages[AT_JB_BASENAME.'admin/categories.php']['title_var'] = 'jb_categories'; - $this->_pages[AT_JB_BASENAME.'admin/categories.php']['parent'] = AT_JB_BASENAME.'index_admin.php'; - $this->_pages[AT_JB_BASENAME.'admin/employers.php']['title_var'] = 'jb_employers'; - $this->_pages[AT_JB_BASENAME.'admin/employers.php']['parent'] = AT_JB_BASENAME.'index_admin.php'; - $this->_pages[AT_JB_BASENAME.'admin/view_post.php']['title_var'] = 'jb_view_post'; - $this->_pages[AT_JB_BASENAME.'admin/view_post.php']['parent'] = AT_JB_BASENAME.'index_admin.php'; - $this->_pages[AT_JB_BASENAME.'admin/edit_post.php']['title_var'] = 'jb_edit_post'; - $this->_pages[AT_JB_BASENAME.'admin/edit_post.php']['parent'] = AT_JB_BASENAME.'index_admin.php'; - $this->_pages[AT_JB_BASENAME.'admin/edit_employer.php']['title_var'] = 'jb_edit_employer'; - $this->_pages[AT_JB_BASENAME.'admin/edit_employer.php']['parent'] = AT_JB_BASENAME.'admin/employers.php'; -} - -/******* - * instructor Manage section: - */ -//$this->_pages[AT_JB_BASENAME.'index_instructor.php']['title_var'] = 'social'; -//$this->_pages[AT_JB_BASENAME.'index_instructor.php']['parent'] = 'tools/index.php'; - -// ** possible alternative: ** -// $this->pages['./index_instructor.php']['title_var'] = 'social'; -// $this->pages['./index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages[AT_JB_BASENAME.'index.php']['title_var'] = 'job_board'; -$this->_pages[AT_JB_BASENAME.'index.php']['img'] = AT_JB_BASENAME.'images/jb_icon.png'; -//$this->_pages[AT_JB_BASENAME.'index.php']['children'] = array(AT_JB_BASENAME.'view_post.php'); -$this->_pages[AT_JB_BASENAME.'employer/login.php']['title_var'] = 'jb_employer_login'; -$this->_pages[AT_JB_BASENAME.'employer/login.php']['parent'] = AT_JB_BASENAME.'index.php'; -$this->_pages[AT_JB_BASENAME.'employer/registration.php']['title_var'] = 'jb_employer_registration'; -$this->_pages[AT_JB_BASENAME.'employer/registration.php']['parent'] = AT_JB_BASENAME.'index.php'; -$this->_pages[AT_JB_BASENAME.'employer/password_reminder.php']['title_var'] = 'password_reminder'; -$this->_pages[AT_JB_BASENAME.'employer/password_reminder.php']['parent'] = AT_JB_BASENAME.'index.php'; - -$this->_pages[AT_JB_BASENAME.'employer/home.php']['title_var'] = 'jb_employer_home'; -$this->_pages[AT_JB_BASENAME.'employer/home.php']['parent'] = AT_JB_BASENAME.'index.php'; -$this->_pages[AT_JB_BASENAME.'employer/home.php']['children'] = array(AT_JB_BASENAME.'employer/add_new_post.php', AT_JB_BASENAME.'employer/profile.php'); -$this->_pages[AT_JB_BASENAME.'employer/view_post.php']['title_var'] = 'jb_view_post'; -$this->_pages[AT_JB_BASENAME.'employer/view_post.php']['parent'] = AT_JB_BASENAME.'employer/home.php'; -$this->_pages[AT_JB_BASENAME.'employer/edit_post.php']['title_var'] = 'jb_edit_post'; -$this->_pages[AT_JB_BASENAME.'employer/edit_post.php']['parent'] = AT_JB_BASENAME.'employer/home.php'; -$this->_pages[AT_JB_BASENAME.'employer/add_new_post.php']['title_var'] = 'jb_add_new_post'; -$this->_pages[AT_JB_BASENAME.'employer/add_new_post.php']['parent'] = AT_JB_BASENAME.'employer/home.php'; -$this->_pages[AT_JB_BASENAME.'employer/profile.php']['title_var'] = 'jb_edit_profile'; -$this->_pages[AT_JB_BASENAME.'employer/profile.php']['parent'] = AT_JB_BASENAME.'employer/home.php'; - -$this->_pages[AT_JB_BASENAME.'view_post.php']['title_var'] = 'jb_view_post'; -$this->_pages[AT_JB_BASENAME.'view_post.php']['parent'] = AT_JB_BASENAME.'index.php'; - -$this->_pages[AT_JB_BASENAME.'subscribe.php']['title_var'] = 'jb_subscribe'; -$this->_pages[AT_JB_BASENAME.'subscribe.php']['parent'] = AT_JB_BASENAME.'index.php'; - -/* public pages */ -$this->_pages[AT_NAV_PUBLIC] = array(AT_JB_BASENAME.'index.php'); -$this->_pages[AT_JB_BASENAME.'index.php']['parent'] = AT_NAV_PUBLIC; - -/* my start page pages */ -if(isset($_SESSION['member_id']) && $_SESSION['member_id']>0) { -$this->_pages[AT_NAV_START] = array(AT_JB_BASENAME.'index.php'); -$this->_pages[AT_JB_BASENAME.'index.php']['parent'] = AT_NAV_START; -} -?> diff --git a/mods/job_board/module.sql b/mods/job_board/module.sql deleted file mode 100644 index e27bde108..000000000 --- a/mods/job_board/module.sql +++ /dev/null @@ -1,160 +0,0 @@ -CREATE TABLE `jb_postings` ( - `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `employer_id` INTEGER UNSIGNED NOT NULL, - `title` VARCHAR(255) NOT NULL, - `description` TEXT, - `is_public` TINYINT(1) UNSIGNED NOT NULL, - `closing_date` TIMESTAMP NOT NULL, - `created_date` TIMESTAMP NOT NULL, - `revised_date` TIMESTAMP NOT NULL, - `approval_state` TINYINT UNSIGNED NOT NULL, - PRIMARY KEY (`id`) -) -ENGINE = MyISAM; - -CREATE TABLE `jb_categories` ( - `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `name` VARCHAR(255) NOT NULL, - PRIMARY KEY (`id`) -) -ENGINE = MyISAM; - -CREATE TABLE `jb_posting_categories` ( - `posting_id` INTEGER UNSIGNED NOT NULL, - `category_id` INTEGER UNSIGNED NOT NULL, - PRIMARY KEY (`posting_id`, `category_id`) -) -ENGINE = MyISAM; - -CREATE TABLE `jb_employers` ( - `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `username` VARCHAR(255) NOT NULL, - `employer_name` VARCHAR(255) NOT NULL, - `password` VARCHAR(40) NOT NULL, - `email` VARCHAR(255) NOT NULL, - `company` VARCHAR(255) NOT NULL, - `description` TEXT NOT NULL, - `website` VARCHAR(255) NOT NULL, - `last_login` TIMESTAMP NOT NULL, - `requested_date` TIMESTAMP NOT NULL, - `approval_state` TINYINT UNSIGNED NOT NULL, - PRIMARY KEY (`id`) -) -ENGINE = MyISAM; - -CREATE TABLE `jb_jobcart` ( - `member_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - `job_id` INTEGER UNSIGNED NOT NULL, - `created_date` TIMESTAMP NOT NULL, - PRIMARY KEY (`member_id`, `job_id`) -) -ENGINE = MyISAM; - -CREATE TABLE `jb_posting_subscribes` ( - `member_id` INTEGER UNSIGNED, - `job_id` INTEGER UNSIGNED, - PRIMARY KEY (`member_id`, `job_id`) -) -ENGINE = MyISAM; - - -CREATE TABLE `jb_category_subscribes` ( - `member_id` INTEGER UNSIGNED, - `category_id` INTEGER UNSIGNED, - PRIMARY KEY (`member_id`, `category_id`) -) -ENGINE = MyISAM; - - -# Module Language -INSERT INTO `language_text` VALUES ('en', '_module','job_board','Job Board',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_search','Search',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_search_filter','Search Filters',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_search_filter_blub','Use the following filters to refine your search',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_subscribe','Subscribe to receive new job postings',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_subscribe_blub','Check the categories below to get email notifications when there is a new job post.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_title','Job Title',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_preferences','Preferences',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_employer','Employer',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_employers','Employers',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_categories','Categories',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_bookmarks','Bookmarks',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_archive','Archive',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_company_description','Company Description',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_post_description','Description',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_post_description_note','Description should include Job Overview, Responsibilities, Qualifications, Contact Information',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_posted_by','Job posted by:',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_closing_date','Closing Date',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_login','Employer sign-in',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_logout','Employer sign-out',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_employer_registration','Employer Registration',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_any_categories','Any Categories',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_employer_login','Employer Login',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_login_text','Login to manage or post new jobs.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_login_name','Employer Login Name',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_employer_name','Employer Name',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_archive','Archive',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_employer_home','Employer Home',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_edit_employer','Edit Employer',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_add_new_post','Add Job Posting',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_edit_post','Edit Post',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_view_post','View Job Posting',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_edit_profile','Edit Profile',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_is_public','Allow non-ATutor users to see this post',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_no_category','No category',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_remove_to_cart','Remove this bookmark',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_website','Website',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_confirmed','Confirmed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_unconfirmed','Unconfirmed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_approval_state','Approval State',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_approval_state_confirmed','Approved',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_approval_state_unconfirmed','Disapproved',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_required_posting_approval','New posting requires approval',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_admin_add_category_blub','To add new categories for the job posting, type the category name in the text field and click "Save".',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_admin_edit_categories_blub','The list below are the current categories within the system. You may edit the item by clicking on them, or delete them by clicking on "Delete".',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_employer_status_unconfirmed','Unconfirmed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_employer_status_confirmed','Confirmed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_employer_status_suspended','Suspended',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_email_confirmation_subject','Job Board Email Confirmation',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_email_confirmation_message','You have registered for a job board account on %1s. Please finish the registration process by confirming your email address by using the following link: %2s.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_add_to_cart','Bookmark this post',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_remove_from_cart','Remove this bookmark',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_subscription_msg','Hi, \n\nA new job post titled %2s has been added to the ATutor Job Board %1s category. The job post can be found at the following link, %3s.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_subscription_mail_subject','New Job Post in ATutor',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_any_categories','Any categories',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_view_job_post','View a job post',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_employer_approval_state_unconfirmed','Unconfirmed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_employer_approval_state_confirmed','Confirmed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_employer_approval_state_suspended','Suspended',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_click_to_edit','Click to edit',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_click_to_delete','Click to delete',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','jb_required_posting_approval','Does job post need to be approved before listing?',NOW(),''); - -# Module Messages -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_JB_POST_ADDED_SUCCESSFULLY','Job posted added successfully.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_JB_POST_PENDING','The job posting will appear when it has been approved.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_JB_POST_DELETED','Job Post deleted successfully.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_JB_POST_UPDATED_SUCCESS','Job Post updated successfully.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_JB_CATEGORY_ADDED_SUCCESSFULLY','Category added successfully.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_JB_CATEGORY_DELETED','Category deleted successfully.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_JB_PROFILE_UPDATED','Profile was successfully updated.',NOW(),''); - -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_JB_MISSING_FIELDS','Email, username, company name, employer name cannot be empty.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_JB_EXISTING_INFO','Username or email has already been used. Please choose another one. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_JB_CATEGORY_NAME_CANNOT_BE_EMPTY','Category name cannot be empty.',NOW(),''); - -# Initial categories -INSERT INTO `jb_categories` (name) VALUES ('Auditing, Accounting'); -INSERT INTO `jb_categories` (name) VALUES ('General Business, Administrative'); -INSERT INTO `jb_categories` (name) VALUES ('HR, Business Service'); -INSERT INTO `jb_categories` (name) VALUES ('Management'); -INSERT INTO `jb_categories` (name) VALUES ('Engineering'); -INSERT INTO `jb_categories` (name) VALUES ('Computer Programming'); -INSERT INTO `jb_categories` (name) VALUES ('Visual Arts, Crafts and Design'); -INSERT INTO `jb_categories` (name) VALUES ('General Science'); -INSERT INTO `jb_categories` (name) VALUES ('General Health, Medical'); -INSERT INTO `jb_categories` (name) VALUES ('Pharmacy and Nutrition'); -INSERT INTO `jb_categories` (name) VALUES ('Teaching'); -INSERT INTO `jb_categories` (name) VALUES ('Performing Arts'); -INSERT INTO `jb_categories` (name) VALUES ('Psychology, Social Work, Counseling, Religion'); -INSERT INTO `jb_categories` (name) VALUES ('Others'); diff --git a/mods/job_board/module.xml b/mods/job_board/module.xml deleted file mode 100644 index d7e599ca5..000000000 --- a/mods/job_board/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Job Board - This module allows employers, who may or may not be a registered ATutor member, to post employment opportunities. An administrator can moderate job postings. Employers can edit and maintain a organization/company's job postings. Potential employees can subscribe the various job categories to receive notices when relevant jobs are posted, and can bookmark jobs to keep track of their job search. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - GPL/ATutor - - 0.2 - 2010-10-25 - Stable - See the module's README file for installation and usage instructions. - - \ No newline at end of file diff --git a/mods/job_board/module_install.php b/mods/job_board/module_install.php deleted file mode 100644 index 734e4e68a..000000000 --- a/mods/job_board/module_install.php +++ /dev/null @@ -1,80 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} -*/ - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/job_board/module_news.php b/mods/job_board/module_news.php deleted file mode 100644 index 7ade6d495..000000000 --- a/mods/job_board/module_news.php +++ /dev/null @@ -1,41 +0,0 @@ - - */ -function job_board_news() { - global $db; - $news = array(); - $job = new Job(); - - $result = $job->getAllJobs('created_date', 'desc'); - - if(is_array($result)){ - foreach ($result as $row){ - $title = htmlentities_utf8($row['title']); - - $news[] = array('time'=>$row['revised_date'], - 'object'=>$row, - 'thumb'=>AT_JB_BASENAME.'images/jb_icon_tiny.png', - 'link'=>''.$title.""); - } - } - return $news; -} - -?> \ No newline at end of file diff --git a/mods/job_board/module_uninstall.php b/mods/job_board/module_uninstall.php deleted file mode 100644 index e85b2a5ac..000000000 --- a/mods/job_board/module_uninstall.php +++ /dev/null @@ -1,49 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/job_board/sublinks.php b/mods/job_board/sublinks.php deleted file mode 100644 index 5fbb7530c..000000000 --- a/mods/job_board/sublinks.php +++ /dev/null @@ -1,40 +0,0 @@ -getAllJobs('created_date', 'desc'); - -if (is_array($result)) { - foreach($result as $row){ - if ($cnt >= $link_limit) break; - $cnt++; - - $title = htmlentities_utf8($row['title']); - $list[] = ''.''.$title.''; - } - return $list; -} else { - return 0; -} - -?> \ No newline at end of file diff --git a/mods/job_board/subscribe.php b/mods/job_board/subscribe.php deleted file mode 100644 index d72ce1a50..000000000 --- a/mods/job_board/subscribe.php +++ /dev/null @@ -1,47 +0,0 @@ -getCategories(); -$subscribed = $job->getSubscribedCategories($_SESSION['member_id']); - -//handle save -if (isset($_POST['submit'])){ - $token = sha1($_SESSION['member_id'].$_SESSION['token']); - //validate if this is a post from the user himself but not anyone else. - if ($_POST['token'] != $token){ - $msg->addError(); - header('Location: index.php'); - exit; - } - $job->subscribeCategories($_SESSION['member_id'], $_POST['jb_subscribe_categories']); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: subscribe.php'); - exit; -} - - -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->assign('categories', $categories); -$savant->assign('job_obj', $job); -$savant->assign('subscribed', $subscribed); -$savant->display('jb_subscribe.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/job_board/view_post.php b/mods/job_board/view_post.php deleted file mode 100644 index eb55f0fcb..000000000 --- a/mods/job_board/view_post.php +++ /dev/null @@ -1,43 +0,0 @@ -getJob($jid); - -//handle add to cart event -if ($_GET['action']=='add_to_cart'){ - $job->addToJobCart($_SESSION['member_id'], $jid); -} elseif ($_GET['action']=='remove_from_cart'){ - $job->removeFromJobCart($_SESSION['member_id'], $jid); -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->assign('job_obj', $job); -$savant->assign('job_post', $job_post); -$savant->display('jb_view_post.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/joomla_atutor/atutor/index_mambo.php b/mods/joomla_atutor/atutor/index_mambo.php deleted file mode 100644 index 0783c68c9..000000000 --- a/mods/joomla_atutor/atutor/index_mambo.php +++ /dev/null @@ -1,74 +0,0 @@ - \ No newline at end of file diff --git a/mods/joomla_atutor/com_atutor.zip b/mods/joomla_atutor/com_atutor.zip deleted file mode 100644 index f42d359ed23894cfbae4d34ba998bf94064d8563..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5067 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'CANCELLED'); - header('Location: index.php'); - exit; -} else if (isset($_POST['submit'])) { - $_POST['ldap_name'] = trim($_POST['ldap_name']); - $_POST['ldap_port'] = intval($_POST['ldap_port']); - $_POST['ldap_base_tree'] = trim($_POST['ldap_base_tree']); - $_POST['ldap_attr_login'] = trim($_POST['ldap_attr_login']); -// $_POST['ldap_attr_password'] = trim($_POST['ldap_attr_password']); - $_POST['ldap_attr_password'] = "__unused_ldap_field__"; - $_POST['ldap_attr_mail'] = trim($_POST['ldap_attr_mail']); - $_POST['ldap_attr_last_name'] = trim($_POST['ldap_attr_last_name']); - $_POST['ldap_attr_first_name'] = trim($_POST['ldap_attr_first_name']); - $_POST['ldap_attr_second_name'] = trim($_POST['ldap_attr_second_name']); - $_POST['ldap_attr_dob'] = trim($_POST['ldap_attr_dob']); - $_POST['ldap_attr_gender'] = trim($_POST['ldap_attr_gender']); - $_POST['ldap_attr_address'] = trim($_POST['ldap_attr_address']); - $_POST['ldap_attr_postal'] = trim($_POST['ldap_attr_postal']); - $_POST['ldap_attr_city'] = trim($_POST['ldap_attr_city']); - $_POST['ldap_attr_province'] = trim($_POST['ldap_attr_province']); - $_POST['ldap_attr_country'] = trim($_POST['ldap_attr_country']); - $_POST['ldap_attr_phone'] = trim($_POST['ldap_attr_phone']); - $_POST['ldap_attr_website'] = trim($_POST['ldap_attr_website']); - - //check that all required values have been set - if (!$_POST['ldap_name']) { - $msg->addError('NO_LDAP_SERVER_NAME'); - } - - - if (!$_POST['ldap_base_tree']) { - $msg->addError('NO_LDAP_BASE_TREE'); - } - - - if (!$_POST['ldap_attr_login']) { - $msg->addError('NO_LDAP_ATTR_LOGIN'); - } - - if (!$_POST['ldap_attr_password']) { - $msg->addError('NO_LDAP_ATTR_PASS'); - } - - if (!$_POST['ldap_attr_mail']) { - $msg->addError('NO_LDAP_ATTR_MAIL'); - } - - if (!$_POST['ldap_attr_last_name']) { - $msg->addError('NO_LDAP_ATTR_LAST_NAME'); - } - - if (!$_POST['ldap_attr_first_name']) { - $msg->addError('NO_LDAP_ATTR_FIRST_NAME'); - } - - if (!$_POST['ldap_attr_second_name']) { - $msg->addError('NO_LDAP_ATTR_SECOND_NAME'); - } - - if (!$msg->containsErrors()) { - $_POST['ldap_name'] = $addslashes($_POST['ldap_name']); - $_POST['ldap_base_tree'] = $addslashes($_POST['ldap_base_tree']); - $_POST['ldap_attr_login'] = $addslashes($_POST['ldap_attr_login']); - $_POST['ldap_attr_password'] = $addslashes($_POST['ldap_attr_password']); - $_POST['ldap_attr_mail'] = $addslashes($_POST['ldap_attr_mail']); - $_POST['ldap_attr_last_name'] = $addslashes($_POST['ldap_attr_last_name']); - $_POST['ldap_attr_first_name'] = $addslashes($_POST['ldap_attr_first_name']); - $_POST['ldap_attr_second_name'] = $addslashes($_POST['ldap_attr_second_name']); - $_POST['ldap_attr_dob'] = $addslashes($_POST['ldap_attr_dob']); - $_POST['ldap_attr_gender'] = $addslashes($_POST['ldap_attr_gender']); - $_POST['ldap_attr_address'] = $addslashes($_POST['ldap_attr_address']); - $_POST['ldap_attr_postal'] = $addslashes($_POST['ldap_attr_postal']); - $_POST['ldap_attr_city'] = $addslashes($_POST['ldap_attr_city']); - $_POST['ldap_attr_province'] = $addslashes($_POST['ldap_attr_province']); - $_POST['ldap_attr_country'] = $addslashes($_POST['ldap_attr_country']); - $_POST['ldap_attr_phone'] = $addslashes($_POST['ldap_attr_phone']); - $_POST['ldap_attr_website'] = $addslashes($_POST['ldap_attr_website']); - - foreach ($_POST as $name => $value) { - $sql = "SELECT * FROM ".TABLE_PREFIX."config_ldap WHERE name='$name'"; - $result = mysql_query($sql, $db); - $row = mysql_fetch_array($result); - echo $row['name']." -> ". $row['value']."
    "; - if (($name != 'submit') && isset($_POST[$name]) && ($_POST[$name] != $row['value'])) { - $sql = "UPDATE ".TABLE_PREFIX."config_ldap SET value='$_POST[$name]' WHERE name='$name'"; - mysql_query($sql,$db); - } - } - - $msg->addFeedback('SYSTEM_PREFS_SAVED'); - header('Location:index.php'); - exit; - - - } -} - -$onload = 'document.form.sitename.focus();'; - -require(AT_INCLUDE_PATH.'header.inc.php'); - -if (!isset($_POST['submit'])) { - $sql = "SELECT * FROM ".TABLE_PREFIX."config_ldap"; - $result = mysql_query($sql,$db); - - if (!($row = mysql_fetch_assoc($result))){ - $msg->printErrors('SOME_ERROR'); - require (AT_INCLUDE_PATH.'footer.inc.php'); - exit; - } - $result = mysql_query($sql,$db); - while ($row = mysql_fetch_assoc($result)){ - $_POST[$row['name']] = $row['value']; - } - -} -?> - -
    -
    -
    -
    *

    - -
    - -
    -
    *

    - -
    - -
    -
    *

    - -
    - -
    -
    -
    -
    *
    -
    - -
    - - - -
    -
    *
    -
    - -
    - -
    -
    *
    -
    - -
    - -
    -
    *
    -
    - -
    - -
    -
    *
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    - -
    - - - -
    - -
    -
    - - \ No newline at end of file diff --git a/mods/ldap/admin/ldap_auth_log.php b/mods/ldap/admin/ldap_auth_log.php deleted file mode 100644 index ee9aa7706..000000000 --- a/mods/ldap/admin/ldap_auth_log.php +++ /dev/null @@ -1,115 +0,0 @@ - 0 ) { - $total_pages = ceil($count/$limit); - } else { - $total_pages = 0; - } - if ($page > $total_pages) $page = $total_pages; - $start = $limit*$page - $limit; - if ($start < 0) $start = 0; - $sql = "SELECT L.member_id, M.login, CONCAT(M.last_name, ' ', M.first_name, ' ', M.second_name) AS full_name, - M.email, L.create_date, L.ldap_source FROM AT_ldap_log L LEFT JOIN AT_members M USING (member_id) ORDER BY ".$sidx." ".$sord. " - LIMIT ".$start." , ".$limit; - $result = mysql_query($sql, $db); - // Construct the json data - $response->page = $page; // current page - $response->total = $total_pages; // total pages - $response->records = $count; // total records - $i=0; - while($row = mysql_fetch_array($result)) { - $response->rows[$i]['id']=$row[member_id]; //id - $response->rows[$i]['cell']=array($row[member_id], - $row[login], - addslashes($row[full_name]), - $row[email], - $row[create_date], - $row[ldap_source]); - $i++; - } - echo json_encode($response); - exit(); -} -require (AT_INCLUDE_PATH.'header.inc.php'); -?> - - - - - - - -
    -
    -
    -
    - diff --git a/mods/ldap/admin/ldap_lib.php b/mods/ldap/admin/ldap_lib.php deleted file mode 100644 index dd045f6e6..000000000 --- a/mods/ldap/admin/ldap_lib.php +++ /dev/null @@ -1,236 +0,0 @@ - 0){ - return false; - exit; - } - } - - $sql = "INSERT INTO ".TABLE_PREFIX."members VALUES (0,'$name','$password','$email','$website','$first_name','$second_name','$last_name', '$dob', '$gender', '$address','$postal','$city','$province','$country', '$phone', $status, '$_config[pref_defaults]', '$now', '$_SESSION[lang]', 1, 1, '0000-00-00 00:00:00')"; - $result = mysql_query($sql, $db); - - if (!$result) { - return false; - }else{ - if ($row = mysql_fetch_assoc($result)){ - return $row['member_id']; - }else{ - return true; - } - } - -} - - -?> diff --git a/mods/ldap/atutor.ldap.mod.struct.sql b/mods/ldap/atutor.ldap.mod.struct.sql deleted file mode 100755 index a19ad6ca5..000000000 --- a/mods/ldap/atutor.ldap.mod.struct.sql +++ /dev/null @@ -1,115 +0,0 @@ --- MySQL dump 10.10 --- --- Host: localhost Database: atutor --- ------------------------------------------------------ --- Server version 5.0.26 - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - --- --- Table structure for table `AT_admin_log` --- - --- --- Table structure for table `AT_auth_cookie` --- - -DROP TABLE IF EXISTS `AT_auth_cookie`; -CREATE TABLE `AT_auth_cookie` ( - `aid` int(11) NOT NULL auto_increment, - `hash` varchar(255) NOT NULL, - `ttl` int(11) NOT NULL, - PRIMARY KEY (`aid`) -) ENGINE=MyISAM AUTO_INCREMENT=199 DEFAULT CHARSET=latin1; - --- --- Table structure for table `AT_config_ldap` --- - -DROP TABLE IF EXISTS `AT_config_ldap`; -CREATE TABLE `AT_config_ldap` ( - `name` varchar(30) NOT NULL, - `value` varchar(255) NOT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; - --- --- Dump data for table `AT_config_ldap` --- - -LOCK TABLES `AT_config_ldap` WRITE; -INSERT INTO `AT_config_ldap` VALUES ('ldap_name',''),('ldap_port','389'),('ldap_base_tree',''),('ldap_attr_login',''),('ldap_attr_password','__unused_ldap_field__'),('ldap_attr_mail',''),('ldap_attr_last_name',''),('ldap_attr_first_name',''),('ldap_attr_second_name',''),('ldap_attr_dob',''),('ldap_attr_gender',''),('ldap_attr_address',''),('ldap_attr_postal',''),('ldap_attr_city',''),('ldap_attr_province',''),('ldap_attr_country',''),('ldap_attr_phone',''),('ldap_attr_website',''); -UNLOCK TABLES; - - - --- --- Table structure for table `AT_ldap_log` --- - -DROP TABLE IF EXISTS `AT_ldap_log`; -CREATE TABLE `AT_ldap_log` ( - `member_id` mediumint(9) NOT NULL, - `create_date` datetime NOT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; - - --- --- Dump data for table `AT_language_text` --- - -LOCK TABLES `AT_language_text` WRITE; -/*!40000 ALTER TABLE `AT_language_text` DISABLE KEYS */; -INSERT INTO `AT_language_text` VALUES -('en','_template','ldap_name','LDAP Server name','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_port','LDAP Server port','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_base_tree','LDAP Server tree
    Base of LDAP tree where stored users entries','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr','LDAP Server fields
    You must specify name of LDAP attributes which associated to ATutor members DB fields ','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_address','Address','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_city','City','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_country','Country','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_dob','DOB (Date Of Birth)','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_first_name','Fisrt name','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_gender','Gender','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_last_name','Last name','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_login','Login ','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_mail','E-mail','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_phone','Phone','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_postal','Postal','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_province','Province','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_second_name','Second name','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_attr_website','Website','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','config_ldap','LDAP Authentication','2007-04-27 00:00:00','atutor_ldap_mod'), -('en','_template','ldap_auth_log','LDAP Auth Log','2007-04-27 00:00:00','atutor_ldap_mod'); -('uk','_template','ldap_name','Імя LDAP-сервера','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_port','Порт LDAP-сервера','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_base_tree','Дерево LDAP-каталога
    Ви повинні вказати дерево LDAP-каталога, де зберігаються записи ','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr','Атрибути LDAP-запису
    Ви повинні вказати атрибути запису в LDAP-каталозі, що відповідають полям в таблиці members БД ATutor','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_address','Адреса','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_city','Місто','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_country','Країна','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_dob','Дата народження','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_first_name','Імя','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_gender','Стать','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_last_name','Прізвище','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_login','Імя для входу','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_mail','Адреса електронної пошти','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_phone','Номер телефону','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_postal','Поштовий індекс','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_province','Область','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_second_name','По батькові','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_attr_website','Сайт','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','config_ldap','LDAP-Автентифікація','2007-04-27 00:00:00','atutor_ldap_mod'), -('uk','_template','ldap_auth_log','Лог LDAP-Автентифікації','2007-04-27 00:00:00','atutor_ldap_mod'); - -/*!40000 ALTER TABLE `AT_language_text` ENABLE KEYS */; -UNLOCK TABLES; - diff --git a/mods/ldap/atutor.ldap.mod.tar.gz b/mods/ldap/atutor.ldap.mod.tar.gz deleted file mode 100644 index 6e15653a526863ec2a6ce0f75b0651ed8af4a18c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214444 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 - - -

    - \ No newline at end of file diff --git a/mods/mahara/README b/mods/mahara/README deleted file mode 100644 index b9e03ab19..000000000 --- a/mods/mahara/README +++ /dev/null @@ -1,82 +0,0 @@ -==================================== -Mahara ePortfolio Integration Module - - by: Boon-Hau Teh -==================================== - - -Overview ----------------- -This is a simple Mahara integration module for ATutor. - - "Mahara is an open source e-portfolio, weblog, resume builder - and social networking system, connecting users and creating - online learner communities. Mahara is designed to provide users - with the tools to demonstrate their life-long learning, skills - and development over time to selected audiences." - - -Requirements ----------------- -* ATutor version 1.6 or above -* Mahara 1.0.2 - - -Installing ----------------- -1. Install ATutor and Mahara on the same server (see their - respective installation documents). - -2. Copy all Mahara module files to /mods/mahara in Atutor. - -3. As an administrator in ATutor, install and enable the module. - -4. A link to 'ePortfolio' should now appear in the navigation menu. - Still logged in as an administrator, enter full the path to the - Mahara installation. - - example on Windows system: - C:\webroot\mahara\ - - example on Linux system: - /usr/local/apache/htdocs/mahara/ - - -Using ePortfolio ----------------- -Once logged into ATutor, a regular user can access his/her -ePortfolio through the main menu or Home page. The ePortfolio -will appear on the page in ATutor as an embedded iframe. The user -has the option of clicking on a button, which closes the iframe and -opens the ePortfolio in a new window/tab of the browser. - -If a user's account on ATutor is deleted, the user's ePortfolio -account on Mahara still remains active. If the user wishes to -continue accessing Mahara, the user should be able to retrieve -the password by entering his/her E-mail (the same E-mail that was -registered in ATutor) through the "Password Reminder" feature of -Mahara. Note that the "Password Reminder" feature is provided -by Mahara 1.0.2 and is external to this module. - - - -Developer's Note ----------------- -This module does not make use of the single-sign-on feature via -XMLRPC provided by Mahara. Instead, it integrates Mahara into -ATutor by directly calling necessary functions found in Mahara. -Therefore, this module may not work in other versions of Mahara if -there are any noticeable changes made to these required functions. - -This module is intended for Mahara to run as an integrated part of -ATutor, and not as a standalone program. Single-sign-on through -ATutor is implemented by storing login information for Mahara in the -ATutor database. When a user accesses the ePortfolio for the first -time, the user is automatically registered into Mahara with a new -account. User details get copied over from ATutor and a password -for Mahara is automatically generated. The username and password -get stored with ATutor and used whenever accessing Mahara -(through Mahara's login script). In the event that the username -and password is lost from the database, the module can still find -the user (by username) on the Mahara database, generate a new -password, and re-save the login information in ATutor. diff --git a/mods/mahara/cookie.php b/mods/mahara/cookie.php deleted file mode 100644 index 04085b5a5..000000000 --- a/mods/mahara/cookie.php +++ /dev/null @@ -1,38 +0,0 @@ - \ No newline at end of file diff --git a/mods/mahara/index.php b/mods/mahara/index.php deleted file mode 100644 index d3a66ba34..000000000 --- a/mods/mahara/index.php +++ /dev/null @@ -1,109 +0,0 @@ -addFeedback ("MAHARA_LOGIN"); - -require (AT_INCLUDE_PATH.'header.inc.php'); - - -// Check if user is logged in as a guest -if (!($_SESSION['is_guest'])) { - // Read login info for Mahara - $sql = "SELECT username, SHA1(password) FROM ".TABLE_PREFIX."mahara WHERE at_login='".$_SESSION['login']."'"; - $result = mysql_query($sql, $db); - - - if (!($row = @mysql_fetch_array($result))) { - define('new_account', 1); - - // if not configured with ATutor, automatically register for account now - require('new_account.php'); - - // refresh the page - header('Location: index.php'); - - } else { - $username = $row[0]; - $password = $row[1]; - - // Login - ?> - - - -
    -

    -
    - - - - diff --git a/mods/mahara/index_admin.php b/mods/mahara/index_admin.php deleted file mode 100644 index 96113e2c0..000000000 --- a/mods/mahara/index_admin.php +++ /dev/null @@ -1,162 +0,0 @@ - 0) ? '\\\\' : '/'; - } - return $path; -} - - - - -if (isset($_POST['uri'])) { - $mahara_path = add_ending_slash(trim($_POST['uri'])); - if (!$mahara_path){ - $msg->addError('MAHARA_MINURL_ADD_EMPTY'); - } - - if (!$msg->containsErrors()) { - // If Magic Quotes are not on, then add necessary slashes - if (!get_magic_quotes_gpc()) - $mahara_path = addslashes($mahara_path); - - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('mahara', '$mahara_path')"; - mysql_query($sql, $db); - $msg->addFeedback('MAHARA_MINURL_ADD_SAVED'); - - header('Location: '.$_SERVER['PHP_SELF']); - exit; - } -} - -if (isset($_config['mahara'])) { - if (!file_exists($_config['mahara'].'config.php')) - $msg->addError ("MAHARA_ERROR_PATH"); -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> - -
    -
    -
    -

    - - -
    - -
    - -
    -
    -
    - - - - - - - - diff --git a/mods/mahara/mahara.gif b/mods/mahara/mahara.gif deleted file mode 100644 index 4c08f10dcae483c0f2e1563dbf0f637c6c24b6d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1883 zcmV-h2c-B%Nk%w1VLSjl0QUd@c9ck*nT4pfC)Cr+Q+gs?g)Db-R-m1X^78MUtZ41* z=l1sXYh*IEv!2z{#e<|<+u_T8cul*xt+cYF=;z?f%fWk-RHUMj=IYzX)woGSBI)Sj z-Q3da>gCJHx%c+=iKk+0i%MdPEt{)8b(Scyy@~Jc>W7*~<>lakohgfmbL{Kp(%8C8 zavj6Lw(acblA}vnh9<45l#r(=qq>MfJsVzyF=UJ~fPG|=qE}K)EMbN_!N05U@9TVc zV5Ojfkc@X|iA8XYP2J_whMHCI@b2>R?u(sNX^=PW?dXJoYNMcz#l*R&rIe+!Fs-VY zh=N*jh$fMYXLF8FpszQ_&#GmJLiqUixX7klhbQLc-bFthVO%}%^6S99vt?mIx3rzC z!jrzdu$-zxiG*a~;M&T_w^>v*hoLEHWJQv#aBXQ#V1_nxZ&cdZ(cw8xzG_4HkcCy0e_VqQU&k#*nR*vQ7b>+0us zkW;U%o0_RfxVEb9?&)-rJ8^7FSbZPF!L4P9J4tUFf0#;4M?AO-MTUIxIl~z|$FGfKhZD>bb zb_MnI^z`)dXnz%(mUZ#)?7YUAb#6cK@a*;V^YQWS@$>Ais*myT?R}9p@bK;G>E!kF z^Yrxd_4M-G+tu#v>*?v{>gndN#h3N=^Xu#A;ON-+_xIe})0e12uDd1k_VB5vmvE3m z$HcRInOLd6j;Xwpr=y5dPcOByn4qyIu)mz3u0ZPUC+gw=B(5IMyN;%H0}aK@ZFcL`R8tr1xf^4gOSELAY#foBmok%f>D3#@k=G+My7jh;es`Fl`2 z#FSI%louS8#ReNT&$FQaI@>i%5FwPc6NGSs&5j*xvN%FDs|&Bixvl1~PnSfD9xfyn5H2oNZD2LO1bP!AlZ z5P8Zv#kAULAu?wF@c>S)g@G4X^}v!IE2LPUnjnH$KuD}8R<@5lgT?d;S)!aGkT^o5 z2CN`N01&G!T@VS_K8#2u$|b54V#Ppu5WtyalEK>3DB99>2X&^w5?3KDoaGMsqj@uzVu*W!zV51g4o2G$VkXvba4yW#0$6J@yDd3GI3%h zWwBVscHtGs5&W*x0>mGq(t;*@)vSw*wzTWiKKJ3Z4!WR_^2yMj5D>_hHP>7c65?bW z)n?NQ0zd&3q7sN8YyTYcAT5x>wJLClAOeFs@AGs| zm29fF-a=IW2n)DyUn0s4VbgVY7E|b{xZ+cw@`(szjWq@=H-u`qS3<0r=H{GFAv6JD zSv3M2NYK3%sYhA2TVdgqC%T8I z{PIG#K!Q?EpkWKGXpsZch08~%eT1Gk-a-mM0YySM)Nggg?MLkp;QF<^_Z}Mr6g>k_ z0?hLYIpuE^3vm~^|NeL1A;rraF%JP4Fa?UJOh5WztD^wWIS`EB_h^ES8GucJ{g6h= zvJjgNl16}!6978Ufd)r}qaVuIAO}l>7mvk2g!3Rl4ECd*FdWV_1!|iJQb2;9gaJ^> z=|?O;)NnXdd?^M5B1H^r(T4@{XMz0~f;%1n0OAmW5F(HTFVv6$M4*sEP+TAe`jCM# VvSJ9)2xE%E$i_B0F(d&206Xu>wzB{L diff --git a/mods/mahara/mahara_login.php b/mods/mahara/mahara_login.php deleted file mode 100644 index ff3ad151f..000000000 --- a/mods/mahara/mahara_login.php +++ /dev/null @@ -1,199 +0,0 @@ -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 ****/ - -/*~~~~~~~~~~~~~~~~~~~~~~~end of vitals.inc.php~~~~~~~~~~~~~~~~~~~~~~*/ - - - - - -// Read Mahara login information from cookies passed by ATutor -$usr = array(); -if (isset($_COOKIE['ATutor_Mahara'])) { - foreach ($_COOKIE['ATutor_Mahara'] as $name => $value) { - $usr[$name] = $value; - - // expire the cookie - ATutor.setcookie ("ATutor_Mahara[".$name."]", "", time() - 3600); - } - //expire the cookie array - ATutor.setcookie ("ATutor_Mahara", "", time() - 3600); -} else { - echo 'Unable to detect cookies or the session has timed out. Please check that cookies are enabled on your browser and try again.'; - exit; -} - -// Get password from ATutor's database -$sql = "SELECT password FROM ".TABLE_PREFIX."mahara WHERE at_login='".$usr["at_login"]."' AND username='".$usr["username"]."' AND SHA1(password)='".$usr["password"]."'"; -$result = mysql_query($sql, $db); -if (!($row = @mysql_fetch_array($result))) { - echo 'Incorrect login information. Please check with course instructor or administrator.'; - exit; -} else { - $pwd = $row[0]; - - if (isset($_config['mahara'])) { - - /****** Taken from index.php of /mahara *****/ - define('INTERNAL', 1); - define('PUBLIC', 1); - define('MENUITEM', ''); - define (MAHARA_PATH, $_config['mahara']); - require (MAHARA_PATH.'init.php'); - define('TITLE', get_string('home')); - - // Check if user exists in Mahara - if (!(record_exists('usr', 'username', $usr["username"]))) { - // Reconnect to ATutor Database and remove the record from the mahara table - $db_atutor = @mysql_connect(DB_HOST . ':' . DB_PORT, DB_USER, DB_PASSWORD); - if (!$db_atutor) { - /* 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_atutor)) { - 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; - } - - // Delete record from ATutor database since it should not be there - $sql = "DELETE FROM ".TABLE_PREFIX."mahara WHERE at_login='".$usr["at_login"]."'"; - - $result = mysql_query($sql, $db_atutor); - - echo "Successfully synchronized user login with Mahara database. Please refresh the page from ATutor."; - exit; - } - - session_start(); - - /*~~~~~~~~~~~copied from index.php of Mahara~~~~~~~~~~~~~~~*/ - // Check for whether the user is logged in, before processing the page. After - // this, we can guarantee whether the user is logged in or not for this page. - if (!$USER->is_logged_in()) { - $lang = param_alphanumext('lang', null); - if (!empty($lang)) { - $SESSION->set('lang', $lang); - } - - // Read login information - $values['login_username'] = $usr["username"]; - $values['login_password'] = $pwd; - $values['submit'] = "Login"; - $values['sesskey'] = ""; - $values['pieform_login'] = ""; - - // login - login_submit(null, $values); - - $adminpage = ($USER->get('admin')) ? 'admin/' : ''; - } - - /* Logged in session should be created. Now redirect to the Mahara page - and it should read from this session - */ - header('Location: '.get_config('wwwroot').$adminpage); - /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - } else { - echo 'You have incorrect config settings for the Mahara module.'; - exit; - } -} - - -?> \ No newline at end of file diff --git a/mods/mahara/module.php b/mods/mahara/module.php deleted file mode 100644 index 4e2c7e3d9..000000000 --- a/mods/mahara/module.php +++ /dev/null @@ -1,52 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_MAHARA', $this->getAdminPrivilege()); - - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_group_tool = $_student_tool = 'mods/mahara/index.php'; - - - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_MAHARA, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/mahara/index_admin.php'); - $this->_pages['mods/mahara/index_admin.php']['title_var'] = 'mahara'; - $this->_pages['mods/mahara/index_admin.php']['parent'] = AT_NAV_ADMIN; -} - -/******* - * instructor Manage section: - */ -//$this->_pages['mods/mahara/index_instructor.php']['title_var'] = 'mahara'; -//$this->_pages['mods/mahara/index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages['mods/mahara/index.php']['title_var'] = 'mahara'; -$this->_pages['mods/mahara/index.php']['img'] = 'mods/mahara/mahara.gif'; - -/* my start page pages */ -$this->_pages[AT_NAV_START] = array('mods/mahara/index.php'); -$this->_pages['mods/mahara/index.php']['title_var'] = 'mahara'; -$this->_pages['mods/mahara/index.php']['parent'] = AT_NAV_START; - -?> \ No newline at end of file diff --git a/mods/mahara/module.sql b/mods/mahara/module.sql deleted file mode 100644 index b46825c6c..000000000 --- a/mods/mahara/module.sql +++ /dev/null @@ -1,21 +0,0 @@ -# sql file for mahara module - -CREATE TABLE `mahara` ( - `at_login` varchar(20) NOT NULL default '', - `username` varchar(30) character set latin1 collate latin1_general_ci NOT NULL, - `password` varchar(40) character set latin1 collate latin1_general_ci NOT NULL, - PRIMARY KEY (`at_login`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - -INSERT INTO `config` VALUES ('mahara', ''); - -INSERT INTO `language_text` VALUES ('en', '_module','mahara','ePortfolio',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','mahara_location','Enter the full path to your Mahara installation:
    Example on Windows: C:\webroot\mahara\
    Example on Linux: /usr/local/apache/htdocs/mahara/
    ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','mahara_new_win','Open Mahara in a New Window',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','mahara_opened','Mahara Opened in a New Window',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_MAHARA_MINURL_ADD_SAVED','Location of Mahara was successfully saved.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_MAHARA_LOGIN','Login to ATutor to access your ePortfolio.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_MAHARA_MINURL_ADD_EMPTY','You must enter a path to the location of your Mahara installation.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_MAHARA_ERROR_INSTALL','Mahara not installed! Please create config.php from config-dist.php',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_MAHARA_ERROR_PATH','Unable to detect Mahara installation. Please check the path and make sure Mahara is set up correctly.',NOW(),''); diff --git a/mods/mahara/module.xml b/mods/mahara/module.xml deleted file mode 100644 index b2bfeea96..000000000 --- a/mods/mahara/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Mahara - Mahara is an open source e-portfolio, weblog, resume builder and social networking system, connecting users and creating online learner communities. Mahara is designed to provide users with the tools to demonstrate their life-long learning, skills and development over time to selected audiences. - - - ATutor - info@atutor.ca - - - http://www.mahara.org - BSD - - 0.4 - 2010-10-25 - stable - This module requires Mahara to be installed first on the same server as ATutor. Refer to the README file included with the Mahara module source code for more details. - - \ No newline at end of file diff --git a/mods/mahara/module_delete.php b/mods/mahara/module_delete.php deleted file mode 100644 index 42a86253d..000000000 --- a/mods/mahara/module_delete.php +++ /dev/null @@ -1,35 +0,0 @@ - \ No newline at end of file diff --git a/mods/mahara/module_install.php b/mods/mahara/module_install.php deleted file mode 100644 index 1d6f00797..000000000 --- a/mods/mahara/module_install.php +++ /dev/null @@ -1,67 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/mahara/module_uninstall.php b/mods/mahara/module_uninstall.php deleted file mode 100644 index 60ce25da8..000000000 --- a/mods/mahara/module_uninstall.php +++ /dev/null @@ -1,26 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/mahara/new_account.php b/mods/mahara/new_account.php deleted file mode 100644 index cae47c02a..000000000 --- a/mods/mahara/new_account.php +++ /dev/null @@ -1,244 +0,0 @@ -username = $row['login']; -$registration->firstname = $row['first_name']; -$registration->lastname = $row['last_name']; -$registration->password = $row['password']; -$registration->email = $row['email']; - -define (MAHARA_PATH, $_config['mahara']); - -/******************from init.php*************************/ -define('INTERNAL', 1); -define('PUBLIC', 1); -define('SECTION_PLUGINTYPE', 'core'); -define('SECTION_PLUGINNAME', 'site'); -define('SECTION_PAGE', 'register'); - -$CFG = new StdClass; -$CFG->docroot = MAHARA_PATH; - -// Figure out our include path -if (!empty($_SERVER['MAHARA_LIBDIR'])) { - $CFG->libroot = $_SERVER['MAHARA_LIBDIR']; -} else { - $CFG->libroot = MAHARA_PATH. 'lib/'; -} -set_include_path($CFG->libroot . PATH_SEPARATOR . $CFG->libroot . 'pear/' . PATH_SEPARATOR . get_include_path()); - -// Set up error handling -require(MAHARA_PATH.'lib/errors.php'); - -if (!is_readable($CFG->docroot . 'config.php')) { - // @todo Later, this will redirect to the installer script. For now, we - // just log and exit. - log_environ(_AT('MAHARA_ERROR_INSTALL')); - header('Location: '.AT_BASE_HREF); -} - -require(MAHARA_PATH.'config.php'); -$CFG = (object)array_merge((array)$cfg, (array)$CFG); - -// Fix up paths in $CFG -foreach (array('docroot', 'dataroot') as $path) { - $CFG->{$path} = (substr($CFG->{$path}, -1) != DIRECTORY_SEPARATOR) ? $CFG->{$path} . DIRECTORY_SEPARATOR : $CFG->{$path}; -} - -// xmldb stuff -$CFG->xmldbdisablenextprevchecking = true; -$CFG->xmldbdisablecommentchecking = true; - -// ensure directorypermissions is set -if (empty($CFG->directorypermissions)) { - $CFG->directorypermissions = 0700; -} - -// core libraries -require(MAHARA_PATH.'lib/mahara.php'); -ensure_sanity(); -require(MAHARA_PATH.'auth/internal/lib.php'); -require(MAHARA_PATH.'lib/dml.php'); -require(MAHARA_PATH.'lib/ddl.php'); -require(MAHARA_PATH.'lib/activity.php'); -require(MAHARA_PATH.'lib/user.php'); -require(MAHARA_PATH.'lib/web.php'); - -// Database access functions -require(MAHARA_PATH.'lib/adodb/adodb-exceptions.inc.php'); -require(MAHARA_PATH.'lib/adodb/adodb.inc.php'); - -try { - // ADODB does not provide the raw driver error message if the connection - // fails for some reason, so we use output buffering to catch whatever - // the error is instead. - ob_start(); - - $db = &ADONewConnection($CFG->dbtype); - $dbgenerator = null; - if (empty($CFG->dbhost)) { - $CFG->dbhost = ''; - } - else if (!empty($CFG->dbport)) { - $CFG->dbhost .= ':'.$CFG->dbport; - } - if (!empty($CFG->dbpersist)) { // Use persistent connection (default) - $dbconnected = $db->PConnect($CFG->dbhost,$CFG->dbuser,$CFG->dbpass,$CFG->dbname); - } - else { // Use single connection - $dbconnected = $db->Connect($CFG->dbhost,$CFG->dbuser,$CFG->dbpass,$CFG->dbname); - } - - $db->SetFetchMode(ADODB_FETCH_ASSOC); - configure_dbconnection(); - ensure_internal_plugins_exist(); - - ob_end_clean(); -} -catch (Exception $e) { - $errormessage = ob_get_contents(); - if (!$errormessage) { - $errormessage = $e->getMessage(); - } - ob_end_clean(); - $errormessage = get_string('dbconnfailed', 'error') . $errormessage; - throw new ConfigSanityException($errormessage); -} -try { - db_ignore_sql_exceptions(true); - load_config(); - db_ignore_sql_exceptions(false); -} -catch (SQLException $e) { - db_ignore_sql_exceptions(false); -} - - -// Only do authentication once we know the page theme, so that the login form -// can have the correct theming. -require_once(MAHARA_PATH.'auth/lib.php'); -$USER = new LiveUser(); -/***************end from init.php*************************/ - - -/*~~~~~~~~~modified from register.php~~~~~~~~~~*/ -$random_password = substr(md5($registration->password.rand(100000, 999999)), 2, 8); - -/*-- from register_submit function --*/ -$registration->salt = substr(md5(rand(1000000, 9999999)), 2, 8); -$registration->password = AuthInternal::encrypt_password($random_password, $registration->salt); -$registration->expiry = NULL; -/*-----------------------------------*/ - - -// Check if user already exists in Mahara -if ($data_record = get_record('usr', 'username', $registration->username)) { - $registration -> id = $data_record -> id; - update_record('usr', $registration, 'username'); -} else { - create_registered_user(); // Send register info to create a new account -} - -// Reconnect to ATutor Database -$db_atutor = @mysql_connect(DB_HOST . ':' . DB_PORT, DB_USER, DB_PASSWORD); -if (!$db_atutor) { - /* 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_atutor)) { - 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; -} - -// Store data into ATutor Databse -$sql = "INSERT INTO ".TABLE_PREFIX."mahara SET at_login='".$_SESSION['login']."', username='".$registration->username."', password='".$random_password."'"; -if (!mysql_query($sql, $db_atutor)) - exit; // in case there's some external error; prevent being caught in an infinite loop - - -/** - * This function is copied and modified from register.php of Mahara - * - * @param array profilefields Array of values from registration form. In this module, we're not using a form so we don't pass anything - * @return boolean Returns true if function exits without any problems - */ -function create_registered_user($profilefields=array()) { - global $registration, $USER; - - db_begin(); - - // Move the user record to the usr table from the registration table - $registrationid = $registration->id; - unset($registration->id); - unset($registration->expiry); - if ($expirytime = get_config('defaultaccountlifetime')) { - $registration->expiry = db_format_timestamp(time() + $expirytime); - } - $registration->lastlogin = db_format_timestamp(time()); - - $user = new User(); - $user->username = $registration->username; - $user->password = $registration->password; - $user->salt = $registration->salt; - $user->passwordchange = 0; - $user->active = 1; - $user->authinstance = $authinstance->id; - $user->firstname = $registration->firstname; - $user->lastname = $registration->lastname; - $user->email = $registration->email; - $user->commit(); - - $registration->id = $user->id; - - // Insert standard stuff as artefacts - set_profile_field($user->id, 'email', $registration->email); - set_profile_field($user->id, 'firstname', $registration->firstname); - set_profile_field($user->id, 'lastname', $registration->lastname); - if (!empty($registration->lang) && $registration->lang != 'default') { - set_account_preference($user->id, 'lang', $registration->lang); - } - - // Set mandatory profile fields - foreach(ArtefactTypeProfile::get_mandatory_fields() as $field => $type) { - // @todo here and above, use the method for getting "always mandatory" fields - if (in_array($field, array('firstname', 'lastname', 'email'))) { - continue; - } - set_profile_field($user->id, $field, $profilefields[$field]); - } - - db_commit(); - handle_event('createuser', $registration); - - return true; -} - -?> \ No newline at end of file diff --git a/mods/mahara/new_account_admin.php b/mods/mahara/new_account_admin.php deleted file mode 100644 index 920576ec7..000000000 --- a/mods/mahara/new_account_admin.php +++ /dev/null @@ -1,281 +0,0 @@ -username = $row['login']; -if (isset($row['real_name']) && $row['real_name'] != '') - $registration->firstname = $row['real_name']; -else - $registration->firstname = $row['login']; -$registration->lastname = ' '; // mahara also requires lastname so enter a space char. -$registration->password = $row['password']; -$registration->email = $row['email']; - -define (MAHARA_PATH, $_config['mahara']); - -/******************from init.php*************************/ -define('INTERNAL', 1); -define('PUBLIC', 1); -define('SECTION_PLUGINTYPE', 'core'); -define('SECTION_PLUGINNAME', 'site'); -define('SECTION_PAGE', 'register'); - -$CFG = new StdClass; -$CFG->docroot = MAHARA_PATH; - -// Figure out our include path -if (!empty($_SERVER['MAHARA_LIBDIR'])) { - $CFG->libroot = $_SERVER['MAHARA_LIBDIR']; -} else { - $CFG->libroot = MAHARA_PATH. 'lib/'; -} -set_include_path($CFG->libroot . PATH_SEPARATOR . $CFG->libroot . 'pear/' . PATH_SEPARATOR . get_include_path()); - -// Set up error handling -require(MAHARA_PATH.'lib/errors.php'); - -if (!is_readable($CFG->docroot . 'config.php')) { - // @todo Later, this will redirect to the installer script. For now, we - // just log and exit. - log_environ(_AT('MAHARA_ERROR_INSTALL')); - header('Location: '.AT_BASE_HREF); -} - -require(MAHARA_PATH.'config.php'); -$CFG = (object)array_merge((array)$cfg, (array)$CFG); - -// Fix up paths in $CFG -foreach (array('docroot', 'dataroot') as $path) { - $CFG->{$path} = (substr($CFG->{$path}, -1) != DIRECTORY_SEPARATOR) ? $CFG->{$path} . DIRECTORY_SEPARATOR : $CFG->{$path}; -} - -// xmldb stuff -$CFG->xmldbdisablenextprevchecking = true; -$CFG->xmldbdisablecommentchecking = true; - -// ensure directorypermissions is set -if (empty($CFG->directorypermissions)) { - $CFG->directorypermissions = 0700; -} - -// core libraries -require(MAHARA_PATH.'lib/mahara.php'); -ensure_sanity(); -require(MAHARA_PATH.'auth/internal/lib.php'); -require(MAHARA_PATH.'lib/dml.php'); -require(MAHARA_PATH.'lib/ddl.php'); -require(MAHARA_PATH.'lib/activity.php'); -require(MAHARA_PATH.'lib/user.php'); -require(MAHARA_PATH.'lib/web.php'); - -// Database access functions -require(MAHARA_PATH.'lib/adodb/adodb-exceptions.inc.php'); -require(MAHARA_PATH.'lib/adodb/adodb.inc.php'); - -try { - // ADODB does not provide the raw driver error message if the connection - // fails for some reason, so we use output buffering to catch whatever - // the error is instead. - ob_start(); - - $db = &ADONewConnection($CFG->dbtype); - $dbgenerator = null; - if (empty($CFG->dbhost)) { - $CFG->dbhost = ''; - } - else if (!empty($CFG->dbport)) { - $CFG->dbhost .= ':'.$CFG->dbport; - } - if (!empty($CFG->dbpersist)) { // Use persistent connection (default) - $dbconnected = $db->PConnect($CFG->dbhost,$CFG->dbuser,$CFG->dbpass,$CFG->dbname); - } - else { // Use single connection - $dbconnected = $db->Connect($CFG->dbhost,$CFG->dbuser,$CFG->dbpass,$CFG->dbname); - } - - $db->SetFetchMode(ADODB_FETCH_ASSOC); - configure_dbconnection(); - ensure_internal_plugins_exist(); - - ob_end_clean(); -} -catch (Exception $e) { - $errormessage = ob_get_contents(); - if (!$errormessage) { - $errormessage = $e->getMessage(); - } - ob_end_clean(); - $errormessage = get_string('dbconnfailed', 'error') . $errormessage; - throw new ConfigSanityException($errormessage); -} -try { - db_ignore_sql_exceptions(true); - load_config(); - db_ignore_sql_exceptions(false); -} -catch (SQLException $e) { - db_ignore_sql_exceptions(false); -} - - -// Only do authentication once we know the page theme, so that the login form -// can have the correct theming. -require_once(MAHARA_PATH.'auth/lib.php'); -$USER = new LiveUser(); -/***************end from init.php*************************/ - - -/*~~~~~~~~~modified from register.php~~~~~~~~~~*/ -$random_password = substr(md5($registration->password.rand(100000, 999999)), 2, 8); - -/*-- from register_submit function --*/ -$registration->salt = substr(md5(rand(1000000, 9999999)), 2, 8); -$registration->password = AuthInternal::encrypt_password($random_password, $registration->salt); -$registration->expiry = NULL; -/*-----------------------------------*/ - - -check_create_admin(); - - - /** - * Uses global variable $registration and checks if the user - * is registered in Mahara as an admin. If so, the record is - * updated. If not, a new Mahara is created using the login name - * or the login name appended by random characters (if the username - * exists in Mahara but not as an admin). This function recursively - * calls itself until a Mahara account is created/updated. - * @param void - * @access private - * @return void - * @author Boon-Hau Teh - */ -function check_create_admin() { - global $registration; - - // Check if user already exists in Mahara - if ($data_record = get_record('usr', 'username', $registration->username)) { - // Check if user is an admin on Mahara as well - if ($data_record -> admin == 1) { - $registration -> id = $data_record -> id; - update_record('usr', $registration, 'username'); - } else { - // create a new admin account with a different name - $registration->username = $_SESSION['login'].substr(md5(rand(100, 999)), 2, 5); - check_create_admin(); // Send register info to create a new account - } - } else { - create_admin_user(); // Send register info to create a new account - } -} - -// Reconnect to ATutor Database -$db_atutor = @mysql_connect(DB_HOST . ':' . DB_PORT, DB_USER, DB_PASSWORD); -if (!$db_atutor) { - /* 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_atutor)) { - 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; -} - -// Store data into ATutor Databse -$sql = "INSERT INTO ".TABLE_PREFIX."mahara SET at_login='".$_SESSION['login']."', username='".$registration->username."', password='".$random_password."'"; -if (!mysql_query($sql, $db_atutor)) - exit; // in case there's some external error; prevent being caught in an infinite loop - - -/** - * This function is copied and modified from register.php of Mahara to create an admin account - * - * @param array profilefields Array of values from registration form. In this module, we're not using a form so we don't pass anything - * @return boolean Returns true if function exits without any problems - */ -function create_admin_user($profilefields=array()) { - global $registration, $USER; - - db_begin(); - - // Move the user record to the usr table from the registration table - $registrationid = $registration->id; - unset($registration->id); - unset($registration->expiry); - if ($expirytime = get_config('defaultaccountlifetime')) { - $registration->expiry = db_format_timestamp(time() + $expirytime); - } - $registration->lastlogin = db_format_timestamp(time()); - - $user = new User(); - $user->username = $registration->username; - $user->password = $registration->password; - $user->salt = $registration->salt; - $user->passwordchange = 0; - $user->active = 1; - $user->authinstance = $authinstance->id; - $user->firstname = $registration->firstname; - $user->lastname = $registration->lastname; - $user->email = $registration->email; - $user->admin = 1; - $user->commit(); - - $registration->id = $user->id; - - // Insert standard stuff as artefacts - set_profile_field($user->id, 'email', $registration->email); - set_profile_field($user->id, 'firstname', $registration->firstname); - set_profile_field($user->id, 'lastname', $registration->lastname); - if (!empty($registration->lang) && $registration->lang != 'default') { - set_account_preference($user->id, 'lang', $registration->lang); - } - - // Set mandatory profile fields - foreach(ArtefactTypeProfile::get_mandatory_fields() as $field => $type) { - // @todo here and above, use the method for getting "always mandatory" fields - if (in_array($field, array('firstname', 'lastname', 'email'))) { - continue; - } - set_profile_field($user->id, $field, $profilefields[$field]); - } - - db_commit(); - handle_event('createuser', $registration); - - return true; -} - -?> \ No newline at end of file diff --git a/mods/marratech/index.php b/mods/marratech/index.php deleted file mode 100644 index 97d5d68d1..000000000 --- a/mods/marratech/index.php +++ /dev/null @@ -1,13 +0,0 @@ - -
    - \ No newline at end of file diff --git a/mods/marratech/marratech.php b/mods/marratech/marratech.php deleted file mode 100644 index 30dcafcf6..000000000 --- a/mods/marratech/marratech.php +++ /dev/null @@ -1,70 +0,0 @@ -addError('MARRATECHURL_ADD_EMPTY'); - } - - if (!$msg->containsErrors()) { - $_POST['uri'] = $addslashes($_POST['uri']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('marratech', '$_POST[uri]')"; - mysql_query($sql, $db); - $msg->addFeedback('MARRATECHURL_ADD_SAVED'); - - header('Location: '.$_SERVER['PHP_SELF']); - exit; - } -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> - - -
    -
    -

    -
    -
    -
    - -
    -
    -
    - -
    -
    -

    -
    -
    - - -
    -
    -
    -

    - - -
    -
    - -
    -
    -
    -
    - - - - -
    - \ No newline at end of file diff --git a/mods/marratech/marratech_logo.jpg b/mods/marratech/marratech_logo.jpg deleted file mode 100644 index f9c33f406a5abee284dfd06c1806f6712a83fe1b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1350 zcmb7;X;4#l6vh89FCmE_;U%D=Ss(;)j{#JON{CJ~fRYF$nA&kGN-K*CRAk2z6tFA> z1Ox^!f&xaA)qr6~Nm&FPa6uvnse>Ympe#}#eYGFjuRV9}`Ebvi-(2lW?Hgd=Bybb} z2!a3y9iSZqE4~RlZ>FN^o5E7Y; zkPw8jg1VAoxY`IoR++9^O`|aw49ZF-i%Dlu=?wbc5D2Z}b@2KGf7#P6NKi__J0{S8ZV=-uIWdJZ32!=5*9)tfHLKql}13C!V zl!NC}m}Z8SF2~RPl0+~v-{bm&U!)8z8AB-Yzd!(C0S2doMrH`gLxH$|V+e!5Sh6Yq zBgf@jlB`tw3h1F_^oRf+=m@A|hAwGTgB!W3&Arb}#s;A&(K}miZliDJ_vyP{Ix7+$ zA5JCe__MrZ{69wt&`O2UtM>jx-=ovi0H=#1mF_)$P4y$knlCLbgwLPc;oiTb5^tSb zMieoUOA>vEeDCyvl&CvzLt<`VmFy}IlI=pR)7!`Nov~CN$@1OrbD3IS_}L>}p1=8! zs}NeyWuK047K}&iAJa?@s6STUHhvI#(S<83$)B4SH8UcpbKSb{Jo}pW1&7vDYRb8L zlHE`JMvmzil#oEGeMsPlNdSD1ExG@E<5?fQI~T6UniqdJTzq032^&+(PpwJN2%^*C zevEIEPjoddGm$o8kv#Xq&7gHGb7$E$amKK^`8*>fYtb z;HV25!ct{tDk?oK1+n8NQ_5~@L5bhv*|2G|iXxAIB^<|Q_mk2WG3DkydHCQFk*N)9 zE3Cq22YtF1|9Z#e9hB5W^Y9Au!7DbuYGft5969`EgOE#`LK5loYb)Js?hXya^-&TX zXWhvDdeK(m^^cefT^m|DJ+vTq@7V~uSMAon&u2wNX78?76pn|oY}C%pNgV?@^Pxd^ z&-(^wD>`le2>R0B zAeD9{J*-)h7iAi9&i3DoleCt`R#gjlII-lV)ih8~g;)kr^|M#gRPrs!afQ(Zi;ivz z@j<^)uUQMe%1wCFc9AAxbjp>Qd8xWO&VOj8pIbMOKXRakXZ_luR|MFjwhPn#<(q8v zjH<}Y_>2OxJf5TOlJS~F;ed;hk)^=b(_g*sk{mKBc9iCL$*-vXI47(pep}dxsSw%> z=cG)METo?TdyG>$yMRi~Nr(!A{ zQ9Q9^M0Yn$5%H11)e|j6bvKF~X6V9uy_B(%o|Xk~CroU3g{BN@3bZ5Dzm@HAeLj>` NZum4$aJ@*|`xju}EgetAdminPrivilege()); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_student_tool = 'mods/marratech/index.php'; - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_MARRATECH, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/marratech/marratech.php'); - $this->_pages['mods/marratech/marratech.php']['title_var'] = 'marratech'; - $this->_pages['mods/marratech/marratech.php']['parent'] = AT_NAV_ADMIN; -} - -/******* - * student page. - */ -$this->_pages['mods/marratech/index.php']['title_var'] = 'marratech'; -$this->_pages['mods/marratech/index.php']['img'] = 'mods/marratech/marratech_logo.jpg'; - - -?> \ No newline at end of file diff --git a/mods/marratech/module.sql b/mods/marratech/module.sql deleted file mode 100644 index 9e1bcb807..000000000 --- a/mods/marratech/module.sql +++ /dev/null @@ -1,12 +0,0 @@ -# sql file for Marratech module - -INSERT INTO `language_text` VALUES ('en', '_module', 'marratech_missing_url', 'You must supply the URL to your Marratech installation in the field below.', NOW(), ''); - -INSERT INTO `language_text` VALUES ('en', '_module','marratech','Marratech',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','marratech_text','Use Marratech to conduct live collaborative activities.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','marratech_open','Open Marratech Admin',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','marratech_passwordln','(Note: Passwords are case sensitive)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','marratech_location','The location of your Marratech installation. This should be the base URL of your Marratech Manager installation (e.g. http://www.myserver.com:8000). You can also use the demo site if you don\'t yet have Marratech Manager installed (http://www.marratech.com/meetnow.html), though your will not be able to connect to the server admin tools.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','marratech_own_window','Open Marratech in a New Window:',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_MARRATECHURL_ADD_SAVED','Marratech configuration options were successfully saved.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_MARRATECHURL_ADD_EMPTY','You must enter a URL to the location of your Marratech installation.',NOW(),''); diff --git a/mods/marratech/module.xml b/mods/marratech/module.xml deleted file mode 100644 index 015a29a32..000000000 --- a/mods/marratech/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Marratech - Marratech is a collaborative Web conferencing environment. Enjoy real-time video with exceptional quality voice plus an interactive whiteboard. Up to five people can meet, talk, see each other and share documents or pictures and make notes on the free version of Marratech Manager. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.1 - 2006-07-03 - stable - Requires Marratech client be installed on the user's system, and the Marratech Manager on the server the user is connecting to. See http://marratech.com, or http://www.marratech.com/free. - - \ No newline at end of file diff --git a/mods/marratech/module_install.php b/mods/marratech/module_install.php deleted file mode 100644 index bff949cac..000000000 --- a/mods/marratech/module_install.php +++ /dev/null @@ -1,25 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/marratech/readme b/mods/marratech/readme deleted file mode 100644 index 229f39f63..000000000 --- a/mods/marratech/readme +++ /dev/null @@ -1,21 +0,0 @@ -#Marratech module for ATutor readme - -Be sure Marratech Manager is installed and functioning properly before attempting to install this module. If you do not have an Marratech server installation, you might instead use the demo server as a temporary installation location to test the module - -Marratech Demo server: -http://www.marratech.com/meetnow.html - -Requires the Maratech client on the users computer. -http://www.marratech.com/download_content.html - -Installation -1. Unzip the module into the ATutor mods/ directory. -2. Login to ATutor as the administrator and run the ATutor administrator's Install Module tool. Select Marratech to install. -3. Once installed, on the administrator modules screen, enabled to module. -4. Open the administrator's Marratech screen and enter the URL to the Marratech installion you will be using. -5. Click on Open Marratech Admin to manage the Marratech server. - - -See http://www.marratech.com for Marratech licensing information. - - diff --git a/mods/mediawiki/MySQL_Auth/Auth_viaMySQL/Auth_viaMySQL.php b/mods/mediawiki/MySQL_Auth/Auth_viaMySQL/Auth_viaMySQL.php deleted file mode 100644 index 317653ccf..000000000 --- a/mods/mediawiki/MySQL_Auth/Auth_viaMySQL/Auth_viaMySQL.php +++ /dev/null @@ -1,105 +0,0 @@ - 'MySQL Auto Authentication -> Auth_viaMySQL', - 'version' => '1.0', - 'author' => 'John Derby Russell', - 'url' => 'http://www.mediawiki.org/w/index.php/Extension:Auth_viaMySQL', - 'description' => 'Auto-authenticates users using MySQL database', -); - -/** - * - * MySQL Login Database Integration - * - */ - -require_once(MW_INSTALL_PATH.'/MySQLActiveUser.php') ; - -$wgHooks['UserLoadFromSession'][] = 'Auth_viaMySQL'; - -// Kill logout url -$wgHooks['PersonalUrls'][] = 'PersonalUrls_killLogout'; /* Disallow logout link */ - -function Auth_viaMySQL( $user, $result ) { - global $MySQLActiveUserData; - $MySQLActiveUserData->distribute_cookie_data() ; - - wfSetupSession(); - - /** - * A lot of this is from User::newFromName - */ - // Force usernames to capital - global $wgContLang; - - $name = $wgContLang->ucfirst( $MySQLActiveUserData->active_user_name ); - - // Clean up name according to title rules - $t = Title::newFromText( $name ); - if( is_null( $t ) ) { - return(true) ; - } - - $canonicalName = $t->getText(); - - if( !User::isValidUserName( $canonicalName ) ) { - return(true) ; - } - - $user->setName( $canonicalName ); - - $user_id_fromMW_DB = $user->idFromName( $MySQLActiveUserData->active_user_name ) ; - - $user->setId( $user_id_fromMW_DB ); - if ( $user->getID() == 0 ) { - /** - * A lot of this is from LoginForm::initUser - * LoginForm in in the file called SpecialUserLogin.php line 342 (version 1.14.0rc1) - */ - $canonicalName = $t->getText(); - $user->setName( $canonicalName ); - $user->addToDatabase(); - - $user->setEmail( $MySQLActiveUserData->active_user_email ); - $user->setRealName( '' ); - $user->setToken(); - - $user->saveSettings(); - } else { - if ( !$user->loadFromDatabase() ) { - // Can't load from ID, user is anonymous - return(true) ; - } - $user->saveToCache(); - } - - $result = 1; // This causes the rest of the authentication process to be skipped. - return(false); // As should this, according to the internal error report: -} - -// Kill logout url -function PersonalUrls_killLogout($personal_urls, $title) { - $personal_urls['logout'] = null ; - $personal_urls['login'] = null ; - $personal_urls['anonlogin'] = null ; - return true ; -} -?> diff --git a/mods/mediawiki/MySQL_Auth/Auth_viaMySQL/CacheTimer_viaMySQL.php b/mods/mediawiki/MySQL_Auth/Auth_viaMySQL/CacheTimer_viaMySQL.php deleted file mode 100644 index 1d4b49619..000000000 --- a/mods/mediawiki/MySQL_Auth/Auth_viaMySQL/CacheTimer_viaMySQL.php +++ /dev/null @@ -1,36 +0,0 @@ - 'MySQL Cache Timer', - 'version' => '1.0', - 'author' => 'John Derby Russell', - 'url' => 'http://www.mediawiki.org/w/index.php/Extension:Auth_viaMySQL', - 'description' => 'Tells Wiki when to regenerate client cache for users', -); - -require_once(MW_INSTALL_PATH.'/MySQLActiveUser.php') ; - -/** - * - * The MySQL cache epoche timer is for when to rebuild the cache stored on the client side. - * This is ussually done at login. - * - */ - -function CacheTimer_viaMySQL( ) { - global $MySQLActiveUserData ; - $MySQLActiveUserData->distribute_cookie_data() ; - - return $MySQLActiveUserData->active_user_login_time ; -} -?> diff --git a/mods/mediawiki/MySQL_Auth/MySQLActiveUser.php b/mods/mediawiki/MySQL_Auth/MySQLActiveUser.php deleted file mode 100644 index e3bc3e817..000000000 --- a/mods/mediawiki/MySQL_Auth/MySQLActiveUser.php +++ /dev/null @@ -1,48 +0,0 @@ -active_user_name = $username ; - $this->active_user_id = $user_id ; - $this->active_user_password = $password_hash ; - $this->active_user_email = $user_email ; - $this->active_user_login_time = $login_time ; - } - - function clear_cookie() { - $this->active_user_name = "" ; - $this->active_user_id = 0 ; - $this->active_user_password = 0 ; - $this->active_user_email = "" ; - $this->active_user_login_time = 0 ; - setcookie("mysql_active_user", - serialize(array("", "", "", "")), time()-60*60*24*100, "/") ; - } - - function distribute_cookie_data() { - $mysql_cookie_name = "mysql_active_user" ; - - if (isset($_COOKIE[$mysql_cookie_name])) - list($this->active_user_name, - $this->active_user_id, - $this->active_user_password, - $this->active_user_email, - $this->active_user_login_time) = @unserialize($_COOKIE[$mysql_cookie_name]); - } -} - -$MySQLActiveUserData = new MySQLActiveUser(); -?> \ No newline at end of file diff --git a/mods/mediawiki/README b/mods/mediawiki/README deleted file mode 100644 index a41569362..000000000 --- a/mods/mediawiki/README +++ /dev/null @@ -1,96 +0,0 @@ -## MediaWiki Integration module for ATutor - -#################### - -This module allows you to manage MediaWiki as a course tool and open MediaWiki in an iframe within ATutor courses, and MyStart areas. It is a community wiki, meaning all users in all courses can access it. It also creates a single sign-on. When a user logs into ATutor, they are automatically logged into Mediawiki. - -**MediaWiki needs to be installed and configured before installing this module. See the MediaWiki documentation for instructions on installing and configuring it. MediaWiki needs to be installed on the same server as ATutor, though it may be installed in its own database. - -http://www.mediawiki.org/wiki/Installation - - -#################### -Installing the ATutor MediaWiki Module: - -1. Unzip the atutor_mediawiki.x.x.x.zip module file into the ATutor mods/ directory to create a "mediawiki/" directory. -2. Login to ATutor as the admin, click on the Modules tab then click Install Modules. Mediawiki should be listed. Select it and press the Install button. -3. Follow the installer instructions. -4. Once the module is installed, select the Mediawiki module now listed in the available modules in the Module Manager, then press the Enable button. This inserts another main navigation tab above. -5. Click the MediaWiki tab then enter the URL to the base directory under which Mediawiki is run (e.g. http://myserver.com/mediawiki/ , including the trailing slash), then press the Save button. MediaWiki should then appear below. -6. Next set the database access information for MediaWiki in the mw_config.php file in the module directory (e.g mods/mediawiki), then save the file. This information is required if you intended on using the module detailed view to display recent changes in the wiki on the course home page, or on the student tools page. - - -##################### -Authenticate MediaWiki Users from the ATutor Members table (Single Sign-on) - -This section is optional. If not implented, users will need to create an account on MediaWiki, and they'll need to manually login. - -To remove the need to setup separate accounts in MediaWiki and ATutor, you can install the Auth viaMySQL extention. This effectively creates a single sign-on between ATutor and MediaWiki based on ATutor member accounts. - -Extention details can be found at: -http://www.mediawiki.org/wiki/Extension:Auth_viaMySQL -(Just for information about the extension's origin. Instead follow the instructions below) - -Note that you will probably want to install this extension before you start using MediaWiki with ATutor. Otherwise you may have conflicts between ATutor users and independent Mediawiki users owbership of content. The only account that should exist before installing the extension is the admin account created during the MediaWiki installation. - -Copy Auth_viaMySQL.php, CacheTimer_viaMySQL.php, and MySQLActiveUser.php from the ATutor MediaWiki module directory (mods/mediawiki/MySQL_Auth/) to the MediaWiki installation directory as follows: - -MediaWiki/extensions/Auth_viaMySQL/Auth_viaMySQL.php -MediaWiki/extensions/Auth_viaMySQL/CacheTimer_viaMySQL.php -MediaWiki/MySQLActiveUser.php - -(**You'll probably need to create the extensions/Auth_viaMySQL directory, and depending on how MediaWiki was installed, you may need root access to do that and to copy the files into the MediaWiki directory) - -After the files are copied to the MediaWiki installation directory, copy the following code and paste it immediately before the first instance of the "$msg->addFeedback('LOGIN_SUCCESS');" statement of the login.php file located in the root directory of ATutor. This sets the MediaWiki authentication cookie for student and instructor users, but not for admin users. The admin user must login manually using the "MediaWiki Login" link under the MediaWiki tab in the admin area, using the admin login information created during the MediaWiki installation. - -##### -# adjust the path in the first line below to the location of your MediaWiki installation directory. - - $mediawiki_install_path = "/var/lib/mediawiki/"; - require_once($mediawiki_install_path.'MySQLActiveUser.php'); - global $MySQLActiveUserData ; - global $db ; - - $userName = $_POST['login'] ; - $command = "SELECT * FROM ".TABLE_PREFIX."members WHERE login='".$userName."';" ; - $result = mysql_query($command, $db); - $account = mysql_fetch_assoc($result) ; - if ($account) - { - $current_mw_timecode = gmdate( 'YmdHis' ) ; - $MySQLActiveUserData->set_cookie($account['login'], - $account['member_id'], - $account['password'], - $account['email'], - $current_mw_timecode) ; - } -##### - -Copy the following code and paste it immediately after the "require(AT_INCLUDE_PATH.'vitals.inc.php');" statement of the logout.php file located in the root directory of ATutor. This deletes the MediaWiki authentication cookie when a user logs out of ATutor. - -##### -# adjust the path in the first line below to the location of your MediaWiki installation directory. - - $mediawiki_install_path = "/var/lib/mediawiki/"; - require_once($mediawiki_install_path.'MySQLActiveUser.php'); - global $MySQLActiveUserData ; - $MySQLActiveUserData->clear_cookie() ; - -##### - -Add the following lines to the end of the MediaWiki LocalSettings.php file - -##### - - require_once($IP."/extensions/Auth_viaMySQL/Auth_viaMySQL.php"); - require_once($IP."/extensions/Auth_viaMySQL/CacheTimer_viaMySQL.php"); - - $local_var_login_time = CacheTimer_viaMySQL() ; - $wgCacheEpoch = max( $wgCacheEpoch, $local_var_login_time ) ; - $wgCachePages = false ; - $wgEditPageFrameOptions='SAMEORIGIN'; - -##### - - - diff --git a/mods/mediawiki/index.php b/mods/mediawiki/index.php deleted file mode 100644 index d3581fc9a..000000000 --- a/mods/mediawiki/index.php +++ /dev/null @@ -1,26 +0,0 @@ -'._AT('mediawiki_login').''; -} - -?> - - - - - - diff --git a/mods/mediawiki/index_admin.php b/mods/mediawiki/index_admin.php deleted file mode 100644 index b2d578622..000000000 --- a/mods/mediawiki/index_admin.php +++ /dev/null @@ -1,48 +0,0 @@ -$mw_config) - if($key != "submit"){ - $sql="REPLACE INTO ".TABLE_PREFIX."config SET name='$key', value='".$mw_config."'"; - if($result= mysql_query($sql, $db)){ - $msg->addFeedback("MW_CONFIG_SAVED"); - $_config['mw-url'] = $_POST['mw-url']; - - }else{ - $msg->addError("WP_CONFIG_FAIL"); - } - - } -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> - -
    - -
    - - -
    - - - -

    - - -

    ?>

    - - - - - \ No newline at end of file diff --git a/mods/mediawiki/index_instructor.php b/mods/mediawiki/index_instructor.php deleted file mode 100644 index 94aacac04..000000000 --- a/mods/mediawiki/index_instructor.php +++ /dev/null @@ -1,18 +0,0 @@ -'._AT('mediawiki_login').''; -} -?> - - - - - \ No newline at end of file diff --git a/mods/mediawiki/index_mystart.php b/mods/mediawiki/index_mystart.php deleted file mode 100644 index ee93ef80f..000000000 --- a/mods/mediawiki/index_mystart.php +++ /dev/null @@ -1,25 +0,0 @@ -'._AT('mediawiki_login').''; - -} -?> - - - - - \ No newline at end of file diff --git a/mods/mediawiki/index_public.php b/mods/mediawiki/index_public.php deleted file mode 100644 index a7ca3d623..000000000 --- a/mods/mediawiki/index_public.php +++ /dev/null @@ -1,26 +0,0 @@ -'._AT('mediawiki_login').''; - -} -?> - - - - - \ No newline at end of file diff --git a/mods/mediawiki/module.css b/mods/mediawiki/module.css deleted file mode 100644 index 0d3ed7171..000000000 --- a/mods/mediawiki/module.css +++ /dev/null @@ -1,5 +0,0 @@ - - -#frame_set{ - border:none; -} \ No newline at end of file diff --git a/mods/mediawiki/module.php b/mods/mediawiki/module.php deleted file mode 100644 index 257abdf7a..000000000 --- a/mods/mediawiki/module.php +++ /dev/null @@ -1,89 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_MEDIAWIKI', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -// Sidemenu block is disbaled by default in this version of the module -//$this->_stacks['mediawiki'] = array('title_var'=>'mediawiki', 'file'=>'mods/mediawiki/side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('mediawiki', array('title_var' => 'mediawiki', 'file' => './side_menu.inc.php'); - -/******* - * create optional sublinks for module "detail view" on course home page - * when this line is uncommented, "mods/mediawiki/sublinks.php" need to be created to return an array of content to be displayed - */ -$this->_list['mediawiki'] = array('title_var'=>'mediawiki','file'=>'mods/mediawiki/sublinks.php'); - -// Uncomment for tiny list bullet icon for module sublinks "icon view" on course home page -$this->_pages['mods/mediawiki/index.php']['icon'] = 'mods/mediawiki/mw_icon_sm.png'; - -// Uncomment for big icon for module sublinks "detail view" on course home page -//$this->_pages['mods/mediawiki/index.php']['img'] = 'mods/mediawiki/mediawiki.jpg'; - -// ** possible alternative: ** -// the text to display on module "detail view" when sublinks are not available -$this->_pages['mods/mediawiki/index.php']['text'] = _AT('mediawiki_text'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_group_tool = $_student_tool = 'mods/mediawiki/index.php'; - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_MEDIAWIKI, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/mediawiki/index_admin.php'); - $this->_pages['mods/mediawiki/index_admin.php']['title_var'] = 'mediawiki'; - $this->_pages['mods/mediawiki/index_admin.php']['parent'] = AT_NAV_ADMIN; -} - -/******* - * instructor Manage section: - */ -$this->_pages['mods/mediawiki/index_instructor.php']['title_var'] = 'mediawiki'; -$this->_pages['mods/mediawiki/index_instructor.php']['parent'] = 'tools/index.php'; -// ** possible alternative: ** -// $this->pages['./index_instructor.php']['title_var'] = 'mediawiki'; -// $this->pages['./index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages['mods/mediawiki/index.php']['title_var'] = 'mediawiki'; -$this->_pages['mods/mediawiki/index.php']['img'] = 'mods/mediawiki/mw_logo.png'; - -// /* public pages */ -// Uncomment the following three lines if MediaWiki should be accessible from public pages -// for users who are not logged into ATutor - -// $this->_pages[AT_NAV_PUBLIC] = array('mods/mediawiki/index_public.php'); -// $this->_pages['mods/mediawiki/index_public.php']['title_var'] = 'mediawiki'; -// $this->_pages['mods/mediawiki/index_public.php']['parent'] = AT_NAV_PUBLIC; - -/* my start page pages */ -$this->_pages[AT_NAV_START] = array('mods/mediawiki/index_mystart.php'); -$this->_pages['mods/mediawiki/index_mystart.php']['title_var'] = 'mediawiki'; -$this->_pages['mods/mediawiki/index_mystart.php']['parent'] = AT_NAV_START; - -function mediawiki_get_group_url($group_id) { - return 'mods/mediawiki/index.php'; -} - -?> \ No newline at end of file diff --git a/mods/mediawiki/module.sql b/mods/mediawiki/module.sql deleted file mode 100644 index c504ac112..000000000 --- a/mods/mediawiki/module.sql +++ /dev/null @@ -1,13 +0,0 @@ -# sql file for mediawiki integration module - - -INSERT INTO `language_text` VALUES ('en', '_module','mediawiki','MediaWiki',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','mediawiki_text','A sample mediawiki text for detailed homepage.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','mediawiki_admin_login','Login to Administer MediaWiki',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','mediawiki_login_url','MediaWiki Base URL',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','mediawiki_login','MediaWiki Login',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','mediawiki_save','Save',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','mediawiki_no_iframes','Your browser does not support iframes. Got to MediaWiki Login',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','mediawiki_do_setup','Enter the URL to the MediaWiki based Web accessible directory (e.g, http://myserver.com/mediawiki/, including the trailing slash), to have MediaWiki appear here.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_MW_CONFIG_SAVED','MediaWiki configuration successfully saved',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_MW_CONFIG_FAIL','MediaWiki configuration failed to save. ',NOW(),''); \ No newline at end of file diff --git a/mods/mediawiki/module.xml b/mods/mediawiki/module.xml deleted file mode 100644 index 816adefcb..000000000 --- a/mods/mediawiki/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - MediaWiki Integration - This module integrates MediaWiki with ATutor, creating a single sign-on, and making MediaWiki available as a single shared wiki used as a course tool across all courses. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 1.0 - 2011-06-14 - Stable - Be sure to read the README file for the module for details on setting up single sign-on. While usable without single sign-on, it needs to be setup manually. You will be required to enable the module once installed, then enter the URL to MediaWiki through the MediaWiki tab added once enabled. - - diff --git a/mods/mediawiki/module_delete.php b/mods/mediawiki/module_delete.php deleted file mode 100644 index 322d3a611..000000000 --- a/mods/mediawiki/module_delete.php +++ /dev/null @@ -1,21 +0,0 @@ - \ No newline at end of file diff --git a/mods/mediawiki/module_install.php b/mods/mediawiki/module_install.php deleted file mode 100644 index 9a828118f..000000000 --- a/mods/mediawiki/module_install.php +++ /dev/null @@ -1,67 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/mediawiki/module_news.php b/mods/mediawiki/module_news.php deleted file mode 100644 index 92f9eea06..000000000 --- a/mods/mediawiki/module_news.php +++ /dev/null @@ -1,38 +0,0 @@ - $this_time, - 'alt'=>_AT('mediawiki_update'), - 'thumb'=>'mods/mediawiki/mw_icon_sm.png', - 'link'=>' SUBLINK_TEXT_LEN ? ' title="'.$row['page_title'].'"' : '') .'>'. - validate_length($row['page_title'], SUBLINK_TEXT_LEN, VALIDATE_LENGTH_FOR_DISPLAY) .''); - $news_count++; - } - } - } - return $news; - -} -?> diff --git a/mods/mediawiki/module_uninstall.php b/mods/mediawiki/module_uninstall.php deleted file mode 100644 index 9ed6969e7..000000000 --- a/mods/mediawiki/module_uninstall.php +++ /dev/null @@ -1,44 +0,0 @@ -addError(array('MODULE_UNINSTALL', '
  • '.$directory.' can not be removed. Please manually remove it.
  • ')); -} - -/****** - * the following code checks if there are any errors (generated previously) - * then uses the SqlUtility to run reverted database queries of module.sql, - * ie. "create table" statement in module.sql is run as drop according table. - */ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/mediawiki/mw_config.php b/mods/mediawiki/mw_config.php deleted file mode 100644 index c9135e038..000000000 --- a/mods/mediawiki/mw_config.php +++ /dev/null @@ -1,13 +0,0 @@ - \ No newline at end of file diff --git a/mods/mediawiki/mw_connect.php b/mods/mediawiki/mw_connect.php deleted file mode 100644 index ea367b843..000000000 --- a/mods/mediawiki/mw_connect.php +++ /dev/null @@ -1,25 +0,0 @@ - \ No newline at end of file diff --git a/mods/mediawiki/mw_icon_sm.png b/mods/mediawiki/mw_icon_sm.png deleted file mode 100644 index e78f017a2a096b61485c2976409b205f924690f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1040 zcmV+r1n>KaP)Px#32;bRa{vGf5&!@T5&_cPe*6Fc00(qQO+^RW1_=}rGVN*BnE(I-qDe$SR5;6R zlU+=eWdO(j&-=U|=e+NGKHzv14oIlbVMlO7FW4GveOT5;rsC>{|bSce1W^Zh!{`#xQH=kNaayZcc*gx@YU zYWw!;JKuPLeA&|M=e<33vT53Sa?V*_oOn#>?Z58=0OxHG9u`=dS$SMjoWs>yyyu(h z!)>CJy?o(HF}gU}`u4?u8ZYSBJ*b|CwK0DuThN60%L3O>n$KMckbaEC+pB|6EEbkm-@cTMcpJQ`;&loKfVLayDf}MPU?1 zMgklk)KCd}jDd$Kn5e$rfs#$( zcYuiDK&jMFQD<{c^Mpi;*x9*H|8MVeH90!^!z1ThxUY$2QtuNjP)fNTm569N2pVPR zE(295HrLt^q6%>o2GdeY!+%w!L<#Sbd-Ogldl793BH&-2VZ~imn5$!x9Yu0000< KMNUMnLSTY}pY3P> diff --git a/mods/mediawiki/mw_logo.png b/mods/mediawiki/mw_logo.png deleted file mode 100644 index 01d2d9297946b3396d40875868cb69df9ef6d56a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6777 zcmV-<8iwVGP)Px#32;bRa{vGf5&!@T5&_cPe*6Fc00(qQO+^RW1_=%cHOq>w1^@sW3rR#lRA}DK znt8NdMVan@Rkg=&JX6le$vhKCLI?&B2!k>yiZ-ICt#&)0Z3|+1`?hVjb337SV>1c8 z1f^R=)D}b=WeAf3k}yhuB#?pR2M1cO+QYi8b#JZpt+iL}s;}N> zSG`ZY^*#lEpz`3IYyahlb!&XU0l4n7waPcY&~wwJpBh+o>$kg$wMPUCfhr(h?DLar zk2vYWA6E5Wulv6#@(%?j^qTMZv$yCofbylEnmdpH_EEqt}O}tay62bY?-mWXrujSn~f4%nets-V|qUY5x55v|1&QH{LYb zNh5oQ=R!|Cll7{D!5Tmog*9^r58j76T9Qhc2e-x^;Qjjl8C4Fq-*?<6zIpkvJ^zy# z`-6ZvwDb8Do|2TjH2CW0=UobPdG5?xrBb$94hYJYlG|l~vCZE*@{3++WWD1!r0v*h zV_m?`{+N04g7rN;oo1;Lta;bPTMgg?!tOu!rSZOX%@Xmu>~Q`NV0yaTH&?n9S)SWh zZqnx+wJN-^yPhox0w0XQ7nTic&FR%jX~WXR;~z{hRvIH><5)lofxY3fW0!0^D!6Gp zzI9z7=MOJG_JJ<}-M~1&m%qA2-hSq)7$a=bu`yupzWL}|)~%Xa7Z>AV>|lux zeDtZm(S`Pb9Eg7L-4iduo%qtq!w7~(tZy&~U4`{LiB7a# zzOwCvp|-NHSS!#vLYv&yyN1fvcou6>Akx?r_x|fqU)->E&yfXFBptz%JL0`t9#5JA zS|2@sao^5cH||@wdf(-%*S5nw%kI%A8@#6cD(QJ4P*1F0FQ+Nm|$kF)1;3)^2 z8xSd>Et8m>B3B?Z5?2I4hEawrDTE^eMyK=SzWe#rqc%_0U{iJ1!X8VdS zT`@f*rL?B77?I&hg*1l33aYL~ViCq73Juoc7;uEax00~rl1^pFP~xhbs5w_Za9h`9 z%a0$LYlO9~QXru)68s(^tR$H*?PFfA-=1rB0uhkDWUyH98tj2veWahs!`@@D1PGB} ztwPAcY`>CKN5ATvFaG(qAFp52q*UrAYE<;-Nd2a-d}Zt}fAsk7;cY*!#wE{qNFmB$ zfJcGNQbd}OS|7(ol%=AHB+?ckB%bS14hxb*ph{(wn^;0ukZB6#;user910PETSAdp z6Z_(%cb~X=$K!p|bgmrz?XO>3QKq@eqr9j^XTScf2FotSPOng}T6e`~KL4TNj|Kgn zt<;Thl||1iEgt=O_5GE_k6(1yGQC~{ju2Em4_Ro6MoJzC!qh>zDG?r>JVz;yz%$6A zAg_jaLSaLLEEL)ms3M?HIacK$%NUi~y3EA+A6om&Prm=qn%@^uDbgtkC`^`N^=~_R zV++JTv%B_9J-DdLu3Nm=U2RcF8DN})V)c>wb;D0qqJ_)iZrw2yiNc&?xL5L<&IEv{EU0lA}bbAgpE#)xZ$Y0eZgivEblQ$A+F?Ga@J}q)Dw) zR75FkLaLdWfUs6jkpkHf$WTzUG+x=ES!gl~b*1QNP2meFo<&zB7=fTdQFbY02Ew6m zB%YLvJXKG&JScv-=Ez`4t*e&hmeRK2eBsfnra9?dCtv=N^S1xsfk%JkiFdtr1Mhrq zSS#6T@ps=`@@lthChF?8f3;!h%&DioY=6tfRWm(aJm~th%f9u^Jv;mQ$6tH$3CR`p zg&`$XQ1V=`8s8Xt=2+r}C2HoBeMw+JU_n@t)W`S<6oOD$8Wu`c;MSqA3L!l5E{Ty9 zFfm17vC>Cn8Womttxwc0uqH-18Yzr@@Ui)#8Wi-_I`*TVn|O;je$@u9{kn?k1D&v| zsws@Yl4GqV*A7yp)@muVhUSQ1^g#bsvI85vQd5@eE^e0LdQerGwCyl&xuJ2;yue&2 zR9X<$1^3_8&GBbUk+fa>QcgP(l&Ti%ND5zILl;{p3YlWV5L6W_1;%R3WK5wYnbW}) z4#rVrnM=)W*h{{(Mtt=jSDi(E^BwBI~UDf!?h-~OvhOXWi(Np7Q7EL2g!(F&BL>>Fxz zOF2(zjHIXm1)ZGGwOoG3D$bref=)^lx*%yuDgy%7iI^GO0_++_25s?>y)b}Z5PC^03M{8vZ6^l7@uz!E;;au{qSDeHCuih#SyBNFk z@|VsEf}jVv{v*cfrdb;9ZjB$B`aphQ?9+i`UJ=TQ4IG401)+!tl}1Jx%4*78kRH&O za*48&QW|q;3@QAYAfHL;UhdM`HA5(JiblfZL`qN-6jBmTWGv`w@Wc~7E7u#Qrwkr3 zMOEO00Xol#jm8ubfg-FW!W2HA`C|FjtA23qd+fnW?*d?Q%Wv-TFOmRZ7cW z_=YpTx$;lX>c8gjBcELyDn%(!xLyugp|S`k1FOIn4a&Nq={QsX4@+Ld$|ADbU&yc&<&25qCeJ zp1<^peACm<7Q+BkKLM@J{>Ps9+~zaq9c<0~uLVnYo^$NB`ql&Bw?B%yokN`^)lHI$h<(Qm^{)L;W063Y3M3}pW&p6 zIlV1<`!$V29;PRtTK93PWvbO-y5^;5rBIGUSV7?kWJPjlG~l~8SAX%jD@U)*^YmU| z|9?!tt(EQ-U-lZi?u*3(|9ZsszNL-T)vCtk8D&|<1``yz2G(MwgA@WQ9jp{couZNm zmBe`3VP;q{JX9mdbJD0F5E)kF>>CQ0$pVCzqLd=>3o34%^kB-uxlNqhprwNj9ZGeV zMTbZDWrG){pnSAv$(@jl0*h-4?TD$#uB?;#E$QU$WBdHt+9ikBvB%>tzO?e}_TGDj zlxNNL69@HB+O`{396@cSBhlF$gv^m9#5y^OG6s#bhJpyo3&4!y(bJ#N*{{fKh>lX+ zAZK`=Au9Xi7$|9M%^?>CS7iv-Wn{#m(&y3@r1<2tT4lQC1bAK(JV{$>I#v+pIZ0uO zQ!P4KjPNH^t+!cn%#81lvUy9-PyXs3UUzDC;KnC_rjP<*ED9)XI`sFp-kSWNZEFvF z{m$18ap`kdR1nX($PonxkM+Gg!{)4w|%e zFUvPr3YF5`XGnd6ksgPpD_JLVTP>~g?ax+z^})Y>_Pd$3cg~(;emkLY^_5+`|3Wwa z{>OXDd;Gs{pR}&Y>ZQAFsTN>xg^-dgwuRDCI;JhGaVS)T>?pSGb9jEJ#y}@VsRE%S zX**}$oPd!?kXb<{6K2MsYaqlG1zzDGv?T5bN_{Cw>J#)?vbbRGQ8}HC1Z5DagGZmd z;TG|apT1__mB2BxXa0j?{u$B^-)a6&FzSz97x2)QOuX}>BiZ>MI)2}s+q%zv{JHt! z;cXSM{o&SQPdprsR)W6%YIWSh>j+B$*5EjTB|Rz22bzo>2q4$^q_n7GTo3DJ#2K`s zoMvL_3O!UJa8iZIEcHZl_?ncl5eKi^;i-omf<8gDHzSS>g>>=D)8d2^)GOcf`jzi{ z_NnCN-G`DLKp_TC&6#}s_n#)|f4yStmKTo0D=u`7TdtS<)BCpEz4YkOg^*!Wi_j8l z6A%VB0pFKAv&EK;b%OnmOKPheoO*{y3o;DC^|8jc9`nVWxAKv-N6oe}}G`=1^@@SXLMxu|$anMq=Zf(5>L( z5EKDj03xLnI_S{So{m{@lxF|Vm}SRUGGj?ZPGNjXfk6UkCPnScBUKmGbir^sq@*D>pNswh>~SRs66349;n z!sK3XOiI})a4Q`s^&*VIVhN)r$!N~rr@A3(;8z6u5BTJ6K!zeua&$*AI1u5*DcX}X z8a4VBT7q(b)7xRu@)kq;Tn3Ivv7$^%$M|7L*|F%tFdc(Xg1pFa0!weHVDG^>_TlZl zIMy5LsbtqUhjusR)}O6?s@C(w;hxM$5{GhVgy&+@v?3_9J@A|nl~M_}lpyOGW4mzU zHn9`nCk08#C!A|pY$n*ZZIH%zg9Qsy9MQr?l5y!%R3x4>WJWSIs#ttfjC5VnWRj|e zuA|Fre@HX1s*6HK_+Chs#853$DuvXn$7e2)-`#M`%*t}$&f7J!U|u^dM4Fda);(NV zy*ykh{_XlD-|Oni&Ns0;b=#ARCwCw0K9FSD*6z@~@WQk9xTX4jzg{n4g4mWEBfQkH zj>$!<J)-Bi4Y&EF_E;`JevTf~t?1qw$xluHhKw|9?iJZIO@UA;X^rzbzL6~E<>ej-9F z?!oSN)l3rKQS9#7SsQfAKYpxFRIAC3X~cOF!7`{XDDBJw)>hxm-Pp z6>Uv4oU7+{73rJb+&egT+01K~&M#j6>SLdO*{a2@Wr430c%s#;>U(al-<3~w2g}wT z=nnclCY~;fzP=1y?m!Tt8y4lcSg(odxOg>5Aq;)X42#z~HtIi2bccsXj6-jiV8yXH zt&te7?x1{)=`LeB8MZqli3(PoCg?QEY`Lk43SEMl!FLdyq-__iG#l$hcW3jXD;^?! zFtZbnApD;BBx4OxDJj}f;l3dF*v^Yv&*1X6ob~eMcWt=s&Z&d<-+cJT=Puv7vb(op zAGsqIYYr>n)D*aa)HpbqgX1-jsm9EJDrHzC#*vh5VlVyY`uO|b?#@Z4tq7#TDNWNE zPiQqg=B@KcG7sA)Y3&izmI>0C1b;rr$Y0K>;e%yv|-J(@VZ&z5B=X~;& zS8cofhKuB?cSAZO&AuPvw4;LA#4~>XTGFxE9P;iPZ@+mr;UhmVNeav*?2BmZ^QkRy$;J|jAZ7JwmcvgDoTq>3Z2agKr#?N=b{nT0U*y}i_udL% zp8W>1X)-ApeB}#~Kxw|tdrs<>t1nby^@V`tmdh7@X70-7fTtbXX$f)rEn>%#Rp3;7 zOq3B%N`gv(%{3`wn)=rc9#gQ=n$ z8T6NN${nVjl~yg#m@38-hX_kKYH)TM9tpFa; zur)ibX_y^X6?WiCPCWgsXB=^IcBF|FU;p9qZO6RfxZ_u?_9x2=6Ph#AI5mk88M&TB zs|<2UUSy=@$Xe-QgvB}r12`_}f?nz1r&e_|LRDxsHQg&LBfAxYzoLg{uR0?@)WTJ}92| z93k>Nu~G*#npV`Rd-&-;+_FiGT)P0(y%81EfMtM{v;LCKf^ifR@{XJO|Mk)B_139x zoI39d*A9OY^4eegdH9CRNw7wWxLu9E^PSq=%FS>}n%&P;?3>>|y)mKvcy2RmEvP~f zQP3$0d&4c+mhthdC42+12GxUcC1WEUR&DZla&w3JphXiS5}a7q#j{U#(AFi1BvIaCV5PM?w?J4b({4>#OG>?N_{e+R(_i_= z!|(d(kLOt`&Xz|5ZD8WXnR!XJ{`f`n`QDGG^K;&| z_sZEu!@%VGPN3w-^oZwo4m@|p+xEYDLBH%v>odGo%l~K9{ad;jE&Q# z&6*Xv@`%cu(~hsK0FuX^%^o}B{NWQOr(2`T7KGC~_vr1dn7y;=g!#{8z+zUmE&!f7 zDARX*aPsUs?(O^v82RJ3g!43k{mSK?kLiMOU?`b%mTtaX|AQZ7UG226d7d#n?&u%< zynPQaGt<(IksbaauVTc^w4~N$*wM1zdG5(#X0jQPnV#wGd(5uu|HZqk6uM$2nnZXB zuREvrl-V3br<1V%trzWiLz0-`*`+lx`_YU4wsbx=X>2F99bgO?&ypCr zwr*;&oqs<~TO-1_Zc-q0>M%Smn(c(~*#Yy(_P}Lv!=;l5+e!_aPI0=w^Kbd58;4vf z-KGSz{`QigtFHd1=p&|3rq#+h`55!gO~(zam}T4~$(cAfk&ex}LH@h%0le&-{|Zw+ zOBDIop{_^ozT5r&Cwt8>gU2$I^qt9I#UH3Pi%+78On|+nuN$=th`0ocQvr@mF zmCN(rBaY3Mvn~?9oqztlcW%nFw~_o8D?fkr@#pV-SlEYd>$A7tP~FR%SG;r900{^o zP(ba9Pt~vg#cjU*@I_sJ2dqEwXx44H-L)5g?zC?Ji+~bPqyFyWF8RcYUtIU)o*RKh z2rProqOd%pIcnD=6%|JjWw_3Pl@^x5-nd)sHvv0wkZxM%g7-uSlwY`W+-@(n`Z zyy`f2*$r38*6YvaZNN$fkLrKj-<@U^+W b%b - -hello world - -assign('dropdown_contents', ob_get_contents()); -ob_end_clean(); - -$savant->assign('title', _AT('mediawiki')); // the box title -$savant->display('include/box.tmpl.php'); -?> \ No newline at end of file diff --git a/mods/mediawiki/sublinks.php b/mods/mediawiki/sublinks.php deleted file mode 100644 index 1010a6ea1..000000000 --- a/mods/mediawiki/sublinks.php +++ /dev/null @@ -1,36 +0,0 @@ - 0) { - while ($row = mysql_fetch_assoc($result)) { - /**** - * SUBLINK_TEXT_LEN, VALIDATE_LENGTH_FOR_DISPLAY are defined in include/lib/constance.lib.inc - * SUBLINK_TEXT_LEN determins the maxium length of the string to be displayed on "detail view" box. - *****/ - $list[] = ' SUBLINK_TEXT_LEN ? ' title="'.$row['page_title'].'"' : '') .'>'. - validate_length($row['page_title'], SUBLINK_TEXT_LEN, VALIDATE_LENGTH_FOR_DISPLAY) .''; - } - return $list; -} else { - return 0; -} - -?> \ No newline at end of file diff --git a/mods/merlot/README b/mods/merlot/README deleted file mode 100644 index 483871d89..000000000 --- a/mods/merlot/README +++ /dev/null @@ -1,28 +0,0 @@ -#Merlot Module for ATutor README -/* -This module provides simple and advanced search tools for searching the Merlot Educational Resource database. Resources listed in search results can be added directly to ATutor course links, if course links are enabled. Students can also add Merlot resources to group links, and to course links with approval from the instructor. Also provide direct links to the full record on the Merlot site, as well as links to assignments where they exist for a particular resource. -*/ -Merlot Location -http://fedsearch.merlot.org:9090/jaxrpc-MerlotSearch/searchservice?WSDL - -Merlot Key -This modules requires a Merlot Key to function. Visit the Merlot Web site to obtain a key. -http://www.merlot.org/merlot/signWebServicesForm.htm - -Requirements -1. php 4.3 + with expat and soap enabled. -or -php 5+ (default install of php 5 includes the required php libraries) -2. ATutor 1.6.2+ - - -Installation -1. Copy the downloaded module into the mods/ directory of ATutor -2. Unzip the module file to produce the merlot/ directory -3. Login to ATutor as the administrator, go to Modules, then Install Module. Choose the merlot module from the list of modules available for installation. -4. Once installed enable the module through the main modules screen. This will produce an admin "Merlot Repository" Tab through which the Merlot module can be configured. -5. Configure the module by entering the key you recieved. -6. Enter the location of the Merlot repository, and save the settings -(http://fedsearch.merlot.org:9090/jaxrpc-MerlotSearch/searchservice?WSDL) -7. Done. Logout as the admin, then login as a course instructor and through Manage>Student Tools enable the module for a course. - diff --git a/mods/merlot/add_to_links.php b/mods/merlot/add_to_links.php deleted file mode 100644 index c9db26c6b..000000000 --- a/mods/merlot/add_to_links.php +++ /dev/null @@ -1,148 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: '.$_base_href.'mods/merlot/index.php'); - exit; -}else if (isset($_POST['add_link']) && isset($_POST['submit'])) { - $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['cat'] = intval($_POST['cat']); - $_POST['title'] = $addslashes($_POST['title']); - $_POST['url'] == $addslashes($_POST['url']); - $_POST['description'] = $addslashes($_POST['description']); - - $name = get_display_name($_SESSION['member_id']); - $email = ''; - - // approve link if submitter is a group member or instructor - $sql = "SELECT * from ".TABLE_PREFIX."links_categories WHERE cat_id='$_POST[cat]' AND owner_type='2' "; - $result = mysql_query($sql, $db); - - while($row = mysql_fetch_assoc($result)){ - $sql2 = "SELECT * from ".TABLE_PREFIX."groups_members WHERE member_id= '$_SESSION[member_id]' AND group_id = '$row[owner_id]' "; - - if($result2 = mysql_query($sql2, $db)){ - $group_member = true; - } - } - - if($_SESSION['is_admin']){ - $approved = 1; //approved for instructor submissions - }else if($group_member){ - $approved = 1; //approved for group member submissions to group links - }else if(authenticate(AT_PRIV_LINKS, true)){ - $approved = 1; //approved for privileged user submissions - }else{ - $approved = 0; //not approved for student submissions to course links - } - ///// - $sql = "INSERT INTO ".TABLE_PREFIX."links VALUES (NULL, $_POST[cat], '$_POST[url]', '$_POST[title]', '$_POST[description]', $approved, '$name', '$email', NOW(), 0)"; - mysql_query($sql, $db); - - $msg->addFeedback('LINK_ADDED'); - header('Location: '.$_base_href.'mods/merlot/index.php'); - exit; - } else { - $_POST['title'] = stripslashes($_POST['title']); - $_POST['url'] == stripslashes($_POST['url']); - $_POST['description'] = stripslashes($_POST['description']); - } -} - -$onload = 'document.form.title.focus();'; -$categories = get_link_categories(); - -require(AT_INCLUDE_PATH.'header.inc.php'); - -?> -
    -

    - -
    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    -
    - -
    - -
    - - -
    -
    -
    - - -
    - - \ No newline at end of file diff --git a/mods/merlot/classes/MerlotResultParser.class.php b/mods/merlot/classes/MerlotResultParser.class.php deleted file mode 100644 index 6e5cca4f2..000000000 --- a/mods/merlot/classes/MerlotResultParser.class.php +++ /dev/null @@ -1,135 +0,0 @@ -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->result_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('merlotMaterialSearchWebService', 'status')) - { - $this->result_rows['status'] = trim($this->character_data); - } - else if ($this->element_path == array('merlotMaterialSearchWebService', 'error', 'message')) - { - $this->result_rows['error'] = trim($this->character_data); - } - else if ($this->element_path == array('merlotMaterialSearchWebService', 'summary', 'totalCount')) - { - $this->result_rows['summary']['totalCount'] = trim($this->character_data); - } - else if ($this->element_path == array('merlotMaterialSearchWebService', 'summary', 'resultCount')) - { - $this->result_rows['summary']['resultCount'] = trim($this->character_data); - } - else if ($this->element_path == array('merlotMaterialSearchWebService', 'summary', 'lastRecNumber')) - { - $this->result_rows['summary']['lastRecNumber'] = trim($this->character_data); - } - else if ($this->element_path === array('merlotMaterialSearchWebService', 'results', 'material', 'title')) - { - $this->result_rows[$this->row_num]['title'] = trim($this->character_data); - } - else if ($this->element_path === array('merlotMaterialSearchWebService', 'results', 'material', 'URL')) - { - $this->result_rows[$this->row_num]['URL'] = trim($this->character_data); - } - else if ($this->element_path === array('merlotMaterialSearchWebService', 'results', 'material', 'authorName')) - { - $this->result_rows[$this->row_num]['authorName'] = trim($this->character_data); - } - else if ($this->element_path === array('merlotMaterialSearchWebService', 'results', 'material', 'creationDate')) - { - $this->result_rows[$this->row_num]['creationDate'] = trim($this->character_data); - } - else if ($this->element_path === array('merlotMaterialSearchWebService', 'results', 'material', 'description')) - { - $this->result_rows[$this->row_num]['description'] = trim($this->character_data); - } - else if ($this->element_path === array('merlotMaterialSearchWebService', 'results', 'material', 'detailURL')) - { - $this->result_rows[$this->row_num]['detailURL'] = trim($this->character_data); - } - else if ($this->element_path === array('merlotMaterialSearchWebService', 'results', 'material', 'creativeCommons')) - { - $this->result_rows[$this->row_num]['creativeCommons'] = trim($this->character_data); - } - else if ($this->element_path === array('merlotMaterialSearchWebService', 'results', 'material')) - { - $this->row_num++; - } - - array_pop($this->element_path); - $this->character_data = ''; - } - - // private - function characterData($parser, $data){ - $this->character_data .= $data; - } - - // public - function getNumOfResults() - { - return count($this->result_rows); - } - - // public - function getParsedArray() - { - return $this->result_rows; - } -} - -?> \ No newline at end of file diff --git a/mods/merlot/index.php b/mods/merlot/index.php deleted file mode 100644 index 2ea4d527c..000000000 --- a/mods/merlot/index.php +++ /dev/null @@ -1,134 +0,0 @@ -addError('MERLOT_NOT_CONFIG'); - - require (AT_INCLUDE_PATH.'header.inc.php'); - $msg->printAll(); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} -else -{ -// If Merlot is configured, display the simple search form, and results -require (AT_INCLUDE_PATH.'header.inc.php'); -?> - - - -
    -
    - -
    - - <?php  echo _AT('merlot'); ?> - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - /> - /> - /> -
    - /> -
    - -
    - -
    -
    -
    - - -
    - -   - - -
    - -
    - - diff --git a/mods/merlot/index_admin.php b/mods/merlot/index_admin.php deleted file mode 100644 index fbab1fbfc..000000000 --- a/mods/merlot/index_admin.php +++ /dev/null @@ -1,71 +0,0 @@ -addError('MERLOTURL_ADD_EMPTY'); - } - - if (!$_POST['merlot_key']){ - $msg->addError('MERLOTKEY_ADD_EMPTY'); - } - - if (!$msg->containsErrors()) { - $_POST['merlot_location'] = $addslashes($_POST['merlot_location']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('merlot_location', '$_POST[merlot_location]')"; - mysql_query($sql, $db); - - $_POST['merlot_key'] = $addslashes($_POST['merlot_key']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('merlot_key', '$_POST[merlot_key]')"; - mysql_query($sql, $db); - - $msg->addFeedback('MERLOT_CONFIG_SAVED'); - - header('Location: '.$_SERVER['PHP_SELF']); - exit; - } -} -require (AT_INCLUDE_PATH.'header.inc.php'); -?> -
    -
    -

    -
    -
    -
    -
    -
    -

    - - -

    - -
    - -
    - -
    -
    -
    - - \ No newline at end of file diff --git a/mods/merlot/merlot.gif b/mods/merlot/merlot.gif deleted file mode 100644 index b73618693c13d7ed9356f14514d19736d506f028..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2041 zcmd^;d0Wy60)T&<0^)^uAgFktcxGm5YCV9rle1o>Gg}TG6&@8SrkMwaisD6Hn3aNJ z-W#^&Xz7NCXXR?Od5q1Fnw6PZdCbh?+BTnK-{<`T?;o#!pr8AZ7-zs4c+&-(g#zbb zAch(^0Rc%wL6gw1WDT|RT3Q#hwJ+-EFm*APu$WXmU6wvJRUemTpvN*aO2gsPjqn+G z!WDvXrm@LY6VohH(`+I!!@?xp!Xm@cGRNF1lSH~|WtC-ZolUmRu_5Q$+OX|xIres3 z2Ya65HxK3?aL7C0%yxFpcRIv#amhP;IN#N^z|EEK?pAojy~yK;z|*7H%d_;TSJ|M?Pw3}=%|Du!b3z6Cu>hc*8h0==1dza1rCx_F+<=*4*dh_yr&d={FDCp<&dj*99MMZrjfR) z(g9)F;I;CH6+(ICwV|pCdCm19QJtdp#_;u<@>}(a`i9{Ku~IASA?)BXK>iojH#l^LkFE?H-eOy}pyz=_P zo7FF?tDEoNeOh1p@?m{zrX?Ek*|b??vpuX|tr zUoqR)^G-Pv!#WdBOiy4jh!Ko4ME}6x5WpVz#$S^Fh<)G(Bq2a19^xT%ZBLEMBs2g( z`}9$|8%K%_4<$Y)YcFxs@H7D-@UC>C(i&z0u<1*qBB!|Mw;2EjTIHU)hPIg==4%?* zBdU?lz%Z1)AdKF;Hd$@v;1X~v=wADY4sCt+adx=(NlvBJQ2#4{`va2kto`%@S6Uug z6Cf~U-84893cc{uXIukI4wZ!rnb&Tr6op!LWhoHFSfxjuPtjc;qHTD+b7-BE5hk5# zILb3|xZfiU{5y>-6kZzEr3kH#+O{VC$M$5sqTtuyx}O=oku*!dCTzF}PhDliw#%kP zR>4*FMaNEiY`=fe;B;9iCyk&T#ru1l2!UBW4oNU{64SG{@GYU2#LQdtIW+Keh^b3ENgkqWU z>Kxk*w!}NNPfURu#mlQp@v6eOGS^=j7HZg>w@bNc11bvC{72?e1*HzL!nZBxX(;vf zP>yMl27qDpgURzGQS_wjwYsBnnuN5>F=*7h;x3)EyetKc;V+Dv`QJ)kC~6_F77|)? zh!kSA07D5G#%p#}1lcqS!%$?gmxn-FAqWdU#;dM2Sd3aZ6=Wl zwccaH%=V?DiQ2~2hSL(CWg1E{)2xp4!4xpAgx$^rTcRP=1X!uNXjlQ@NP&hNR4#K9XBxUjj z?3tv<=2T1UmIijNBz2-8@7j=hSf8W-$1Q0@U>(p@IDxrx5NVgWC~MePKQ3BC8fZB& z6(}3F+}EnaeTIW{>=DznvsKx=QnxqjE(V$efC|?jIOSUw+f$ceddEYCjXPDBcu*tz zms|bq%%{E(%n20$4v(q`z+f4|Cb*lbd(yb0`23MU2@3=Qw;dC*v9$z@FPzq9l(klw zB;S4iCZ}-^g!55(VQUB#(9)yP4e4{$qV+(7>z;BD6uI)R09}H#l>?pa_;kX=DyE3REzJ~h_Bl^7NR`GAmq-wT44`VsKA07e1jY6sgQ3b*Y0qy*85a4khZPzM?yE8q>r($({LfDXneiVo$z%`Bf#3$aQKuGS88Tzh^CP5A$qu5{>6KOT21|kAc z#Heo-Zvm*WAw=iQHqs%U2yEkocr8vI5=DV62SM!&L2Bl$L@>Q} limitNum){ - alert("You have exceeded the number of characters for this field"); - limitField.value = limitField.value.substring(0, limitNum-1); - } - -} - -function limitCopy(limitField, limitNum) { - if (limitField.value.length > limitNum) limitField.value = limitField.value.substring(0, limitNum); -} - -function confirmPost() { - if (confirm("Posting this composite review makes it appear on the material detail page and available to the public. Are you sure you want to continue?")) { - return true; - } else { - return false; - } -} - -function confirmUnpost() { - if (confirm("Unposting this review will put this material back into the workflow process. Are you sure you want to continue?")) { - return true; - } else { - return false; - } -} - - function showOther(mySelect, targetId) { - var selected = mySelect.options[mySelect.selectedIndex].text; - if (selected == 'Other') { - if (document.getElementById) { - target = document.getElementById(targetId); - if (target.style.display == "none"){ - target.style.display = ""; - } - } - } else { - if (document.getElementById) { - target = document.getElementById(targetId); - if (target.style.display != "none"){ - target.style.display = "none"; - } - } - } - } - -function cat(id, parentId, name) { - this.id = id; - this.parentId = parentId; - this.name = name; -} - -var cats = new Array( -new cat('','-1','All'), - - -new cat('2175','','Arts'), - -new cat('2176','2175','Art History'), - -new cat('2177','2175','Cinema'), - -new cat('2178','2175','Dance'), - -new cat('2179','2175','Fine Arts'), - -new cat('2180','2175','General'), - -new cat('2181','2175','Music'), - -new cat('2182','2181','Aural Skill and Ear Training'), - -new cat('2183','2181','Composition'), - -new cat('2184','2181','Music Appreciation'), - -new cat('2185','2181','Music Education'), - -new cat('2186','2181','Music History'), - -new cat('2187','2181','Music Technology'), - -new cat('2188','2181','Performance'), - -new cat('2189','2181','Theory and Analysis'), - -new cat('2190','2181','World Music'), - -new cat('2191','2175','Photography'), - -new cat('2192','2175','Theatre'), - -new cat('2193','2192','Critical Strategies'), - -new cat('2194','2192','Design and Technology'), - -new cat('2195','2192','Management'), - -new cat('2196','2192','Music Theatre and Dance'), - -new cat('2197','2192','Performing'), - -new cat('2198','2192','Playwriting'), - -new cat('2199','2192','Theatre Artists and Companies'), - -new cat('2200','2192','Theatre History'), - -new cat('2201','2192','Theatre for Specific Audiences'), - -new cat('2202','','Business'), - -new cat('2203','2202','Accounting'), - -new cat('2204','2203','Accounting Education'), - -new cat('2213','2203','Tax'), - -new cat('2205','2203','Accounting Information Systems'), - -new cat('2206','2203','Auditing'), - -new cat('2207','2203','Ethics'), - -new cat('2208','2203','Financial'), - -new cat('2209','2203','International'), - -new cat('2210','2203','Introductory'), - -new cat('2211','2203','Managerial'), - -new cat('2212','2203','Not for Profit'), - -new cat('2259','2202','Marketing'), - -new cat('2260','2259','Advertising'), - -new cat('2261','2259','Business Marketing'), - -new cat('2262','2259','Consumer Behavior'), - -new cat('2263','2259','General'), - -new cat('2264','2259','International'), - -new cat('2265','2259','Market Research'), - -new cat('2266','2259','Sales'), - -new cat('2214','2202','Business Law'), - -new cat('2215','2202','E-Commerce'), - -new cat('2216','2202','Economics'), - -new cat('2217','2216','Agricultural and Natural Resources'), - -new cat('2226','2216','Industrial Organization'), - -new cat('2227','2216','International'), - -new cat('2228','2216','Labor and Demographics'), - -new cat('2229','2216','Law and Economics'), - -new cat('2230','2216','Macro'), - -new cat('2231','2216','Mathematical and Quant.'), - -new cat('2232','2216','Micro'), - -new cat('2233','2216','Public'), - -new cat('2234','2216','Urban, Rural and Regional'), - -new cat('2218','2216','Bus Adm and Bus Mktg'), - -new cat('2219','2216','Econometrics'), - -new cat('2220','2216','Economic Development'), - -new cat('2221','2216','Economic Systems'), - -new cat('2222','2216','Financial'), - -new cat('2223','2216','General'), - -new cat('2224','2216','Health, Ed and Welfare'), - -new cat('2225','2216','History of Ec. Thought'), - -new cat('2235','2202','Finance'), - -new cat('2236','2235','Corporate'), - -new cat('2245','2235','Real Estate'), - -new cat('2237','2235','Derivatives'), - -new cat('2238','2235','Financial Institutions'), - -new cat('2239','2235','Financial Markets'), - -new cat('2240','2235','Insurance'), - -new cat('2241','2235','International'), - -new cat('2242','2235','Investments'), - -new cat('2243','2235','Money and Banking'), - -new cat('2244','2235','Personal Finance'), - -new cat('2246','2202','General'), - -new cat('2247','2202','International Business'), - -new cat('227461','2247','Country Information and Geography'), - -new cat('227462','2247','Cross Cultural Management/OB'), - -new cat('227463','2247','Export and International Trade'), - -new cat('227464','2247','Globalization'), - -new cat('227465','2247','Human Resources in a Global Environment'), - -new cat('227466','2247','International Case Studies'), - -new cat('227467','2247','International Finance'), - -new cat('227468','2247','International Marketing'), - -new cat('227469','2247','International Project Management'), - -new cat('227470','2247','Multicultural Issues Diversity'), - -new cat('2248','2202','Management'), - -new cat('2250','2248','Conflict Resolution'), - -new cat('2251','2248','Entrepreneurship'), - -new cat('2252','2248','Ethics'), - -new cat('2253','2248','Human Resources'), - -new cat('2254','2248','International'), - -new cat('2255','2248','Org Behavior and Development'), - -new cat('2256','2248','Production and Oper Mgnt'), - -new cat('2257','2248','Project Management'), - -new cat('2258','2248','Strategy'), - -new cat('2249','2202','Management Information Systems'), - -new cat('2267','','Education'), - -new cat('2268','2267','General'), - -new cat('2269','2267','Library and Information Services'), - -new cat('2270','2269','General'), - -new cat('2271','2269','Information Literacy'), - -new cat('2272','2269','Information Retrieval'), - -new cat('2273','2269','Information Technology'), - -new cat('2274','2269','Issues in Librarianship'), - -new cat('2275','2269','Library Specialties'), - -new cat('2276','2267','TeacherEd'), - -new cat('2277','2276','Classroom Management'), - -new cat('2278','2276','Diversity and Multicultural Ed'), - -new cat('2279','2276','Educational Foundations'), - -new cat('2280','2276','Educational Psychology'), - -new cat('2281','2276','Educational Research'), - -new cat('2282','2276','Instructional Technology'), - -new cat('2283','2276','Special Education'), - -new cat('2284','2276','Student Assessment'), - -new cat('2285','2276','Teaching Methods'), - -new cat('2286','2285','Arts'), - -new cat('2287','2285','English'), - -new cat('2288','2285','Foreign Language'), - -new cat('2289','2285','Mathematics'), - -new cat('2290','2285','Physical Education'), - -new cat('2291','2285','Reading and Language Arts'), - -new cat('2292','2285','Science'), - -new cat('2293','2285','Social Science'), - -new cat('2294','2285','Vocational Education'), - -new cat('2295','2267','Teaching and Technology'), - -new cat('2296','2295','Accessibility'), - -new cat('2298','2295','Assessment and Evaluation'), - -new cat('2299','2295','Best Teaching Practices'), - -new cat('2300','2299','Case Studies'), - -new cat('2301','2299','Cooperative Learning'), - -new cat('2302','2299','Lecture and Presentation'), - -new cat('2303','2299','Multicultural and Diversity'), - -new cat('2304','2299','Online Communications'), - -new cat('2305','2299','Other'), - -new cat('2306','2299','Problem Based Learning'), - -new cat('2307','2299','Service Learning'), - -new cat('2308','2295','Instructional Design'), - -new cat('2309','2295','Policies'), - -new cat('2310','2309','Intellectual Property'), - -new cat('2311','2309','Other'), - -new cat('2312','2295','Scholarship of Teaching and Learning'), - -new cat('2313','2295','Selecting and Using Tools'), - -new cat('2314','2313','Communication Tools'), - -new cat('2315','2313','Course Management Tools'), - -new cat('2316','2315','Angel'), - -new cat('2317','2315','Blackboard'), - -new cat('2318','2315','Desire2Learn'), - -new cat('2319','2315','Other'), - -new cat('2320','2315','WebCT'), - -new cat('2321','2313','Hardware and Networks'), - -new cat('2322','2313','Multimedia Tools'), - -new cat('2323','2313','Other'), - -new cat('2324','2313','Using MERLOT'), - -new cat('2325','2313','Web Page Editors'), - -new cat('2326','2295','Support and Training'), - -new cat('2327','','Humanities'), - -new cat('2328','2327','General'), - -new cat('2329','2327','History'), - -new cat('2330','2329','Area Studies'), - -new cat('2331','2330','Africa'), - -new cat('2332','2331','Central Africa'), - -new cat('2333','2331','East Africa'), - -new cat('2334','2331','North Africa'), - -new cat('2335','2331','Southern Africa'), - -new cat('2336','2331','West Africa'), - -new cat('2337','2330','Americas'), - -new cat('2338','2337','Brazil'), - -new cat('2339','2337','Canada'), - -new cat('2340','2337','Caribbean'), - -new cat('2341','2337','Central America'), - -new cat('2342','2337','Mexico'), - -new cat('2343','2337','South America'), - -new cat('2344','2337','United States'), - -new cat('2345','2344','1789-1865'), - -new cat('2346','2344','1865-1900'), - -new cat('2347','2344','20th Century'), - -new cat('2348','2344','American Revolution'), - -new cat('2349','2344','Civil War'), - -new cat('2350','2344','Colonial'), - -new cat('2351','2344','Pre-Columbian'), - -new cat('2352','2330','Asia'), - -new cat('2353','2352','Central Asia'), - -new cat('2354','2352','China'), - -new cat('2355','2352','Eastern'), - -new cat('2356','2352','Japan'), - -new cat('2357','2352','Korea'), - -new cat('2358','2352','Middle East'), - -new cat('2359','2352','South Asia'), - -new cat('2360','2352','Southeast Asia'), - -new cat('2361','2330','Europe'), - -new cat('2362','2361','Balkans'), - -new cat('2371','2361','Italy'), - -new cat('2372','2361','Northern'), - -new cat('2373','2361','Scandinavia'), - -new cat('2374','2361','Southern'), - -new cat('2375','2361','Western'), - -new cat('2363','2361','Benelux'), - -new cat('2364','2361','Eastern'), - -new cat('2365','2361','European Union'), - -new cat('2366','2361','France'), - -new cat('2367','2361','Germany and Central Europe'), - -new cat('2368','2361','Great Britain and Ireland'), - -new cat('2369','2361','Greece'), - -new cat('2370','2361','Iberia'), - -new cat('2376','2330','Oceania'), - -new cat('2377','2376','Australia'), - -new cat('2378','2376','New Zealand'), - -new cat('2379','2376','Pacific Islands'), - -new cat('2380','2330','World Systems'), - -new cat('2381','2329','Resources'), - -new cat('2382','2381','Document Archives'), - -new cat('2383','2381','Image and Photographic Archives'), - -new cat('2384','2381','Map Archives'), - -new cat('2385','2329','Theory and Method'), - -new cat('2386','2385','Epistemology of History'), - -new cat('2387','2385','Historiography'), - -new cat('2388','2385','History Education'), - -new cat('2389','2385','Methods'), - -new cat('2390','2385','Philosophy of History'), - -new cat('2391','2329','Topical'), - -new cat('2392','2391','African-American'), - -new cat('2401','2391','Genealogy'), - -new cat('2402','2391','Hispanic and Latino American'), - -new cat('2403','2391','Intellectual'), - -new cat('2404','2403','Diplomatic'), - -new cat('2405','2403','Economic'), - -new cat('2406','2391','Labour'), - -new cat('2407','2391','Legal and Constitutional'), - -new cat('2408','2391','Local and Regional'), - -new cat('2409','2391','Military'), - -new cat('2410','2391','Native American'), - -new cat('2411','2391','Political'), - -new cat('2412','2391','Popular Culture'), - -new cat('2393','2391','Archaeology'), - -new cat('2413','2391','Popular Culture'), - -new cat('2414','2391','Public History'), - -new cat('2415','2391','Race and Ethnicity'), - -new cat('2416','2391','Religion'), - -new cat('2417','2391','Rural'), - -new cat('2418','2391','Science, Medicine, and Technology'), - -new cat('2419','2391','Sexuality'), - -new cat('2420','2391','Slavery'), - -new cat('2421','2391','Social'), - -new cat('2422','2391','Subaltern'), - -new cat('2394','2391','Art History'), - -new cat('2423','2391','Wars'), - -new cat('2424','2391','Women'), - -new cat('2425','2391','World and Global'), - -new cat('2395','2391','Biography'), - -new cat('2396','2391','Business and Economics'), - -new cat('2397','2391','Class'), - -new cat('2398','2391','Education'), - -new cat('2399','2391','Environmental History'), - -new cat('2400','2391','Gender'), - -new cat('2426','2327','Language and Literature'), - -new cat('2427','2426','Communications'), - -new cat('2436','2426','Rhetoric'), - -new cat('2437','2426','Speech'), - -new cat('2428','2426','Composition'), - -new cat('2429','2426','Criticism'), - -new cat('2430','2426','Drama and Theatre'), - -new cat('2431','2426','History'), - -new cat('2432','2426','Journalism'), - -new cat('2433','2426','Linguistics'), - -new cat('2434','2426','Literature'), - -new cat('2435','2426','Poetry'), - -new cat('2438','2327','Philosophy'), - -new cat('2439','2327','Religion'), - -new cat('2440','2327','World Languages'), - -new cat('2441','2440','Arabic'), - -new cat('2442','2441','Culture'), - -new cat('2443','2441','Language'), - -new cat('2444','2441','Teacher Resources'), - -new cat('2445','2441','culture'), - -new cat('2486','2440','Korean'), - -new cat('2487','2486','Culture'), - -new cat('2488','2486','Language'), - -new cat('2489','2486','Teacher Resources'), - -new cat('2490','2486','culture'), - -new cat('2491','2440','Latin'), - -new cat('2492','2491','Culture'), - -new cat('2493','2491','Language'), - -new cat('2494','2491','Teacher Resources'), - -new cat('2495','2491','culture'), - -new cat('2496','2440','Less Commonly Taught Languages'), - -new cat('2497','2440','Multilingual Resources'), - -new cat('2498','2440','Portuguese'), - -new cat('2499','2498','Culture'), - -new cat('2500','2498','Language'), - -new cat('2501','2498','Teacher Resources'), - -new cat('2502','2498','culture'), - -new cat('2503','2440','Russian'), - -new cat('2504','2503','Culture'), - -new cat('2505','2503','Language'), - -new cat('2506','2503','Teacher Resources'), - -new cat('2507','2503','culture'), - -new cat('2508','2440','Spanish'), - -new cat('2509','2508','Culture'), - -new cat('2510','2508','Language'), - -new cat('2511','2508','Teacher Resources'), - -new cat('2512','2508','culture'), - -new cat('2446','2440','Chinese'), - -new cat('2447','2446','Culture'), - -new cat('2448','2446','Language'), - -new cat('2449','2446','Teacher Resources'), - -new cat('2450','2446','culture'), - -new cat('2451','2440','ESL'), - -new cat('2452','2451','Culture'), - -new cat('2453','2451','Language'), - -new cat('2454','2451','Teacher Resources'), - -new cat('2455','2451','culture'), - -new cat('2456','2440','French'), - -new cat('2457','2456','Culture'), - -new cat('2458','2456','Language'), - -new cat('2459','2456','Teacher Resources'), - -new cat('2460','2456','culture'), - -new cat('2461','2440','German'), - -new cat('2462','2461','Culture'), - -new cat('2463','2461','Language'), - -new cat('2464','2461','Teacher Resources'), - -new cat('2465','2461','culture'), - -new cat('2466','2440','Greek'), - -new cat('2467','2466','Culture'), - -new cat('2468','2466','Language'), - -new cat('2469','2466','Teacher Resources'), - -new cat('2470','2466','culture'), - -new cat('2471','2440','Hebrew'), - -new cat('2472','2471','Culture'), - -new cat('2473','2471','Language'), - -new cat('2474','2471','Teacher Resources'), - -new cat('2475','2471','culture'), - -new cat('2476','2440','Italian'), - -new cat('2477','2476','Culture'), - -new cat('2478','2476','Language'), - -new cat('2479','2476','Teacher Resources'), - -new cat('2480','2476','culture'), - -new cat('2481','2440','Japanese'), - -new cat('2482','2481','Culture'), - -new cat('2483','2481','Language'), - -new cat('2484','2481','Teacher Resources'), - -new cat('2485','2481','culture'), - -new cat('2513','','Mathematics and Statistics'), - -new cat('2514','2513','Mathematics'), - -new cat('2515','2514','Algebra and Number Theory'), - -new cat('2516','2515','Abstract Algebra'), - -new cat('2517','2515','Cryptography'), - -new cat('2518','2515','Linear Algebra'), - -new cat('2519','2515','Number Theory'), - -new cat('2560','2514','General and Liberal Arts Math'), - -new cat('2561','2560','Consumer Mathematics'), - -new cat('2562','2560','History of Mathematics'), - -new cat('2563','2560','Mathematical Modeling'), - -new cat('2564','2560','Mathematics in Art and Music'), - -new cat('2565','2560','Recreational Mathematics'), - -new cat('2566','2514','Geometry and Topology'), - -new cat('2567','2566','Computational Geometry'), - -new cat('2568','2566','Differential Geometry'), - -new cat('2569','2566','Euclidean Geometry'), - -new cat('2570','2566','Knot Theory'), - -new cat('2571','2566','Non-Euclidean Geometry'), - -new cat('2572','2566','Topology'), - -new cat('2573','2566','Transformational Geometry'), - -new cat('2574','2514','Mathematical Modeling'), - -new cat('2575','2574','Continuous'), - -new cat('2576','2574','Discrete'), - -new cat('2577','2574','Mathematical Biology'), - -new cat('2578','2514','Mathematics Publishing Tools'), - -new cat('2579','2578','Computer Algebra Systems'), - -new cat('2580','2578','HTML and MathML'), - -new cat('2581','2578','Java'), - -new cat('2582','2578','Non-Java Programming'), - -new cat('2583','2578','Scientific Word Processors'), - -new cat('2584','2578','Tex'), - -new cat('2585','2578','Text Editors'), - -new cat('2586','2514','Numerical Analysis'), - -new cat('2587','2586','Numerical Differential Equations'), - -new cat('2588','2586','Numerical Linear Algebra'), - -new cat('2589','2586','Numerical Partial Differential Equations'), - -new cat('2590','2586','Numerical Solution of Equations'), - -new cat('2591','2514','Pre-Calculus Mathematics'), - -new cat('2592','2591','Algebra'), - -new cat('2593','2591','Analytic Geometry'), - -new cat('2594','2591','Trigonometry'), - -new cat('2520','2514','Analysis'), - -new cat('2521','2520','Complex Analysis'), - -new cat('2522','2520','Fourier Analysis'), - -new cat('2523','2520','Functional Analysis'), - -new cat('2524','2520','Real Analysis'), - -new cat('2525','2520','Wavelets'), - -new cat('2526','2514','Applied Mathematics'), - -new cat('2527','2514','Calculus'), - -new cat('2528','2527','Differential, One Variable'), - -new cat('2529','2527','Integral, One Variable'), - -new cat('2530','2527','Multivariable'), - -new cat('2531','2527','Sequences and Series'), - -new cat('2532','2514','Developmental Mathematics'), - -new cat('2533','2532','Arithmetic'), - -new cat('2534','2532','Geometry'), - -new cat('2535','2532','Pre-Algebra'), - -new cat('2536','2514','Differential Equations'), - -new cat('2537','2536','Advanced'), - -new cat('2538','2536','Diffusion'), - -new cat('2539','2536','Elementary'), - -new cat('2540','2536','Fluid Dynamics'), - -new cat('2541','2536','PDE?s'), - -new cat('2542','2536','Wave Phenomena'), - -new cat('2543','2514','Discrete Mathematics'), - -new cat('2544','2543','Cellular Automata'), - -new cat('2545','2543','Combinatorics'), - -new cat('2546','2543','Game Theory'), - -new cat('2547','2543','Genetic Algorithms'), - -new cat('2548','2543','Graph Theory'), - -new cat('2549','2543','Linear Programming'), - -new cat('2550','2543','Theory of Computation'), - -new cat('2551','2514','Dynamical Systems'), - -new cat('2552','2551','Complex Dynamics'), - -new cat('2553','2551','Difference Equations'), - -new cat('2554','2551','Fractal Geometry'), - -new cat('2555','2551','Real Variable Dynamics'), - -new cat('2556','2551','Symbolic Dynamics and Coding Theory'), - -new cat('2557','2514','Foundations of Mathematics'), - -new cat('2558','2557','Logic'), - -new cat('2559','2557','Set Theory'), - -new cat('2595','2513','Statistics and Probability'), - -new cat('2596','2595','Bayesian Analysis'), - -new cat('2597','2595','Brownian Motion'), - -new cat('2598','2595','Data Analysis'), - -new cat('2599','2595','Linear Regression'), - -new cat('2600','2595','Markov Chains'), - -new cat('2601','2595','Nonlinear Regression'), - -new cat('2602','2595','Probability'), - -new cat('2603','2595','Queueing Theory'), - -new cat('2604','2595','Statistics'), - -new cat('2605','','Science and Technology'), - -new cat('2606','2605','Agriculture'), - -new cat('2683','2605','Health Sciences'), - -new cat('2684','2683','Cardiology'), - -new cat('2693','2683','Geriatrics'), - -new cat('2694','2683','Hematology'), - -new cat('2695','2683','Internal Medicine'), - -new cat('2696','2683','Medical Laboratory Technology'), - -new cat('2697','2683','Nephrology'), - -new cat('2698','2683','Neurology'), - -new cat('2699','2683','Nursing'), - -new cat('2700','2683','Nutrition'), - -new cat('2701','2683','OB and Gyn'), - -new cat('2702','2683','Oncology'), - -new cat('2685','2683','Dentistry'), - -new cat('2703','2683','Ophthalmology'), - -new cat('2704','2683','Orthopedics'), - -new cat('2705','2683','Other'), - -new cat('2706','2683','Pathology'), - -new cat('2707','2683','Pediatrics'), - -new cat('2708','2683','Pharmacy'), - -new cat('2709','2683','Psychiatry and Mental Health'), - -new cat('2710','2683','Public Health'), - -new cat('2711','2683','Pulmonary Medicine'), - -new cat('2712','2683','Radiology'), - -new cat('2686','2683','Dermatology'), - -new cat('2713','2683','Rheumatology'), - -new cat('2714','2683','Sports Medicine'), - -new cat('2715','2683','Surgery'), - -new cat('2716','2683','Therapeutics'), - -new cat('2687','2683','Ear, Nose, and Throat'), - -new cat('2688','2683','Endocrinology'), - -new cat('2689','2683','Epidemiology'), - -new cat('2690','2683','Gastroenterology'), - -new cat('2691','2683','General'), - -new cat('2692','2683','Genetics and Infectious Disease'), - -new cat('2717','2605','Information Technology'), - -new cat('2718','2717','Applications'), - -new cat('2727','2717','Security'), - -new cat('2728','2717','Software Engineering'), - -new cat('2729','2717','Systems Analysis'), - -new cat('2730','2717','Web'), - -new cat('2719','2717','Computer Information Systems'), - -new cat('2720','2717','Database'), - -new cat('2721','2717','E-commerce'), - -new cat('2722','2717','Hardware'), - -new cat('2723','2717','Information Literacy'), - -new cat('2724','2717','Networking'), - -new cat('2725','2717','Operating Systems'), - -new cat('2726','2717','Programming'), - -new cat('2731','2605','Nanotechnology'), - -new cat('2732','2731','Computation and Software'), - -new cat('2733','2731','Nano-bio Device and Systems'), - -new cat('2734','2731','Nano-electromechanical Systems (NEMS)'), - -new cat('2735','2731','Nano-electronics'), - -new cat('2736','2605','Physics'), - -new cat('2737','2736','Classical Mechanics'), - -new cat('2738','2737','1D Kinematics'), - -new cat('2747','2737','Reference Frames'), - -new cat('2748','2737','Statics'), - -new cat('2739','2737','2D Kinematics'), - -new cat('2740','2737','Angular Motion and Torques'), - -new cat('2741','2737','Energy and Momentum'), - -new cat('2742','2737','Forces and Dynamics'), - -new cat('2743','2737','Gravity'), - -new cat('2744','2737','Linear Motion, Forces, and Equilibrium'), - -new cat('2745','2737','Projectile Motion'), - -new cat('2746','2737','Pulleys and Atwood Machines'), - -new cat('2749','2736','Electricity and Magnetism'), - -new cat('2750','2749','Capacitance'), - -new cat('2751','2749','Charges in Fields'), - -new cat('2752','2749','Circuits'), - -new cat('2753','2749','Electric Fields'), - -new cat('2754','2749','Electric Potentials'), - -new cat('2755','2749','Faradays Law and Induction'), - -new cat('2756','2749','Gauss and Coulombs Law'), - -new cat('2757','2749','Magnetic Fields'), - -new cat('2758','2736','General'), - -new cat('2759','2758','Collections'), - -new cat('2760','2758','Curriculum'), - -new cat('2761','2758','History'), - -new cat('2762','2758','Mathematics'), - -new cat('2763','2758','Measurement and Units'), - -new cat('2764','2758','Physics Education Research'), - -new cat('2765','2758','Reference'), - -new cat('2766','2758','Vector Algebra'), - -new cat('2767','2736','Modern Physics'), - -new cat('2768','2767','Atomic and Molecular'), - -new cat('2769','2767','Condensed Matter'), - -new cat('2770','2767','General'), - -new cat('2771','2767','Laser Physics'), - -new cat('2772','2767','Nuclear and Particle'), - -new cat('2773','2767','Relativity'), - -new cat('2774','2736','Optics'), - -new cat('2775','2774','Geometric Optics'), - -new cat('2776','2774','Physical Optics'), - -new cat('2777','2774','Radiation'), - -new cat('2778','2736','Oscillations and Waves'), - -new cat('2779','2778','Oscillators'), - -new cat('2780','2778','Pendulum Motion'), - -new cat('2781','2778','Waves'), - -new cat('2782','2736','Quantum Mechanics'), - -new cat('2783','2736','Thermodynamics and Statistical Mechanics'), - -new cat('2784','2783','Fluids'), - -new cat('2785','2783','Statistical Mechanics'), - -new cat('2786','2783','Thermodynamics'), - -new cat('2607','2605','Astronomy'), - -new cat('2608','2605','Biology'), - -new cat('2609','2608','Botany'), - -new cat('2618','2608','Microbiology'), - -new cat('2619','2608','Molecular Biology'), - -new cat('2620','2608','Natural History'), - -new cat('2621','2608','Physiology'), - -new cat('2622','2608','Zoology'), - -new cat('2610','2608','Cytology'), - -new cat('2611','2608','Development'), - -new cat('2612','2608','Ecology'), - -new cat('2613','2608','Evolution'), - -new cat('2614','2608','General'), - -new cat('2615','2608','Genetics'), - -new cat('2616','2608','Human Anatomy'), - -new cat('2617','2608','Life'), - -new cat('2623','2605','Chemistry'), - -new cat('2624','2623','Analytical'), - -new cat('2633','2623','Physical'), - -new cat('2634','2623','Polymer and Macromolecular'), - -new cat('2625','2623','Biochemistry'), - -new cat('2626','2623','Chemical Education'), - -new cat('2627','2623','Environmental'), - -new cat('2628','2623','Inorganic'), - -new cat('2629','2623','Introductory and General'), - -new cat('2630','2623','Materials'), - -new cat('2631','2623','Nuclear'), - -new cat('2632','2623','Organic'), - -new cat('2635','2605','Computer Science'), - -new cat('2636','2635','Artificial Intelligence'), - -new cat('2645','2635','Programming'), - -new cat('2646','2635','Programming Languages'), - -new cat('2647','2635','Robotics'), - -new cat('2648','2635','Study and Teaching'), - -new cat('2649','2635','Theory'), - -new cat('2650','2635','User Interfaces'), - -new cat('2637','2635','Computer Simulation'), - -new cat('2638','2635','Computer Software'), - -new cat('2639','2635','Databases'), - -new cat('2640','2635','Documentation'), - -new cat('2641','2635','General'), - -new cat('2642','2635','Human-Computer Interaction'), - -new cat('2643','2635','Internet'), - -new cat('2644','2635','Multimedia'), - -new cat('2651','2605','Engineering'), - -new cat('2652','2651','Aerospace and Aeronautical Engineering'), - -new cat('2661','2651','General'), - -new cat('2662','2651','Geological Engineering'), - -new cat('2663','2651','Industrial and Systems'), - -new cat('2664','2651','Manufacturing Engineering'), - -new cat('2665','2651','Materials Science and Engineering'), - -new cat('2666','2651','Mechanical Engineering'), - -new cat('2667','2651','Mining Engineering'), - -new cat('2668','2651','Nuclear Engineering'), - -new cat('2669','2651','Ocean Engineering'), - -new cat('2670','2651','Petroleum Engineering'), - -new cat('2653','2651','Agricultural and Biological Engineering'), - -new cat('2654','2651','Biomedical Engineering'), - -new cat('2655','2651','Chemical Engineering'), - -new cat('2656','2651','Civil Engineering'), - -new cat('2657','2651','Computer Engineering'), - -new cat('2658','2651','Electrical Engineering'), - -new cat('2659','2651','Engineering Science'), - -new cat('2660','2651','Environmental Engineering'), - -new cat('2671','2605','Fire Safety'), - -new cat('2672','2671','Building Construction for Fire Protection'), - -new cat('2673','2671','Disaster Planning'), - -new cat('2674','2671','Fire Administration'), - -new cat('2675','2671','Fire Behavior and Combustion'), - -new cat('2676','2671','Fire Investigation'), - -new cat('2677','2671','Fire Prevention'), - -new cat('2678','2671','Fire Protection Systems'), - -new cat('2679','2671','Foundations of Emergency Services'), - -new cat('2680','2671','Hazardous Materials'), - -new cat('2681','2605','General Science'), - -new cat('2682','2605','Geology'), - -new cat('2787','','Social Sciences'), - -new cat('2788','2787','Anthropology'), - -new cat('2827','2787','Statistics'), - -new cat('2828','2787','Womens Studies'), - -new cat('2789','2787','Criminal Justice'), - -new cat('2790','2789','Corrections'), - -new cat('2800','2789','Law Enforcement'), - -new cat('2799','2789','Law \& Society'), - -new cat('2801','2789','Victims'), - -new cat('2791','2789','Courts'), - -new cat('2792','2789','Crime'), - -new cat('2793','2789','Crime and Communites'), - -new cat('2794','2789','Drugs'), - -new cat('2795','2789','Forensics'), - -new cat('2796','2789','Intelligence'), - -new cat('2797','2789','Justice System'), - -new cat('2798','2789','Juvenile Justice'), - -new cat('2802','2787','General'), - -new cat('2803','2787','Geography'), - -new cat('2804','2787','Law'), - -new cat('2805','2787','Political Science'), - -new cat('2806','2787','Psychology'), - -new cat('2807','2806','Biological'), - -new cat('2819','2806','Industrial and Organizational'), - -new cat('2820','2806','Learning and Memory'), - -new cat('2821','2806','Personality'), - -new cat('2822','2806','Sensation and Perception'), - -new cat('2823','2806','Social'), - -new cat('2824','2806','Statistics and Research Methods'), - -new cat('2808','2806','Clinical and Counseling'), - -new cat('2809','2808','Abnormal and Psychopathology'), - -new cat('2810','2808','Assessment'), - -new cat('2811','2808','Therapy and Treatment'), - -new cat('2812','2806','Cognitive'), - -new cat('2813','2806','Community and Health'), - -new cat('2814','2806','Developmental and Life-Span'), - -new cat('2815','2806','Diversity'), - -new cat('2816','2806','Ethics'), - -new cat('2817','2806','General'), - -new cat('2818','2806','History and Systems'), - -new cat('2825','2787','Sociology'), - -new cat('2826','2787','Sports and Games') - -); - -function subcat(value,field) { - subcatID(value, field, 0); -} - -function subcatID(value,field,show_id) { - var selectedValue; - var pathList="Selected: "; - var el = document.getElementById('catPath'); - - var j=1; - var tempId; - var selectedCat; - var childrenNameStack= new Array(); - var childrenIdStack = new Array(); - var pathNameStack = new Array(); - var pathIdStack = new Array(); - - if (value == "-1") selectedValue = document.merlotForm.elements[field].options[document.merlotForm.elements[field].selectedIndex].value; - else selectedValue = value; - - for (i=0; i<=cats.length-1; i++) if(cats[i].id == selectedValue) selectedCat = cats[i]; - tempId = selectedCat.parentId; - - for (i=cats.length-1;i>=0 ;i--) { - if (cats[i].id == tempId) { - pathNameStack.push(cats[i].name); - pathIdStack.push(cats[i].id); - tempId = cats[i].parentId; - } - if (cats[i].parentId == selectedValue) { - childrenNameStack.push(cats[i].name); - childrenIdStack.push(cats[i].id); - tempId = cats[i].parentId; - } - } - - document.merlotForm.elements[field].options.length = 0; - if (selectedCat.id > 0){ - if (childrenNameStack.length > 0) document.merlotForm.elements[field].options[0]= new Option('See sub-categories in ' + selectedCat.name +"...", selectedCat.id); - else document.merlotForm.elements[field].options[0]= new Option(selectedCat.name, selectedCat.id); - } - else document.merlotForm.elements[field].options[0]= new Option(selectedCat.name, selectedCat.id); - if (selectedValue !="") - { - document.merlotForm.elements[field].options[1]= new Option('--UP--', selectedCat.parentId); - j++; - } - for (i=childrenNameStack.length-1; i>=0; i--){ - document.merlotForm.elements[field].options[j]= new Option(childrenNameStack[i], childrenIdStack[i]); - j++ - } - if (selectedValue == "" && cats[0].name != "All"); - else pathList = pathList + "All"; - for (i=pathNameStack.length-2; i>=0; i--) pathList = pathList + " > " + pathNameStack[i] +""; - if (selectedCat.id != pathIdStack[0]) pathList = pathList + " > " + selectedCat.name +""; - if (show_id == 1) pathList = pathList + "  (" + selectedCat.id + ")"; - el.innerHTML = pathList; -} - -function defaultCat(id, field) { -subcat(id, field); -} - -function defaultCatWithId(id, field) { -subcatID(id, field, 1); -} - -var Today = new Date(); - -var MonthDays = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); -var MonthNames = new Array('January','February','March','April','May','June','July','August','September','October','November','December'); -var curYear = Today.getFullYear(); -var curMonth = Today.getMonth() + 1; -var curDay = Today.getDate(); -var monthFlag = "false"; -var dayFlag = "false"; -var yearFlag = "false"; -var time = Today.getTime(); -var yearsBack = 60; -var yearsAhead = 5; - -function setCurrent(field, form, el) -{ - monthFieldName = "month"+ field; - dayFieldName = "day"+ field; - yearFieldName = "year"+ field; - - if(el.checked==true){ - if (document.forms[form].elements[monthFieldName]) document.forms[form].elements[monthFieldName].disabled=true; - if (document.forms[form].elements[dayFieldName]) document.forms[form].elements[dayFieldName].disabled=true; - if (document.forms[form].elements[yearFieldName]) document.forms[form].elements[yearFieldName].disabled=true; - document.forms[form].elements[field].value=""; - } - else{ - if (document.forms[form].elements[monthFieldName]) document.forms[form].elements[monthFieldName].disabled=false; - if (document.forms[form].elements[dayFieldName]) document.forms[form].elements[dayFieldName].disabled=false; - if (document.forms[form].elements[yearFieldName]) document.forms[form].elements[yearFieldName].disabled=false; - - hiddenDate = ""; - if (document.forms[form].elements[yearFieldName]) hiddenDate = hiddenDate + document.forms[formName].elements[yearFieldName].options[document.forms[formName].elements[yearFieldName].selectedIndex].value; - else hiddenDate = hiddenDate + "9999"; - - hiddenDate = hiddenDate + "-"; - - if (document.forms[form].elements[monthFieldName]){ - monthIndex= document.forms[formName].elements[monthFieldName].selectedIndex + 1; - hiddenDate = hiddenDate + monthIndex; - } - else hiddenDate = hiddenDate + "01"; - - hiddenDate = hiddenDate + "-"; - - if (document.forms[form].elements[dayFieldName]) hiddenDate = hiddenDate + document.forms[formName].elements[dayFieldName].options[document.forms[formName].elements[dayFieldName].selectedIndex].value; - else hiddenDate = hiddenDate + "01"; - - document.forms[form].elements[field].value= hiddenDate; - } -} - -function setupDatePulldowns(field, form, inputDate, format, currentFlag, id) -{ - -formName = form; -dateFieldFormat = format; - -monthFieldName = "month"+ field; -dayFieldName = "day"+ field; -yearFieldName = "year"+ field; -currentFieldName = "current"+ field; - - -if (format.indexOf('{M}') >= 0) monthFlag = "true"; -if (format.indexOf('{D}') >= 0) dayFlag = "true"; -if (format.indexOf('{Y}') >= 0) yearFlag = "true"; - -if (inputDate=="") -{ - - if (monthFlag == "true") selectedMonth = curMonth; - if (dayFlag == "true") selectedDay = curDay; - if (yearFlag == "true") selectedYear = curYear; -} -else -{ -selectedMonth = inputDate.substring(5,7); -selectedDay = inputDate.substring(8,10); -selectedYear = inputDate.substring(0,4); -} - -monthField = ""; -dayField = ""; -yearField = ""; -currentField = " Current"; - -if (monthFlag == "true") dateFieldFormat = dateFieldFormat.replace("{M}",monthField); -if (dayFlag == "true") dateFieldFormat = dateFieldFormat.replace("{D}",dayField); -if (yearFlag == "true") dateFieldFormat = dateFieldFormat.replace("{Y}",yearField); -if (currentFlag == "true") dateFieldFormat = dateFieldFormat + currentField; - -document.writeln(dateFieldFormat + ""); - -if (monthFlag == "true") -{ - for (i=0;i<=11;i++) document.forms[formName].elements[monthFieldName].options[i] = new Option(MonthNames[i],i+1); - - if (selectedMonth>0) document.forms[formName].elements[monthFieldName].selectedIndex = selectedMonth-1; - else document.forms[formName].elements[monthFieldName].selectedIndex = 0; -} - -if (dayFlag == "true") -{ - if (selectedMonth==2) - { - if(selectedYear%4 == 0) pdEndDate = 29; - else pdEndDate = 28; - } - else pdEndDate = MonthDays[document.forms[formName].elements[monthFieldName].selectedIndex]; - - for (i=0; i<= pdEndDate-1; i++)document.forms[formName].elements[dayFieldName].options[i] = new Option(i+1,i+1); - document.forms[formName].elements[dayFieldName].selectedIndex = selectedDay-1; -} - -if (yearFlag == "true") -{ - for (i=0;i<=(yearsBack+yearsAhead);i++)document.forms[formName].elements[yearFieldName].options[i] = new Option(curYear-i+yearsAhead,curYear-i+yearsAhead); - document.forms[formName].elements[yearFieldName].selectedIndex = curYear-selectedYear+yearsAhead; -} - -hiddenDate = ""; - -if (yearFlag == "true") hiddenDate = hiddenDate + document.forms[formName].elements[yearFieldName].options[document.forms[formName].elements[yearFieldName].selectedIndex].value; -else hiddenDate = hiddenDate + "1999"; -hiddenDate = hiddenDate + "-"; - -if (monthFlag == "true") - { - monthIndex= document.forms[formName].elements[monthFieldName].selectedIndex + 1; - hiddenDate = hiddenDate + monthIndex; - } -else hiddenDate = hiddenDate + "01"; -hiddenDate = hiddenDate + "-"; - -if (dayFlag == "true") hiddenDate = hiddenDate + document.forms[formName].elements[dayFieldName].options[document.forms[formName].elements[dayFieldName].selectedIndex].value; -else hiddenDate = hiddenDate + "01"; - -document.forms[formName].elements[field].value= hiddenDate; - -if (currentFlag=="true" && inputDate=="" && id !="") -{ - document.forms[formName].elements[currentFieldName].checked=true; - setCurrent(field, formName, document.forms[formName].elements[currentFieldName]); -} - -} - -function update(fieldName) -{ -monthFieldName = "month"+ fieldName; -dayFieldName = "day"+ fieldName; -yearFieldName = "year"+ fieldName; - - if (monthFlag == "true") selectedMonth = document.forms[formName].elements[monthFieldName].selectedIndex + 1; - else selectedMonth = 1; - if (yearFlag == "true") selectedYear = document.forms[formName].elements[yearFieldName].options[document.forms[formName].elements[yearFieldName].selectedIndex].value; - else selectedYear = 1900; - -if (dayFlag == "true") -{ - selectedDay = document.forms[formName].elements[dayFieldName].selectedIndex; - - for (i=0;i<= document.forms[formName].elements[dayFieldName].length;i++) document.forms[formName].elements[dayFieldName].options[i] = null; - - if (selectedMonth==2) - { - if(selectedYear%4 == 0) pdEndDate = 29; - else pdEndDate = 28; - } - else pdEndDate = MonthDays[document.forms[formName].elements[monthFieldName].selectedIndex]; - - if (selectedDay > MonthDays[document.forms[formName].elements[monthFieldName].selectedIndex]) selectedDay = MonthDays[document.forms[formName].elements[monthFieldName].selectedIndex]; - - for (i=0; i<= pdEndDate-1; i++) document.forms[formName].elements[dayFieldName].options[i] = new Option(i+1,i+1); - if (selectedDay > document.forms[formName].elements[dayFieldName].length -1) selectedDay = document.forms[formName].elements[dayFieldName].length -1; - document.forms[formName].elements[dayFieldName].selectedIndex = selectedDay; -} -hiddenDate = ""; - -if (yearFlag == "true") hiddenDate = hiddenDate + document.forms[formName].elements[yearFieldName].options[document.forms[formName].elements[yearFieldName].selectedIndex].value; -else hiddenDate = hiddenDate + "1999"; -hiddenDate = hiddenDate + "-"; - -if (monthFlag == "true") - { - monthIndex= document.forms[formName].elements[monthFieldName].selectedIndex + 1; - hiddenDate = hiddenDate + monthIndex; - } -else hiddenDate = hiddenDate + "01"; -hiddenDate = hiddenDate + "-"; - -if (dayFlag == "true") hiddenDate = hiddenDate + document.forms[formName].elements[dayFieldName].options[document.forms[formName].elements[dayFieldName].selectedIndex].value; -else hiddenDate = hiddenDate + "01"; - -document.forms[formName].elements[fieldName].value= hiddenDate; -} - - - diff --git a/mods/merlot/merlot_adv.php b/mods/merlot/merlot_adv.php deleted file mode 100644 index c94b1f0ad..000000000 --- a/mods/merlot/merlot_adv.php +++ /dev/null @@ -1,172 +0,0 @@ - -
    -
    - - - - <?php  echo _AT('merlot'); ?> - - : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - -
    - - - -
    :
    - : - - -
    - : - - -
    - : - - -
    - : - -
    - - - -
    - : - - - -
    - : - - -
    - : - - -
    - : -
    - - - -
    -
    - - -
    -
    -
    -
    diff --git a/mods/merlot/merlot_rest.php b/mods/merlot/merlot_rest.php deleted file mode 100644 index 6d3019b75..000000000 --- a/mods/merlot/merlot_rest.php +++ /dev/null @@ -1,130 +0,0 @@ - "" || $title <> "" || $description <> "" || $author <> "" || $_REQUEST["creativeCommons"] == "true") -{ - $page = intval($_REQUEST['p']); - if (!$page) { - $page = 1; - } - - if ($results_per_page > $default_results_per_page || $results_per_page == 0) - $results_per_page = $default_results_per_page; - - $page_str = "results_per_page=".$results_per_page; - $url_search = "&size=".$results_per_page."&firstRecNumber=".$results_per_page*($page - 1); - - if ($keywords <> "") - { - $page_str .= SEP."keywords=".urlencode($keywords); - $url_search .= "&keywords=".urlencode($keywords); - } - if ($title <> "") - { - $page_str .= SEP."title=".urlencode($title); - $url_search .= "&title=".urlencode($title); - } - if ($description <> "") - { - $page_str .= SEP. "description=".urlencode($description); - $url_search .= "&description=".urlencode($description); - } - if ($author <> "") - { - $page_str .= SEP. "author=".urlencode($author); - $url_search .= "&author=".urlencode($author); - } - - if (isset($_REQUEST["search_type"])) - $page_str .= SEP."search_type=".$_REQUEST["search_type"]; - - if ($_REQUEST["search_type"] == 0) $url_search .= "&allKeyWords=true"; - if ($_REQUEST["search_type"] == 1) $url_search .= "&anyKeyWords=true"; - if ($_REQUEST["search_type"] == 2) $url_search .= "&exactPhraseKeyWords=true"; - if ($_REQUEST["creativeCommons"] == "true") - { - $page_str .= SEP. "creativeCommons=true"; - $url_search .= "&creativeCommons=true"; - } - - $url = $_config['merlot_location']."?licenseKey=".$_config['merlot_key'].$url_search; - - $xml_results = file_get_contents($url); - - if (!$xml_results) - { - $infos = array('CANNOT_CONNECT_SERVER', $_config['merlot_location']); - $msg->addInfo($infos); - } - else - { - $MerlotResultParser =& new MerlotResultParser(); - $MerlotResultParser->parse($xml_results); - $result_list = $MerlotResultParser->getParsedArray(); - - if ($result_list['status'] == 'failed') // failed, display error - echo ""._AT('error').": ".$result_list['error'].""; - else // success, display results - { - if (is_array($result_list)) - { - $num_results = $result_list["summary"]["totalCount"]; - $num_pages = max(ceil($num_results / $results_per_page), 1); - - echo '
    '; - echo "

    ". _AT('results')." (".$result_list["summary"]["resultCount"]." out of ".$num_results.")

    "; - - print_paginator($page, $num_results, htmlspecialchars($page_str), $results_per_page); - - foreach ($result_list as $key=>$result) - { - if (is_int($key)) - { -?> - -
    - -
    -

    - -
    -
    - -
    -
    - -
    -
    120) echo substr(htmlspecialchars($result['description']), 0, 120). "..."; else echo htmlspecialchars($result['description']); ?>
    - -
    -
    -
    -
    -'; - } - } - } -} -?> \ No newline at end of file diff --git a/mods/merlot/merlot_soap.php b/mods/merlot/merlot_soap.php deleted file mode 100644 index 77324db24..000000000 --- a/mods/merlot/merlot_soap.php +++ /dev/null @@ -1,115 +0,0 @@ -'; - if($_REQUEST['keywords'] != ''){ - $keywords = stripslashes($_REQUEST['keywords']); - $search .= ''.$keywords.''; - } - - if($_REQUEST['title'] != ''){ - $title = stripslashes($_REQUEST['title']); - $search .= ''.$title.''; - } - - if($_REQUEST['contributorName'] != ''){ - $author = stripslashes($_REQUEST['contributorName']); - $search .= ''.$author.''; - } - - if($_REQUEST['url'] != ''){ - $url = stripslashes($_REQUEST['url']); - $search .= ''.$url.''; - } - - if($_REQUEST['description'] != ''){ - $description = stripslashes($_REQUEST['description']); - $search .= ''.$description.''; - } - - if($_REQUEST['category'] != ''){ - $category = intval($_REQUEST['category']); - $search .= ''.$category.''; - } - - if($_REQUEST['language'] != ''){ - $language = stripslashes($_REQUEST['language']); - $search .= ''.$language.''; - } - - if($_REQUEST['materialType'] != ''){ - $type = stripslashes($_REQUEST['materialType']); - $search .= ''.$type.''; - } - - if($_REQUEST['audience'] != ''){ - $context = stripslashes($_REQUEST['audience']); - $search .= ''.$context.''; - } - - $search .= ''; - } - - $search_input = array($merlot_key, $search,'0','25'); - $client = new SoapClient($merlot_location); - - if($search && $search != '' && $search != ''){ - $results = $client->__soapCall('doSearch', $search_input); - $results = get_object_vars($results); - - $result_count = count($results['resultElements']); - echo '

    '. _AT('merlot_results_found') .' - '.$results['totalResultsCount'].' -- '._AT('merlot_results_displayed').' '. $result_count.'

    '; - - for($i = 0; $i < $result_count; $i++){ - $this_result = get_object_vars($results['resultElements'][$i]); - if(fmod($i,2) ==0){ - $bgstyle = "#ffffff"; - }else{ - $bgstyle = "#eeeeee"; - } - - echo '
    '; - echo ''.$this_result['title'].' [ '._AT('merlot_full_record').' ] '; - - // if links db is enabled for this course allow results to be added to it. - if($this_result['numAssignments']){ - echo '[ '._AT('merlot_view_assignments').' ]'; - } - if($links == true){ - echo '[ '._AT('merlot_add_to_link').' ]'; - } - - echo '
    '._AT('merlot_author').": ".$this_result['authorName'].'
    '; - echo _AT('merlot_description').": ".substr($this_result['description'], 0,200).'...
    '; - echo _AT('merlot_type').": ".$this_result['itemType'].'
    '; - echo _AT('merlot_creation_date').": ".date("F j, Y",strtotime($this_result['creationDate'])).'
    '; - echo '
    '; - unset($this_result); - } - }else if($results['totalResultsCount'] < 1){ - echo '

    '. _AT('merlot_results_found', $result_count).' 0

    '; - } - -?> \ No newline at end of file diff --git a/mods/merlot/merlotlogo.gif b/mods/merlot/merlotlogo.gif deleted file mode 100644 index ad201af31e71553a279e23f979294888559ed0dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4762 zcmWlY`#%%<XS>kjX79*4Kaky;D&! z^Ww$JM~@y|yH?L+-VzFnXtZPt3mJovNhHpF{K&*$K2AtfiVByf9ZC1vv1%2{P81m^X60f`c)ATAD%xyZEW1m;VdsNFa7+v z@cnxf6#98;>hrsIiK|y^X4L*K0Q8OxO;bTaB!ljX|{_?j;rgXu&^i?thcOe_~y;FoE+)?{RRI14;mX| zw6&-I{`=?re1?k5OGFECy~gzGTG(G$WO0cu{Lf@ zv9g+(nE3wX%iEEW@$T***bau*5ooY%*;JCTvY~9LoaER2>sy=a| zEj#G#sFx2PimBAUE?gLDZ5_RRTe4?Q zUsY9YOw1o>^t0aH2Te_R6v{1;NRgU)&f5AfiRAqH^?Xmy>uG5`506wEo6AvA^?&?P z86N(;ukX)-f~!eMU3q!w_Vz7o_U*z#O>=WYT%2&%uEFcqg+4x#y?ck-+tt<8$>!!a zb8{yK1|D9yQu50$7Xkz8e*gX1ojcs^+pndhynXVd@yr?7(W5uAvd);8bntk&+qRV- zI&`nL_C{vrZLxT2badkW{ilEa*(ngb=W4 z`yT;t_<#KW69BmaNRuqGLZ-@aBd?*WnU#e{maPKHrZT#F`FQI@|1+DadkwbH)EWjQ z69LhWfCXT?X<3|2ZN_T07L>iCHr2B$@m02;!1&bb3DI>G)MjUTN~@xlUb*d805X;}lrCfzx%$-y+8bialAuz|KKhuV_U#7wKeXkWdgZo6IB=@CaO7hdnZ zV<+HO^lCaQInt_;)n*?LM9?b3dE-vH9?{Jo{&-x4>YlL~_$5MM`Os*u()~?9F9Hz| zMRjK%f7)1VmicuDTbr*(>k*TlU|LDh*p*A2#Y`8+TnOj!&V5~VT- zHty2=1U$b zitoWFCf0D{Tnh_@OCIzg1?^Ffxjyz%>R~I$2V37}POl@MgqQOUy_PwxN=#qv3 ziS&=q>;sU~mb;9OL_DQ{822-m_00%zb(k_LMv0t%+xYL!Kj}jwoB4J%yp1uCj8If! zD!wt8KUb(~EmJY~kdDz4g0x-cj`92rCjrfIOb@0N9V=R zRPOzDMr5&l@$IHz!+rN}nV@;h0|VMVhjn)82L!RaNvi?&4)9sMQXU31a(F)HGc#A% zcQ4?%Mo+!=$RK)E$bvP?aH+kgIqY>(RAO_S{EA6u8M{Z@#pK%=PVgG3|9$TDxuw|` zZ0GVp>fpV@0t@H3?E)C=a_ePe4g->SaccYcxSL{?-|A!Ta;Y;84W zy62#oWw+l}_h$s|2S2}f$a5UT$<22iXA69dJWgg~B!4i3MjwQsb3>Ji)S0(tT%~^R zWCjL5%R=mdtlEFs#6hV=Gh>tCx0w)(Jo^s!H@H@B#F znJJ;M5xNNhrqD7(#1|U}Q zK|d1f9javAM7Ck2H{1y#iM(7+*F=%73wUQWI+flvj$MxFQI&7phG2En)KDzdp+;3;8B_qTz%VuFP z@5|9%B z(;&07U1oS+0bgW{X<=#W4Se2f!xYGsp0r`MvoYEG%{b;3;&r9Dr@8{Y&&Odn>L|iK z3TB9u<(LpDhz$Rp(uJVxnI;M(j$A>4g|a_Wv$XC`^{rd;M!2)A()^8oBrnQtOw-=*oS25g#zB9X3MJrVjF*Rw!iL55QlVd9L_l2k4 zrH{&xOSBAKN!72%R#JSN#Uz|9g;JK{P`hn+TVcuXjn$QsNl#T9A*jN`VoDg8)n{Ny zj%B((=Co2XE6OHwLIWdlTYZGeM|oF6YY#pDaH6H@l?+Z^w7D+PF~J|NMD5 z_FxYAiWdHvL29+_P=4@XRu=sRlC13LexzZRso}FL@T1aT)G6$t`M@m9c5h~y@iRx1 z3%)CcO^h^a9v|_w!SeY~yIvZ5__r+G?baDADViksg8$^CoqmA+c*>Ke@ltf5a)$p&h#6XC_Q88bfy~a|0Mz#tu`t z=w-J8DD0z)JehR^fNKKdm%&!VjNrozS7byV;+)cWL(3U<)WpZr@R2c;do|m?@s0MW z2@{!lS$X_iwFa+x8_HuurNdqtFU>1WJ%Tf0<#*PMZO%f+(nEx=O9hYS`%O7>ITe>d z+%oYFcPlvAm1U{3ME6O&XW24R=?lz5_@-ovB5VV}6-VDis;Yd(mncn7s%(56M9qE4 zm!UssyDhg^K|>Bl=ocJNZQFc0^aF3ssx~Rm!6O)oad~O=jkeq2(s7)P-Wij!_%gcK4>CoUG&F1BO(s^xzR^0fsTYl+=SGGN2Mc2A-w< z>_e|?(NTKa!SDx3yoo4*o^s1oP8JS9$)(_BCdb;nu-hH6Mv9j*2U$1&xCjBCV&msL z+qVsSWzDEr?B`Z6SH2Q{=;lGY11$KuP-d3x420k&;XodW-tnVUxOQMlzmu5;Oho;}iQU1C~+&wa}4AD;0RZtVP|#y7|iw{C3c>`+>h zskJ-D&(5BV*xzn}(ZT?|t8CtuRGDeKIv?R5i@s$!?JOlTROvYqv)+hR(w{pdx-k4yWFgm|j=-gFc7&LemEyP%a@UhS@ zCa-auMcgDK&JeYq&=CE{cTTYo2}HCvQLB=LNMl74RH&U6aI#2SK-O`c)e!;&Lx~BW zfVoY<9$O%)h`N%k*u%5XUs-So85*e3`G=_Oz(O-;!|`#DqfGDz8HQm&Sr9!0EmYN# zU1k}6cs{#~tu>%T^vLu%7DxsMOJ%@c%^K8OK;jkfSe%9NL^hTJxl@#r(w>_-nwvJC z%ffRq+&EcuPEHbsBjxbgIf79Rcf}3pLb)Wi70wbMmD!8rwaY9ZoHK&Vav!e3R!DQ; zM3+NSE-nbjrZ@o*pohU~$-wKESP30i*toagJ>*kph=$v$MlX^*jW+XC&Y*Y-4ae|8 zuJaACKv#)=sOFie07_{MRe;hYFzgKQK3u&CP%7t&q~J+AKv@X1Sb4SnU^EGg`FqYF zL9H8BVvAiQ=c9=HfALrZIe!ERbTPhg8PH+uhcotzU*$hc01yiy7Ave(3##1s5^25x zR{-p=NC5uCW5=h^&!!5H%57Q``F(Wo+E$P_37}-BFZg`Amq4NxNbmr~;2Nx0fW=wf zG62I+;L#0+GxM+zKsP+!j6AhWbb=_i!IWUI4;UYm(1(PB-$fUb_`U6XuW2-jMKMsK zoAJK>^}xfb;MTlAH%LP2w|4*Gug&BlnS9@Vev7RORt5a*+-Y{eBN_)LieVz)NxhIr zz&h7+ce@uXEBLlv;QFWtLIb7k`~;L3g(<=fqLu!hNFskrwDgf17RCg6GVUSjS{SV) zt3&EZ*a#Js&@+m}(M8Lkq(WV=%*yMQ1H(y>LnysjFSY0|fXG1SYwU0V&{l3ECQGkU z3kB2CoAt#?f3S~$Eg}>;m6Ux&ijj6@2`e4oKU-;+wDd{8@TNaE!JU^tz4$sDSj zF+7nPcx)*qqzH8G$uRG$m9|wPX&He6Y`ByT4nWdCvzU(nrQ_UnGkq7{pxFxSjjliwK-s7iqN%}d7T=sc?8tR%q1TF?#ix07-|!m~bi@pv z+#Z$Jx#ClE;C;=Jh1v>t;SjyPD5YLnT3@=IW1B3H2LaeZHVo5{HeYbTwvH4h!d8kQ z;WbcG_gZ^wlTMCTfOT@)#un@i<0CG>bkJ^wc(vLM4dd2H!yAx980M~_oJV0uY)QZ?LONI`SY$i4mS{5Ww%1Xpu`66$MpN(0Q-%3%zPlTDdS^ zFdq$c?n##|_-36ADIGvbEwyQ=$aAk+%@?HD9qshFBz{_IHc;_*@^#a{OTVln3jX77%kCdTz-TEI|BG-(YzZ00;9ObC8S`heZ?cfHLCq3y10=V zP>K{)8Jc39_}8BBZft9)&Y_ksD*-~IxI(zm+}(ESr|3x64axYW1$Fre-3up9;w0)8 zPpT(vBlc!zLCigCz!3b}*cSTXLi3mMW#WyL=(hCL8*kkcJ>ZCDxNS@IZ3ePhXkX<@R&xwt2~4ic!%!4z^aO4ltG9 z4%HAll^$OTUTsvRzPi1RTD`lgKH#(ece$!$!9V`JYK&5%>(OX6!}*{ix}4JO@T@xk Iivc_S4@_fTwEzGB diff --git a/mods/merlot/module.css b/mods/merlot/module.css deleted file mode 100644 index 452670ea3..000000000 --- a/mods/merlot/module.css +++ /dev/null @@ -1,230 +0,0 @@ -.fieldLabel {font-weight: bold; text-align: right; vertical-align: top;} -.fieldError {color: #660000;}. -.buttonBar {text-align: right; vertical-align: top;} -.input.text {width:275px;} - -/* -.fieldError {color: #660000;}.fiyatext {font-size: 8pt; color: #333333;} -.fiyatitle {font-size: 9pt; color: #836B3E;} -.fiyatitle a {color: #836B3E; font-weight: bold; text-decoration: none;} -.fiyatitle a:hover {color: #660000; text-decoration: none;} -.fiyaheader {font-size: 11pt; color: #FFFFFF; font-weight: bold;} -.fiyaheadersub {font-size: 10pt; color: #FFFFFF; font-weight: bold;} -.footer {font-size: 11px; color: #CCBB82;} -.footer a {font-size: 11px; color: #EEEEEE; text-decoration: none;} -.footer a:hover {font-size: 11px; color: #FFFFFF; text-decoration: underline;} -.footer td {font-size: 11px; color: #CCBB82;} -.graytext {font-size: 8pt; color: #676767;} -.header1 {font-size: 14pt; font-weight: bold; color: #AAAAAA;} -.header2 {font-size: 10pt; font-weight: bold; color: #AAAAAA;} -.header2 a {color: #AAAAAA; text-decoration: underline;} -.header2 a:hover {color: #101010; text-decoration: none;} - -.hitlistextras a {color: #660000; } -.hitlistextras a:hover {color: #816B23;} -.hpdisc a {color: #660000; text-decoration: none;} -.hpdisc a:hover {color: #676767; text-decoration: underline;} -.hpdisc td {font-size: 8pt; color: #660000;} -.learnbold {font-size: 9pt; color: #FFFFFF;} -.learnbold a {color: #FFFFFF; font-weight: bold; text-decoration: none;} -.learnbold a:hover {color: #cccccc; text-decoration: none;} -.learnsmall {font-size: 7pt; color: #FFFFFF;} -.leftside a {color: #000000; text-decoration: none;} -.leftside a:hover {color: #777777; text-decoration: underline;} -.leftside td {font-size: 8pt; color: #000000; } -.leftsideshowmore a {color: #816B23; text-decoration: none; font-size: 8pt;} -.leftsideshowmore a:hover {color: #660000; text-decoration: underline; font-size: 8pt;} - -.login {font-size: 11px;} -.materialadded {font-size: 8pt;} -.materialdescription {font-weight: bold; color: #333333;} -.materialtitle {font-size: 14pt; font-weight: bold; color: #333333;} -.peerreviewtitle {font-size: 12pt; font-weight: bold;} -.peerreviewtitle a {color: #660000;} -.peerreviewtitle a:hover {color: #816B23; text-decoration: none;} -.smalltext {font-size: 7pt;} - -.rightside a {color: #660000;} -.rightside a:hover {color: #816B23;} -.rightside td {font-size: 8pt; background-color: #f7f7f7;} -.rightside2 a {color: #660000;} -.rightside2 a:hover {color: #816B23;} -.rightside2 td {font-size: 8pt; background-color: #fafafa;} -.rightside3 a {color: #660000;} -.rightside3 a:hover {color: #816B23;} -.rightside3 td {font-size: 8pt; background-color: #fafafa;} -.rightsideborder {background-color: #816B23;} -.rightsideborder2 {background-color: #9E883E;} -.rightsideborder3 {background-color: #BBA458;} - -.centeredImage {vertical-align: middle;} - -.search {font-size: 11px;} -.search a {font-size: 10px; color: #660000; text-decoration: none;} -.search a:hover {font-size: 10px; color: #816B23; text-decoration: underline;} -.search td {font-size: 11px;} - -.whatsnewbold {color: #660000; font-weight: bold;} -.whatsnewheader {color: #000000;} -.whatsnewheader a {color: #000000; text-decoration: none;} -.whatsnewheader a:hover {color: #aaaaaa; text-decoration: underline;} -.whatsnew a {color: #676767; text-decoration: none;} -.whatsnew a:hover {color: #aaaaaa; text-decoration: underline;} -.whatsnew td {font-size: 8pt; color: #000000; } -.whatsnew {font-size: 8pt; color: #000000; } - -.rightsidepartners {font-size: 8pt; color: #000000; } -.rightsidepartners a {color: #000000; text-decoration: none;} -.rightsidepartners a:hover {color: #aaaaaa; text-decoration: underline;} - -.rightsideloginheader {font-size: 12px; font-weight: bold; color: #FFFFFF;} -.rightsideloginheader2 a {font-size: 10px; font-weight: bold; color: #FFFFFF; text-decoration:none;} -.rightsideloginheader2 a:hover {font-size: 10px; font-weight: bold; color: #CCCCCC; text-decoration:underline;} -.rightsidelogin a {font-size: 7pt; color: #816B23; text-decoration: none;} -.rightsidelogin a:hover {color: #660000; text-decoration: underline;} -.rightsidelogin td {font-size: 9pt; font-weight: bold; color: #660000;} -.rightsideloggedin a {font-size: 8pt; color: #000000; text-decoration: none;} -.rightsideloggedin a:hover {color: #777777; text-decoration: underline;} -.rightsideloggedin {font-size: 8pt; color: #660000;} -.rightsideloggedinbold {font-size: 8pt; font-weight: bold; color: #660000;} -.rightsidejoinnowHeader {font-size: 11pt; font-weight: bold; color: #660000;} -.rightsidejoinnowHeader2 {font-size: 8pt; font-weight: bold; color: #660000;} -.rightsidejoinnow {font-size: 8pt; color: #816B23;} -.rightsidejoinnowbold {font-size: 8pt; color: #816B23; font-weight: bold;} -.rightsidejoinnow a {font-weight: bold; font-size: 9pt; color: #816B23; text-decoration:none;} -.rightsidejoinnow a:hover {font-weight: bold; font-size: 9pt; color: #660000; text-decoration:underline;} - -.rightsidecontributeheader {font-size: 12px; font-weight: bold; color: #FFFFFF;} -.rightsidecontributeheader2 {font-size: 9pt; color: #816B23; font-weight: bold;} -.rightsidecontribute {font-size: 7pt; font-weight: bold; color: #660000;} -.rightsidecontribute td {font-size: 7pt; font-weight: bold; color: #660000;} -.rightsidecontribute a {font-size: 7pt; color: #816B23; text-decoration: none;} -.rightsidecontribute a:hover {color: #660000; text-decoration: underline;} - -.whitetext {font-size: 8pt; color: #FFFFFF; } -.whitetext a {color: #DDDDDD;} -.whitetext a:hover {color: #FFFFFF;} -a {color: #816B23;} -a.login {font-size: 11px; color: #660000; text-decoration: underline;} -a.login:hover {font-size: 11px; color: #816B23; text-decoration: none;} -a:hover {color: #660000;} -body {font-family: Arial, Helvetica, sans-serif; font-size: 9pt;} -td {font-family: Arial, Helvetica, sans-serif; font-size: 9pt;} -.caption {color: #FFFFFF; background-color: #BBA458; font-weight: bold;} -.caption a {color: #FFFFFF; font-weight: normal;} -.caption-main {color: #FFFFFF; background-color: #660000; font-weight: bold;} -.caption-main a {color: #FFFFFF; font-weight: normal;} -.caption-main-white {font-size: 9pt; color: #FFFFFF;} -.caption-main-white a {color: #FFFFFF; font-weight: bold; text-decoration: none;} -.caption-main-white a:hover {color: #cccccc; font-weight:bold; text-decoration: none;} -.caption-sub {color: #FFFFFF; background-color: #BBA458; font-weight: bold;} -.caption-sub a {color: #660000; font-weight: bold; text-decoration: none;} -.caption-sub a:hover {color: #cccccc; font-weight: bold; text-decoration: none;} -.search-results {color: #101010; background-color: #EFEDCF; font-weight: bold;} -.search-results-header {background-color: #CCCCCC; color: #000000; font-weight: normal;text-align: right;} -.search-results a {color: #101010; font-weight: normal;} -.content {background-color: #FFFFFF; color: #000000; font-weight: normal} -.content a {color: #816B23;} -.content-table {background-color: #FFFFFF; color: #000000;} -.content-header {background-color: #AAAAAA; color: #000000; font-weight: bold;text-align: left; vertical-align: top;} -.content-header a {background-color: #AAAAAA; color: #606060; font-weight: bold;text-align: left; vertical-align: top;} -.content-odd {background-color: #FFFFFF; color: #000000; font-weight: normal; vertical-align: top;} -.content-odd a {color: #816B23;} -.content-even {background-color: #EEEEEE; color: #000000; font-weight: normal; vertical-align: top;} -.content-even a {color: #816B23;} -.content-no-data {background-color: #FFFFFF; color: #707070; font-weight: normal; font-style: italic; text-align: center; vertical-align: top;} -.content-action-row {padding-top: 0px; background-color: #FFFFFF; color: #000000; font-weight: bold; font-style: normal; vertical-align: top;} -.value-table {background-color: #FFFFFF; color: #000000; font-weight: normal; border: solid 1px #DDDDDD; border-collapse: collapse} -.value-header {background-color: #EEEEEE; color: #000000; font-weight: normal; text-align: left; vertical-align: top;} -.value-odd {background-color: #FFFFFF; color: #000000; font-weight: normal; vertical-align: top;} -.valuet-odd a {color: #816B23;} -.value-even {background-color: #FFFFFF; color: #000000; font-weight: normal; vertical-align: top;} -.value-even a {color: #816B23;} -.value-table {background-color: #FFFFFF; color: #000000; font-weight: normal; border: solid 1px #DDDDDD; border-collapse: collapse} -.value-header {background-color: #EEEEEE; color: #000000; font-weight: normal; text-align: left; vertical-align: top;} -.value-odd {background-color: #FFFFFF; color: #000000; font-weight: normal; vertical-align: top;} -.valuet-odd a {color: #816B23;} -.value-even {background-color: #FFFFFF; color: #000000; font-weight: normal; vertical-align: top;} -.value-even a {color: #816B23;} -.form {font-weight: normal; margin: 0px; border: 0px; padding: 0px; border-spacing: 8px;} -.form-instruction {padding: 10px; width: 450px;} -.atlernate-form {background-color: #EEEEEE; border: solid 1px #CCCCCC; border-collapse: separate; border-spacing: 3px; padding: 6px 6px 6px 6px;} -.alternate-form-Label {font-weight: bold; text-align: left; vertical-align: top; padding: 6px 6px 12px 6px;} -.fieldLabel {font-weight: bold; text-align: right; vertical-align: top;} -.fieldCenteredLabel {font-weight: bold; text-align: right; vertical-align: middel;} -.field {text-align: left; vertical-align: top;} -.buttonBar {text-align: right; vertical-align: top;} -.detail {font-weight: normal; margin: 0px; border: 0px; padding: 0px; border-spacing: 8px;} -.detailLabel {font-weight: bold; text-align: right; vertical-align: top; color: #AAAAAA;} -hr {height: 1px; border: 0px; background-color: #AAAAAA; color: #AAAAAA;} -.wizardTab {font-weight: bold; text-align: left; margin: 0px; border: 0px; padding: 0px;} -.wizardTab-line1 {font-size: 8pt; vertical-align: top;} -.wizardTab-line2 {font-size: 7pt; vertical-align: top;} -.wizardTab-current {font-weight: bold; text-align: left; color: #000000; margin: 0px; border: 0px; padding: 0px;} -.wizardTab a:link {color: #816B23;} - .wizardTab a:visited {color: #816B23;} -.wizardTab a:hover {color: #000000;} -.browse-left-table {background-color: #F4F4F4; color: #000000; font-weight: normal; border: solid 1px #CCCCCC; border-collapse: separate; border-spacing: 3px; padding: 0px; } -.browse-left-table-section-header { background-color: #CCCCCC; color: #660000; font-weight: bold; } -.browse-left-table td {padding: 3px 6px 3px 6px;} -.input {width:275px;} -*/ - -/* This is the style for the informational messages presented to the user */ - -div.error, div.message { background: #ffc; border: 1px solid #000; color: #000000; font-family: Arial, Helvetica, sans-serif; font-size: 0.9em; font-weight: normal; margin: 10px auto; padding: 3px; text-align: left; vertical-align: bottom;} - - -/* use a different color for the errors */ - -div.error { border: 2px solid red;} -img.validationWarning,div.errors img.icon, div.messages img.icon { border: 0; width: 14px; height: 13px; vertical-align: top;} -div.message a { background: transparent; color: #0000FF;} -div.message a:visited { background: transparent; color: #0000FF;} -div.message a:hover { background: transparent; color: #008000;} -div.message a:active { text-decoration: underline overline;} -div.message img.icon { vertical-align: middle;} -span.fieldError { color: red; font-size: .95em; font-weight: bold;} - -.portfolio{ font-size:11px; width:185; margin-top:2; margin-bottom:2; background-color: #ffffff; color:#660000; } - -.communities { - color: #660000; font-size: 14px; font-weight: bold; -} - -.ScrollDiv { -width:500px; -height:175px; -overflow: auto; -background-color: #E3E1DD; -border-color: #CCCCCC #666666 #666666 #CCCCCC; -border: 1px solid; -} -.legend {font-family: Arial, Helvetica, sans-serif; font-size: 8pt;} -.legend-left-table {background-color: #F4F4F4; color: #000000;font-weight: normal;border: solid 1px #CCCCCC; border-collapse: separate;border-spacing: 3px;padding: 0px;} -.legend-left-table-section-header {background-color: #CCCCCC; color: #660000; font-weight: bold;} -.legend-left-table td {padding: 1px 1px 1px 1px;} - -/* browse courses */ -dl.browse-result { - width: 100%; - padding-bottom: 25px; - background-color: #fffaf0; - border:1px #6F7172 solid; - width:90%; - margin:auto; -} -dl.browse-result dt { - float: left; - font-weight: bold; - width: 25%; - text-align: right; - padding: 5px 10px 5px 0px; - vertical-align: middle; -} -dl.browse-result dd { - margin-bottom: 5px; - clear: right; - padding: 5px 0px 5px 10px; - margin-left: 26%; -} diff --git a/mods/merlot/module.php b/mods/merlot/module.php deleted file mode 100644 index 609673190..000000000 --- a/mods/merlot/module.php +++ /dev/null @@ -1,43 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_MERLOT', $this->getAdminPrivilege()); - -/* if this module is to be made available to students on the Home or Main Navigation. */ - -$_student_tool = 'mods/merlot/index.php'; -$this->_pages['mods/merlot/add_to_links.php']['title_var'] = 'add_link'; - -/******* - * add the admin page so the Userplane ID can be managed - */ - -if (admin_authenticate(AT_ADMIN_PRIV_USERPLANE, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/merlot/index_admin.php'); - $this->_pages['mods/merlot/index_admin.php']['title_var'] = 'merlot'; - $this->_pages['mods/merlot/index_admin.php']['parent'] = AT_NAV_ADMIN; -} - -/******* - * student or instructor page. - */ -$this->_pages['mods/merlot/index.php']['title_var'] = 'merlot'; -$this->_pages['mods/merlot/index.php']['img'] = 'mods/merlot/merlot.gif'; - -?> \ No newline at end of file diff --git a/mods/merlot/module.sql b/mods/merlot/module.sql deleted file mode 100644 index b79a94fa6..000000000 --- a/mods/merlot/module.sql +++ /dev/null @@ -1,48 +0,0 @@ -# sql file for Merlot module - -INSERT INTO `language_text` VALUES ('en', '_module','merlot','MERLOT Repository',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_howto','Enter terms to search for in the MERLOT Repository of Educational Resources.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_results_displayed','Results Displayed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_results_found','Results Found',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_add_to_link_howto','The following link will be added to the course links. Select a category and adjust the title and description as needed.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_creation_date','Creation Date',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_full_record','View MERLOT Record',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_add_to_link','Add to course links',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_attribute','Find material by attributes',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_keywords','Keywords',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_by_keywords','Find material by keyword',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_simple','Simple Search',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_advanced','Advanced Search',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_title','Title',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_url','URL',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_description','Description',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_subjects','Subject Categories',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_language','Language',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_material_type','Material Type',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_audience','Audience',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_by_author','Find Material by Author',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_author','Author',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_search','Search',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_description','Description',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_type','Type',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_save','Save',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_name','Name',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_view_assignments','View Assignments',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_cancel','Cancel',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_category','Link Category',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_submit','Submit',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_add_link','Add Course Link',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_creative_commons','Creative Commons',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_results_per_page','Number of Results to Display Per Page',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_web_service_agreement','MERLOT Web Services and Related Software Agreement',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_user_agreement','MERLOT Acceptable Use Agreement',NOW(),''); - -INSERT INTO `language_text` VALUES ('en', '_module','merlot_config','Enter the location of the MERLOT repository (http://www.merlot.org/merlot/materials.rest) and the MERLOT key. A free MERLOT key can be obtained at: (http://www.merlot.org/merlot/signWebServicesForm.htm) ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_location','MERLOT Location',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','merlot_key','MERLOT Key',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_MERLOT_NOT_CONFIG','The MERLOT Repository does not appear to be activated. Please contact your ATutor administrator to have it turned on.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_MERLOT_CONFIG_SAVED','The MERLOT configuration was successfully saved.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_MERLOTKEY_ADD_EMPTY','The MERLOT Key field can not be empty.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_MERLOTURL_ADD_EMPTY','The MERLOT Location field can not be empty.',NOW(),''); - - diff --git a/mods/merlot/module.xml b/mods/merlot/module.xml deleted file mode 100644 index c78c66554..000000000 --- a/mods/merlot/module.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - MERLOT Search Module - A REST web service client for searching the MERLOT content repository. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - GPL - - 0.3 - - - - - 2010-10-25 - stable - A MERLOT key is required to activate this module. See the README included with the module source code for details. - - \ No newline at end of file diff --git a/mods/merlot/module_install.php b/mods/merlot/module_install.php deleted file mode 100644 index 204f471bd..000000000 --- a/mods/merlot/module_install.php +++ /dev/null @@ -1,66 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/merlot/module_uninstall.php b/mods/merlot/module_uninstall.php deleted file mode 100644 index 60ce25da8..000000000 --- a/mods/merlot/module_uninstall.php +++ /dev/null @@ -1,26 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/openmeetings/TODO.txt b/mods/openmeetings/TODO.txt deleted file mode 100644 index 29cf825cd..000000000 --- a/mods/openmeetings/TODO.txt +++ /dev/null @@ -1,42 +0,0 @@ -+======+ -| TODO | -+======+ -@author harris w. -@date June 05,08 - -June 05, 08 ------------- -- allow admin to change the room size. -- clean room after course is deleted. -- though these would be way easier to do it in the openmeeting's end -- upgrade nusoup script -- update readme, and write up something that teaches the user to setup red5 -- allow 2 modes - - -June 11, 08 ------------- -- Allow each group to have their own meeting, anyone in the group can start off the meeting, and when all exit, room should be deleted. -- Course meeting should be triggered by instructor only. Otherwise page should display the meeting time (There is no meeting at the moment. THe next available meeting is at xxxx) -- Instructor should probably be capable to adjust their own meeting size in their own config. -- Research on how recorded video works, see if we can remove meetings as well. -- admin/openmeetings, check if there is a slash at the end. - - -June 19, 08 ------------- -- Allow users to retrieve the recordings. [June 25, 08 - milestone for version 5.3] -- Make the index page a bit more pretty. - -June 25, 08 ------------- -- Admin can now delete or create group meetings - -June 26, 08 ------------- -- Added the ability to create diff type of rooms: conference/audience - -Feb 5, 09 ------------- -- Added the ability to delete conference rooms. -- Now compatible with Openmeetings 0.7RC1 (Red5 7.0+) \ No newline at end of file diff --git a/mods/openmeetings/add_group_meetings.php b/mods/openmeetings/add_group_meetings.php deleted file mode 100644 index 80242b24b..000000000 --- a/mods/openmeetings/add_group_meetings.php +++ /dev/null @@ -1,141 +0,0 @@ -addError('OPENMEETINGS_ADD_FAILED'); - header('index.php'); - exit; - } - $result = mysql_query($sql, $db); - $row = mysql_fetch_assoc($result); -} - -//Initiate Openmeeting -$om_obj = new Openmeetings($_SESSION['course_id'], $_SESSION['member_id'], $group_id); - -//Login -$om_obj->om_login(); - -//Get the room id -//TODO: Course title added/removed after creation. Affects the algo here. -if ($_row['title']!=''){ - $room_name = $_row['title']; -} else { - $room_name = 'group_'.$group_id; -} - -//Form action -//Handle form action -if (isset($_POST['create_room']) || (isset($_POST['update_room']) && isset($_POST['room_id']))) { - //mysql escape - $_POST['openmeetings_roomtype'] = intval($_POST['openmeetings_roomtype']); - $_POST['openmeetings_num_of_participants'] = intval($_POST['openmeetings_num_of_participants']); - (intval($_POST['openmeetings_ispublic']) == 1)?$_POST['openmeetings_ispublic']='true':$_POST['openmeetings_ispublic']='false'; - $_POST['openmeetings_vid_w'] = intval($_POST['openmeetings_vid_w']); - $_POST['openmeetings_vid_h'] = intval($_POST['openmeetings_vid_h']); - (intval($_POST['openmeetings_show_wb']) == 1)?$_POST['openmeetings_show_wb']='true':$_POST['openmeetings_show_wb']='false'; - $_POST['openmeetings_wb_w'] = intval($_POST['openmeetings_wb_w']); - $_POST['openmeetings_wb_h'] = intval($_POST['openmeetings_wb_h']); - (intval($_POST['openmeetings_show_fp']) == 1)?$_POST['openmeetings_show_fp']='true':$_POST['openmeetings_show_fp']='false'; - $_POST['openmeetings_fp_w'] = intval($_POST['openmeetings_fp_w']); - $_POST['openmeetings_fp_h'] = intval($_POST['openmeetings_fp_h']); - - //create a new room - if (isset($_POST['create_room'])){ - //Get the room id - //TODO: Course title added/removed after creation. Affects the algo here. - if (isset($_SESSION['course_title']) && $_SESSION['course_title']!=''){ - $room_name = $_SESSION['course_title']; - } else { - $room_name = 'course_'.$course_id; - } - - //add the room with the given parameters. - $om_obj->om_addRoom($room_name, $_POST); - $msg->addFeedback('OPENMEETINGS_ADDED_SUCEEDED'); - header('Location: index.php'); - exit; - } elseif (isset($_POST['update_room'])){ - //update a room - $om_obj->om_updateRoom(intval($_POST['room_id']), $_POST); - $msg->addFeedback('OPENMEETINGS_UPDATE_SUCEEDED'); - header('Location: index.php'); - exit; - } -} elseif (isset($_POST['cancel'])){ - $msg->addFeedback('OPENMEETINGS_CANCELLED'); - header('Location: index.php'); - exit; -} elseif (isset($_REQUEST['edit_room']) && isset($_POST['room_id'])){ - //Log into the room - $room_id = $_POST['room_id']; - - //Get the room obj - $room_obj = $om_obj->om_getRoomById($room_id); - - //Assign existing variables to the room - $_POST['openmeetings_roomtype'] = intval($room_obj['return']['roomtype']['roomtypes_id']); - $_POST['openmeetings_room_name'] = $addslashes($room_obj['return']['name']); - $_POST['openmeetings_num_of_participants'] = $addslashes($room_obj['return']['numberOfPartizipants']); - (($room_obj['return']['ispublic'])=='true')?$_POST['openmeetings_ispublic']=1:$_POST['openmeetings_ispublic']=0; - $_POST['openmeetings_vid_w'] = intval($room_obj['return']['videoPodWidth']); - $_POST['openmeetings_vid_h'] = intval($room_obj['return']['videoPodHeight']); - (($room_obj['return']['showWhiteBoard'])=='true')?$_POST['openmeetings_show_wb']=1:$_POST['openmeetings_show_wb']=0; - $_POST['openmeetings_wb_w'] = intval($room_obj['return']['whiteBoardPanelWidth']); - $_POST['openmeetings_wb_h'] = intval($room_obj['return']['whiteBoardPanelHeight']); - (($room_obj['return']['showFilesPanel'])=='true')?$_POST['openmeetings_show_fp']=1:$_POST['openmeetings_show_fp']=0; - $_POST['openmeetings_fp_w'] = intval($room_obj['return']['filesPanelWidth']); - $_POST['openmeetings_fp_h'] = intval($room_obj['return']['filesPanelHeight']); - - include (AT_INCLUDE_PATH.'header.inc.php'); - include ('html/update_room.inc.php'); - include (AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} elseif (isset($_GET['action']) && $_GET['action'] == 'view'){ - $room_id = intval($_GET['room_id']); - $sid = $addslashes($_GET['sid']); - header('Location: view_meetings.php?room_id='.$room_id.SEP.'sid='.$sid); - exit; -} - -$room_id = $om_obj->om_getRoom(); - -require (AT_INCLUDE_PATH.'header.inc.php'); -if ($room_id == false) { - include ('html/create_room.inc.php'); -} else { - //include page - include ('html/edit_room.inc.php'); -} -require (AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/openmeetings/html/course_meeting.inc.php b/mods/openmeetings/html/course_meeting.inc.php deleted file mode 100644 index e00bb44a7..000000000 --- a/mods/openmeetings/html/course_meeting.inc.php +++ /dev/null @@ -1,43 +0,0 @@ -om_getRoom()): -?> -
    -
    - -
    - -om_addRoom($room_name); - ?> -
    -
    -
      -
    • -
    -

    - - \ No newline at end of file diff --git a/mods/openmeetings/html/create_room.inc.php b/mods/openmeetings/html/create_room.inc.php deleted file mode 100644 index ac8174236..000000000 --- a/mods/openmeetings/html/create_room.inc.php +++ /dev/null @@ -1,44 +0,0 @@ - -
    -
    -

    -
    -
    - - -
    - -
    -
    -
    - - diff --git a/mods/openmeetings/html/create_room.tmpl.php b/mods/openmeetings/html/create_room.tmpl.php deleted file mode 100644 index 3c81bbe24..000000000 --- a/mods/openmeetings/html/create_room.tmpl.php +++ /dev/null @@ -1,81 +0,0 @@ - -
    -

    - - /> - /> -
    -
    -

    - -
    -
    -

    - - /> - /> -
    - - -
    -

    - -
    -
    -

    - -
    - - -
    - -

    - onclick="om_toggler('openmeetings_wb', true);"/> - - onclick="om_toggler('openmeetings_wb', false);"/> -
    -
    -

    - -
    -
    -

    - -
    - - -
    - -

    - onclick="om_toggler('openmeetings_fp', true);"/> - onclick="om_toggler('openmeetings_fp', false);"/> -
    -
    -

    - -
    -
    -

    - -
    \ No newline at end of file diff --git a/mods/openmeetings/html/edit_room.inc.php b/mods/openmeetings/html/edit_room.inc.php deleted file mode 100644 index 12590645d..000000000 --- a/mods/openmeetings/html/edit_room.inc.php +++ /dev/null @@ -1,28 +0,0 @@ - -
    -
    -
    getSid()); ?>
    -
    -
    - - - - -
    -
    - -
    \ No newline at end of file diff --git a/mods/openmeetings/html/group_meeting.inc.php b/mods/openmeetings/html/group_meeting.inc.php deleted file mode 100644 index 5e787506b..000000000 --- a/mods/openmeetings/html/group_meeting.inc.php +++ /dev/null @@ -1,48 +0,0 @@ -
    '._AT('openmeetings_group_conference').'
    '; - echo _AT('openmeetings_no_group_meetings').'
    '; -} else { - echo '
    '._AT('openmeetings_group_conference').'
    '; - $group_list = implode(',', $_SESSION['groups']); - $sql = "SELECT group_id, title FROM ".TABLE_PREFIX."groups WHERE group_id IN ($group_list) ORDER BY title"; - - $result = mysql_query($sql, $db); - - echo '
      '; - //loop through each group and print out a link beside them - while ($row = mysql_fetch_assoc($result)) { - //Check in the db and see if this group has a meeting alrdy, create on if not. - $om_obj->setGid($row['group_id']); - if ($om_obj->om_getRoom()){ - //Log into the room - $room_id = $om_obj->om_addRoom($room_name); - echo '
    • '.$row['title'].' Room-id: '.$room_id.''; - if ($om_obj->isMine($room_id) || authenticate(AT_PRIV_OPENMEETINGS, true)) { - //if 'I' created this room, then I will have the permission to edit/delete it from the database. - echo ' ['._AT('edit').']'; - echo ' ['._AT('delete').']'; - - } - echo '
    • '; - } else { - echo '
    • '.$row['title'].' Start a conference '.'
    • '; - } - } - echo '
    '; -} - -?> diff --git a/mods/openmeetings/html/update_room.inc.php b/mods/openmeetings/html/update_room.inc.php deleted file mode 100644 index b3b8fae3e..000000000 --- a/mods/openmeetings/html/update_room.inc.php +++ /dev/null @@ -1,41 +0,0 @@ - -
    -
    - - -
    - - - - -
    -
    -
    - - diff --git a/mods/openmeetings/index.php b/mods/openmeetings/index.php deleted file mode 100644 index 4806b45af..000000000 --- a/mods/openmeetings/index.php +++ /dev/null @@ -1,57 +0,0 @@ -om_login(); - -//Handles form actions -if (isset($_GET['delete']) && isset($_GET['room_id'])){ - //have to makesure the user really do have permission over the paramater room id - $_GET['room_id'] = intval($_GET['room_id']); - if ($om_obj->isMine($_GET['room_id'])){ - $om_obj->om_deleteRoom($_GET['room_id']); - $msg->addFeedback('OPENMEETINGS_DELETE_SUCEEDED'); - } else { - $msg->addError('OPENMEETINGS_DELETE_FAILED'); - } -} - -//Course meetings -include_once('html/course_meeting.inc.php'); - -//Group meetings -include_once('html/group_meeting.inc.php'); - -require (AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/openmeetings/lib/SOAP_openmeetings.php b/mods/openmeetings/lib/SOAP_openmeetings.php deleted file mode 100644 index 843af5181..000000000 --- a/mods/openmeetings/lib/SOAP_openmeetings.php +++ /dev/null @@ -1,238 +0,0 @@ -_wsdl = $wsdl; - $this->_soapClient = new nusoap_client($this->_wsdl, true); - $getSession_obj = $this->_performAPICall('getSession', ''); - //check session id - if (!$getSession_obj){ - $this->_sid = session_id(); //openmeeting will return error code on this - } else { - $this->_sid = $getSession_obj['return']['session_id']; - } - } - - /** - * Login as an user and sets a session - * - * @param array - * @return mixed - * @access public - */ - function login($parameters = array()) { - if (!isset($parameters["username"])) { - return false; - } - return $this->_performAPICall( - "loginUser", - - array( - "SID" => $this->_sid, - "username" => $parameters["username"], - "userpass" => $parameters["userpass"] - ) - ); - } - - - /** - * Sets user object - * @param array - * @return mixed - * @access public - */ - function saveUserInstance($parameters = array()) { - return $this->_performAPICall( - "setUserObject", - - array( - "SID" => $this->_sid, - "username" => $parameters["username"], - "firstname" => $parameters["firstname"], - "lastname" => $parameters["lastname"], - "profilePictureUrl" => $parameters[""], - "email" => $parameters["email"] - ) - ); - } - - /** - * Get error message - */ - function getError($code){ - return $this->_performAPICall( - "getErrorByCode", - array( - "SID" => $this->_sid, - "errorid" => $code, - "language_id" => 1 - ) - ); - } - - /** - * Creating a room - */ - function addRoom($parameters = array()){ - return $this->_performAPICall( - "addRoom", - - array( - "SID" => $parameters["SID"], - 'name' => $parameters["name"], - 'roomtypes_id' => $parameters["roomtypes_id"], - 'comment' => 'Room created by ATutor', - 'numberOfPartizipants' => $parameters["numberOfPartizipants"], - 'ispublic' => $parameters["ispublic"], - 'videoPodWidth' => $parameters["videoPodWidth"], - 'videoPodHeight' => $parameters["videoPodHeight"], - 'videoPodXPosition' => 2, - 'videoPodYPosition' => 2, - 'moderationPanelXPosition' => 400, - 'showWhiteBoard' => $parameters["showWhiteBoard"], - 'whiteBoardPanelXPosition' => 276, - 'whiteBoardPanelYPosition' => 2, - 'whiteBoardPanelHeight' => $parameters["whiteBoardPanelHeight"], - 'whiteBoardPanelWidth' => $parameters["whiteBoardPanelWidth"], - 'showFilesPanel' => $parameters["showFilesPanel"], - 'filesPanelXPosition' => 2, - 'filesPanelYPosition' => 284, - 'filesPanelHeight' => $parameters["filesPanelHeight"], - 'filesPanelWidth' => $parameters["filesPanelWidth"] - ) - ); - } - - - /** - * Updating a room - */ - function updateRoom($parameters = array()){ - return $this->_performAPICall( - "updateRoom", - - array( - 'SID' => $parameters["SID"], - 'rooms_id' => $parameters["rooms_id"], - 'name' => $parameters["name"], - 'roomtypes_id' => $parameters["roomtypes_id"], - 'comment' => 'Room created by ATutor', - 'numberOfPartizipants' => $parameters["numberOfPartizipants"], - 'ispublic' => $parameters["ispublic"], - 'videoPodWidth' => $parameters["videoPodWidth"], - 'videoPodHeight' => $parameters["videoPodHeight"], - 'videoPodXPosition' => 2, - 'videoPodYPosition' => 2, - 'moderationPanelXPosition' => 400, - 'showWhiteBoard' => $parameters["showWhiteBoard"], - 'whiteBoardPanelXPosition' => 276, - 'whiteBoardPanelYPosition' => 2, - 'whiteBoardPanelHeight' => $parameters["whiteBoardPanelHeight"], - 'whiteBoardPanelWidth' => $parameters["whiteBoardPanelWidth"], - 'showFilesPanel' => $parameters["showFilesPanel"], - 'filesPanelXPosition' => 2, - 'filesPanelYPosition' => 284, - 'filesPanelHeight' => $parameters["filesPanelHeight"], - 'filesPanelWidth' => $parameters["filesPanelWidth"] - ) - ); - } - - - /** - * Delete room - */ - function deleteRoom($parameters = array()){ - return $this->_performAPICall( - "deleteRoom", - array( - "SID" => $parameters["SID"], - "rooms_id" => $parameters["rooms_id"] - ) - ); - } - - - /** - * return the session id. - */ - function getSid(){ - return $this->_sid; - } - - /** - * Get room by id - */ - function getRoomById($parameters = array()){ - return $this->_performAPICall( - "getRoomById", - array( - "SID" => $parameters["SID"], - "rooms_id" => $parameters["rooms_id"] - ) - ); - } - - - - /** - * @param string - * @param array - * @return mixed - * @access private - */ - function _performAPICall($apiCall, $parameters) { - $result = $this->_soapClient->call( - $apiCall, - $parameters - ); - - if ($this->_soapClient->fault){ - return false; - } elseif ($this->_soapClient->getError()){ - return false; - } - - // if (!PEAR::isError($result)) { - if (is_array($result)) { - return $result; - } else { - return false; - } - } - - function myErrors(){ - return $this->_soapClient->getError(); - } -} -?> \ No newline at end of file diff --git a/mods/openmeetings/lib/nusoap.php b/mods/openmeetings/lib/nusoap.php deleted file mode 100644 index b2263502a..000000000 --- a/mods/openmeetings/lib/nusoap.php +++ /dev/null @@ -1,7024 +0,0 @@ -globalDebugLevel = 9; - -/** -* -* nusoap_base -* -* @author Dietrich Ayala -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $ -* @access public -*/ -class nusoap_base { - /** - * Identification for HTTP headers. - * - * @var string - * @access private - */ - var $title = 'NuSOAP'; - /** - * Version for HTTP headers. - * - * @var string - * @access private - */ - var $version = '0.7.3'; - /** - * CVS revision for HTTP headers. - * - * @var string - * @access private - */ - var $revision = '$Revision: 1.114 $'; - /** - * Current error string (manipulated by getError/setError) - * - * @var string - * @access private - */ - var $error_str = ''; - /** - * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment) - * - * @var string - * @access private - */ - var $debug_str = ''; - /** - * toggles automatic encoding of special characters as entities - * (should always be true, I think) - * - * @var boolean - * @access private - */ - var $charencoding = true; - /** - * the debug level for this instance - * - * @var integer - * @access private - */ - var $debugLevel; - - /** - * set schema version - * - * @var string - * @access public - */ - var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema'; - - /** - * charset encoding for outgoing messages - * - * @var string - * @access public - */ - var $soap_defencoding = 'ISO-8859-1'; - //var $soap_defencoding = 'UTF-8'; - - /** - * namespaces in an array of prefix => uri - * - * this is "seeded" by a set of constants, but it may be altered by code - * - * @var array - * @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/' - ); - - /** - * namespaces used in the current context, e.g. during serialization - * - * @var array - * @access private - */ - var $usedNamespaces = array(); - - /** - * XML Schema types in an array of uri => (array of xml type => php type) - * is this legacy yet? - * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings. - * @var array - * @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', - // abstract "any" types - 'anyType'=>'string','anySimpleType'=>'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/2000/10/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://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') - ); - - /** - * XML entities to convert - * - * @var array - * @access public - * @deprecated - * @see expandEntities - */ - var $xmlEntities = array('quot' => '"','amp' => '&', - 'lt' => '<','gt' => '>','apos' => "'"); - - /** - * constructor - * - * @access public - */ - function nusoap_base() { - $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel; - } - - /** - * gets the global debug level, which applies to future instances - * - * @return integer Debug level 0-9, where 0 turns off - * @access public - */ - function getGlobalDebugLevel() { - return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel; - } - - /** - * sets the global debug level, which applies to future instances - * - * @param int $level Debug level 0-9, where 0 turns off - * @access public - */ - function setGlobalDebugLevel($level) { - $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level; - } - - /** - * gets the debug level for this instance - * - * @return int Debug level 0-9, where 0 turns off - * @access public - */ - function getDebugLevel() { - return $this->debugLevel; - } - - /** - * sets the debug level for this instance - * - * @param int $level Debug level 0-9, where 0 turns off - * @access public - */ - function setDebugLevel($level) { - $this->debugLevel = $level; - } - - /** - * adds debug data to the instance debug string with formatting - * - * @param string $string debug data - * @access private - */ - function debug($string){ - if ($this->debugLevel > 0) { - $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n"); - } - } - - /** - * adds debug data to the instance debug string without formatting - * - * @param string $string debug data - * @access public - */ - function appendDebug($string){ - //echo "## appendDebug: ".$string."
    "; - if ($this->debugLevel > 0) { - // it would be nice to use a memory stream here to use - // memory more efficiently - $this->debug_str .= $string; - } - } - - /** - * clears the current debug data for this instance - * - * @access public - */ - function clearDebug() { - // it would be nice to use a memory stream here to use - // memory more efficiently - $this->debug_str = ''; - } - - /** - * gets the current debug data for this instance - * - * @return debug data - * @access public - */ - function &getDebug() { - // it would be nice to use a memory stream here to use - // memory more efficiently - return $this->debug_str; - } - - /** - * gets the current debug data for this instance as an XML comment - * this may change the contents of the debug data - * - * @return debug data as an XML comment - * @access public - */ - function &getDebugAsXMLComment() { - // it would be nice to use a memory stream here to use - // memory more efficiently - while (strpos($this->debug_str, '--')) { - $this->debug_str = str_replace('--', '- -', $this->debug_str); - } - $ret = ""; - return $ret; - } - - /** - * expands entities, e.g. changes '<' to '<'. - * - * @param string $val The string in which to expand entities. - * @access private - */ - function expandEntities($val) { - if ($this->charencoding) { - $val = str_replace('&', '&', $val); - $val = str_replace("'", ''', $val); - $val = str_replace('"', '"', $val); - $val = str_replace('<', '<', $val); - $val = str_replace('>', '>', $val); - } - return $val; - } - - /** - * returns error string if present - * - * @return mixed error string or false - * @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 mixed $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'. - * - * @param mixed $val The value to serialize - * @param string $name The name (local part) of the XML element - * @param string $type The XML schema type (local part) for the element - * @param string $name_ns The namespace for the name of the XML element - * @param string $type_ns The namespace for the type of the element - * @param array $attributes The attributes to serialize as name=>value pairs - * @param string $use The WSDL "use" (encoded|literal) - * @param boolean $soapval Whether this is called from soapval. - * @return string The serialized element, possibly with child elements - * @access public - */ - function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) { - $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval"); - $this->appendDebug('value=' . $this->varDump($val)); - $this->appendDebug('attributes=' . $this->varDump($attributes)); - - if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) { - $this->debug("serialize_val: serialize soapval"); - $xml = $val->serialize($use); - $this->appendDebug($val->getDebug()); - $val->clearDebug(); - $this->debug("serialize_val of soapval returning $xml"); - return $xml; - } - // force valid name if necessary - if (is_numeric($name)) { - $name = '__numeric_' . $name; - } elseif (! $name) { - $name = 'noname'; - } - // 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=\"".$this->expandEntities($v).'"'; - } - } - // serialize null value - if (is_null($val)) { - $this->debug("serialize_val: serialize null"); - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$xmlns$atts/>"; - $this->debug("serialize_val returning $xml"); - return $xml; - } else { - if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>"; - $this->debug("serialize_val returning $xml"); - return $xml; - } - } - // serialize if an xsd built-in primitive type - if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){ - $this->debug("serialize_val: serialize xsd built-in primitive type"); - if (is_bool($val)) { - if ($type == 'boolean') { - $val = $val ? 'true' : 'false'; - } elseif (! $val) { - $val = 0; - } - } else if (is_string($val)) { - $val = $this->expandEntities($val); - } - if ($use == 'literal') { - $xml = "<$name$xmlns$atts>$val"; - $this->debug("serialize_val returning $xml"); - return $xml; - } else { - $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val"; - $this->debug("serialize_val returning $xml"); - return $xml; - } - } - // detect type and serialize - $xml = ''; - switch(true) { - case (is_bool($val) || $type == 'boolean'): - $this->debug("serialize_val: serialize boolean"); - if ($type == 'boolean') { - $val = $val ? 'true' : 'false'; - } elseif (! $val) { - $val = 0; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val"; - } - break; - case (is_int($val) || is_long($val) || $type == 'int'): - $this->debug("serialize_val: serialize int"); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val"; - } - break; - case (is_float($val)|| is_double($val) || $type == 'float'): - $this->debug("serialize_val: serialize float"); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val"; - } - break; - case (is_string($val) || $type == 'string'): - $this->debug("serialize_val: serialize string"); - $val = $this->expandEntities($val); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val"; - } - break; - case is_object($val): - $this->debug("serialize_val: serialize object"); - if (get_class($val) == 'soapval') { - $this->debug("serialize_val: serialize soapval object"); - $pXml = $val->serialize($use); - $this->appendDebug($val->getDebug()); - $val->clearDebug(); - } else { - if (! $name) { - $name = get_class($val); - $this->debug("In serialize_val, used class name $name as element name"); - } else { - $this->debug("In serialize_val, do not override name $name for element name for class " . 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); - } - } - if(isset($type) && isset($type_prefix)){ - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$pXml"; - } else { - $xml .= "<$name$xmlns$type_str$atts>$pXml"; - } - break; - break; - case (is_array($val) || $type): - // detect if struct or array - $valueType = $this->isArraySimpleOrStruct($val); - if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){ - $this->debug("serialize_val: serialize array"); - $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; - } elseif (is_array($v)) { - $tt = $this->isArraySimpleOrStruct($v); - } else { - $tt = gettype($v); - } - $array_types[$tt] = 1; - // TODO: for literal, the name should be $name - $xml .= $this->serialize_val($v,'item',false,false,false,false,$use); - ++$i; - } - if(count($array_types) > 1){ - $array_typename = 'xsd:anyType'; - } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) { - if ($tt == 'integer') { - $tt = 'int'; - } - $array_typename = 'xsd:'.$tt; - } elseif(isset($tt) && $tt == 'arraySimple'){ - $array_typename = 'SOAP-ENC:Array'; - } elseif(isset($tt) && $tt == 'arrayStruct'){ - $array_typename = 'unnamed_struct_use_soapval'; - } 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\" SOAP-ENC:arrayType=\"xsd:anyType[0]\""; - } - } - // TODO: for array in literal, there is no wrapper here - $xml = "<$name$xmlns$type_str$atts>".$xml.""; - } else { - // got a struct - $this->debug("serialize_val: serialize 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 .= ''; - $xml .= $this->serialize_val($k,'key',false,false,false,false,$use); - $xml .= $this->serialize_val($v,'value',false,false,false,false,$use); - $xml .= ''; - } else { - $xml .= $this->serialize_val($v,$k,false,false,false,false,$use); - } - } - $xml .= ""; - } - break; - default: - $this->debug("serialize_val: serialize unknown"); - $xml .= 'not detected, got '.gettype($val).' for '.$val; - break; - } - $this->debug("serialize_val returning $xml"); - return $xml; - } - - /** - * serializes a message - * - * @param string $body the XML of the SOAP body - * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array - * @param array $namespaces optional the namespaces used in generating the body and headers - * @param string $style optional (rpc|document) - * @param string $use optional (encoded|literal) - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - * @return string the message - * @access public - */ - function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){ - // 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 - - $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle"); - $this->debug("headers:"); - $this->appendDebug($this->varDump($headers)); - $this->debug("namespaces:"); - $this->appendDebug($this->varDump($namespaces)); - - // serialize namespaces - $ns_string = ''; - foreach(array_merge($this->namespaces,$namespaces) as $k => $v){ - $ns_string .= " xmlns:$k=\"$v\""; - } - if($encodingStyle) { - $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string"; - } - - // serialize headers - if($headers){ - if (is_array($headers)) { - $xml = ''; - foreach ($headers as $k => $v) { - if (is_object($v) && get_class($v) == 'soapval') { - $xml .= $this->serialize_val($v, false, false, false, false, false, $use); - } else { - $xml .= $this->serialize_val($v, $k, false, false, false, false, $use); - } - } - $headers = $xml; - $this->debug("In serializeEnvelope, serialized array of headers to $headers"); - } - $headers = "".$headers.""; - } - //echo "####
    "; - //echo $body; - //echo "
    ####
    "; - // serialize envelope - return - 'soap_defencoding .'"?'.">". - '". - $headers. - "". - $body. - "". - ""; - } - - /** - * formats a string to be inserted into an HTML stream - * - * @param string $str The string to format - * @return string The formatted string - * @access public - * @deprecated - */ - function formatDump($str){ - $str = htmlspecialchars($str); - return nl2br($str); - } - - /** - * contracts (changes namespace to prefix) a qualified name - * - * @param string $qname 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 (changes prefix to namespace) a qualified name - * - * @param string $qname 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 $str The prefixed string - * @return string The local part - * @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 $str The prefixed string - * @return mixed The prefix or false if there is no prefix - * @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 - * - * @param string $prefix The prefix - * @return mixed The namespace, false if no namespace has the specified prefix - * @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 $ns The namespace - * @return mixed The prefix, false if the namespace has no prefixes - * @access public - */ - function getPrefixFromNamespace($ns) { - foreach ($this->namespaces as $p => $n) { - if ($ns == $n || $ns == $p) { - $this->usedNamespaces[$p] = $n; - return $p; - } - } - return false; - } - - /** - * returns the time in ODBC canonical form with microseconds - * - * @return string The time in ODBC canonical form with microseconds - * @access public - */ - function getmicrotime() { - if (function_exists('gettimeofday')) { - $tod = gettimeofday(); - $sec = $tod['sec']; - $usec = $tod['usec']; - } else { - $sec = time(); - $usec = 0; - } - return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec); - } - - /** - * Returns a string with the output of var_dump - * - * @param mixed $data The variable to var_dump - * @return string The output of var_dump - * @access public - */ - function varDump($data) { - ob_start(); - var_dump($data); - $ret_val = ob_get_contents(); - ob_end_clean(); - return $ret_val; - } - - /** - * represents the object as a string - * - * @return string - * @access public - */ - function __toString() { - return $this->varDump($this); - } -} - -// XML Schema Datatype Helper Functions - -//xsd:dateTime helpers - -/** -* convert unix timestamp to ISO 8601 compliant date string -* -* @param string $timestamp Unix time stamp -* @param boolean $utc Whether the time stamp is UTC or local -* @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 gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); -// return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z"); - } else { - return false; - } -} - -/** -* sleeps some number of microseconds -* -* @param string $usec the number of microseconds to sleep -* @access public -* @deprecated -*/ -function usleepWindows($usec) -{ - $start = gettimeofday(); - - do - { - $stop = gettimeofday(); - $timePassed = 1000000 * ($stop['sec'] - $start['sec']) - + $stop['usec'] - $start['usec']; - } - while ($timePassed < $usec); -} - -?> -* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $ -* @access public -*/ -class nusoap_fault extends nusoap_base { - /** - * The fault code (client|server) - * @var string - * @access private - */ - var $faultcode; - /** - * The fault actor - * @var string - * @access private - */ - var $faultactor; - /** - * The fault string, a description of the fault - * @var string - * @access private - */ - var $faultstring; - /** - * The fault detail, typically a string or array of string - * @var mixed - * @access private - */ - var $faultdetail; - - /** - * constructor - * - * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server) - * @param string $faultactor only used when msg routed between multiple actors - * @param string $faultstring human readable error message - * @param mixed $faultdetail detail, typically a string or array of string - */ - function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){ - parent::nusoap_base(); - $this->faultcode = $faultcode; - $this->faultactor = $faultactor; - $this->faultstring = $faultstring; - $this->faultdetail = $faultdetail; - } - - /** - * serialize a fault - * - * @return string The serialization of the fault instance. - * @access public - */ - function serialize(){ - $ns_string = ''; - foreach($this->namespaces as $k => $v){ - $ns_string .= "\n xmlns:$k=\"$v\""; - } - $return_msg = - 'soap_defencoding.'"?>'. - '\n". - ''. - ''. - $this->serialize_val($this->faultcode, 'faultcode'). - $this->serialize_val($this->faultactor, 'faultactor'). - $this->serialize_val($this->faultstring, 'faultstring'). - $this->serialize_val($this->faultdetail, 'detail'). - ''. - ''. - ''; - return $return_msg; - } -} - -/** - * Backward compatibility - */ -class soap_fault extends nusoap_fault { -} - -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $ -* @access public -*/ -class nusoap_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 $complexTypeStack = array(); - var $currentComplexType = null; - var $elements = array(); - var $elementStack = array(); - var $currentElement = null; - var $simpleTypes = array(); - var $simpleTypeStack = array(); - var $currentSimpleType = null; - // 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 nusoap_xmlschema($schema='',$xml='',$namespaces=array()){ - parent::nusoap_base(); - $this->debug('nusoap_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()!!'); - } - } - - /** - * gets a type name for an unnamed type - * - * @param string Element name - * @return string A type name for an unnamed type - * @access private - */ - function CreateTypeName($ename) { - $scope = ''; - for ($i = 0; $i < count($this->complexTypeStack); $i++) { - $scope .= $this->complexTypeStack[$i] . '_'; - } - return $scope . $ename . '_ContainedType'; - } - - /** - * 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' || $v == 'http://www.w3.org/2000/10/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': // (optional) compositor content for a complexType - case 'choice': - case 'group': - 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': // complexType attribute - //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']); - $this->xdebug("parsing attribute:"); - $this->appendDebug($this->varDump($attrs)); - if (!isset($attrs['form'])) { - $attrs['form'] = $this->schemaInfo['attributeFormDefault']; - } - 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($this->currentComplexType){ // This should *always* be - $this->complexTypes[$this->currentComplexType]['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 'complexContent': // (optional) content for a complexType - break; - case 'complexType': - array_push($this->complexTypeStack, $this->currentComplexType); - if(isset($attrs['name'])){ - // TODO: what is the scope of named complexTypes that appear - // nested within other c complexTypes? - $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'; - // This is for constructs like - // - // - // - // - // - if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){ - $this->xdebug('complexType is unusual array'); - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } else { - $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - } - } else { - $name = $this->CreateTypeName($this->currentElement); - $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name); - $this->currentComplexType = $name; - //$this->currentElement = false; - $this->complexTypes[$this->currentComplexType] = $attrs; - $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType'; - // This is for constructs like - // - // - // - // - // - if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){ - $this->xdebug('complexType is unusual array'); - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } else { - $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - } - } - break; - case 'element': - array_push($this->elementStack, $this->currentElement); - if (!isset($attrs['form'])) { - $attrs['form'] = $this->schemaInfo['elementFormDefault']; - } - if(isset($attrs['type'])){ - $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']); - if (! $this->getPrefix($attrs['type'])) { - if ($this->defaultNamespace[$pos]) { - $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type']; - $this->xdebug('used default namespace to make type ' . $attrs['type']); - } - } - // This is for constructs like - // - // - // - // - // - if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') { - $this->xdebug('arrayType for unusual array is ' . $attrs['type']); - $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type']; - } - $this->currentElement = $attrs['name']; - $ename = $attrs['name']; - } elseif(isset($attrs['ref'])){ - $this->xdebug("processing element as ref to ".$attrs['ref']); - $this->currentElement = "ref to ".$attrs['ref']; - $ename = $this->getLocalPart($attrs['ref']); - } else { - $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']); - $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type); - $this->currentElement = $attrs['name']; - $attrs['type'] = $this->schemaTargetNamespace . ':' . $type; - $ename = $attrs['name']; - } - if (isset($ename) && $this->currentComplexType) { - $this->xdebug("add element $ename to complexType $this->currentComplexType"); - $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs; - } elseif (!isset($attrs['ref'])) { - $this->xdebug("add element $ename to elements array"); - $this->elements[ $attrs['name'] ] = $attrs; - $this->elements[ $attrs['name'] ]['typeClass'] = 'element'; - } - break; - case 'enumeration': // restriction value list member - $this->xdebug('enumeration ' . $attrs['value']); - if ($this->currentSimpleType) { - $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value']; - } elseif ($this->currentComplexType) { - $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value']; - } - break; - case 'extension': // simpleContent or complexContent type extension - $this->xdebug('extension ' . $attrs['base']); - if ($this->currentComplexType) { - $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base']; - } - 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 'list': // simpleType value list - break; - case 'restriction': // simpleType, simpleContent or complexContent value restriction - $this->xdebug('restriction ' . $attrs['base']); - if($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'; - } - if (!isset($attrs['attributeFormDefault'])) { - $this->schemaInfo['attributeFormDefault'] = 'unqualified'; - } - break; - case 'simpleContent': // (optional) content for a complexType - break; - case 'simpleType': - array_push($this->simpleTypeStack, $this->currentSimpleType); - 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 { - $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement); - $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name); - $this->currentSimpleType = $name; - //$this->currentElement = false; - $this->simpleTypes[$this->currentSimpleType] = $attrs; - $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar'; - } - break; - case 'union': // simpleType type list - 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]; - } - // get element prefix - if ($prefix = $this->getPrefix($name)){ - // get unqualified name - $name = $this->getLocalPart($name); - } else { - $prefix = ''; - } - // move on... - if($name == 'complexType'){ - $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)')); - $this->currentComplexType = array_pop($this->complexTypeStack); - //$this->currentElement = false; - } - if($name == 'element'){ - $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)')); - $this->currentElement = array_pop($this->elementStack); - } - if($name == 'simpleType'){ - $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)')); - $this->currentSimpleType = array_pop($this->simpleTypeStack); - } - } - - /** - * 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']) . "\""; - foreach ($eParts as $aName => $aValue) { - // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable - if ($aName != 'name' && $aName != 'type') { - $contentStr .= " $aName=\"$aValue\""; - } - } - $contentStr .= "/>\n"; - } - } - // compositor wraps elements - if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) { - $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." \n"; - } - } - // attributes - if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){ - foreach($attrs['attrs'] as $attr => $aParts){ - $contentStr .= " <$schemaPrefix:attribute"; - foreach ($aParts as $a => $v) { - if ($a == 'ref' || $a == 'type') { - $contentStr .= " $a=\"".$this->contractQName($v).'"'; - } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') { - $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl']; - $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"'; - } else { - $contentStr .= " $a=\"$v\""; - } - } - $contentStr .= "/>\n"; - } - } - // if restriction - if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){ - $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." \n"; - // complex or simple content - if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){ - $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." \n"; - } - } - // finalize complex type - if($contentStr != ''){ - $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." \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 => $eParts){ - $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n"; - if (isset($eParts['enumeration'])) { - foreach ($eParts['enumeration'] as $e) { - $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n"; - } - } - $xml .= " \n "; - } - } - // 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 - $attr = ''; - foreach ($this->schemaInfo as $k => $v) { - if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') { - $attr .= " $k=\"$v\""; - } - } - $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n"; - foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) { - $el .= " xmlns:$nsp=\"$ns\""; - } - $xml = $el . ">\n".$xml."\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 - * @deprecated - */ - function getPHPType($type,$ns){ - if(isset($this->typemap[$ns][$type])){ - //print "found type '$type' and ns $ns in typemap
    "; - return $this->typemap[$ns][$type]; - } elseif(isset($this->complexTypes[$type])){ - //print "getting type '$type' and ns $ns from complexTypes array
    "; - return $this->complexTypes[$type]['phpType']; - } - return false; - } - - /** - * returns an associative array of information about a given type - * returns false if no type exists by the given name - * - * For a complexType typeDef = array( - * 'restrictionBase' => '', - * 'phpType' => '', - * 'compositor' => '(sequence|all)', - * 'elements' => array(), // refs to elements array - * 'attrs' => array() // refs to attributes array - * ... and so on (see addComplexType) - * ) - * - * For simpleType or element, the array has different keys. - * - * @param string $type - * @return mixed - * @access public - * @see addComplexType - * @see addSimpleType - * @see addElement - */ - function getTypeDef($type){ - //$this->debug("in getTypeDef for type $type"); - if (substr($type, -1) == '^') { - $is_element = 1; - $type = substr($type, 0, -1); - } else { - $is_element = 0; - } - - if((! $is_element) && isset($this->complexTypes[$type])){ - $this->xdebug("in getTypeDef, found complexType $type"); - return $this->complexTypes[$type]; - } elseif((! $is_element) && 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) { - $this->xdebug("in getTypeDef, found type for simpleType $type:"); - $this->xdebug($this->varDump($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) { - $this->xdebug("in getTypeDef, found type for element $type:"); - $this->xdebug($this->varDump($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->xdebug("in getTypeDef, element $type is an XSD type"); - $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]; - } elseif (ereg('_ContainedType$', $type)) { - $this->xdebug("in getTypeDef, have an untyped element $type"); - $typeDef['typeClass'] = 'simpleType'; - $typeDef['phpType'] = 'scalar'; - $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string'; - return $typeDef; - } - $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 - * @deprecated - */ - function serializeTypeDef($type){ - //print "in sTD() for type $type
    "; - if($typeDef = $this->getTypeDef($type)){ - $str .= '<'.$type; - if(is_array($typeDef['attrs'])){ - foreach($typeDef['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 .= ""; - } elseif($typeDef['typeClass'] == 'element') { - $str .= ">"; - } 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 - * @deprecated - */ - function typeToForm($name,$type){ - // get typedef - if($typeDef = $this->getTypeDef($type)){ - // if struct - if($typeDef['phpType'] == 'struct'){ - $buffer .= ''; - foreach($typeDef['elements'] as $child => $childDef){ - $buffer .= " - - "; - } - $buffer .= '
    $childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):
    '; - // if array - } elseif($typeDef['phpType'] == 'array'){ - $buffer .= ''; - for($i=0;$i < 3; $i++){ - $buffer .= " - - "; - } - $buffer .= '
    array item (type: $typeDef[arrayType]):
    '; - // if scalar - } else { - $buffer .= ""; - } - } else { - $buffer .= ""; - } - 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) - * @access public - * @see getTypeDef - */ - 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->appendDebug($this->varDump($this->complexTypes[$name])); - } - - /** - * adds a simple type to the schema - * - * @param string $name - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param string $typeClass (should always be simpleType) - * @param string $phpType (should always be scalar) - * @param array $enumeration array of values - * @access public - * @see nusoap_xmlschema - * @see getTypeDef - */ - function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { - $this->simpleTypes[$name] = array( - 'name' => $name, - 'typeClass' => $typeClass, - 'phpType' => $phpType, - 'type' => $restrictionBase, - 'enumeration' => $enumeration - ); - - $this->xdebug("addSimpleType $name:"); - $this->appendDebug($this->varDump($this->simpleTypes[$name])); - } - - /** - * adds an element to the schema - * - * @param array $attrs attributes that must include name and type - * @see nusoap_xmlschema - * @access public - */ - function addElement($attrs) { - if (! $this->getPrefix($attrs['type'])) { - $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type']; - } - $this->elements[ $attrs['name'] ] = $attrs; - $this->elements[ $attrs['name'] ]['typeClass'] = 'element'; - - $this->xdebug("addElement " . $attrs['name']); - $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ])); - } -} - -/** - * Backward compatibility - */ -class XMLSchema extends nusoap_xmlschema { -} - -?> -* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $ -* @access public -*/ -class soapval extends nusoap_base { - /** - * The XML element name - * - * @var string - * @access private - */ - var $name; - /** - * The XML type name (string or false) - * - * @var mixed - * @access private - */ - var $type; - /** - * The PHP value - * - * @var mixed - * @access private - */ - var $value; - /** - * The XML element namespace (string or false) - * - * @var mixed - * @access private - */ - var $element_ns; - /** - * The XML type namespace (string or false) - * - * @var mixed - * @access private - */ - var $type_ns; - /** - * The XML element attributes (array or false) - * - * @var mixed - * @access private - */ - var $attributes; - - /** - * constructor - * - * @param string $name optional name - * @param mixed $type optional type name - * @param mixed $value optional value - * @param mixed $element_ns optional namespace of value - * @param mixed $type_ns optional namespace of type - * @param mixed $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) { - parent::nusoap_base(); - $this->name = $name; - $this->type = $type; - $this->value = $value; - $this->element_ns = $element_ns; - $this->type_ns = $type_ns; - $this->attributes = $attributes; - } - - /** - * return serialized value - * - * @param string $use The WSDL use value (encoded|literal) - * @return string XML data - * @access public - */ - function serialize($use='encoded') { - return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true); - } - - /** - * decodes a soapval object into a PHP native type - * - * @return mixed - * @access public - */ - function decode(){ - return $this->value; - } -} - - - -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $ -* @access public -*/ -class soap_transport_http extends nusoap_base { - - var $url = ''; - var $uri = ''; - var $digest_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 $incoming_cookies = array(); - var $outgoing_payload = ''; - var $incoming_payload = ''; - var $response_status_line; // HTTP response status line - var $useSOAPAction = true; - var $persistentConnection = false; - var $ch = false; // cURL handle - var $ch_options = array(); // cURL custom options - var $use_curl = false; // force cURL use - var $proxy = null; // proxy information (associative array) - var $username = ''; - var $password = ''; - var $authtype = ''; - var $digestRequest = array(); - var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional) - // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem' - // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem' - // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem' - // passphrase: SSL key password/passphrase - // certpassword: SSL certificate password - // verifypeer: default is 1 - // verifyhost: default is 1 - - /** - * constructor - * - * @param string $url The URL to which to connect - * @param array $curl_options User-specified cURL options - * @param boolean $use_curl Whether to try to force cURL use - * @access public - */ - function soap_transport_http($url, $curl_options = NULL, $use_curl = false){ - parent::nusoap_base(); - $this->debug("ctor url=$url use_curl=$use_curl curl_options:"); - $this->appendDebug($this->varDump($curl_options)); - $this->setURL($url); - if (is_array($curl_options)) { - $this->ch_options = $curl_options; - } - $this->use_curl = $use_curl; - ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev); - $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')'); - } - - /** - * sets a cURL option - * - * @param mixed $option The cURL option (always integer?) - * @param mixed $value The cURL option value - * @access private - */ - function setCurlOption($option, $value) { - $this->debug("setCurlOption option=$option, value="); - $this->appendDebug($this->varDump($value)); - curl_setopt($this->ch, $option, $value); - } - - /** - * sets an HTTP header - * - * @param string $name The name of the header - * @param string $value The value of the header - * @access private - */ - function setHeader($name, $value) { - $this->outgoing_headers[$name] = $value; - $this->debug("set header $name: $value"); - } - - /** - * unsets an HTTP header - * - * @param string $name The name of the header - * @access private - */ - function unsetHeader($name) { - if (isset($this->outgoing_headers[$name])) { - $this->debug("unset header $name"); - unset($this->outgoing_headers[$name]); - } - } - - /** - * sets the URL to which to connect - * - * @param string $url The URL to which to connect - * @access private - */ - function setURL($url) { - $this->url = $url; - - $u = parse_url($url); - foreach($u as $k => $v){ - $this->debug("parsed URL $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; - $this->digest_uri = $this->uri; - - // build headers - if (!isset($u['port'])) { - $this->setHeader('Host', $this->host); - } else { - $this->setHeader('Host', $this->host.':'.$this->port); - } - - if (isset($u['user']) && $u['user'] != '') { - $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : ''); - } - } - - /** - * gets the I/O method to use - * - * @return string I/O method to use (socket|curl|unknown) - * @access private - */ - function io_method() { - if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) - return 'curl'; - if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) - return 'socket'; - return 'unknown'; - } - - /** - * establish an HTTP connection - * - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @return boolean true if connected, false if not - * @access private - */ - 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'); -// } -// } -// } - $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port"); - if ($this->io_method() == 'socket') { - if (!is_array($this->proxy)) { - $host = $this->host; - $port = $this->port; - } else { - $host = $this->proxy['host']; - $port = $this->proxy['port']; - } - - // 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://' . $host; - } - $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout); - - // 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) { - $msg = 'Couldn\'t open socket connection to server ' . $this->url; - if ($this->errno) { - $msg .= ', Error ('.$this->errno.'): '.$this->error_str; - } else { - $msg .= ' prior to connect(). This is often a problem looking up the host name.'; - } - $this->debug($msg); - $this->setError($msg); - return false; - } - - // set response timeout - $this->debug('set response timeout to ' . $response_timeout); - socket_set_timeout( $this->fp, $response_timeout); - - $this->debug('socket connected'); - return true; - } else if ($this->io_method() == 'curl') { - if (!extension_loaded('curl')) { -// $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS'); - $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to included cURL.'); - return false; - } - // Avoid warnings when PHP does not have these options - if (defined('CURLOPT_CONNECTIONTIMEOUT')) - $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT; - else - $CURLOPT_CONNECTIONTIMEOUT = 78; - if (defined('CURLOPT_HTTPAUTH')) - $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH; - else - $CURLOPT_HTTPAUTH = 107; - if (defined('CURLOPT_PROXYAUTH')) - $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH; - else - $CURLOPT_PROXYAUTH = 111; - if (defined('CURLAUTH_BASIC')) - $CURLAUTH_BASIC = CURLAUTH_BASIC; - else - $CURLAUTH_BASIC = 1; - if (defined('CURLAUTH_DIGEST')) - $CURLAUTH_DIGEST = CURLAUTH_DIGEST; - else - $CURLAUTH_DIGEST = 2; - if (defined('CURLAUTH_NTLM')) - $CURLAUTH_NTLM = CURLAUTH_NTLM; - else - $CURLAUTH_NTLM = 8; - - $this->debug('connect using cURL'); - // init CURL - $this->ch = curl_init(); - // set url - $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host"; - // add path - $hostURL .= $this->path; - $this->setCurlOption(CURLOPT_URL, $hostURL); - // follow location headers (re-directs) - if (ini_get('safe_mode') || ini_get('open_basedir')) { - $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION'); - $this->debug('safe_mode = '); - $this->appendDebug($this->varDump(ini_get('safe_mode'))); - $this->debug('open_basedir = '); - $this->appendDebug($this->varDump(ini_get('open_basedir'))); - } else { - $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1); - } - // ask for headers in the response output - $this->setCurlOption(CURLOPT_HEADER, 1); - // ask for the response output as the return value - $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1); - // encode - // We manage this ourselves through headers and encoding -// if(function_exists('gzuncompress')){ -// $this->setCurlOption(CURLOPT_ENCODING, 'deflate'); -// } - // persistent connection - if ($this->persistentConnection) { - // I believe the following comment is now bogus, having applied to - // the code when it used CURLOPT_CUSTOMREQUEST to send the request. - // The way we send data, we cannot use persistent connections, since - // there will be some "junk" at the end of our request. - //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true); - $this->persistentConnection = false; - $this->setHeader('Connection', 'close'); - } - // set timeouts - if ($connection_timeout != 0) { - $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout); - } - if ($response_timeout != 0) { - $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout); - } - - if ($this->scheme == 'https') { - $this->debug('set cURL SSL verify options'); - // 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. - //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt'); - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0); - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0); - - // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo) - if ($this->authtype == 'certificate') { - $this->debug('set cURL certificate options'); - if (isset($this->certRequest['cainfofile'])) { - $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']); - } - if (isset($this->certRequest['verifypeer'])) { - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']); - } else { - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1); - } - if (isset($this->certRequest['verifyhost'])) { - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']); - } else { - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1); - } - if (isset($this->certRequest['sslcertfile'])) { - $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']); - } - if (isset($this->certRequest['sslkeyfile'])) { - $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']); - } - if (isset($this->certRequest['passphrase'])) { - $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']); - } - if (isset($this->certRequest['certpassword'])) { - $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']); - } - } - } - if ($this->authtype && ($this->authtype != 'certificate')) { - if ($this->username) { - $this->debug('set cURL username/password'); - $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password"); - } - if ($this->authtype == 'basic') { - $this->debug('set cURL for Basic authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC); - } - if ($this->authtype == 'digest') { - $this->debug('set cURL for digest authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST); - } - if ($this->authtype == 'ntlm') { - $this->debug('set cURL for NTLM authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM); - } - } - if (is_array($this->proxy)) { - $this->debug('set cURL proxy options'); - if ($this->proxy['port'] != '') { - $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']); - } else { - $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']); - } - if ($this->proxy['username'] || $this->proxy['password']) { - $this->debug('set cURL proxy authentication options'); - $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']); - if ($this->proxy['authtype'] == 'basic') { - $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC); - } - if ($this->proxy['authtype'] == 'ntlm') { - $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM); - } - } - } - $this->debug('cURL connection set up'); - return true; - } else { - $this->setError('Unknown scheme ' . $this->scheme); - $this->debug('Unknown scheme ' . $this->scheme); - return false; - } - } - - /** - * sends the SOAP request and gets the SOAP response via HTTP[S] - * - * @param string $data message data - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @param array $cookies cookies to send - * @return string data - * @access public - */ - function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) { - - $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, $cookies)){ - return false; - } - - // get response - $respdata = $this->getResponse(); - } else { - $this->setError("Too many tries to get an OK response ($this->response_status_line)"); - } - } - $this->debug('end of send()'); - return $respdata; - } - - - /** - * sends the SOAP request and gets the SOAP response via HTTPS using CURL - * - * @param string $data message data - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @param array $cookies cookies to send - * @return string data - * @access public - * @deprecated - */ - function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) { - return $this->send($data, $timeout, $response_timeout, $cookies); - } - - /** - * if authenticating, set user credentials here - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $digestRequest (keys must be nonce, nc, realm, qop) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - * @access public - */ - function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) { - $this->debug("setCredentials username=$username authtype=$authtype digestRequest="); - $this->appendDebug($this->varDump($digestRequest)); - $this->debug("certRequest="); - $this->appendDebug($this->varDump($certRequest)); - // cf. RFC 2617 - if ($authtype == 'basic') { - $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$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. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password; - - // H(A1) = MD5(A1) - $HA1 = md5($A1); - - // A2 = Method ":" digest-uri-value - $A2 = $this->request_method . ':' . $this->digest_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); - - $opaque = ''; - if (isset($digestRequest['opaque'])) { - $opaque = ', opaque="' . $digestRequest['opaque'] . '"'; - } - - $this->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . $opaque . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"'); - } - } elseif ($authtype == 'certificate') { - $this->certRequest = $certRequest; - $this->debug('Authorization header not set for certificate'); - } elseif ($authtype == 'ntlm') { - // do nothing - $this->debug('Authorization header not set for ntlm'); - } - $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->setHeader('SOAPAction', '"' . $soapaction . '"'); - } - - /** - * use http encoding - * - * @param string $enc encoding style. supported values: gzip, deflate, or both - * @access public - */ - function setEncoding($enc='gzip, deflate') { - if (function_exists('gzdeflate')) { - $this->protocol_version = '1.1'; - $this->setHeader('Accept-Encoding', $enc); - if (!isset($this->outgoing_headers['Connection'])) { - $this->setHeader('Connection', 'close'); - $this->persistentConnection = false; - } - set_magic_quotes_runtime(0); - // deprecated - $this->encoding = $enc; - } - } - - /** - * set proxy info here - * - * @param string $proxyhost use an empty string to remove proxy - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - * @param string $proxyauthtype (basic|ntlm) - * @access public - */ - function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') { - if ($proxyhost) { - $this->proxy = array( - 'host' => $proxyhost, - 'port' => $proxyport, - 'username' => $proxyusername, - 'password' => $proxypassword, - 'authtype' => $proxyauthtype - ); - if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') { - $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword)); - } - } else { - $this->debug('remove proxy'); - $proxy = null; - unsetHeader('Proxy-Authorization'); - } - } - - - /** - * Test if the given string starts with a header that is to be skipped. - * Skippable headers result from chunked transfer and proxy requests. - * - * @param string $data The string to check. - * @returns boolean Whether a skippable header was found. - * @access private - */ - function isSkippableCurlHeader(&$data) { - $skipHeaders = array( 'HTTP/1.1 100', - 'HTTP/1.0 301', - 'HTTP/1.1 301', - 'HTTP/1.0 302', - 'HTTP/1.1 302', - 'HTTP/1.0 401', - 'HTTP/1.1 401', - 'HTTP/1.0 200 Connection established'); - foreach ($skipHeaders as $hd) { - $prefix = substr($data, 0, strlen($hd)); - if ($prefix == $hd) return true; - } - - return false; - } - - /** - * 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 - * @deprecated - */ - 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 the payload, including HTTP headers, to $this->outgoing_payload. - * - * @param string $data HTTP body - * @param string $cookie_str data for HTTP Cookie header - * @return void - * @access private - */ - function buildPayload($data, $cookie_str = '') { - // Note: for cURL connections, $this->outgoing_payload is ignored, - // as is the Content-Length header, but these are still created as - // debugging guides. - - // add content-length header - $this->setHeader('Content-Length', strlen($data)); - - // start building outgoing payload: - if ($this->proxy) { - $uri = $this->url; - } else { - $uri = $this->uri; - } - $req = "$this->request_method $uri HTTP/$this->protocol_version"; - $this->debug("HTTP request: $req"); - $this->outgoing_payload = "$req\r\n"; - - // loop thru headers, serializing - foreach($this->outgoing_headers as $k => $v){ - $hdr = $k.': '.$v; - $this->debug("HTTP header: $hdr"); - $this->outgoing_payload .= "$hdr\r\n"; - } - - // add any cookies - if ($cookie_str != '') { - $hdr = 'Cookie: '.$cookie_str; - $this->debug("HTTP header: $hdr"); - $this->outgoing_payload .= "$hdr\r\n"; - } - - // header/body separator - $this->outgoing_payload .= "\r\n"; - - // add data - $this->outgoing_payload .= $data; - } - - /** - * sends the SOAP request via HTTP[S] - * - * @param string $data message data - * @param array $cookies cookies to send - * @return boolean true if OK, false if problem - * @access private - */ - function sendRequest($data, $cookies = NULL) { - // build cookie string - $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https'))); - - // build payload - $this->buildPayload($data, $cookie_str); - - if ($this->io_method() == 'socket') { - // 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->io_method() == 'curl') { - // set payload - // 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 (so we no longer use this method!) - //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload); - $curl_headers = array(); - foreach($this->outgoing_headers as $k => $v){ - if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') { - $this->debug("Skip cURL header $k: $v"); - } else { - $curl_headers[] = "$k: $v"; - } - } - if ($cookie_str != '') { - $curl_headers[] = 'Cookie: ' . $cookie_str; - } - $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers); - $this->debug('set cURL HTTP headers'); - if ($this->request_method == "POST") { - $this->setCurlOption(CURLOPT_POST, 1); - $this->setCurlOption(CURLOPT_POSTFIELDS, $data); - $this->debug('set cURL POST data'); - } else { - } - // insert custom user-set cURL options - foreach ($this->ch_options as $key => $val) { - $this->setCurlOption($key, $val); - } - - $this->debug('set cURL payload'); - return true; - } - } - - /** - * gets the SOAP response via HTTP[S] - * - * @return string the response (also sets member variables like incoming_payload) - * @access private - */ - function getResponse(){ - $this->incoming_payload = ''; - - if ($this->io_method() == 'socket') { - // 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; - } - - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read line of $tmplen bytes: " . trim($tmp)); - - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of headers timed out after length ' . strlen($data)); - $this->debug("read before timeout: " . $data); - $this->setError('socket read of headers timed out'); - return false; - } - - $data .= $tmp; - $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 headers - 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); - $this->incoming_headers = array(); - $this->incoming_cookies = array(); - 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]); - if ($header_name == 'set-cookie') { - // TODO: allow multiple cookies from parseCookie - $cookie = $this->parseCookie(trim($arr[1])); - if ($cookie) { - $this->incoming_cookies[] = $cookie; - $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']); - } else { - $this->debug('did not find cookie in ' . trim($arr[1])); - } - } - } else if (isset($header_name)) { - // append continuation line to previous header - $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line; - } - } - - // loop until msg has been received - if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') { - $content_length = 2147483647; // ignore any content-length header - $chunked = true; - $this->debug("want to read chunked content"); - } elseif (isset($this->incoming_headers['content-length'])) { - $content_length = $this->incoming_headers['content-length']; - $chunked = false; - $this->debug("want to read content of length $content_length"); - } else { - $content_length = 2147483647; - $chunked = false; - $this->debug("want to read content to EOF"); - } - $data = ''; - do { - if ($chunked) { - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read chunk line of $tmplen bytes"); - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of chunk length timed out after length ' . strlen($data)); - $this->debug("read before timeout:\n" . $data); - $this->setError('socket read of chunk length timed out'); - return false; - } - $content_length = hexdec(trim($tmp)); - $this->debug("chunk length $content_length"); - } - $strlen = 0; - while (($strlen < $content_length) && (!feof($this->fp))) { - $readlen = min(8192, $content_length - $strlen); - $tmp = fread($this->fp, $readlen); - $tmplen = strlen($tmp); - $this->debug("read buffer of $tmplen bytes"); - if (($tmplen == 0) && (!feof($this->fp))) { - $this->incoming_payload = $data; - $this->debug('socket read of body timed out after length ' . strlen($data)); - $this->debug("read before timeout:\n" . $data); - $this->setError('socket read of body timed out'); - return false; - } - $strlen += $tmplen; - $data .= $tmp; - } - if ($chunked && ($content_length > 0)) { - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read chunk terminator of $tmplen bytes"); - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of chunk terminator timed out after length ' . strlen($data)); - $this->debug("read before timeout:\n" . $data); - $this->setError('socket read of chunk terminator timed out'); - return false; - } - } - } while ($chunked && ($content_length > 0) && (!feof($this->fp))); - if (feof($this->fp)) { - $this->debug('read to EOF'); - } - $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']) && strtolower($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 "
    \nde-chunked:\n---------------\n$data\n\n---------------\n
    "; - // set decoded payload -// $this->incoming_payload = $header_data.$lb.$lb.$data; -// } - - } else if ($this->io_method() == 'curl') { - // 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.'
    '; - // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE - foreach(curl_getinfo($this->ch) as $k => $v){ - $err .= "$k: $v
    "; - } - $this->debug($err); - $this->setError($err); - curl_close($this->ch); - return false; - } else { - ////echo '
    ';
    -			//var_dump(curl_getinfo($this->ch));
    -			////echo '
    '; - } - // close curl - $this->debug('No cURL error, closing cURL'); - curl_close($this->ch); - - // try removing skippable headers - $savedata = $data; - while ($this->isSkippableCurlHeader($data)) { - $this->debug("Found HTTP header to skip"); - if ($pos = strpos($data,"\r\n\r\n")) { - $data = ltrim(substr($data,$pos)); - } elseif($pos = strpos($data,"\n\n") ) { - $data = ltrim(substr($data,$pos)); - } - } - - if ($data == '') { - // have nothing left; just remove 100 header(s) - $data = $savedata; - while (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){ - $header_name = strtolower(trim($arr[0])); - $this->incoming_headers[$header_name] = trim($arr[1]); - if ($header_name == 'set-cookie') { - // TODO: allow multiple cookies from parseCookie - $cookie = $this->parseCookie(trim($arr[1])); - if ($cookie) { - $this->incoming_cookies[] = $cookie; - $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']); - } else { - $this->debug('did not find cookie in ' . trim($arr[1])); - } - } - } else if (isset($header_name)) { - // append continuation line to previous header - $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line; - } - } - } - - $this->response_status_line = $header_array[0]; - $arr = explode(' ', $this->response_status_line, 3); - $http_version = $arr[0]; - $http_status = intval($arr[1]); - $http_reason = count($arr) > 2 ? $arr[2] : ''; - - // see if we need to resend the request with http digest authentication - if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) { - $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']); - $this->setURL($this->incoming_headers['location']); - $this->tryagain = true; - return false; - } - - // see if we need to resend the request with http digest authentication - if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) { - $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']); - if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) { - $this->debug('Server wants digest authentication'); - // remove "Digest " from our elements - $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']); - - // parse elements into array - $digestElements = explode(',', $digestString); - foreach ($digestElements as $val) { - $tempElement = explode('=', trim($val), 2); - $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]); - } - - // should have (at least) qop, realm, nonce - if (isset($digestRequest['nonce'])) { - $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; - } - - if ( - ($http_status >= 300 && $http_status <= 307) || - ($http_status >= 400 && $http_status <= 417) || - ($http_status >= 501 && $http_status <= 505) - ) { - $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)"); - 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('gzinflate')){ - //$timer->setMarker('starting decoding of gzip/deflated content'); - // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress) - // this means there are no Zlib headers, although there should be - $this->debug('The gzinflate function exists'); - $datalen = strlen($data); - if ($this->incoming_headers['content-encoding'] == 'deflate') { - if ($degzdata = @gzinflate($data)) { - $data = $degzdata; - $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes'); - if (strlen($data) < $datalen) { - // test for the case that the payload has been compressed twice - $this->debug('The inflated payload is smaller than the gzipped one; try again'); - if ($degzdata = @gzinflate($data)) { - $data = $degzdata; - $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes'); - } - } - } else { - $this->debug('Error using gzinflate to inflate the payload'); - $this->setError('Error using gzinflate to inflate the payload'); - } - } elseif ($this->incoming_headers['content-encoding'] == 'gzip') { - if ($degzdata = @gzinflate(substr($data, 10))) { // do our best - $data = $degzdata; - $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes'); - if (strlen($data) < $datalen) { - // test for the case that the payload has been compressed twice - $this->debug('The un-gzipped payload is smaller than the gzipped one; try again'); - if ($degzdata = @gzinflate(substr($data, 10))) { - $data = $degzdata; - $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes'); - } - } - } else { - $this->debug('Error using gzinflate to un-gzip the payload'); - $this->setError('Error using gzinflate to un-gzip the payload'); - } - } - //$timer->setMarker('finished decoding of gzip/deflated content'); - //print "\nde-inflated:\n---------------\n$data\n-------------\n"; - // set decoded payload - $this->incoming_payload = $header_data.$lb.$lb.$data; - } else { - $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.'); - $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.'); - } - } else { - $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']); - $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']); - } - } else { - $this->debug('No Content-Encoding header'); - } - - if(strlen($data) == 0){ - $this->debug('no data after headers!'); - $this->setError('no data present after HTTP headers'); - return false; - } - - return $data; - } - - /** - * sets the content-type for the SOAP message to be sent - * - * @param string $type the content type, MIME style - * @param mixed $charset character set used for encoding (or false) - * @access public - */ - function setContentType($type, $charset = false) { - $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : '')); - } - - /** - * specifies that an HTTP persistent connection should be used - * - * @return boolean whether the request was honored by this method. - * @access public - */ - function usePersistentConnection(){ - if (isset($this->outgoing_headers['Accept-Encoding'])) { - return false; - } - $this->protocol_version = '1.1'; - $this->persistentConnection = true; - $this->setHeader('Connection', 'Keep-Alive'); - return true; - } - - /** - * parse an incoming Cookie into it's parts - * - * @param string $cookie_str content of cookie - * @return array with data of that cookie - * @access private - */ - /* - * TODO: allow a Set-Cookie string to be parsed into multiple cookies - */ - function parseCookie($cookie_str) { - $cookie_str = str_replace('; ', ';', $cookie_str) . ';'; - $data = split(';', $cookie_str); - $value_str = $data[0]; - - $cookie_param = 'domain='; - $start = strpos($cookie_str, $cookie_param); - if ($start > 0) { - $domain = substr($cookie_str, $start + strlen($cookie_param)); - $domain = substr($domain, 0, strpos($domain, ';')); - } else { - $domain = ''; - } - - $cookie_param = 'expires='; - $start = strpos($cookie_str, $cookie_param); - if ($start > 0) { - $expires = substr($cookie_str, $start + strlen($cookie_param)); - $expires = substr($expires, 0, strpos($expires, ';')); - } else { - $expires = ''; - } - - $cookie_param = 'path='; - $start = strpos($cookie_str, $cookie_param); - if ( $start > 0 ) { - $path = substr($cookie_str, $start + strlen($cookie_param)); - $path = substr($path, 0, strpos($path, ';')); - } else { - $path = '/'; - } - - $cookie_param = ';secure;'; - if (strpos($cookie_str, $cookie_param) !== FALSE) { - $secure = true; - } else { - $secure = false; - } - - $sep_pos = strpos($value_str, '='); - - if ($sep_pos) { - $name = substr($value_str, 0, $sep_pos); - $value = substr($value_str, $sep_pos + 1); - $cookie= array( 'name' => $name, - 'value' => $value, - 'domain' => $domain, - 'path' => $path, - 'expires' => $expires, - 'secure' => $secure - ); - return $cookie; - } - return false; - } - - /** - * sort out cookies for the current request - * - * @param array $cookies array with all cookies - * @param boolean $secure is the send-content secure or not? - * @return string for Cookie-HTTP-Header - * @access private - */ - function getCookiesForRequest($cookies, $secure=false) { - $cookie_str = ''; - if ((! is_null($cookies)) && (is_array($cookies))) { - foreach ($cookies as $cookie) { - if (! is_array($cookie)) { - continue; - } - $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']); - if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) { - if (strtotime($cookie['expires']) <= time()) { - $this->debug('cookie has expired'); - continue; - } - } - if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) { - $domain = preg_quote($cookie['domain']); - if (! preg_match("'.*$domain$'i", $this->host)) { - $this->debug('cookie has different domain'); - continue; - } - } - if ((isset($cookie['path'])) && (! empty($cookie['path']))) { - $path = preg_quote($cookie['path']); - if (! preg_match("'^$path.*'i", $this->path)) { - $this->debug('cookie is for a different path'); - continue; - } - } - if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) { - $this->debug('cookie is secure, transport is not'); - continue; - } - $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; '; - $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']); - } - } - return $cookie_str; - } -} - -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $ -* @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; - var $curl_options = array(); // User-specified cURL options - var $use_curl = false; // whether to always try to use cURL - // for HTTP authentication - var $username = ''; // Username for HTTP authentication - var $password = ''; // Password for HTTP authentication - var $authtype = ''; // Type of HTTP authentication - var $certRequest = array(); // Certificate for HTTP SSL authentication - - /** - * 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 - * @param array $curl_options user-specified cURL options - * @param boolean $use_curl try to use cURL - * @access public - */ - function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){ - parent::nusoap_base(); - $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout"); - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - $this->timeout = $timeout; - $this->response_timeout = $response_timeout; - if (is_array($curl_options)) - $this->curl_options = $curl_options; - $this->use_curl = $use_curl; - $this->fetchWSDL($wsdl); - } - - /** - * fetches the WSDL document and parses it - * - * @access public - */ - function fetchWSDL($wsdl) { - $this->debug("parse and process WSDL path=$wsdl"); - $this->wsdl = $wsdl; - // parse wsdl file - if ($this->wsdl != "") { - $this->parseWSDL($this->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'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') . - 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'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') . - 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'] ]; - } - // Set operation style if necessary, but do not override one already provided - if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['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 = '') { - $this->debug("parse WSDL at path=$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, $this->curl_options, $this->use_curl); - $tr->request_method = 'GET'; - $tr->useSOAPAction = false; - if($this->proxyhost && $this->proxyport){ - $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword); - } - if ($this->authtype != '') { - $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest); - } - $tr->setEncoding('gzip, deflate'); - $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->appendDebug($tr->getDebug()); - // catch errors - if($err = $tr->getError() ){ - $errstr = 'HTTP ERROR: '.$err; - $this->debug($errstr); - $this->setError($errstr); - unset($tr); - return false; - } - unset($tr); - $this->debug("got WSDL URL"); - } 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; - } - } - $this->debug('Parse WSDL'); - // 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); - $this->debug('Parsing WSDL done'); - // 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->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - } elseif (ereg('schema$', $name)) { - $this->debug('Parsing WSDL schema'); - // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")"); - $this->status = 'schema'; - $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces); - $this->currentSchema->schemaStartElement($parser, $name, $attrs); - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - } 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' => ''); - // process attributes - if (count($attrs) > 0) { - // register namespace declarations - foreach($attrs as $k => $v) { - 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' || $v == 'http://www.w3.org/2000/10/XMLSchema') { - $this->XMLSchemaVersion = $v; - $this->namespaces['xsi'] = $v . '-instance'; - } - } - } - // expand each attribute prefix to its namespace - foreach($attrs as $k => $v) { - $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(); - } - // get element prefix, namespace and name - 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); - } - // process attributes, expanding any prefixes to namespaces - // find status, register data - switch ($this->status) { - case 'message': - if ($name == 'part') { - if (isset($attrs['type'])) { - $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs)); - $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type']; - } - if (isset($attrs['element'])) { - $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs)); - $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->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema; - $this->debug('Parsing WSDL schema done'); - } - 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; - } - } - - /** - * if authenticating, set user credentials here - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - * @access public - */ - function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) { - $this->debug("setCredentials username=$username authtype=$authtype certRequest="); - $this->appendDebug($this->varDump($certRequest)); - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->certRequest = $certRequest; - } - - 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 and soap12 are currently supported) - * @return array - * @access public - */ - function getOperations($bindingType = 'soap') { - $ops = array(); - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } - // 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, soap12 - * @return array - * @access public - */ - function getOperationData($operation, $bindingType = 'soap') - { - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } - // 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) { - // note that we could/should also check the namespace here - if ($operation == $bOperation) { - $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation]; - return $opData; - } - } - } - } - } - - /** - * returns an associative array of data necessary for calling an operation - * - * @param string $soapAction soapAction for operation - * @param string $bindingType type of binding eg: soap, soap12 - * @return array - * @access public - */ - function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') { - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } - // loop thru ports - foreach($this->ports as $port => $portData) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - // loop through operations for the binding - foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { - if ($opData['soapAction'] == $soapAction) { - 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 string $type the type - * @param string $ns namespace (not prefix) of the type - * @return mixed - * @access public - * @see nusoap_xmlschema - */ - function getTypeDef($type, $ns) { - $this->debug("in getTypeDef: type=$type, ns=$ns"); - if ((! $ns) && isset($this->namespaces['tns'])) { - $ns = $this->namespaces['tns']; - $this->debug("in getTypeDef: type namespace forced to $ns"); - } - if (!isset($this->schemas[$ns])) { - foreach ($this->schemas as $ns0 => $schema0) { - if (strcasecmp($ns, $ns0) == 0) { - $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0"); - $ns = $ns0; - break; - } - } - } - if (isset($this->schemas[$ns])) { - $this->debug("in getTypeDef: have schema for namespace $ns"); - for ($i = 0; $i < count($this->schemas[$ns]); $i++) { - $xs = &$this->schemas[$ns][$i]; - $t = $xs->getTypeDef($type); - //$this->appendDebug($xs->getDebug()); - //$xs->clearDebug(); - if ($t) { - if (!isset($t['phpType'])) { - // get info for type to tack onto the element - $uqType = substr($t['type'], strrpos($t['type'], ':') + 1); - $ns = substr($t['type'], 0, strrpos($t['type'], ':')); - $etype = $this->getTypeDef($uqType, $ns); - if ($etype) { - $this->debug("found type for [element] $type:"); - $this->debug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $t['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $t['elements'] = $etype['elements']; - } - if (isset($etype['attrs'])) { - $t['attrs'] = $etype['attrs']; - } - } - } - return $t; - } - } - } else { - $this->debug("in getTypeDef: do not have schema for namespace $ns"); - } - return false; - } - - /** - * prints html description of services - * - * @access private - */ - function webDescription(){ - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $PHP_SELF = $_SERVER['PHP_SELF']; - } elseif (isset($HTTP_SERVER_VARS)) { - $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF']; - } else { - $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); - } - - $b = ' - NuSOAP: '.$this->serviceName.' - - - - -
    -

    -
    '.$this->serviceName.'
    - -
    '; - return $b; - } - - /** - * serialize the parsed wsdl - * - * @param mixed $debug whether to put debug=1 in endpoint URL - * @return string serialization of WSDL - * @access public - */ - function serialize($debug = 0) - { - $xml = ''; - $xml .= "\nnamespaces 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 .= ''; - } else { - $xml .= ''; - } - } - } - } - // types - if (count($this->schemas)>=1) { - $xml .= "\n\n"; - foreach ($this->schemas as $ns => $list) { - foreach ($list as $xs) { - $xml .= $xs->serializeSchema(); - } - } - $xml .= ''; - } - // messages - if (count($this->messages) >= 1) { - foreach($this->messages as $msgName => $msgParts) { - $xml .= "\n'; - if(is_array($msgParts)){ - foreach($msgParts as $partName => $partType) { - // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'
    '; - if (strpos($partType, ':')) { - $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType)); - } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) { - // print 'checking typemap: '.$this->XMLSchemaVersion.'
    '; - $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!"); - } - } - $ns = $this->getNamespaceFromPrefix($typePrefix); - $localPart = $this->getLocalPart($partType); - $typeDef = $this->getTypeDef($localPart, $ns); - if ($typeDef['typeClass'] == 'element') { - $elementortype = 'element'; - if (substr($localPart, -1) == '^') { - $localPart = substr($localPart, 0, -1); - } - } else { - $elementortype = 'type'; - } - $xml .= "\n" . ' '; - } - } - $xml .= '
    '; - } - } - // bindings & porttypes - if (count($this->bindings) >= 1) { - $binding_xml = ''; - $portType_xml = ''; - foreach($this->bindings as $bindingName => $attrs) { - $binding_xml .= "\n'; - $binding_xml .= "\n" . ' '; - $portType_xml .= "\n'; - foreach($attrs['operations'] as $opName => $opParts) { - $binding_xml .= "\n" . ' '; - $binding_xml .= "\n" . ' '; - if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') { - $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"'; - } else { - $enc_style = ''; - } - $binding_xml .= "\n" . ' '; - if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') { - $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"'; - } else { - $enc_style = ''; - } - $binding_xml .= "\n" . ' '; - $binding_xml .= "\n" . ' '; - $portType_xml .= "\n" . ' ' . htmlspecialchars($opParts['documentation']) . ''; - } - $portType_xml .= "\n" . ' '; - $portType_xml .= "\n" . ' '; - $portType_xml .= "\n" . ' '; - } - $portType_xml .= "\n" . ''; - $binding_xml .= "\n" . ''; - } - $xml .= $portType_xml . $binding_xml; - } - // services - $xml .= "\nserviceName . '">'; - if (count($this->ports) >= 1) { - foreach($this->ports as $pName => $attrs) { - $xml .= "\n" . ' '; - $xml .= "\n" . ' '; - $xml .= "\n" . ' '; - } - } - $xml .= "\n" . ''; - return $xml . "\n"; - } - - /** - * determine whether a set of parameters are unwrapped - * when they are expect to be wrapped, Microsoft-style. - * - * @param string $type the type (element name) of the wrapper - * @param array $parameters the parameter values for the SOAP call - * @return boolean whether they parameters are unwrapped (and should be wrapped) - * @access private - */ - function parametersMatchWrapped($type, &$parameters) { - $this->debug("in parametersMatchWrapped type=$type, parameters="); - $this->appendDebug($this->varDump($parameters)); - - // split type into namespace:unqualified-type - if (strpos($type, ':')) { - $uqType = substr($type, strrpos($type, ':') + 1); - $ns = substr($type, 0, strrpos($type, ':')); - $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns"); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns"); - } - } else { - // TODO: should the type be compared to types in XSD, and the namespace - // set to XSD if the type matches? - $this->debug("in parametersMatchWrapped: No namespace for type $type"); - $ns = ''; - $uqType = $type; - } - - // get the type information - if (!$typeDef = $this->getTypeDef($uqType, $ns)) { - $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type."); - return false; - } - $this->debug("in parametersMatchWrapped: found typeDef="); - $this->appendDebug($this->varDump($typeDef)); - if (substr($uqType, -1) == '^') { - $uqType = substr($uqType, 0, -1); - } - $phpType = $typeDef['phpType']; - $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''); - $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType"); - - // we expect a complexType or element of complexType - if ($phpType != 'struct') { - $this->debug("in parametersMatchWrapped: not a struct"); - return false; - } - - // see whether the parameter names match the elements - if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { - $elements = 0; - $matches = 0; - $change = false; - if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) { - $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap"); - $change = true; - } - foreach ($typeDef['elements'] as $name => $attrs) { - if ($change) { - $this->debug("in parametersMatchWrapped: change parameter $element to name $name"); - $parameters[$name] = $parameters[$elements]; - unset($parameters[$elements]); - $matches++; - } elseif (isset($parameters[$name])) { - $this->debug("in parametersMatchWrapped: have parameter named $name"); - $matches++; - } else { - $this->debug("in parametersMatchWrapped: do not have parameter named $name"); - } - $elements++; - } - - $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names"); - if ($matches == 0) { - return false; - } - return true; - } - - // since there are no elements for the type, if the user passed no - // parameters, the parameters match wrapped. - $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType"); - return count($parameters) == 0; - } - - /** - * serialize PHP values according to a WSDL message definition - * contrary to the method name, this is not limited to RPC - * - * TODO - * - multi-ref serialization - * - validate PHP values against type definitions, return errors if invalid - * - * @param string $operation operation name - * @param string $direction (input|output) - * @param mixed $parameters parameter value(s) - * @param string $bindingType (soap|soap12) - * @return mixed parameters serialized as XML or false on error (e.g. operation not found) - * @access public - */ - function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') { - $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType"); - - //echo "in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType"."
    "; - //print_r($parameters); - //echo "
    "; - - $this->appendDebug('parameters=' . $this->varDump($parameters)); - - 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, $bindingType)) { - $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); - $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); - return false; - } - $this->debug('in serializeRPCParameters: opData:'); - $this->appendDebug($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) { - $parts = &$opData[$direction]['parts']; - $part_count = sizeof($parts); - $style = $opData['style']; - $use = $opData[$direction]['use']; - $this->debug("have $part_count part(s) to serialize using $style/$use"); - if (is_array($parameters)) { - $parametersArrayType = $this->isArraySimpleOrStruct($parameters); - $parameter_count = count($parameters); - $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize"); - // check for Microsoft-style wrapped parameters - if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) { - $this->debug('check whether the caller has wrapped the parameters'); - if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) { - $this->debug('check whether caller\'s parameters match the wrapped ones'); - if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) { - $this->debug('wrap the parameters for the caller'); - $parameters = array('parameters' => $parameters); - $parameter_count = 1; - } - } - } - foreach ($parts as $name => $type) { - //echo "serializing part $name of type $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') { - //echo "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])) { - //echo "array SECOND
    "; - $this->debug('calling serializeType w/named param'); - //echo "PARAMS: "; - //print_r ($parameters[$name]); - //echo "
    "; - $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); - } else { - //echo "array THIRD
    "; - // TODO: only send nillable - $this->debug('calling serializeType w/null param'); - //echo "PARAMS: "; - //print_r ($parameters); - //echo "
    "; - //For some reason this does not work!! I am heavily (!) thinking about WHY the params here - //are passed as NULL?! What should be the resulting XML if you pass NULL as paramlist?!?!? - //seba.wagner at gmail dot com 2008/05/12 - //$xml .= $this->serializeType($name, $type, null, $use, $enc_style); - $xml .= $this->serializeLinuxAxis2Type($name, $type, $parameters, $use, $enc_style); - } - //echo "PART XML: ".htmlentities($xml)."
    "; - } - } else { - $this->debug('no parameters passed.'); - } - } - $this->debug("serializeRPCParameters returning: $xml"); - //echo "
    "."serializeRPCParameters returning: ".htmlentities($xml)."
    "; - 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 $operation operation name - * @param string $direction (input|output) - * @param mixed $parameters parameter value(s) - * @return mixed parameters serialized as XML or false on error (e.g. operation not found) - * @access public - * @deprecated - */ - function serializeParameters($operation, $direction, $parameters) - { - $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); - $this->appendDebug('parameters=' . $this->varDump($parameters)); - - 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('opData:'); - $this->appendDebug($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.'); - } - } - $this->debug("serializeParameters returning: $xml"); - return $xml; - } - - function serializeLinuxAxis2Type($name, $type, $params, $use='encoded', $encodingStyle=false, $unqualified=false) - { - $xml = ''; - if (strpos($type, ':')) { - $uqType = substr($type, strrpos($type, ':') + 1); - $ns = substr($type, 0, strrpos($type, ':')); - $this->debug("in serializeType: got a prefixed type: $uqType, $ns"); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - $this->debug("in serializeType: expanded prefixed type: $uqType, $ns"); - } - - //echo "NameSpace: ".$ns."
    "; - //echo "Method: ".$uqType."
    "; - $methodName = substr($uqType,0,strlen($uqType)-1); - - //echo "Method: ".$methodName."
    "; - - $xml .= '<'.$methodName.' xmlns="'.$ns.'">'; - - foreach ($params as $key => $val){ - //echo "Key".$key." Value".$val."
    "; - - $insertVal = $val; - - //If Boolean rewrite the Value - if (is_bool($val)){ - if ($val) { - $insertVal = "true"; - } else { - $insertVal = "false"; - } - } - $xml .= '<'.$key.'>'.$insertVal.''; - } - - $xml .= ''; - - //echo htmlentities($xml)."
    "; - return $xml; - // - } - - } - /** - * serializes a PHP value according a given type definition - * - * @param string $name name of value (part or element) - * @param string $type XML schema type of value (type or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $use use for part (encoded|literal) - * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style) - * @param boolean $unqualified a kludge for what should be XML namespace form handling - * @return string value serialized as an XML string - * @access private - */ - function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false) - { - $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified")); - //echo "in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified")."
    "; - - //echo "SerialieType: ".$type."
    "; - - $this->appendDebug("value=" . $this->varDump($value)); - if($use == 'encoded' && $encodingStyle) { - $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"'; - } - - // if a soapval has been supplied, let its type override the WSDL - if (is_object($value) && get_class($value) == 'soapval') { - ////echo "IS OBJECT "."
    "; - if ($value->type_ns) { - $type = $value->type_ns . ':' . $value->type; - $forceType = true; - $this->debug("in serializeType: soapval overrides type to $type"); - } elseif ($value->type) { - $type = $value->type; - $forceType = true; - $this->debug("in serializeType: soapval overrides type to $type"); - } else { - $forceType = false; - $this->debug("in serializeType: soapval does not override type"); - } - $attrs = $value->attributes; - $value = $value->value; - $this->debug("in serializeType: soapval overrides value to $value"); - if ($attrs) { - if (!is_array($value)) { - $value['!'] = $value; - } - foreach ($attrs as $n => $v) { - $value['!' . $n] = $v; - } - $this->debug("in serializeType: soapval provides attributes"); - } - } else { - $forceType = false; - } - - $xml = ''; - if (strpos($type, ':')) { - $uqType = substr($type, strrpos($type, ':') + 1); - - //echo "FIRST ### uqType: ".$uqType."
    "; - - $ns = substr($type, 0, strrpos($type, ':')); - $this->debug("in serializeType: got a prefixed type: $uqType, $ns"); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - $this->debug("in serializeType: expanded prefixed type: $uqType, $ns"); - } - - //echo "NameSpace: ".$ns."
    "; - if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){ - $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type'); - if ($unqualified && $use == 'literal') { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$elementNS/>"; - } else { - // TODO: depends on nillable, which should be checked before calling this method - $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - //echo "uqType: ".$uqType."
    "; - if ($uqType == 'Array') { - // JBoss/Axis does this sometimes - return $this->serialize_val($value, $name, false, false, false, false, $use); - } - if ($uqType == 'boolean') { - if ((is_string($value) && $value == 'false') || (! $value)) { - $value = 'false'; - } else { - $value = 'true'; - } - } - if ($uqType == 'string' && gettype($value) == 'string') { - $value = $this->expandEntities($value); - } - if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') { - $value = sprintf("%.0lf", $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) { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value"; - } else { - $xml = "<$name$elementNS>$value"; - } - } else { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)'); - } else if ($ns == 'http://xml.apache.org/xml-soap') { - $this->debug('in serializeType: appears to be Apache SOAP type'); - if ($uqType == 'Map') { - $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); - if (! $tt_prefix) { - $this->debug('in serializeType: Add namespace for Apache SOAP type'); - $tt_prefix = 'ns' . rand(1000, 9999); - $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap'; - // force this to be added to usedNamespaces - $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); - } - $contents = ''; - foreach($value as $k => $v) { - $this->debug("serializing map element: key $k, value $v"); - $contents .= ''; - $contents .= $this->serialize_val($k,'key',false,false,false,false,$use); - $contents .= $this->serialize_val($v,'value',false,false,false,false,$use); - $contents .= ''; - } - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents"; - } else { - $xml = "<$name>$contents"; - } - } else { - $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - $this->debug('in serializeType: Apache SOAP type, but only support Map'); - } - } else { - // TODO: should the type be compared to types in XSD, and the namespace - // set to XSD if the type matches? - $this->debug("in serializeType: 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("in serializeType: $type ($uqType) is not a supported type."); - return false; - } else { - $this->debug("in serializeType: found typeDef"); - $this->appendDebug('typeDef=' . $this->varDump($typeDef)); - if (substr($uqType, -1) == '^') { - $uqType = substr($uqType, 0, -1); - } - } - $phpType = $typeDef['phpType']; - $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); - // if php type == struct, map value to the 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 { - $elementNS = " xmlns=\"\""; - } - } else { - $elementName = $name; - if ($unqualified) { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$elementName$elementNS/>"; - } else { - $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - if (is_object($value)) { - $value = get_object_vars($value); - } - if (is_array($value)) { - $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType); - if ($use == 'literal') { - if ($forceType) { - $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">"; - } else { - $xml = "<$elementName$elementNS$elementAttrs>"; - } - } else { - $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>"; - } - - $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle); - $xml .= ""; - } else { - $this->debug("in serializeType: phpType is struct, but value is not an array"); - $this->setError("phpType is struct, but value is not an array: see debug output for details"); - $xml = ''; - } - } elseif ($phpType == 'array') { - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - if ($unqualified) { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$elementNS/>"; - } else { - $xml = "<$name$elementNS xsi:nil=\"true\" 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'])."[0]\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - 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) { - ////echo "IS ARRAY !! ".sizeof($value)."
    "; - $rows = sizeof($value); - $contents = ''; - foreach($value as $k => $v) { - - ////echo $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'])) { - //echo "CALL AGAIN HEHRERERERER ###########
    "; - $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use); - } else { - $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use); - } - } - } 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 - .""; - } 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 - .""; - } - } elseif ($phpType == 'scalar') { - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - if ($unqualified) { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - } - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value"; - } else { - $xml = "<$name$elementNS>$value"; - } - } else { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value"; - } - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - - /** - * serializes the attributes for a complexType - * - * @param array $typeDef our internal representation of an XML schema type (or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $ns the namespace of the type - * @param string $uqType the local part of the type - * @return string value serialized as an XML string - * @access private - */ - function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) { - $xml = ''; - if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) { - $this->debug("serialize attributes for XML Schema type $ns:$uqType"); - if (is_array($value)) { - $xvalue = $value; - } elseif (is_object($value)) { - $xvalue = get_object_vars($value); - } else { - $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); - $xvalue = array(); - } - foreach ($typeDef['attrs'] as $aName => $attrs) { - if (isset($xvalue['!' . $aName])) { - $xname = '!' . $aName; - $this->debug("value provided for attribute $aName with key $xname"); - } elseif (isset($xvalue[$aName])) { - $xname = $aName; - $this->debug("value provided for attribute $aName with key $xname"); - } elseif (isset($attrs['default'])) { - $xname = '!' . $aName; - $xvalue[$xname] = $attrs['default']; - $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName); - } else { - $xname = ''; - $this->debug("no value provided for attribute $aName"); - } - if ($xname) { - $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\""; - } - } - } else { - $this->debug("no attributes to serialize for XML Schema type $ns:$uqType"); - } - if (isset($typeDef['extensionBase'])) { - $ns = $this->getPrefix($typeDef['extensionBase']); - $uqType = $this->getLocalPart($typeDef['extensionBase']); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - } - if ($typeDef = $this->getTypeDef($uqType, $ns)) { - $this->debug("serialize attributes for extension base $ns:$uqType"); - $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType); - } else { - $this->debug("extension base $ns:$uqType is not a supported type"); - } - } - return $xml; - } - - /** - * serializes the elements for a complexType - * - * @param array $typeDef our internal representation of an XML schema type (or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $ns the namespace of the type - * @param string $uqType the local part of the type - * @param string $use use for part (encoded|literal) - * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style) - * @return string value serialized as an XML string - * @access private - */ - function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) { - $xml = ''; - if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { - $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType"); - if (is_array($value)) { - $xvalue = $value; - } elseif (is_object($value)) { - $xvalue = get_object_vars($value); - } else { - $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); - $xvalue = array(); - } - // toggle whether all elements are present - ideally should validate against schema - if (count($typeDef['elements']) != count($xvalue)){ - $optionals = true; - } - foreach ($typeDef['elements'] as $eName => $attrs) { - if (!isset($xvalue[$eName])) { - if (isset($attrs['default'])) { - $xvalue[$eName] = $attrs['default']; - $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName); - } - } - // if user took advantage of a minOccurs=0, then only serialize named parameters - if (isset($optionals) - && (!isset($xvalue[$eName])) - && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true') - ){ - if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') { - $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']); - } - // do nothing - $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing"); - } else { - // get value - if (isset($xvalue[$eName])) { - $v = $xvalue[$eName]; - } else { - $v = null; - } - if (isset($attrs['form'])) { - $unqualified = ($attrs['form'] == 'unqualified'); - } else { - $unqualified = false; - } - if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') { - $vv = $v; - foreach ($vv as $k => $v) { - if (isset($attrs['type']) || isset($attrs['ref'])) { - // serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } else { - // serialize generic type (can this ever really happen?) - $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']) || isset($attrs['ref'])) { - // serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } else { - // serialize generic type (can this ever really happen?) - $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 { - $this->debug("no elements to serialize for XML Schema type $ns:$uqType"); - } - if (isset($typeDef['extensionBase'])) { - $ns = $this->getPrefix($typeDef['extensionBase']); - $uqType = $this->getLocalPart($typeDef['extensionBase']); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - } - if ($typeDef = $this->getTypeDef($uqType, $ns)) { - $this->debug("serialize elements for extension base $ns:$uqType"); - $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle); - } else { - $this->debug("extension base $ns:$uqType is not a supported type"); - } - } - return $xml; - } - - /** - * adds an XML Schema complex type to the WSDL types - * - * @param string $name - * @param string $typeClass (complexType|simpleType|attribute) - * @param string $phpType currently supported are array and struct (php assoc array) - * @param string $compositor (all|sequence|choice) - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param array $elements e.g. array ( name => array(name=>'',type=>'') ) - * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]')) - * @param string $arrayType as namespace:name (xsd:string) - * @see nusoap_xmlschema - * @access public - */ - function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') { - if (count($elements) > 0) { - $eElements = array(); - foreach($elements as $n => $e){ - // expand each element - $ee = array(); - 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 string $name - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param string $typeClass (should always be simpleType) - * @param string $phpType (should always be scalar) - * @param array $enumeration array of values - * @see nusoap_xmlschema - * @access public - */ - function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { - $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, $enumeration); - } - - /** - * adds an element to the WSDL types - * - * @param array $attrs attributes that must include name and type - * @see nusoap_xmlschema - * @access public - */ - function addElement($attrs) { - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addElement($attrs); - } - - /** - * register an operation with the server - * - * @param string $name operation (method) name - * @param array $in assoc array of input values: key = param name, value = param type - * @param array $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 Note: when 'document' is specified, parameter and return wrappers are created for you automatically - * @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 - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - * @access public - */ - function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){ - if ($use == 'encoded' && $encodingStyle == '') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } - - if ($style == 'document') { - $elements = array(); - foreach ($in as $n => $t) { - $elements[$n] = array('name' => $n, 'type' => $t); - } - $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements); - $this->addElement(array('name' => $name, 'type' => $name . 'RequestType')); - $in = array('parameters' => 'tns:' . $name . '^'); - - $elements = array(); - foreach ($out as $n => $t) { - $elements[$n] = array('name' => $n, 'type' => $t); - } - $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements); - $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified')); - $out = array('parameters' => 'tns:' . $name . 'Response' . '^'); - } - - // 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; - } -} -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $ -* @access public -*/ -class nusoap_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; // parsed SOAP Body - var $soapheader = NULL; // parsed SOAP Header - 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 that actually does the parsing - * - * @param string $xml SOAP message - * @param string $encoding character encoding scheme of message - * @param string $method method for which XML is parsed (unused?) - * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1 - * @access public - */ - function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){ - parent::nusoap_base(); - $this->xml = $xml; - $this->xml_encoding = $encoding; - $this->method = $method; - $this->decode_utf8 = $decode_utf8; - - // Check whether content has been read. - if(!empty($xml)){ - // Check XML encoding - $pos_xml = strpos($xml, '', $pos_xml + 2) - $pos_xml + 1); - if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) { - $xml_encoding = $res[1]; - if (strtoupper($xml_encoding) != $encoding) { - $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'"; - $this->debug($err); - if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') { - $this->setError($err); - return; - } - // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed - } else { - $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration'); - } - } else { - $this->debug('No encoding specified in XML declaration'); - } - } else { - $this->debug('No XML declaration'); - } - $this->debug('Entering nusoap_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 - if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){ - $this->soapheader = $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]); - if (is_array($idVal) && isset($idVal['!id'])) { - unset($idVal['!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 resource $parser XML parser object - * @param string $name element name - * @param array $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->status = 'envelope'){ - $this->root_header = $pos; - $this->status = 'header'; - } elseif($name == 'Body' && $this->status = 'envelope'){ - $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'){ - if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') { - // do nothing: already processed arrayType - } else { - $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]; - } - // specifies nil value (or not) - } elseif ($key_localpart == 'nil'){ - $this->message[$pos]['nil'] = ($value == 'true' || $value == '1'); - // some other attribute - } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') { - $this->message[$pos]['xattrs']['!' . $key] = $value; - } - - if ($key == 'xmlns') { - $this->default_namespace = $value; - } - // 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 resource $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 complexType 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); - } - // build complexType values of attributes and possibly simpleContent - } elseif (isset($this->message[$pos]['xattrs'])) { - if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) { - $this->message[$pos]['xattrs']['!'] = null; - } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') { - if (isset($this->message[$pos]['type'])) { - $this->message[$pos]['xattrs']['!'] = $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]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata']; - } - } - } - $this->message[$pos]['result'] = $this->message[$pos]['xattrs']; - // set value of simpleType (or nil complexType) - } else { - //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']); - if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) { - $this->message[$pos]['xattrs']['!'] = null; - } elseif (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 .= ""; - } - } elseif($pos >= $this->root_struct){ - $this->document .= ""; - } - // 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 resource $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 (SOAP Body) - * - * @return mixed - * @access public - * @deprecated use get_soapbody instead - */ - function get_response(){ - return $this->soapresponse; - } - - /** - * get the parsed SOAP Body (NULL if there was none) - * - * @return mixed - * @access public - */ - function get_soapbody(){ - return $this->soapresponse; - } - - /** - * get the parsed SOAP Header (NULL if there was none) - * - * @return mixed - * @access public - */ - function get_soapheader(){ - return $this->soapheader; - } - - /** - * get the unparsed SOAP Header - * - * @return string XML or empty if no Header - * @access public - */ - function getHeaders(){ - return $this->responseHeaders; - } - - /** - * 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 - * @return mixed PHP value - * @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') { - $this->debug('Decode base64 value'); - 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; - } - // bogus: parser treats array with no elements as a simple type - if ($type == 'array') { - return array(); - } - // everything else - return (string) $value; - } - - /** - * builds response structures for compound values (arrays/structs) - * and scalars - * - * @param integer $pos position in node tree - * @return mixed PHP value - * @access private - */ - function buildVal($pos){ - if(!isset($this->message[$pos]['type'])){ - $this->message[$pos]['type'] = ''; - } - $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']); - // if there are children... - if($this->message[$pos]['children'] != ''){ - $this->debug('in buildVal, there are 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("in buildVal, 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('in buildVal, 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'){ - $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']); - 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 - $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']); - if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') { - $notstruct = 1; - } else { - $notstruct = 0; - } - // - foreach($children as $child_pos){ - if($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']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) { - $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']; - } - } - } - } - if (isset($this->message[$pos]['xattrs'])) { - $this->debug('in buildVal, handling attributes'); - foreach ($this->message[$pos]['xattrs'] as $n => $v) { - $params[$n] = $v; - } - } - // handle simpleContent - if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') { - $this->debug('in buildVal, handling simpleContent'); - if (isset($this->message[$pos]['type'])) { - $params['!'] = $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'])) { - $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $params['!'] = $this->message[$pos]['cdata']; - } - } - } - $ret = is_array($params) ? $params : array(); - $this->debug('in buildVal, return:'); - $this->appendDebug($this->varDump($ret)); - return $ret; - } else { - $this->debug('in buildVal, no children, building scalar'); - $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : ''; - if (isset($this->message[$pos]['type'])) { - $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - $this->debug("in buildVal, return: $ret"); - return $ret; - } - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - $this->debug("in buildVal, return: $ret"); - return $ret; - } - $ret = $this->message[$pos]['cdata']; - $this->debug("in buildVal, return: $ret"); - return $ret; - } - } -} - -/** - * Backward compatibility - */ -class soap_parser extends nusoap_parser { -} - -?>call( string methodname [ ,array parameters] ); -* -* // bye bye client -* unset($soapclient); -* -* @author Dietrich Ayala -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $ -* @access public -*/ -class nusoap_client extends nusoap_base { - - var $username = ''; // Username for HTTP authentication - var $password = ''; // Password for HTTP authentication - var $authtype = ''; // Type of HTTP authentication - var $certRequest = array(); // Certificate for HTTP SSL authentication - var $requestHeaders = false; // SOAP headers in request (text) - var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text) - var $responseHeader = NULL; // SOAP Header from response (parsed) - var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text) - var $endpoint; - var $forceEndpoint = ''; // overrides WSDL endpoint - 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; // HTTP connection timeout - var $response_timeout = 30; // HTTP response timeout - var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error - var $persistentConnection = false; - var $defaultRpcParams = false; // This is no longer used - var $request = ''; // HTTP request - var $response = ''; // HTTP response - var $responseData = ''; // SOAP payload of response - var $cookies = array(); // Cookies from response or for request - var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode() - var $operations = array(); // WSDL operations, empty for WSDL initialization error - var $curl_options = array(); // User-specified cURL options - var $bindingType = ''; // WSDL operation binding type - var $use_curl = false; // whether to always try to use cURL - - /* - * fault related variables - */ - /** - * @var fault - * @access public - */ - var $fault; - /** - * @var faultcode - * @access public - */ - var $faultcode; - /** - * @var faultstring - * @access public - */ - var $faultstring; - /** - * @var faultdetail - * @access public - */ - var $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 nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30){ - parent::nusoap_base(); - $this->endpoint = $endpoint; - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - $this->timeout = $timeout; - $this->response_timeout = $response_timeout; - - $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout"); - $this->appendDebug('endpoint=' . $this->varDump($endpoint)); - - // make values - if($wsdl){ - if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) { - $this->wsdl = $endpoint; - $this->endpoint = $this->wsdl->wsdl; - $this->wsdlFile = $this->endpoint; - $this->debug('existing wsdl instance created from ' . $this->endpoint); - $this->checkWSDL(); - } else { - $this->wsdlFile = $this->endpoint; - $this->wsdl = null; - $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint); - } - $this->endpointType = 'wsdl'; - } else { - $this->debug("instantiate SOAP with endpoint at $endpoint"); - $this->endpointType = 'soap'; - } - } - - /** - * calls method, returns PHP native type - * - * @param string $operation SOAP server URL or path - * @param mixed $params An array, associative or simple, of the parameters - * for the method call, or a string that is the XML - * for the call. For rpc style, this call will - * wrap the XML in a tag named after the method, as - * well as the SOAP Envelope and Body. For document - * style, this will only wrap with the Envelope and Body. - * IMPORTANT: when using an array with 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 mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array - * @param boolean $rpcParams optional (no longer used) - * @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 response from SOAP call - * @access public - */ - function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){ - $this->operation = $operation; - $this->fault = false; - $this->setError(''); - $this->request = ''; - $this->response = ''; - $this->responseData = ''; - $this->faultstring = ''; - $this->faultcode = ''; - $this->opData = array(); - - $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType"); - $this->appendDebug('params=' . $this->varDump($params)); - $this->appendDebug('headers=' . $this->varDump($headers)); - if ($headers) { - $this->requestHeaders = $headers; - } - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) - return false; - } - // serialize parameters - if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){ - // use WSDL for operation - //echo "use WSDL for operation
    "; - $this->opData = $opData; - $this->debug("found operation"); - $this->appendDebug('opData=' . $this->varDump($opData)); - if (isset($opData['soapAction'])) { - $soapAction = $opData['soapAction']; - } - if (! $this->forceEndpoint) { - $this->endpoint = $opData['endpoint']; - } else { - $this->endpoint = $this->forceEndpoint; - } - $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace; - $style = $opData['style']; - $use = $opData['input']['use']; - // add ns to ns array - if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){ - $nsPrefix = 'ns' . rand(1000, 9999); - $this->wsdl->namespaces[$nsPrefix] = $namespace; - } - $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace); - // serialize payload - if (is_string($params)) { - $this->debug("serializing param string for WSDL operation $operation"); - $payload = $params; - } elseif (is_array($params)) { - $this->debug("serializing param array for WSDL operation $operation"); - $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType); - //echo "#####PAYLOAD 2 ####
    "; - //echo htmlentities($payload)."
    "; - //echo "#####PAYLOAD 2 ####
    "; - } else { - $this->debug('params must be array or string'); - $this->setError('params must be array or string'); - return false; - } - $usedNamespaces = $this->wsdl->usedNamespaces; - if (isset($opData['input']['encodingStyle'])) { - $encodingStyle = $opData['input']['encodingStyle']; - } else { - $encodingStyle = ''; - } - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if ($errstr = $this->wsdl->getError()) { - $this->debug('got wsdl error: '.$errstr); - $this->setError('wsdl error: '.$errstr); - return false; - } - } elseif($this->endpointType == 'wsdl') { - // operation not in WSDL - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->setError( 'operation '.$operation.' not present.'); - $this->debug("operation '$operation' not present."); - return false; - } else { - // no WSDL - //$this->namespaces['ns1'] = $namespace; - $nsPrefix = 'ns' . rand(1000, 9999); - // serialize - $payload = ''; - if (is_string($params)) { - $this->debug("serializing param string for operation $operation"); - $payload = $params; - } elseif (is_array($params)) { - $this->debug("serializing param array for operation $operation"); - foreach($params as $k => $v){ - $payload .= $this->serialize_val($v,$k,false,false,false,false,$use); - } - } else { - $this->debug('params must be array or string'); - $this->setError('params must be array or string'); - return false; - } - $usedNamespaces = array(); - if ($use == 'encoded') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } else { - $encodingStyle = ''; - } - } - //echo "#####PAYLOAD 1 ####
    "; - //echo htmlentities($payload)."
    "; - //echo "#####PAYLOAD 1 ####
    "; - // wrap RPC calls with method element - if ($style == 'rpc') { - if ($use == 'literal') { - $this->debug("wrapping RPC request with literal method element"); - if ($namespace) { - // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace - $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" . - $payload . - ""; - } else { - $payload = "<$operation>" . $payload . ""; - } - } else { - $this->debug("wrapping RPC request with encoded method element"); - if ($namespace) { - $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" . - $payload . - ""; - } else { - $payload = "<$operation>" . - $payload . - ""; - } - } - } - //echo "#####PAYLOAD####
    "; - //echo htmlentities($payload)."
    "; - //echo "#####PAYLOAD####
    "; - // serialize envelope - $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle); - $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle"); - $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000)); - // send - $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)); - $this->appendDebug('return=' . $this->varDump($return)); - - // 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
    "); - } - return $return; - } elseif ($style == 'document') { - // NOTE: if the response is defined to have multiple parts (i.e. unwrapped), - // we are only going to return the first part here...sorry about that - return $return; - } else { - // array of return values - if(is_array($return)){ - // multiple 'out' parameters, which we return wrapped up - // in the array - if(sizeof($return) > 1){ - return $return; - } - // single 'out' parameter (normally the return value) - $return = array_shift($return); - $this->debug('return shifted value: '); - $this->appendDebug($this->varDump($return)); - return $return; - // nothing returned (ie, echoVoid) - } else { - return ""; - } - } - } - } - - /** - * check WSDL passed as an instance or pulled from an endpoint - * - * @access private - */ - function checkWSDL() { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('checkWSDL'); - // catch errors - if ($errstr = $this->wsdl->getError()) { - $this->debug('got wsdl error: '.$errstr); - $this->setError('wsdl error: '.$errstr); - } elseif ($this->operations = $this->wsdl->getOperations('soap')) { - $this->bindingType = 'soap'; - $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType); - } elseif ($this->operations = $this->wsdl->getOperations('soap12')) { - $this->bindingType = 'soap12'; - $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType); - $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************'); - } else { - $this->debug('getOperations returned false'); - $this->setError('no operations defined in the WSDL document!'); - } - } - - /** - * instantiate wsdl object and parse wsdl file - * - * @access public - */ - function loadWSDL() { - $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile); - $this->wsdl =& new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl); - $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest); - $this->wsdl->fetchWSDL($this->wsdlFile); - $this->checkWSDL(); - } - - /** - * 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 ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) - return false; - } - 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) { - $this->checkCookies(); - // 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, $this->curl_options, $this->use_curl); - 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->authtype != '') { - $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest); - } - 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,$this->cookies); - } 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 - $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies); - } else { - $this->setError('no http/s in endpoint url'); - } - $this->request = $http->outgoing_payload; - $this->response = $http->incoming_payload; - $this->appendDebug($http->getDebug()); - $this->UpdateCookies($http->incoming_cookies); - - // save transport object if using persistent connections - if ($this->persistentConnection) { - $http->clearDebug(); - 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 private - */ - function parseResponse($headers, $data) { - $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:'); - $this->appendDebug($this->varDump($headers)); - if (!strstr($headers['content-type'], 'text/xml')) { - $this->setError('Response not of type text/xml: ' . $headers['content-type']); - 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 for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser'); - $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8); - // add parser debug data to our debug - $this->appendDebug($parser->getDebug()); - // 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 SOAP headers - $this->responseHeader = $parser->get_soapheader(); - // get decoded message - $return = $parser->get_soapbody(); - // add document for doclit support - $this->document = $parser->document; - // destroy the parser object - unset($parser); - // return decode message - return $return; - } - } - - /** - * sets user-specified cURL options - * - * @param mixed $option The cURL option (always integer?) - * @param mixed $value The cURL option value - * @access public - */ - function setCurlOption($option, $value) { - $this->debug("setCurlOption option=$option, value="); - $this->appendDebug($this->varDump($value)); - $this->curl_options[$option] = $value; - } - - /** - * sets the SOAP endpoint, which can override WSDL - * - * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override - * @access public - */ - function setEndpoint($endpoint) { - $this->debug("setEndpoint(\"$endpoint\")"); - $this->forceEndpoint = $endpoint; - } - - /** - * set the SOAP headers - * - * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers - * @access public - */ - function setHeaders($headers){ - $this->debug("setHeaders headers="); - $this->appendDebug($this->varDump($headers)); - $this->requestHeaders = $headers; - } - - /** - * get the SOAP response headers (namespace resolution incomplete) - * - * @return string - * @access public - */ - function getHeaders(){ - return $this->responseHeaders; - } - - /** - * get the SOAP response Header (parsed) - * - * @return mixed - * @access public - */ - function getHeader(){ - return $this->responseHeader; - } - - /** - * 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 - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - * @access public - */ - function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) { - $this->debug("setCredentials username=$username authtype=$authtype certRequest="); - $this->appendDebug($this->varDump($certRequest)); - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->certRequest = $certRequest; - } - - /** - * use HTTP encoding - * - * @param string $enc HTTP encoding - * @access public - */ - function setHTTPEncoding($enc='gzip, deflate'){ - $this->debug("setHTTPEncoding(\"$enc\")"); - $this->http_encoding = $enc; - } - - /** - * Set whether to try to use cURL connections if possible - * - * @param boolean $use Whether to try to use cURL - * @access public - */ - function setUseCURL($use) { - $this->debug("setUseCURL($use)"); - $this->use_curl = $use; - } - - /** - * use HTTP persistent connections if possible - * - * @access public - */ - function useHTTPPersistentConnection(){ - $this->debug("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. - * - * This is no longer used. - * - * @return boolean - * @access public - * @deprecated - */ - 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. - * - * This is no longer used. - * - * @param boolean $rpcParams - * @access public - * @deprecated - */ - function setDefaultRpcParams($rpcParams) { - $this->defaultRpcParams = $rpcParams; - } - - /** - * dynamically creates an instance of a proxy class, - * allowing user to directly call methods from wsdl - * - * @return object soap_proxy object - * @access public - */ - function getProxy() { - $r = rand(); - $evalStr = $this->_getProxyClassCode($r); - //$this->debug("proxy class: $evalStr"); - if ($this->getError()) { - $this->debug("Error from _getProxyClassCode, so return NULL"); - return null; - } - // eval the class - eval($evalStr); - // instantiate proxy object - eval("\$proxy = new nusoap_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->soap_defencoding = $this->soap_defencoding; - $proxy->username = $this->username; - $proxy->password = $this->password; - $proxy->authtype = $this->authtype; - $proxy->certRequest = $this->certRequest; - $proxy->requestHeaders = $this->requestHeaders; - $proxy->endpoint = $this->endpoint; - $proxy->forceEndpoint = $this->forceEndpoint; - $proxy->proxyhost = $this->proxyhost; - $proxy->proxyport = $this->proxyport; - $proxy->proxyusername = $this->proxyusername; - $proxy->proxypassword = $this->proxypassword; - $proxy->http_encoding = $this->http_encoding; - $proxy->timeout = $this->timeout; - $proxy->response_timeout = $this->response_timeout; - $proxy->persistentConnection = &$this->persistentConnection; - $proxy->decode_utf8 = $this->decode_utf8; - $proxy->curl_options = $this->curl_options; - $proxy->bindingType = $this->bindingType; - $proxy->use_curl = $this->use_curl; - return $proxy; - } - - /** - * dynamically creates proxy class code - * - * @return string PHP/NuSOAP code for the proxy class - * @access private - */ - function _getProxyClassCode($r) { - $this->debug("in getProxy endpointType=$this->endpointType"); - $this->appendDebug("wsdl=" . $this->varDump($this->wsdl)); - if ($this->endpointType != 'wsdl') { - $evalStr = 'A proxy can only be created for a WSDL client'; - $this->setError($evalStr); - $evalStr = "echo \"$evalStr\";"; - return $evalStr; - } - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) { - return "echo \"" . $this->getError() . "\";"; - } - } - $evalStr = ''; - foreach ($this->operations as $operation => $opData) { - if ($operation != '') { - // create param string and param comment string - if (sizeof($opData['input']['parts']) > 0) { - $paramStr = ''; - $paramArrayStr = ''; - $paramCommentStr = ''; - foreach ($opData['input']['parts'] as $name => $type) { - $paramStr .= "\$$name, "; - $paramArrayStr .= "'$name' => \$$name, "; - $paramCommentStr .= "$type \$$name, "; - } - $paramStr = substr($paramStr, 0, strlen($paramStr)-2); - $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2); - $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2); - } else { - $paramStr = ''; - $paramArrayStr = ''; - $paramCommentStr = 'void'; - } - $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace']; - $evalStr .= "// $paramCommentStr - function " . str_replace('.', '__', $operation) . "($paramStr) { - \$params = array($paramArrayStr); - return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."'); - } - "; - unset($paramStr); - unset($paramCommentStr); - } - } - $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client { - '.$evalStr.' -}'; - return $evalStr; - } - - /** - * dynamically creates proxy class code - * - * @return string PHP/NuSOAP code for the proxy class - * @access public - */ - function getProxyClassCode() { - $r = rand(); - return $this->_getProxyClassCode($r); - } - - /** - * 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 private - */ - 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 private - */ - 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 private - */ - 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; - } - - /** - * adds a new Cookie into $this->cookies array - * - * @param string $name Cookie Name - * @param string $value Cookie Value - * @return boolean if cookie-set was successful returns true, else false - * @access public - */ - function setCookie($name, $value) { - if (strlen($name) == 0) { - return false; - } - $this->cookies[] = array('name' => $name, 'value' => $value); - return true; - } - - /** - * gets all Cookies - * - * @return array with all internal cookies - * @access public - */ - function getCookies() { - return $this->cookies; - } - - /** - * checks all Cookies and delete those which are expired - * - * @return boolean always return true - * @access private - */ - function checkCookies() { - if (sizeof($this->cookies) == 0) { - return true; - } - $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies'); - $curr_cookies = $this->cookies; - $this->cookies = array(); - foreach ($curr_cookies as $cookie) { - if (! is_array($cookie)) { - $this->debug('Remove cookie that is not an array'); - continue; - } - if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) { - if (strtotime($cookie['expires']) > time()) { - $this->cookies[] = $cookie; - } else { - $this->debug('Remove expired cookie ' . $cookie['name']); - } - } else { - $this->cookies[] = $cookie; - } - } - $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array'); - return true; - } - - /** - * updates the current cookies with a new set - * - * @param array $cookies new cookies with which to update current ones - * @return boolean always return true - * @access private - */ - function UpdateCookies($cookies) { - if (sizeof($this->cookies) == 0) { - // no existing cookies: take whatever is new - if (sizeof($cookies) > 0) { - $this->debug('Setting new cookie(s)'); - $this->cookies = $cookies; - } - return true; - } - if (sizeof($cookies) == 0) { - // no new cookies: keep what we've got - return true; - } - // merge - foreach ($cookies as $newCookie) { - if (!is_array($newCookie)) { - continue; - } - if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) { - continue; - } - $newName = $newCookie['name']; - - $found = false; - for ($i = 0; $i < count($this->cookies); $i++) { - $cookie = $this->cookies[$i]; - if (!is_array($cookie)) { - continue; - } - if (!isset($cookie['name'])) { - continue; - } - if ($newName != $cookie['name']) { - continue; - } - $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN'; - $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN'; - if ($newDomain != $domain) { - continue; - } - $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH'; - $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH'; - if ($newPath != $path) { - continue; - } - $this->cookies[$i] = $newCookie; - $found = true; - $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']); - break; - } - if (! $found) { - $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']); - $this->cookies[] = $newCookie; - } - } - return true; - } -} - -if (!extension_loaded('soap')) { - /** - * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded. - */ - class soapclient extends nusoap_client { - } -} -?> diff --git a/mods/openmeetings/lib/openmeetings.class.php b/mods/openmeetings/lib/openmeetings.class.php deleted file mode 100644 index 9419f5422..000000000 --- a/mods/openmeetings/lib/openmeetings.class.php +++ /dev/null @@ -1,243 +0,0 @@ -_course_id = abs($course_id); - $this->_member_id = abs($member_id); - $this->_group_id = abs($group_id); - - } - - /** - * Login to openmeetings - * Login process is, login, saveuserinstance - */ - function om_login() { - global $_config; - $om = new SOAP_openmeetings($_config['openmeetings_location'].'/services/UserService?wsdl'); - $param = array ( 'username' => $_config['openmeetings_username'], - 'userpass' => $_config['openmeetings_userpass']); - - /** - * Login to the openmeetings - * ref: http://code.google.com/p/openmeetings/wiki/DirectLoginSoapGeneralFlow - */ - $result = $om->login($param); - if ($result < 0){ - debug($om->getError($result), 'error'); - return; - } - - //If no error, then get the generated OM session id - $this->_sid = $om->getSid(); - - //Retrieve members information - $sql = 'SELECT login, first_name, last_name, email FROM '.TABLE_PREFIX.'members WHERE member_id='.$this->_member_id; - $result = mysql_query($sql); - $row = mysql_fetch_assoc($result); - - // Save user instance - $params = array( - "username" => $row['login'], - "firstname" => $row['first_name'], - "lastname" => $row['last_name'], - "profilePictureUrl" => '', - "email" => $row['email'] - ); - $om->saveUserInstance($params); - } - - - - /** - * Add a room to the db iff it has not been created. Each course should only have one room to it. - * @param int sid is the auth session id that was logged in into openmeetings. - * @param array the specification for openmeetings - * @return room # of the created room, or the room # of the existed room - */ - function om_addRoom($room_name, $om_param=array()){ - global $_config; - - if ($this->_course_id < 0){ - return false; - } - - //Check if the room has already been created for this - if (($room_id = $this->om_getRoom()) !=false){ - //instead of returning room id, we might have to delete it and carry on. - return $room_id; - } - - //Add this room - $om = new SOAP_openmeetings($_config['openmeetings_location'].'/services/RoomService?wsdl'); - $param = array ( - 'SID' => $this->_sid, - 'name' => $room_name, - 'roomtypes_id' => $om_param['openmeetings_roomtype'], - 'numberOfPartizipants' => $om_param['openmeetings_num_of_participants'], - 'ispublic' => $om_param['openmeetings_ispublic'], - 'videoPodWidth' => $om_param['openmeetings_vid_w'], - 'videoPodHeight' => $om_param['openmeetings_vid_h'], - 'showWhiteBoard' => $om_param['openmeetings_show_wb'], - 'whiteBoardPanelWidth' => $om_param['openmeetings_wb_w'], - 'whiteBoardPanelHeight' => $om_param['openmeetings_wb_h'], - 'showFilesPanel' => $om_param['openmeetings_show_fp'], - 'filesPanelHeight' => $om_param['openmeetings_fp_h'], - 'filesPanelWidth' => $om_param['openmeetings_fp_w'] - ); - $result = $om->addRoom($param); - //TODO: Check for error, and handles success/failure - if ($result){ - //TODO: On success, add to DB entry. - $sql = 'INSERT INTO '.TABLE_PREFIX.'openmeetings_rooms SET rooms_id='.$result['return'].', course_id='.$this->_course_id - . ', owner_id=' . $this->_member_id; - $rs = mysql_query($sql); - if (!$rs){ - return false; - } - $om_id = mysql_insert_id(); - $sql = 'INSERT INTO '.TABLE_PREFIX."openmeetings_groups SET om_id=$om_id, group_id=$this->_group_id"; - $rs = mysql_query($sql); - - if ($rs){ - return $result['return']; - } - } - return false; - } - - - /** - * update room - */ - function om_updateRoom($room_id, $om_param=array()){ - global $_config; - - //update this room - $om = new SOAP_openmeetings($_config['openmeetings_location'].'/services/RoomService?wsdl'); - $param = array ( - 'SID' => $this->_sid, - 'rooms_id' => $room_id, - 'name' => $om_param['openmeetings_room_name'], - 'roomtypes_id' => $om_param['openmeetings_roomtype'], - 'numberOfPartizipants' => $om_param['openmeetings_num_of_participants'], - 'ispublic' => $om_param['openmeetings_ispublic'], - 'videoPodWidth' => $om_param['openmeetings_vid_w'], - 'videoPodHeight' => $om_param['openmeetings_vid_h'], - 'showWhiteBoard' => $om_param['openmeetings_show_wb'], - 'whiteBoardPanelWidth' => $om_param['openmeetings_wb_w'], - 'whiteBoardPanelHeight' => $om_param['openmeetings_wb_h'], - 'showFilesPanel' => $om_param['openmeetings_show_fp'], - 'filesPanelHeight' => $om_param['openmeetings_fp_h'], - 'filesPanelWidth' => $om_param['openmeetings_fp_w'] - ); - $result = $om->updateRoom($param); - return $result; - } - - /** - * Retrieve Session id - */ - function getSid(){ - return $this->_sid; - } - - /** - * Checks if there is a room for the given course id. - * - * @param course id - * @return the room id if there is a room already assigned to this course; false otherwise - */ - function om_getRoom(){ -// $sql = 'SELECT rooms_id FROM '.TABLE_PREFIX.'openmeetings_rooms INNER JOIN '.TABLE_PREFIX."openmeetings_groups WHERE -// course_id = $this->_course_id AND owner_id = $this->_member_id AND group_id = $this->_group_id"; - $sql = 'SELECT rooms_id FROM '.TABLE_PREFIX.'openmeetings_rooms r NATURAL JOIN '.TABLE_PREFIX."openmeetings_groups g WHERE - course_id = $this->_course_id AND group_id = $this->_group_id"; - $result = mysql_query($sql); - if (mysql_numrows($result) > 0){ - $row = mysql_fetch_assoc($result); - //instead of returning room id, we might have to delete it and carry on. - return $row['rooms_id']; - } - return false; - } - - - /** - * Get room obj form the given room id - */ - function om_getRoomById($room_id){ - global $_config; - if ($room_id == ''){ - return false; - } - $om = new SOAP_openmeetings($_config['openmeetings_location'].'/services/RoomService?wsdl'); - $param = array ( - 'SID' => $this->_sid, - 'rooms_id' => $room_id - ); - $result = $om->getRoomById($param); - return $result; - } - - /** - * Set the group id - * @param int group id. - */ - function setGid($gid){ - $this->_group_id = $gid; - } - - /** - * Delete a room - */ - function om_deleteRoom($room_id){ - global $_config; - $om = new SOAP_openmeetings($_config['openmeetings_location'].'/services/RoomService?wsdl'); - $param = array ( - 'SID' => $this->_sid, - 'rooms_id' => $room_id - ); - - $result = $om->deleteRoom($param); - $sql = 'DELETE r, g FROM (SELECT om_id FROM '.TABLE_PREFIX."openmeetings_rooms WHERE rooms_id=$room_id) AS t, ".TABLE_PREFIX - .'openmeetings_rooms r NATURAL JOIN '.TABLE_PREFIX.'openmeetings_groups g WHERE r.om_id =t.om_id'; - mysql_query($sql); - } - - - /** - * Return true if this user created the given room. - * @param int room id - * @return true if it is, false otherwise. - */ - function isMine($room_id){ - $sql = 'SELECT * FROM '.TABLE_PREFIX."openmeetings_rooms WHERE rooms_id=$room_id AND owner_id=$this->_member_id"; - $result = mysql_query($sql); - if (mysql_numrows($result) > 0){ - return true; - } - return false; - } -} -?> \ No newline at end of file diff --git a/mods/openmeetings/lib/openmeetings.inc.php b/mods/openmeetings/lib/openmeetings.inc.php deleted file mode 100644 index cfe55b6dc..000000000 --- a/mods/openmeetings/lib/openmeetings.inc.php +++ /dev/null @@ -1,61 +0,0 @@ - 1, //conference - 'openmeetings_num_of_participants' => 5, - 'openmeetings_ispublic' => 1, //true - 'openmeetings_vid_w' => 270, - 'openmeetings_vid_h' => 270, - 'openmeetings_show_wb' => 1, //true - 'openmeetings_wb_w' => 600, - 'openmeetings_wb_h' => 660, - 'openmeetings_show_fp' => 1, //true - 'openmeetings_fp_w' => 270, - 'openmeetings_fp_h' => 270 - ); - - //replace each key if empty - foreach ($_om_config as $key=>$value){ - if (empty($post[$key])){ - $post[$key] = $value; - } - } - - return $post; -} - - -/** - * Check if openmeeting is being setup correctly. - * @param int the course id - */ -function checkAccess($course_id){ - global $_config, $msg; - if (!isset($_config['openmeetings_username']) || !isset($_config['openmeetings_userpass'])){ - include(AT_INCLUDE_PATH.'header.inc.php'); - $msg->addError('OPENMEETINGS_NOT_SETUP'); - include(AT_INCLUDE_PATH.'footer.inc.php'); - exit; - } -} -?> \ No newline at end of file diff --git a/mods/openmeetings/module.css b/mods/openmeetings/module.css deleted file mode 100644 index caf2f0249..000000000 --- a/mods/openmeetings/module.css +++ /dev/null @@ -1,17 +0,0 @@ -div.openmeetings { - background-color: #F8F8F8; - border: 1px solid #666; - padding: 1em; - margin: 1em; -} - -div.openmeetings ul{ - list-style: none; - font-family: Verdana, Helevetica, Arial, sans-serif; -} - -div.openmeetings h5{ - padding-top: 0; - padding-bottom: 0.5em; -} - diff --git a/mods/openmeetings/module.php b/mods/openmeetings/module.php deleted file mode 100644 index b0824227a..000000000 --- a/mods/openmeetings/module.php +++ /dev/null @@ -1,59 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_OPENMEETINGS', $this->getAdminPrivilege()); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_group_tool = $_student_tool = 'mods/openmeetings/index.php'; - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_OPENMEETINGS, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/openmeetings/openmeetings.php'); - $this->_pages['mods/openmeetings/openmeetings.php']['title_var'] = 'openmeetings'; - $this->_pages['mods/openmeetings/openmeetings.php']['parent'] = AT_NAV_ADMIN; -} - -/******* - * instructor Manage section: - */ -$this->_pages['mods/openmeetings/openmeetings_instructor.php']['title_var'] = 'openmeetings_course_meetings'; -$this->_pages['mods/openmeetings/openmeetings_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages['mods/openmeetings/index.php']['title_var'] = 'openmeetings'; -$this->_pages['mods/openmeetings/index.php']['img'] = 'mods/openmeetings/openmeetings_logo.png'; - -$this->_pages['mods/openmeetings/view_meetings.php']['title_var'] = 'openmeetings_view_meetings'; -$this->_pages['mods/openmeetings/view_meetings.php']['parent'] = 'mods/openmeetings/index.php'; -$this->_pages['mods/openmeetings/add_group_meetings.php']['title_var'] = 'openmeetings_grp_meetings'; -$this->_pages['mods/openmeetings/add_group_meetings.php']['parent'] = 'mods/openmeetings/index.php'; -$this->_pages['mods/openmeetings/openmeetings_delete.php']['title_var'] = 'openmeetings_delete'; -$this->_pages['mods/openmeetings/openmeetings_delete.php']['parent'] = 'mods/openmeetings/index.php'; -$this->_pages['mods/openmeetings/openmeetings_group.php']['title_var'] = 'openmeetings_grp_meetings'; -$this->_pages['mods/openmeetings/openmeetings_group.php']['parent'] = 'mods/openmeetings/index.php'; - -/******* - * Group functions - */ -function openmeetings_get_group_url($group_id) { - return 'mods/openmeetings/openmeetings_group.php?gid='.$group_id; -} -?> \ No newline at end of file diff --git a/mods/openmeetings/module.sql b/mods/openmeetings/module.sql deleted file mode 100644 index 4fea709ce..000000000 --- a/mods/openmeetings/module.sql +++ /dev/null @@ -1,66 +0,0 @@ -# sql file for Openmeeting module - -# Table for openmeetings -CREATE TABLE `openmeetings_rooms` ( - `om_id` mediumint(8) UNSIGNED NOT NULL AUTO_INCREMENT, - `course_id` mediumint(8) unsigned NOT NULL, - `owner_id` mediumint(8) unsigned NOT NULL, - `rooms_id` bigint( 20 ) NOT NULL , - PRIMARY KEY ( `om_id` ) -); - -CREATE TABLE `openmeetings_groups` ( - `om_id` mediumint(8) unsigned NOT NULL, - `group_id` mediumint(8) unsigned NOT NULL, - PRIMARY KEY ( `om_id`, `group_id` ) -); - -INSERT INTO `language_text` VALUES ('en', '_module', 'openmeetings_missing_url', 'You must supply the URL to your Openmeetings installation in the field below.', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings','Openmeetings',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_open','Open Openmeetings Admin',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_location','The location of your Openmeetings installation. This should be the base URL of your Openmeetings installation (e.g. http://www.myserver.com:5080/openmeetings).',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_own_window','Open Openmeetings in a New Window:',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_course_meetings','Course Openmeetings',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_view_meetings','View Openmeetings',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_grp_meetings','Group Openmeetings',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_existing_room','You already have started a room, would you like to edit your room or to start a new one?',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_deleting_warning','(Note, starting a new room will close your current room. Once the room is closed, all chat logs and associated room materials will be deleted.)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_no_course_meetings','There is no course meeting at the moment. Instructor can add a course meeting.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_no_group_meetings','There is no group meeting at the moment. You have to be assigned to a group in order to start a group meeting.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_course_conference','Course conference:',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_group_conference','Group conference(s):',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_num_of_participants','Number of participants',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_ispublic','Public meeting?',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_vid_w','Video Width (in pixel)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_vid_h','Video Height (in pixel)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_show_wb','Display whiteboard?',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_wb_w','Whiteboard Width (in pixel)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_wb_h','Whiteboard Height (in pixel)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_show_fp','Display file panel?',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_fp_w','File Panel Width (in pixel)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_fp_h','File Panel Height (in pixel)',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_username','Openmeeting Username (Must have admin-rights)', NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_userpass','Openmeeting Password',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_grp_meetings','Openmeeting Group Meetings',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_delete','Delete Meeting Room',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_confirm_delete','Are you sure you want to delete this conference room? All the associated chats and files will be deleted.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_roomtype','Room Mode',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_conference','Conference Mode',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_audience','Audience Mode',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_create_room_instr','Adjust the following settings, then click "Create" to start the conference/audience room. For more information on the settings, please see the Openmeetings documentation.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_edit_room','Edit room',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_create_room','Create new room',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','openmeetings_delete_room','Remove room',NOW(),''); - -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_OPENMEETINGS_URL_ADD_SAVED','Openmeetings configuration options were successfully saved.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_OPENMEETINGS_CANCELLED','Successfully cancelled without saving any changes.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_OPENMEETINGS_DELETE_SUCEEDED','The room has been successfully deleted.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_OPENMEETINGS_ADDED_SUCEEDED','The room has been added successfully.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_OPENMEETINGS_UPDATE_SUCEEDED','The room has been updated successfully.',NOW(),''); - -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_OPENMEETINGS_NOT_SETUP','Openmeetings has not been setup yet, please contact your administrator.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_OPENMEETINGS_ADD_FAILED','The room cannot be created. You must be belong to this group or you must have the permission to create a room.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_OPENMEETINGS_DELETE_FAILED','An error has occured while deleting the room, please contact the administrator.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_OPENMEETINGS_URL_ADD_EMPTY','You must enter a URL to the location of your Openmeetings installation.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_OPENMEETINGS_USERNAME_ADD_EMPTY','You must enter an username to the account of your Openmeetings installation.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_OPENMEETINGS_USERPASS_ADD_EMPTY','You must enter a password to the account of your Openmeetings installation.',NOW(),''); diff --git a/mods/openmeetings/module.xml b/mods/openmeetings/module.xml deleted file mode 100644 index 2e7d1e33b..000000000 --- a/mods/openmeetings/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Openmeetings - Openmeetings is a Multi-Language Cross-Platform Customizable Video-Conferencing and Collaboration Flash based web application. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - GNU - - 0.4 - 2010-10-25 - stable - Requires Openmeetings server(Red5) be installed on the user's system. Details can be found at http://code.google.com/p/openmeetings/ - - \ No newline at end of file diff --git a/mods/openmeetings/module_install.php b/mods/openmeetings/module_install.php deleted file mode 100644 index 3aef4b0bc..000000000 --- a/mods/openmeetings/module_install.php +++ /dev/null @@ -1,46 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/openmeetings/module_uninstall.php b/mods/openmeetings/module_uninstall.php deleted file mode 100644 index 60ce25da8..000000000 --- a/mods/openmeetings/module_uninstall.php +++ /dev/null @@ -1,26 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/openmeetings/openmeetings.php b/mods/openmeetings/openmeetings.php deleted file mode 100644 index 37e3fd5c0..000000000 --- a/mods/openmeetings/openmeetings.php +++ /dev/null @@ -1,82 +0,0 @@ -addError('OPENMEETINGS_URL_ADD_EMPTY'); - } - if (!$_POST['om_username']){ - $msg->addError('OPENMEETINGS_USERNAME_ADD_EMPTY'); - } - if (!$_POST['om_userpass']){ - $msg->addError('OPENMEETINGS_USERPASS_ADD_EMPTY'); - } - - if (!$msg->containsErrors()) { - $_POST['om_uri'] = $addslashes($_POST['om_uri']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('openmeetings_location', '$_POST[om_uri]'), ('openmeetings_username', '$_POST[om_username]'), ('openmeetings_userpass', '$_POST[om_userpass]')"; - mysql_query($sql, $db); - $msg->addFeedback('OPENMEETINGS_URL_ADD_SAVED'); - - header('Location: '.$_SERVER['PHP_SELF']); - exit; - } -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> -
    -
    -
    -

    - -
    -
    -

    - - -

    - -
    -
    - -
    -
    -
    -
    - - - - - - -
    - \ No newline at end of file diff --git a/mods/openmeetings/openmeetings_delete.php b/mods/openmeetings/openmeetings_delete.php deleted file mode 100644 index cecd9c270..000000000 --- a/mods/openmeetings/openmeetings_delete.php +++ /dev/null @@ -1,65 +0,0 @@ -om_login(); - -//Handles form actions -if (isset($_POST['submit']) && $_REQUEST['room_id']){ - //have to makesure the user really do have permission over the paramater room id - if ($om_obj->isMine($_REQUEST['room_id']) || authenticate(AT_PRIV_OPENMEETINGS, true)){ - $om_obj->om_deleteRoom($_REQUEST['room_id']); - $msg->addFeedback('OPENMEETINGS_DELETE_SUCEEDED'); - header('Location: index.php'); - exit; - } else { - $msg->addError('OPENMEETINGS_DELETE_FAILED'); - } -} elseif (isset($_POST['cancel'])) { - $msg->addFeedback('OPENMEETINGS_CANCELLED'); - header('Location: index.php'); - exit; -} - -//Header begins here -require (AT_INCLUDE_PATH.'header.inc.php'); -?> - -
    -
    -
    -

    -
    -
    - - - -
    -
    -
    - - diff --git a/mods/openmeetings/openmeetings_group.php b/mods/openmeetings/openmeetings_group.php deleted file mode 100644 index 30035c20a..000000000 --- a/mods/openmeetings/openmeetings_group.php +++ /dev/null @@ -1,60 +0,0 @@ -om_login(); - -//Group meetings -$sql = "SELECT title FROM ".TABLE_PREFIX."groups WHERE group_id=$_GET[gid] ORDER BY title"; -//TODO: Check group permission from group table. -$result = mysql_query($sql, $db); -$row = mysql_fetch_assoc($result); - -if (mysql_numrows($result) == 0){ - echo '
    '._AT('openmeetings_no_group_meetings').'
    '; - require (AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -//Check in the db and see if this group has a meeting alrdy, create on if not. -$om_obj->setGid($_GET['gid']); -if ($om_obj->om_getRoom()){ - //Log into the room - $room_id = $om_obj->om_addRoom($room_name); - header('Location: '.AT_BASE_HREF.'mods/openmeetings/view_meetings.php?room_id='.$room_id.SEP.'sid='.$om_obj->getSid()); - exit; -} else { - //Header begins here - require (AT_INCLUDE_PATH.'header.inc.php'); - echo '
    '.$row['title'].' Start a conference
    '; - require (AT_INCLUDE_PATH.'footer.inc.php'); -} -?> \ No newline at end of file diff --git a/mods/openmeetings/openmeetings_instructor.php b/mods/openmeetings/openmeetings_instructor.php deleted file mode 100644 index 1eedeab74..000000000 --- a/mods/openmeetings/openmeetings_instructor.php +++ /dev/null @@ -1,122 +0,0 @@ -om_login(); - -//Handle form action -if (isset($_POST['create_room']) && isset($_POST['room_id'])) { - //delete course room - $_POST['room_id'] = intval($_POST['room_id']); - $om_obj->om_deleteRoom($_POST['room_id']); - $msg->addFeedback('OPENMEETINGS_DELETE_SUCEEDED'); -} elseif (isset($_POST['delete_room']) && isset($_POST['room_id'])){ - $_POST['room_id'] = intval($_POST['room_id']); - $om_obj->om_deleteRoom($_POST['room_id']); - $msg->addFeedback('OPENMEETINGS_DELETE_SUCEEDED'); -} elseif (isset($_POST['create_room']) || (isset($_POST['update_room']) && isset($_POST['room_id']))){ - //mysql escape - $_POST['openmeetings_roomtype'] = intval($_POST['openmeetings_roomtype']); - $_POST['openmeetings_num_of_participants'] = intval($_POST['openmeetings_num_of_participants']); - (intval($_POST['openmeetings_ispublic']) == 1)?$_POST['openmeetings_ispublic']='true':$_POST['openmeetings_ispublic']='false'; - $_POST['openmeetings_vid_w'] = intval($_POST['openmeetings_vid_w']); - $_POST['openmeetings_vid_h'] = intval($_POST['openmeetings_vid_h']); - (intval($_POST['openmeetings_show_wb']) == 1)?$_POST['openmeetings_show_wb']='true':$_POST['openmeetings_show_wb']='false'; - $_POST['openmeetings_wb_w'] = intval($_POST['openmeetings_wb_w']); - $_POST['openmeetings_wb_h'] = intval($_POST['openmeetings_wb_h']); - (intval($_POST['openmeetings_show_fp']) == 1)?$_POST['openmeetings_show_fp']='true':$_POST['openmeetings_show_fp']='false'; - $_POST['openmeetings_fp_w'] = intval($_POST['openmeetings_fp_w']); - $_POST['openmeetings_fp_h'] = intval($_POST['openmeetings_fp_h']); - - //create a new room - if (isset($_POST['create_room'])){ - //Get the room id - //TODO: Course title added/removed after creation. Affects the algo here. - if (isset($_SESSION['course_title']) && $_SESSION['course_title']!=''){ - $room_name = $_SESSION['course_title']; - } else { - $room_name = 'course_'.$course_id; - } - - //add the room with the given parameters. - $om_obj->om_addRoom($room_name, $_POST); - $msg->addFeedback('OPENMEETINGS_ADDED_SUCEEDED'); - header('Location: index.php'); - exit; - } elseif (isset($_POST['update_room'])){ - //update a room - $om_obj->om_updateRoom(intval($_POST['room_id']), $_POST); - $msg->addFeedback('OPENMEETINGS_UPDATE_SUCEEDED'); - header('Location: index.php'); - exit; - } -} elseif (isset($_POST['edit_room']) && isset($_POST['room_id'])){ - //Log into the room - $room_id = $om_obj->om_getRoom(); - - //Get the room obj - $room_obj = $om_obj->om_getRoomById($room_id); - - //Assign existing variables to the room - $_POST['openmeetings_roomtype'] = intval($room_obj['return']['roomtype']['roomtypes_id']); - $_POST['openmeetings_room_name'] = $addslashes($room_obj['return']['name']); - $_POST['openmeetings_num_of_participants'] = $addslashes($room_obj['return']['numberOfPartizipants']); - (($room_obj['return']['ispublic'])=='true')?$_POST['openmeetings_ispublic']=1:$_POST['openmeetings_ispublic']=0; - $_POST['openmeetings_vid_w'] = intval($room_obj['return']['videoPodWidth']); - $_POST['openmeetings_vid_h'] = intval($room_obj['return']['videoPodHeight']); - (($room_obj['return']['showWhiteBoard'])=='true')?$_POST['openmeetings_show_wb']=1:$_POST['openmeetings_show_wb']=0; - $_POST['openmeetings_wb_w'] = intval($room_obj['return']['whiteBoardPanelWidth']); - $_POST['openmeetings_wb_h'] = intval($room_obj['return']['whiteBoardPanelHeight']); - (($room_obj['return']['showFilesPanel'])=='true')?$_POST['openmeetings_show_fp']=1:$_POST['openmeetings_show_fp']=0; - $_POST['openmeetings_fp_w'] = intval($room_obj['return']['filesPanelWidth']); - $_POST['openmeetings_fp_h'] = intval($room_obj['return']['filesPanelHeight']); - include (AT_INCLUDE_PATH.'header.inc.php'); - include ('html/update_room.inc.php'); - include (AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} elseif (isset($_POST['cancel'])){ - $msg->addFeedback('OPENMEETINGS_CANCELLED'); - header('Location: index.php'); - exit; -} elseif (isset($_GET['action']) && $_GET['action'] == 'view'){ - $room_id = intval($_GET['room_id']); - $sid = $addslashes($_GET['sid']); - header('Location: view_meetings.php?room_id='.$room_id.SEP.'sid='.$sid); - exit; -} - -//Log into the room -$room_id = $om_obj->om_getRoom(); - -require (AT_INCLUDE_PATH.'header.inc.php'); -if ($room_id == false) { - include ('html/create_room.inc.php'); -} else { - //include page - include ('html/edit_room.inc.php'); -} -require (AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/openmeetings/openmeetings_logo.png b/mods/openmeetings/openmeetings_logo.png deleted file mode 100644 index 554d000e7d37ced8cb493dea251792f5f630fe28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15745 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
    - - - - -
    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 diff --git a/mods/openmeetings/readme b/mods/openmeetings/readme deleted file mode 100644 index 3ee1886fa..000000000 --- a/mods/openmeetings/readme +++ /dev/null @@ -1,61 +0,0 @@ -#Openmeetings module for ATutor readme - -Be sure Openmeetings is installed and functioning properly before attempting to install this module. - -Requires Openmeetings to be installed on this server, installation guide can be found at: -http://code.google.com/p/openmeetings/ - -Installation -1. Unzip the module into the ATutor mods/ directory. -2. Login to ATutor as the administrator and run the ATutor administrator's Install Module tool. Select Openmeetings to install. -3. Once installed, on the administrator modules screen, enabled to module. -4. Open the administrator's Openmeetings screen and enter the URL, username and password to the Openmeetings installion you will be using. The user account must have Admin-rights. - -This module has been tested on the following specifications: -Openmeetings 0.7 (RC1) -Red5 0.7+ [http://osflash.org/red5] - - -License: -GNU Lesser General Public License - - - -Changelog: -============ -Feb 5, 09 ------------- -- Added the ability to delete conference rooms. -- Now compatible with Openmeetings 0.7RC1 (Red5 7.0+) - -June 26, 08 ------------- -- Added the ability to create diff type of rooms: conference/audience - -June 25, 08 ------------- -- Admin can now delete or create group meetings - -June 19, 08 ------------- -- Allow users to retrieve the recordings. [June 25, 08 - milestone for version 5.3] -- Make the index page a bit more pretty. - -June 11, 08 ------------- -- Allow each group to have their own meeting, anyone in the group can start off the meeting, and when all exit, room should be deleted. -- Course meeting should be triggered by instructor only. Otherwise page should display the meeting time (There is no meeting at the moment. THe next available meeting is at xxxx) -- Instructor should probably be capable to adjust their own meeting size in their own config. -- Research on how recorded video works, see if we can remove meetings as well. -- admin/openmeetings, check if there is a slash at the end. - -June 05, 08 ------------- -- allow admin to change the room size. -- clean room after course is deleted. -- though these would be way easier to do it in the openmeeting's end -- upgrade nusoup script -- update readme, and write up something that teaches the user to setup red5 -- allow 2 modes - - diff --git a/mods/openmeetings/view_meetings.php b/mods/openmeetings/view_meetings.php deleted file mode 100644 index f1b20a33c..000000000 --- a/mods/openmeetings/view_meetings.php +++ /dev/null @@ -1,60 +0,0 @@ -printInfos('NOT_ENROLLED'); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -if (!isset($_config['openmeetings_username']) || !isset($_config['openmeetings_userpass'])){ - require(AT_INCLUDE_PATH.'header.inc.php'); - echo 'Contact admin plz'; - //Please contact your administrator, om needs to be setup. - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - - -//Header begins here -require (AT_INCLUDE_PATH.'header.inc.php'); - -$_GET['room_id'] = abs($_GET['room_id']); -$_GET['sid'] = addslashes($_GET['sid']); -?> - -
    - - - - -
    - \ No newline at end of file diff --git a/mods/patcher/README b/mods/patcher/README deleted file mode 100644 index 85ca7da59..000000000 --- a/mods/patcher/README +++ /dev/null @@ -1,52 +0,0 @@ -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/patcher/classes/Patch.class.php b/mods/patcher/classes/Patch.class.php deleted file mode 100644 index 4f1a56ed9..000000000 --- a/mods/patcher/classes/Patch.class.php +++ /dev/null @@ -1,732 +0,0 @@ -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->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, return true - if (!is_array($this->patch_array[files])) 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"=>preg_quote($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"=>preg_quote($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"=>preg_quote($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] .= ''. $folder . "
    "; - } - - foreach($this->need_access_to_files as $file) - { - $this->errors[0] .= ''. $file . "
    "; - } - - $notes = '
    -
    - - - - -
    -
    '; - - 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'] . '
    '; - $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']) . '
    '; - $overwrite_modified_files = true; - } - if ($patch_file['action']=='alter') - { - $alter_files .= realpath($patch_file['location'] . $patch_file['name']) . '
    '; - $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 = ' -
    -
    - - - - -
    -
    '; - - 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('../..', '', $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 - * 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"]."', - '".preg_quote($patch_summary_array["patch_folder"])."', - '".preg_quote($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']."', - '".preg_quote($patch_files_array['name'])."', - '".preg_quote($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']."', - '".preg_replace('/\'/', '\\\'', $patch_files_actions_array['code_from'])."', - '".preg_replace('/\'/', '\\\'', $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/patcher/classes/PatchCreator.class.php b/mods/patcher/classes/PatchCreator.class.php deleted file mode 100644 index 8eaa2d963..000000000 --- a/mods/patcher/classes/PatchCreator.class.php +++ /dev/null @@ -1,386 +0,0 @@ - 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 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 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 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 (isset($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
    - * @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) .'/', "
    ", $str); - else - return $str; - } - -} - -?> \ No newline at end of file diff --git a/mods/patcher/classes/PatchListParser.class.php b/mods/patcher/classes/PatchListParser.class.php deleted file mode 100644 index 2a1c8035d..000000000 --- a/mods/patcher/classes/PatchListParser.class.php +++ /dev/null @@ -1,128 +0,0 @@ -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/patcher/classes/PatchParser.class.php b/mods/patcher/classes/PatchParser.class.php deleted file mode 100644 index a9b646c08..000000000 --- a/mods/patcher/classes/PatchParser.class.php +++ /dev/null @@ -1,139 +0,0 @@ -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/patcher/include/common.inc.php b/mods/patcher/include/common.inc.php deleted file mode 100644 index 4095f482a..000000000 --- a/mods/patcher/include/common.inc.php +++ /dev/null @@ -1,132 +0,0 @@ - -
    - - - - - - - -
    -

    Warning

    - '; - foreach ($errors as $p) { - echo '
  • '.$p.'
  • '; - } - echo ''; - ?> -
    - -
    -
    - -
    - - - - - - - -

    The patch has been installed successfully!

    - '; - foreach ($feedback as $p) { - echo '
  • '.$p.'
  • '; - } - echo ''; - ?>
    - -
    -
    - $value) - { - $sql_middle .= $key . "='" . $value . "', "; - } - - $sql = substr($sql_prefix . $sql_middle, 0, -2) . " where patches_id = " . $patch_id; - - $result = mysql_query($sql, $db) or die(mysql_error()); - - return true; -} - -/** -* This function deletes $dir recrusively without deleting $dir itself. -* @access public -* @param string $charsets_array The name of the directory where all files and folders under needs to be deleted -* @author Cindy Qi Li -*/ -function clear_dir($dir) { - include_once(AT_INCLUDE_PATH . '/lib/filemanager.inc.php'); - - 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 lib function to clear subdirectories recrusively */ - if(!clr_dir($dir.'/'.$readdir)) { - return false; - } - } - } - } /* end while */ - - @closedir($opendir); - - return true; -} - -/** - * Check if the patch has been installed - */ -function is_patch_installed($patch_id) -{ - global $db; - - // Only displays the patches that are not installed - $sql = "select count(*) num_of_installed from ".TABLE_PREFIX."patches " . - "where atutor_patch_id = '" . $patch_id ."'". - " and status like '%Installed'"; - - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - if ($row["num_of_installed"] > 0) return true; - else return false; -} - -?> diff --git a/mods/patcher/include/json.inc.php b/mods/patcher/include/json.inc.php deleted file mode 100644 index 1fa31d746..000000000 --- a/mods/patcher/include/json.inc.php +++ /dev/null @@ -1,71 +0,0 @@ - $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/patcher/include/patch_xml_template.inc.php b/mods/patcher/include/patch_xml_template.inc.php deleted file mode 100644 index c6c477736..000000000 --- a/mods/patcher/include/patch_xml_template.inc.php +++ /dev/null @@ -1,44 +0,0 @@ - - - {ATUTOR_PATCH_ID} - {APPLIED_VERSION} - {DESCRIPTION} - -{DEPENDENT_PATCHES} - - - -{SQL} - - - -{FILES} - -'; - -$dependent_patch_xml = -' {DEPENDENT_PATCH} -'; - -$patch_file_xml = -' - {ACTION} - {NAME} - {LOCATION} -{ACTION_DETAILS} - - -'; - -$patch_action_detail_xml = -' - {TYPE} - {CODE_FROM} - {CODE_TO} - - -'; -?> diff --git a/mods/patcher/index_admin.php b/mods/patcher/index_admin.php deleted file mode 100644 index ff18d54e4..000000000 --- a/mods/patcher/index_admin.php +++ /dev/null @@ -1,424 +0,0 @@ -" . $dependent_patches . ""; -?> - id="r_"> - /> - - - - - - 0 && ($patch_row["remove_permission_files"]<> "" || $patch_row["backup_files"]<>"" || $patch_row["patch_files"]<> "")) - echo ' -
    - -
    '; - ?> - - -Error: Cannot connect to patch server: '. $update_server . ''; - exit; -} - -// 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 === FALSE) -{ - echo _AT('none_found'); -} -else -{ - $patchListParser =& new PatchListParser(); - $patchListParser->parse($patch_list_xml); - $patch_list_array = $patchListParser->getMyParsedArrayForVersion(VERSION); -} -// end of get patch list - -$module_content_folder = AT_CONTENT_DIR . "patcher"; - -if ($_POST['install_upload'] && $_POST['uploading']) -{ - include_once(AT_INCLUDE_PATH . '/classes/pclzip.lib.php'); - - // clean up module content folder - clear_dir($module_content_folder); - - // 1. unzip uploaded file to module's content directory - $archive = new PclZip($_FILES['patchfile']['tmp_name']); - - if ($archive->extract(PCLZIP_OPT_PATH, $module_content_folder) == 0) - { - clear_dir($module_content_folder); - $msg->addError('CANNOT_UNZIP'); - } -} - -// Installation process -if ($_POST['install'] || $_POST['install_upload']) -{ - - if (isset($_POST['id'])) $id=$_POST['id']; - else $id = $_REQUEST['id']; - - if ($_POST['install'] && $id == "") - { - $msg->addError('CHOOSE_UNINSTALLED_PATCH'); - } - else - { - if ($_POST['install']) - { - $patchURL = $patch_folder . $patch_list_array[$id][patch_folder] . "/"; - } - else if ($_POST['install_upload']) - { - $patchURL = $module_content_folder . "/"; - } - - $patch_xml = @file_get_contents($patchURL . 'patch.xml'); - - if ($patch_xml === FALSE) - { - $msg->addError('PATCH_XML_NOT_FOUND'); - } - else - { - require_once('classes/PatchParser.class.php'); - require_once('classes/Patch.class.php'); - - $patchParser =& new PatchParser(); - $patchParser->parse($patch_xml); - - $patch_array = $patchParser->getParsedArray(); - - if ($_POST["install_upload"]) - { - $current_patch_list = array('atutor_patch_id' => $patch_array['atutor_patch_id'], - 'applied_version' => $patch_array['applied_version'], - 'patch_folder' => $patchURL, - 'available_to' => 'private', - 'description' => $patch_array['description'], - 'dependent_patches' => $patch_array['dependent_patches']); - } - - if ($_POST["install"]) - { - $current_patch_list = $patch_list_array[$id]; - } - - if ($_POST["install_upload"] && is_patch_installed($patch_array["atutor_patch_id"])) - $msg->addError('PATCH_ALREADY_INSTALLED'); - else - { - $patch = & new Patch($patch_array, $current_patch_list, $skipFilesModified, $patchURL); - - if ($patch->applyPatch()) $patch_id = $patch->getPatchID(); - } - } - } -} -// end of patch installation - -// display permission and backup files message -if (isSet($_REQUEST['patch_id'])) $patch_id = $_REQUEST['patch_id']; -elseif ($_POST['patch_id']) $patch_id=$_POST['patch_id']; - -if ($patch_id > 0) -{ - // clicking on button "Done" at displaying remove permission info page - if ($_POST['done']) - { - $permission_files = array(); - - if (is_array($_SESSION['remove_permission'])) - { - foreach ($_SESSION['remove_permission'] as $file) - { - if (is_writable($file)) $permission_files[] = $file; - } - } - - if (count($permission_files) == 0) - { - $updateInfo = array("remove_permission_files"=>"", "status"=>"Installed"); - - updatePatchesRecord($patch_id, $updateInfo); - } - else - { - foreach($permission_files as $permission_file) - $remove_permission_files .= $permission_file. '|'; - - $updateInfo = array("remove_permission_files"=>preg_quote($remove_permission_files), "status"=>"Partly Installed"); - - updatePatchesRecord($patch_id, $updateInfo); - } - - } - - // display remove permission info - unset($_SESSION['remove_permission']); - - $sql = "SELECT * FROM ".TABLE_PREFIX."patches - WHERE patches_id = " . $patch_id; - - $result = mysql_query($sql, $db) or die(mysql_error()); - $row = mysql_fetch_assoc($result); - - if ($row["remove_permission_files"]<> "") - { - $remove_permission_files = $_SESSION['remove_permission'] = get_array_by_delimiter($row["remove_permission_files"], "|"); - - if (count($_SESSION['remove_permission']) > 0) - { - if ($_POST['done']) $msg->printErrors('REMOVE_WRITE_PERMISSION'); - else $msg->printInfos('PATCH_INSTALLED_AND_REMOVE_PERMISSION'); - - $feedbacks[] = _AT('remove_write_permission'); - - foreach($remove_permission_files as $remove_permission_file) - if ($remove_permission_file <> "") $feedbacks[count($feedbacks)-1] .= "" . $remove_permission_file . "
    "; - - $notes = '
    -
    - - -
    -
    '; - } - - print_errors($feedbacks, $notes); - } - - // display backup file info after remove permission step - if ($row["remove_permission_files"] == "") - { - $msg->printFeedbacks('PATCH_INSTALLED_SUCCESSFULLY'); - - if ($row["backup_files"]<> "") - { - $backup_files = get_array_by_delimiter($row["backup_files"], "|"); - - if (count($backup_files) > 0) - { - $feedbacks[] = _AT('patcher_show_backup_files'); - - foreach($backup_files as $backup_file) - if ($backup_file <> "") $feedbacks[count($feedbacks)-1] .= "" . $backup_file . "
    "; - } - } - - if ($row["patch_files"]<> "") - { - $patch_files = get_array_by_delimiter($row["patch_files"], "|"); - - if (count($patch_files) > 0) - { - $feedbacks[] = _AT('patcher_show_patch_files'); - - foreach($patch_files as $patch_file) - if ($patch_file <> "") $feedbacks[count($feedbacks)-1] .= "" . $patch_file . "
    "; - - } - } - - if (count($feedbacks)> 0) - print_feedback($feedbacks); - else - print_feedback(array()); - } -} - -$msg->printErrors(); - -?> - -
    -
    - - - - - - - - - - - - - - - - $new_patch) - { - if (!is_patch_installed($new_patch['atutor_patch_id'])) - { - $dependent_patches_installed = true; - - // check if the dependent patches are installed - if (is_array($new_patch["dependent_patches"])) - { - $dependent_patches = ""; - foreach ($new_patch["dependent_patches"] as $num => $dependent_patch) - { - if (!is_patch_installed($dependent_patch)) - { - $dependent_patches_installed = false; - $dependent_patches .= $dependent_patch. ", "; - } - } - - // remove the last comma in the string - if ($dependent_patches <> "") $dependent_patches = substr($dependent_patches, 0, -2); - } - - // display patch row - if ($dependent_patches_installed) - print_patch_row($new_patch, $array_id++, true); - else - { - print_patch_row($new_patch, $array_id++, false); - $dependent_patches_installed = true; - } - } - else - $array_id++; - } - -?> - - - - - - - - -
     
    - -
    - -
    -
    - -
    - -
    -
    - -
    - - -
    - -
    - - -
    -
    - -
    - - - - diff --git a/mods/patcher/module.css b/mods/patcher/module.css deleted file mode 100644 index 15da01381..000000000 --- a/mods/patcher/module.css +++ /dev/null @@ -1,11 +0,0 @@ -div#helloworld { - border: 1px solid #ccc; - padding: 10px; - width: 50%; - margin-right: auto; - margin-left: auto; - background-color: #efefef; - color: #444; - margin-top: 30px; - margin-bottom: 30px; -} \ No newline at end of file diff --git a/mods/patcher/module.php b/mods/patcher/module.php deleted file mode 100644 index 84300cf15..000000000 --- a/mods/patcher/module.php +++ /dev/null @@ -1,43 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_PATCHER', $this->getAdminPrivilege()); - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_PATCHER, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/patcher/index_admin.php'); - $this->_pages['mods/patcher/index_admin.php']['title_var'] = 'patcher'; - $this->_pages['mods/patcher/index_admin.php']['parent'] = AT_NAV_ADMIN; - - $this->_pages['mods/patcher/index_admin.php']['children'] = array('mods/patcher/myown_patches.php','mods/patcher/patch_create.php'); - $this->_pages['mods/patcher/myown_patches.php']['title_var'] = 'myown_patches'; - $this->_pages['mods/patcher/myown_patches.php']['parent'] = 'mods/patcher/index_admin.php'; - - $this->_pages['mods/patcher/myown_patches.php']['children'] = array('mods/patcher/patch_create.php'); - $this->_pages['mods/patcher/patch_create.php']['title_var'] = 'create_patch'; - $this->_pages['mods/patcher/patch_create.php']['parent'] = 'mods/patcher/myown_patches.php'; - - $this->_pages['mods/patcher/patch_edit.php']['title_var'] = 'edit_patch'; - $this->_pages['mods/patcher/patch_edit.php']['parent'] = 'mods/patcher/myown_patches.php'; - - $this->_pages['mods/patcher/patch_delete.php']['title_var'] = 'delete_patch'; - $this->_pages['mods/patcher/patch_delete.php']['parent'] = 'mods/patcher/myown_patches.php'; -} -$this->_pages['mods/patcher/index_admin.php']['guide'] = 'admin/?p=patcher.php'; -$this->_pages['mods/patcher/patch_create.php']['guide'] = 'admin/?p=create_patches.php'; - -?> diff --git a/mods/patcher/module.sql b/mods/patcher/module.sql deleted file mode 100644 index 4d8184a8f..000000000 --- a/mods/patcher/module.sql +++ /dev/null @@ -1,145 +0,0 @@ -# -------------------------------------------------------- -# 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 records for table `language_text` -# since 1.6.1 - -INSERT INTO `language_text` VALUES ('en', '_module','patcher','Patcher',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_template', 'get_my_patch', 'Get My Patch', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'atutor_patch_id', 'ATutor Patch ID', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'available_to', 'Available To', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'available_patches', 'Available Patches', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'available_patches_text', 'There are %s patches available to install.', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PATCH_ALREADY_INSTALLED', 'The selected patch is already installed.', now(), 'error msg'); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_CHOOSE_UNINSTALLED_PATCH', 'Please choose an uninstalled patch.', now(), 'error msg'); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PATCH_XML_NOT_FOUND', 'Patch XML file is not found.', now(), 'error msg'); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_REMOVE_WRITE_PERMISSION', 'Please remove write permission from the listed files.', now(), 'error msg'); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_CANNOT_UNZIP', 'Can NOT unzip the uploaded file.', now(), 'error msg'); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PATCH_INSTALLED_SUCCESSFULLY', 'The patch has been installed successfully.', now(), 'feedback msg'); -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'); -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'); -INSERT INTO `language_text` VALUES ('en', '_template', 'patcher_overwrite_modified_files', -'The listed files are modified locally. If you choose to proceed, the patch file will be copied to your local machine. -You have to manually merge this file and your local copy.
    ', now(), 'patcher'); -INSERT INTO `language_text` VALUES ('en', '_template', 'patch_local_file_not_exist', -'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.
    ', now(), 'patcher'); -INSERT INTO `language_text` VALUES ('en', '_template', 'patcher_alter_modified_files', -'The listed files are modified locally. If you choose to proceed, your local file will be modified. The original -file will be backup before the modification. Please note that the modification on your customized code may break your customization.
    ', now(), 'patcher'); -INSERT INTO `language_text` VALUES ('en', '_template', 'grant_write_permission', -'Please grant write permission to folders and files listed below:

    Note: To change permissions on Unix use chmod a+rw then the file name.

    ', now(), 'patcher'); -INSERT INTO `language_text` VALUES ('en', '_template', 'remove_write_permission', -'Please REMOVE write permission on the listed folders and files for your security:

    Note: To remove permissions on Unix use chmod 755 then the file name..

    ', now(), 'patcher'); -INSERT INTO `language_text` VALUES ('en', '_template', 'patcher_show_backup_files', -'Below is the list of the backup files created by patch installation. After ensuring ATutor works properly with the patch, you may want to -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 -to the original file names, removing the [patch_id].old portion of the file name.
    ', now(), 'patcher'); -INSERT INTO `language_text` VALUES ('en', '_template', 'patcher_show_patch_files', -'Below is the list of the patch files copied to your computer. -Please manually merge the change between the patch files and your local copy.
    ', now(), 'patcher'); -INSERT INTO `language_text` VALUES ('en', '_template', 'patch_dependent_patch_not_installed', -'
    Waring: Due to patch dependency, please install the listed patches first: ', now(), 'patcher'); -INSERT INTO `language_text` VALUES ('en', '_template', 'upload_patch', -'Upload a zip file to install patch:', now(), 'patcher'); - -# -------------------------------------------------------- -# 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`) -); - -# -------------------------------------------------------- -# New records for table `language_text` (for patch creator) -# since 1.6.1 - -INSERT INTO `language_text` VALUES ('en', '_template', 'myown_patches', 'My Own Patches', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'atutor_patch_id', 'ATutor Patch ID', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'atutor_version_to_apply', 'ATutor Version to Apply', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'dependent_patches', 'Dependent Patches', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'dependent_patch_id', 'Dependent Patch ID', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'add_dependent_patch', 'Add A Dependent Patch', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'sql_statement', 'SQL Statement', now(), ''); -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(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'create_patch', 'Create Patch', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'edit_patch', 'Edit Patch', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'delete_patch', 'Delete Patch', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'add_a_file', 'Add A File', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'delete_this_file', 'Delete This File', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'replace_file', 'Replace File', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'alter', 'Alter', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'code_to_replace_from', 'Code To Replace From', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'code_to_replace_to', 'Code To Replace To', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_CHOOSE_ACTION', 'Please choose action for file %s', now(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PATCH_CREATED_SUCCESSFULLY', 'The patch has been created successfully.', now(), 'feedback msg'); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_CONFIRM_DELETE_MYOWN_PATCH', 'Are you sure you want to delete patch %s', now(), ''); diff --git a/mods/patcher/module.xml b/mods/patcher/module.xml deleted file mode 100644 index 45afb60b5..000000000 --- a/mods/patcher/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Patcher - 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. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.1 - 2008-02-08 - stable - - - \ No newline at end of file diff --git a/mods/patcher/module_install.php b/mods/patcher/module_install.php deleted file mode 100644 index f517c4270..000000000 --- a/mods/patcher/module_install.php +++ /dev/null @@ -1,67 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/patcher/myown_patches.php b/mods/patcher/myown_patches.php deleted file mode 100644 index 949835231..000000000 --- a/mods/patcher/myown_patches.php +++ /dev/null @@ -1,99 +0,0 @@ -addError('NO_ITEM_SELECTED'); -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -?> -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     
    -
    - - -
    -
    />
    - -
    - - diff --git a/mods/patcher/patch_create.php b/mods/patcher/patch_create.php deleted file mode 100644 index f67500d33..000000000 --- a/mods/patcher/patch_create.php +++ /dev/null @@ -1,23 +0,0 @@ - diff --git a/mods/patcher/patch_creator.php b/mods/patcher/patch_creator.php deleted file mode 100644 index c76ccfe85..000000000 --- a/mods/patcher/patch_creator.php +++ /dev/null @@ -1,134 +0,0 @@ -$action) - { - // must upload a file if action is add or overwrite - if ($action == "add" && $_FILES['add_upload_file']['name'][$i] == "" && $_POST['add_uploaded_file'] == "") - $missing_fields[] = _AT("upload_file") . " for ". _AT("file_name") . " " . $_POST['add_filename'][$i] . ""; - - if ($action == "overwrite" && $_FILES['overwrite_upload_file']['name'][$i] == "" && $_POST['overwrite_uploaded_file'] == "") - $missing_fields[] = _AT("upload_file") . " for ". _AT("file_name") . " " . $_POST['overwrite_filename'][$i] . ""; - } - } - // end of checking missing fields - - if ($missing_fields) - { - $missing_fields = implode(', ', $missing_fields); - $msg->addError(array('EMPTY_FIELDS', $missing_fields)); - } - - if (!(eregi("^[a-zA-Z0-9_.-]([a-zA-Z0-9_.-])*$", $_POST['atutor_patch_id']))) - $msg->addError('LOGIN_CHARS'); - - // main process - if (!$msg->containsErrors()) - { - $patch_info = array("atutor_patch_id"=>$_POST["atutor_patch_id"], - "atutor_version_to_apply"=>$_POST["atutor_version_to_apply"], - "description"=>$_POST["description"], - "sql_statement"=>$_POST["sql_statement"]); - - // remove empty dependent patches - if (is_array($_POST["dependent_patch"])) - { - foreach ($_POST["dependent_patch"] as $dependent_patch) - if (trim($dependent_patch) <> "") - $dependent_patches[] = $dependent_patch; - } - - if (is_array($dependent_patches)) - $patch_info["dependent_patches"] = $dependent_patches; - - if (is_array($_POST['rb_action'])) - { - foreach ($_POST['rb_action'] as $i=>$action) - { - if ($action == "add" && $_POST['add_filename'][$i] <> "") - { - if ($_FILES['add_upload_file']['tmp_name'][$i] <> "") - $upload_file = $_FILES['add_upload_file']['tmp_name'][$i]; - else - $upload_file = stripslashes($_POST['add_uploaded_file'][$i]); - - $patch_info["files"][] = array("action"=>$action, - "file_name"=>$_POST['add_filename'][$i], - "directory"=>$_POST['add_dir'][$i], - "upload_tmp_name"=>$upload_file); - } - - if ($action == "alter" && $_POST['alter_filename'][$i] <> "") - $patch_info["files"][] = array("action"=>$action, - "file_name"=>$_POST['alter_filename'][$i], - "directory"=>$_POST['alter_dir'][$i], - "code_from"=>$_POST['alter_code_from'][$i], - "code_to"=>$_POST['alter_code_to'][$i]); - - if ($action == "delete" && $_POST['delete_filename'][$i] <> "") - $patch_info["files"][] = array("action"=>$action, - "file_name"=>$_POST['delete_filename'][$i], - "directory"=>$_POST['delete_dir'][$i]); - - if ($action == "overwrite" && $_POST['overwrite_filename'][$i] <> "") - { - if ($_FILES['overwrite_upload_file']['tmp_name'][$i] <> "") - $upload_file = $_FILES['overwrite_upload_file']['tmp_name'][$i]; - else - $upload_file = stripslashes($_POST['overwrite_uploaded_file'][$i]); - - $patch_info["files"][] = array("action"=>$action, - "file_name"=>$_POST['overwrite_filename'][$i], - "directory"=>$_POST['overwrite_dir'][$i], - "upload_tmp_name"=>$upload_file); - } - } - } - - require_once("classes/PatchCreator.class.php"); - - $patch_creator =& new PatchCreator($patch_info, $patch_id); - - if ($_POST['create']) - $patch_creator->create_patch(); - else if ($_POST['save']) - { - $patch_creator->saveInfo(); - header('Location: myown_patches.php'); - } - - } -} - -$msg->printErrors(); -?> diff --git a/mods/patcher/patch_delete.php b/mods/patcher/patch_delete.php deleted file mode 100644 index e059087bf..000000000 --- a/mods/patcher/patch_delete.php +++ /dev/null @@ -1,71 +0,0 @@ -addFeedback('CANCELLED'); - header('Location: myown_patches.php'); - exit; -} else if (isset($_POST['submit_yes'])) { - /* delete has been confirmed, delete this category */ - $myown_patch_id = intval($_POST['myown_patch_id']); - - $sql = "DELETE FROM ".TABLE_PREFIX."myown_patches WHERE myown_patch_id=$myown_patch_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - write_to_log(AT_ADMIN_LOG_DELETE, 'myown_patches', mysql_affected_rows($db), $sql); - - $sql = "DELETE FROM ".TABLE_PREFIX."myown_patches_dependent WHERE myown_patch_id=$myown_patch_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - write_to_log(AT_ADMIN_LOG_DELETE, 'myown_patches_dependent', mysql_affected_rows($db), $sql); - - $sql = "DELETE FROM ".TABLE_PREFIX."myown_patches_files WHERE myown_patch_id=$myown_patch_id"; - $result = mysql_query($sql, $db) or die(mysql_error()); - - write_to_log(AT_ADMIN_LOG_DELETE, 'myown_patches_files', mysql_affected_rows($db), $sql); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: myown_patches.php'); - exit; -} - -//require('../../include/header.inc.php'); -require(AT_INCLUDE_PATH.'header.inc.php'); - -$_GET['myown_patch_id'] = intval($_GET['myown_patch_id']); - -$sql = "SELECT myown_patch_id, atutor_patch_id FROM ".TABLE_PREFIX."myown_patches m WHERE m.myown_patch_id=$_GET[myown_patch_id]"; -$result = mysql_query($sql,$db) or die(mysql_error()); - -if (mysql_num_rows($result) == 0) { - $msg->printErrors('ITEM_NOT_FOUND'); -} else { - $row = mysql_fetch_assoc($result); - - $hidden_vars['atutor_patch_id']= $row['atutor_patch_id']; - $hidden_vars['myown_patch_id'] = $row['myown_patch_id']; - - $confirm = array('DELETE_MYOWN_PATCH', $row['atutor_patch_id']); - $msg->addConfirm($confirm, $hidden_vars); - - $msg->printConfirm(); -} - -require(AT_INCLUDE_PATH.'footer.inc.php'); - -?> \ No newline at end of file diff --git a/mods/patcher/patch_edit.php b/mods/patcher/patch_edit.php deleted file mode 100644 index eea59c39b..000000000 --- a/mods/patcher/patch_edit.php +++ /dev/null @@ -1,42 +0,0 @@ -addError('NO_ITEM_SELECTED'); - exit; -} - -$myown_patch_id = $_REQUEST["myown_patch_id"]; - -// URL called by form action -$url = dirname($_SERVER['PHP_SELF']) . "/patch_creator.php?myown_patch_id=" . $myown_patch_id; - -$sql_patches = "SELECT * from ".TABLE_PREFIX."myown_patches m where myown_patch_id=". $myown_patch_id; -$result_patches = mysql_query($sql_patches, $db) or die(mysql_error()); -$row_patches = mysql_fetch_assoc($result_patches); - -$sql_patch_dependent = "SELECT * from ".TABLE_PREFIX."myown_patches_dependent m where myown_patch_id=". $myown_patch_id; -$result_patch_dependent = mysql_query($sql_patch_dependent, $db) or die(mysql_error()); - -$sql_patch_files = "SELECT * from ".TABLE_PREFIX."myown_patches_files m where myown_patch_id=". $myown_patch_id . " order by myown_patches_files_id"; -$result_patch_files = mysql_query($sql_patch_files, $db) or die(mysql_error()); - -require ('patch_edit_interface.tmpl.php'); - -?> diff --git a/mods/patcher/patch_edit_interface.tmpl.php b/mods/patcher/patch_edit_interface.tmpl.php deleted file mode 100644 index ea8d84056..000000000 --- a/mods/patcher/patch_edit_interface.tmpl.php +++ /dev/null @@ -1,349 +0,0 @@ - - -
    - -
    - - -
    - -
    -
    *

    - ·
    -
    -
    - -
    -
    *

    -
    -
    - -
    -
    -
    -
    - -
    -
    -
    -
    - -
    -
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - -
    -
    -
    - -





    -
    -
    - · -
    - -
    -
    - -
    - -
    - -

    - -
    - - - -
    - -
    -
    - - - - - - - diff --git a/mods/patcher/sample_patch.xml b/mods/patcher/sample_patch.xml deleted file mode 100644 index f2007ee83..000000000 --- a/mods/patcher/sample_patch.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - 00001 - 1.6 - Sample patch XML - - 00002 - 00003 - - - - ALTER TABLE `tests` ADD `description` TEXT NOT NULL AFTER `title`; - - - - - alter - create_test.php - tools/tests/ - - delete - - - - - replace - - - - - - - add - calendar.gif - docs/images/ - - - - delete - results_all_csv.php - tools/tests/ - - - - overwrite - results_all.php - tools/tests/ - - - diff --git a/mods/patcher/sample_patch_list.xml b/mods/patcher/sample_patch_list.xml deleted file mode 100644 index 13de25077..000000000 --- a/mods/patcher/sample_patch_list.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - 00001 - 1.6 - 1_6-1 - Patch No. 1 for ATutor 1.6 - public - - - - - 00002 - 1.6 - 1_6-2 - Patch No. 2 for ATutor 1.6 - public - - 00001 - 00003 - - - diff --git a/mods/patcher/xml_special_chars.txt b/mods/patcher/xml_special_chars.txt deleted file mode 100644 index a72031528..000000000 --- a/mods/patcher/xml_special_chars.txt +++ /dev/null @@ -1,5 +0,0 @@ -< < less than -> > greater than -& & ampersand -' ' apostrophe -" " quotation mark \ No newline at end of file diff --git a/mods/pdf_converter/README b/mods/pdf_converter/README deleted file mode 100644 index d8d2a2be6..000000000 --- a/mods/pdf_converter/README +++ /dev/null @@ -1,27 +0,0 @@ -PDF CONVERTER - -Convert course content to a pdf document. This module creates a side menu block with a link that when clicked generates the page being viewd as a PDF file. - -Note: After installing, make for file muestra_pdf.txt writable, if it is not already. - -INSTALATION INSTRUCTIONS - -1.- Unzip the downloaded file into ATutor/mods directory. - -On Windows systems use an application such as WinZip, WinRar or default Windows XP File Extractor. - -On Unix/Linux systems use the following command: - -tar xzvf pdf_converter-0.1.tar.gz - -2.- Make for file muestra_pdf.txt writable, if it is not already. - -3.- Login into ATutor as administration, go to modules tab, install modules. PDF Converter should be listed there select and install it. - -4.- Once the module has been installed, enabled it. - -5.- The go to home tab and select your preferable course. - -6.- Go to Manage tab, side menu and select PDF converter on the select menu. This allow to see the PDF Converter link on side menu. Apply changes. - -7.- Now you can select course content on the side menu to read/edit and you can convert it to a pdf document, just click the link on PDF Converter on side menu. \ No newline at end of file diff --git a/mods/pdf_converter/class.ezpdf.php b/mods/pdf_converter/class.ezpdf.php deleted file mode 100644 index 049df6a6c..000000000 --- a/mods/pdf_converter/class.ezpdf.php +++ /dev/null @@ -1,1555 +0,0 @@ -10); // used for storing most of the page configuration parameters -var $y; // this is the current vertical positon on the page of the writing point, very important -var $ezPages=array(); // keep an array of the ids of the pages, making it easy to go back and add page numbers etc. -var $ezPageCount=0; - -// ------------------------------------------------------------------------------ - -function Cezpdf($paper='a4',$orientation='portrait'){ - // Assuming that people don't want to specify the paper size using the absolute coordinates - // allow a couple of options: - // orientation can be 'portrait' or 'landscape' - // or, to actually set the coordinates, then pass an array in as the first parameter. - // the defaults are as shown. - // - // ------------------------- - // 2002-07-24 - Nicola Asuni (info@tecnick.com): - // Added new page formats (45 standard ISO paper formats and 4 american common formats) - // paper cordinates are calculated in this way: (inches * 72) where 1 inch = 2.54 cm - // - // Now you may also pass a 2 values array containing the page width and height in centimeters - // ------------------------- - - if (!is_array($paper)){ - switch (strtoupper($paper)){ - case '4A0': {$size = array(0,0,4767.87,6740.79); break;} - case '2A0': {$size = array(0,0,3370.39,4767.87); break;} - case 'A0': {$size = array(0,0,2383.94,3370.39); break;} - case 'A1': {$size = array(0,0,1683.78,2383.94); break;} - case 'A2': {$size = array(0,0,1190.55,1683.78); break;} - case 'A3': {$size = array(0,0,841.89,1190.55); break;} - case 'A4': default: {$size = array(0,0,595.28,841.89); break;} - case 'A5': {$size = array(0,0,419.53,595.28); break;} - case 'A6': {$size = array(0,0,297.64,419.53); break;} - case 'A7': {$size = array(0,0,209.76,297.64); break;} - case 'A8': {$size = array(0,0,147.40,209.76); break;} - case 'A9': {$size = array(0,0,104.88,147.40); break;} - case 'A10': {$size = array(0,0,73.70,104.88); break;} - case 'B0': {$size = array(0,0,2834.65,4008.19); break;} - case 'B1': {$size = array(0,0,2004.09,2834.65); break;} - case 'B2': {$size = array(0,0,1417.32,2004.09); break;} - case 'B3': {$size = array(0,0,1000.63,1417.32); break;} - case 'B4': {$size = array(0,0,708.66,1000.63); break;} - case 'B5': {$size = array(0,0,498.90,708.66); break;} - case 'B6': {$size = array(0,0,354.33,498.90); break;} - case 'B7': {$size = array(0,0,249.45,354.33); break;} - case 'B8': {$size = array(0,0,175.75,249.45); break;} - case 'B9': {$size = array(0,0,124.72,175.75); break;} - case 'B10': {$size = array(0,0,87.87,124.72); break;} - case 'C0': {$size = array(0,0,2599.37,3676.54); break;} - case 'C1': {$size = array(0,0,1836.85,2599.37); break;} - case 'C2': {$size = array(0,0,1298.27,1836.85); break;} - case 'C3': {$size = array(0,0,918.43,1298.27); break;} - case 'C4': {$size = array(0,0,649.13,918.43); break;} - case 'C5': {$size = array(0,0,459.21,649.13); break;} - case 'C6': {$size = array(0,0,323.15,459.21); break;} - case 'C7': {$size = array(0,0,229.61,323.15); break;} - case 'C8': {$size = array(0,0,161.57,229.61); break;} - case 'C9': {$size = array(0,0,113.39,161.57); break;} - case 'C10': {$size = array(0,0,79.37,113.39); break;} - case 'RA0': {$size = array(0,0,2437.80,3458.27); break;} - case 'RA1': {$size = array(0,0,1729.13,2437.80); break;} - case 'RA2': {$size = array(0,0,1218.90,1729.13); break;} - case 'RA3': {$size = array(0,0,864.57,1218.90); break;} - case 'RA4': {$size = array(0,0,609.45,864.57); break;} - case 'SRA0': {$size = array(0,0,2551.18,3628.35); break;} - case 'SRA1': {$size = array(0,0,1814.17,2551.18); break;} - case 'SRA2': {$size = array(0,0,1275.59,1814.17); break;} - case 'SRA3': {$size = array(0,0,907.09,1275.59); break;} - case 'SRA4': {$size = array(0,0,637.80,907.09); break;} - case 'LETTER': {$size = array(0,0,612.00,792.00); break;} - case 'LEGAL': {$size = array(0,0,612.00,1008.00); break;} - case 'EXECUTIVE': {$size = array(0,0,521.86,756.00); break;} - case 'FOLIO': {$size = array(0,0,612.00,936.00); break;} - } - switch (strtolower($orientation)){ - case 'landscape': - $a=$size[3]; - $size[3]=$size[2]; - $size[2]=$a; - break; - } - } else { - if (count($paper)>2) { - // then an array was sent it to set the size - $size = $paper; - } - else { //size in centimeters has been passed - $size[0] = 0; - $size[1] = 0; - $size[2] = ( $paper[0] / 2.54 ) * 72; - $size[3] = ( $paper[1] / 2.54 ) * 72; - } - } - $this->Cpdf($size); - $this->ez['pageWidth']=$size[2]; - $this->ez['pageHeight']=$size[3]; - - // also set the margins to some reasonable defaults - $this->ez['topMargin']=30; - $this->ez['bottomMargin']=30; - $this->ez['leftMargin']=30; - $this->ez['rightMargin']=30; - - // set the current writing position to the top of the first page - $this->y = $this->ez['pageHeight']-$this->ez['topMargin']; - // and get the ID of the page that was created during the instancing process. - $this->ezPages[1]=$this->getFirstPageId(); - $this->ezPageCount=1; -} - -// ------------------------------------------------------------------------------ -// 2002-07-24: Nicola Asuni (info@tecnick.com) -// Set Margins in centimeters -function ezSetCmMargins($top,$bottom,$left,$right){ - $top = ( $top / 2.54 ) * 72; - $bottom = ( $bottom / 2.54 ) * 72; - $left = ( $left / 2.54 ) * 72; - $right = ( $right / 2.54 ) * 72; - $this->ezSetMargins($top,$bottom,$left,$right); -} -// ------------------------------------------------------------------------------ - - -function ezColumnsStart($options=array()){ - // start from the current y-position, make the set number of columne - if (isset($this->ez['columns']) && $this->ez['columns']==1){ - // if we are already in a column mode then just return. - return; - } - $def=array('gap'=>10,'num'=>2); - foreach($def as $k=>$v){ - if (!isset($options[$k])){ - $options[$k]=$v; - } - } - // setup the columns - $this->ez['columns']=array('on'=>1,'colNum'=>1); - - // store the current margins - $this->ez['columns']['margins']=array( - $this->ez['leftMargin'] - ,$this->ez['rightMargin'] - ,$this->ez['topMargin'] - ,$this->ez['bottomMargin'] - ); - // and store the settings for the columns - $this->ez['columns']['options']=$options; - // then reset the margins to suit the new columns - // safe enough to assume the first column here, but start from the current y-position - $this->ez['topMargin']=$this->ez['pageHeight']-$this->y; - $width=($this->ez['pageWidth']-$this->ez['leftMargin']-$this->ez['rightMargin']-($options['num']-1)*$options['gap'])/$options['num']; - $this->ez['columns']['width']=$width; - $this->ez['rightMargin']=$this->ez['pageWidth']-$this->ez['leftMargin']-$width; - -} -// ------------------------------------------------------------------------------ -function ezColumnsStop(){ - if (isset($this->ez['columns']) && $this->ez['columns']['on']==1){ - $this->ez['columns']['on']=0; - $this->ez['leftMargin']=$this->ez['columns']['margins'][0]; - $this->ez['rightMargin']=$this->ez['columns']['margins'][1]; - $this->ez['topMargin']=$this->ez['columns']['margins'][2]; - $this->ez['bottomMargin']=$this->ez['columns']['margins'][3]; - } -} -// ------------------------------------------------------------------------------ -function ezInsertMode($status=1,$pageNum=1,$pos='before'){ - // puts the document into insert mode. new pages are inserted until this is re-called with status=0 - // by default pages wil be inserted at the start of the document - switch($status){ - case '1': - if (isset($this->ezPages[$pageNum])){ - $this->ez['insertMode']=1; - $this->ez['insertOptions']=array('id'=>$this->ezPages[$pageNum],'pos'=>$pos); - } - break; - case '0': - $this->ez['insertMode']=0; - break; - } -} -// ------------------------------------------------------------------------------ - -function ezNewPage(){ - $pageRequired=1; - if (isset($this->ez['columns']) && $this->ez['columns']['on']==1){ - // check if this is just going to a new column - // increment the column number -//echo 'HERE
    '; - $this->ez['columns']['colNum']++; -//echo $this->ez['columns']['colNum'].'
    '; - if ($this->ez['columns']['colNum'] <= $this->ez['columns']['options']['num']){ - // then just reset to the top of the next column - $pageRequired=0; - } else { - $this->ez['columns']['colNum']=1; - $this->ez['topMargin']=$this->ez['columns']['margins'][2]; - } - - $width = $this->ez['columns']['width']; - $this->ez['leftMargin']=$this->ez['columns']['margins'][0]+($this->ez['columns']['colNum']-1)*($this->ez['columns']['options']['gap']+$width); - $this->ez['rightMargin']=$this->ez['pageWidth']-$this->ez['leftMargin']-$width; - } -//echo 'left='.$this->ez['leftMargin'].' right='.$this->ez['rightMargin'].'
    '; - - if ($pageRequired){ - // make a new page, setting the writing point back to the top - $this->y = $this->ez['pageHeight']-$this->ez['topMargin']; - // make the new page with a call to the basic class. - $this->ezPageCount++; - if (isset($this->ez['insertMode']) && $this->ez['insertMode']==1){ - $id = $this->ezPages[$this->ezPageCount] = $this->newPage(1,$this->ez['insertOptions']['id'],$this->ez['insertOptions']['pos']); - // then manipulate the insert options so that inserted pages follow each other - $this->ez['insertOptions']['id']=$id; - $this->ez['insertOptions']['pos']='after'; - } else { - $this->ezPages[$this->ezPageCount] = $this->newPage(); - } - } else { - $this->y = $this->ez['pageHeight']-$this->ez['topMargin']; - } -} - -// ------------------------------------------------------------------------------ - -function ezSetMargins($top,$bottom,$left,$right){ - // sets the margins to new values - $this->ez['topMargin']=$top; - $this->ez['bottomMargin']=$bottom; - $this->ez['leftMargin']=$left; - $this->ez['rightMargin']=$right; - // check to see if this means that the current writing position is outside the - // writable area - if ($this->y > $this->ez['pageHeight']-$top){ - // then move y down - $this->y = $this->ez['pageHeight']-$top; - } - if ( $this->y < $bottom){ - // then make a new page - $this->ezNewPage(); - } -} - -// ------------------------------------------------------------------------------ - -function ezGetCurrentPageNumber(){ - // return the strict numbering (1,2,3,4..) number of the current page - return $this->ezPageCount; -} - -// ------------------------------------------------------------------------------ - -function ezStartPageNumbers($x,$y,$size,$pos='left',$pattern='{PAGENUM} of {TOTALPAGENUM}',$num=''){ - // put page numbers on the pages from here. - // place then on the 'pos' side of the coordinates (x,y). - // pos can be 'left' or 'right' - // use the given 'pattern' for display, where (PAGENUM} and {TOTALPAGENUM} are replaced - // as required. - // if $num is set, then make the first page this number, the number of total pages will - // be adjusted to account for this. - // Adjust this function so that each time you 'start' page numbers then you effectively start a different batch - // return the number of the batch, so that they can be stopped in a different order if required. - if (!$pos || !strlen($pos)){ - $pos='left'; - } - if (!$pattern || !strlen($pattern)){ - $pattern='{PAGENUM} of {TOTALPAGENUM}'; - } - if (!isset($this->ez['pageNumbering'])){ - $this->ez['pageNumbering']=array(); - } - $i = count($this->ez['pageNumbering']); - $this->ez['pageNumbering'][$i][$this->ezPageCount]=array('x'=>$x,'y'=>$y,'pos'=>$pos,'pattern'=>$pattern,'num'=>$num,'size'=>$size); - return $i; -} - -// ------------------------------------------------------------------------------ - -function ezWhatPageNumber($pageNum,$i=0){ - // given a particular generic page number (ie, document numbered sequentially from beginning), - // return the page number under a particular page numbering scheme ($i) - $num=0; - $start=1; - $startNum=1; - if (!isset($this->ez['pageNumbering'])) - { - $this->addMessage('WARNING: page numbering called for and wasn\'t started with ezStartPageNumbers'); - return 0; - } - foreach($this->ez['pageNumbering'][$i] as $k=>$v){ - if ($k<=$pageNum){ - if (is_array($v)){ - // start block - if (strlen($v['num'])){ - // a start was specified - $start=$v['num']; - $startNum=$k; - $num=$pageNum-$startNum+$start; - } - } else { - // stop block - $num=0; - } - } - } - return $num; -} - -// ------------------------------------------------------------------------------ - -function ezStopPageNumbers($stopTotal=0,$next=0,$i=0){ - // if stopTotal=1 then the totalling of pages for this number will stop too - // if $next=1, then do this page, but not the next, else do not do this page either - // if $i is set, then stop that particular pagenumbering sequence. - if (!isset($this->ez['pageNumbering'])){ - $this->ez['pageNumbering']=array(); - } - if ($next && isset($this->ez['pageNumbering'][$i][$this->ezPageCount]) && is_array($this->ez['pageNumbering'][$i][$this->ezPageCount])){ - // then this has only just been started, this will over-write the start, and nothing will appear - // add a special command to the start block, telling it to stop as well - if ($stopTotal){ - $this->ez['pageNumbering'][$i][$this->ezPageCount]['stoptn']=1; - } else { - $this->ez['pageNumbering'][$i][$this->ezPageCount]['stopn']=1; - } - } else { - if ($stopTotal){ - $this->ez['pageNumbering'][$i][$this->ezPageCount]='stopt'; - } else { - $this->ez['pageNumbering'][$i][$this->ezPageCount]='stop'; - } - if ($next){ - $this->ez['pageNumbering'][$i][$this->ezPageCount].='n'; - } - } -} - -// ------------------------------------------------------------------------------ - -function ezPRVTpageNumberSearch($lbl,&$tmp){ - foreach($tmp as $i=>$v){ - if (is_array($v)){ - if (isset($v[$lbl])){ - return $i; - } - } else { - if ($v==$lbl){ - return $i; - } - } - } - return 0; -} - -// ------------------------------------------------------------------------------ - -function ezPRVTaddPageNumbers(){ - // this will go through the pageNumbering array and add the page numbers are required - if (isset($this->ez['pageNumbering'])){ - $totalPages1 = $this->ezPageCount; - $tmp1=$this->ez['pageNumbering']; - $status=0; - foreach($tmp1 as $i=>$tmp){ - // do each of the page numbering systems - // firstly, find the total pages for this one - $k = $this->ezPRVTpageNumberSearch('stopt',$tmp); - if ($k && $k>0){ - $totalPages = $k-1; - } else { - $l = $this->ezPRVTpageNumberSearch('stoptn',$tmp); - if ($l && $l>0){ - $totalPages = $l; - } else { - $totalPages = $totalPages1; - } - } - foreach ($this->ezPages as $pageNum=>$id){ - if (isset($tmp[$pageNum])){ - if (is_array($tmp[$pageNum])){ - // then this must be starting page numbers - $status=1; - $info = $tmp[$pageNum]; - $info['dnum']=$info['num']-$pageNum; - // also check for the special case of the numbering stopping and starting on the same page - if (isset($info['stopn']) || isset($info['stoptn']) ){ - $status=2; - } - } else if ($tmp[$pageNum]=='stop' || $tmp[$pageNum]=='stopt'){ - // then we are stopping page numbers - $status=0; - } else if ($status==1 && ($tmp[$pageNum]=='stoptn' || $tmp[$pageNum]=='stopn')){ - // then we are stopping page numbers - $status=2; - } - } - if ($status){ - // then add the page numbering to this page - if (strlen($info['num'])){ - $num=$pageNum+$info['dnum']; - } else { - $num=$pageNum; - } - $total = $totalPages+$num-$pageNum; - $pat = str_replace('{PAGENUM}',$num,$info['pattern']); - $pat = str_replace('{TOTALPAGENUM}',$total,$pat); - $this->reopenObject($id); - switch($info['pos']){ - case 'right': - $this->addText($info['x'],$info['y'],$info['size'],$pat); - break; - default: - $w=$this->getTextWidth($info['size'],$pat); - $this->addText($info['x']-$w,$info['y'],$info['size'],$pat); - break; - } - $this->closeObject(); - } - if ($status==2){ - $status=0; - } - } - } - } -} - -// ------------------------------------------------------------------------------ - -function ezPRVTcleanUp(){ - $this->ezPRVTaddPageNumbers(); -} - -// ------------------------------------------------------------------------------ - -function ezStream($options=''){ - $this->ezPRVTcleanUp(); - $this->stream($options); -} - -// ------------------------------------------------------------------------------ - -function ezOutput($options=0){ - $this->ezPRVTcleanUp(); - return $this->output($options); -} - -// ------------------------------------------------------------------------------ - -function ezSetY($y){ - // used to change the vertical position of the writing point. - $this->y = $y; - if ( $this->y < $this->ez['bottomMargin']){ - // then make a new page - $this->ezNewPage(); - } -} - -// ------------------------------------------------------------------------------ - -function ezSetDy($dy,$mod=''){ - // used to change the vertical position of the writing point. - // changes up by a positive increment, so enter a negative number to go - // down the page - // if $mod is set to 'makeSpace' and a new page is forced, then the pointed will be moved - // down on the new page, this will allow space to be reserved for graphics etc. - $this->y += $dy; - if ( $this->y < $this->ez['bottomMargin']){ - // then make a new page - $this->ezNewPage(); - if ($mod=='makeSpace'){ - $this->y += $dy; - } - } -} - -// ------------------------------------------------------------------------------ - -function ezPrvtTableDrawLines($pos,$gap,$x0,$x1,$y0,$y1,$y2,$col,$inner,$outer,$opt=1){ - $x0=1000; - $x1=0; - $this->setStrokeColor($col[0],$col[1],$col[2]); - $cnt=0; - $n = count($pos); - foreach($pos as $x){ - $cnt++; - if ($cnt==1 || $cnt==$n){ - $this->setLineStyle($outer); - } else { - $this->setLineStyle($inner); - } - $this->line($x-$gap/2,$y0,$x-$gap/2,$y2); - if ($x>$x1){ $x1=$x; }; - if ($x<$x0){ $x0=$x; }; - } - $this->setLineStyle($outer); - $this->line($x0-$gap/2-$outer/2,$y0,$x1-$gap/2+$outer/2,$y0); - // only do the second line if it is different to the first, AND each row does not have - // a line on it. - if ($y0!=$y1 && $opt<2){ - $this->line($x0-$gap/2,$y1,$x1-$gap/2,$y1); - } - $this->line($x0-$gap/2-$outer/2,$y2,$x1-$gap/2+$outer/2,$y2); -} - -// ------------------------------------------------------------------------------ - -function ezPrvtTableColumnHeadings($cols,$pos,$maxWidth,$height,$decender,$gap,$size,&$y,$optionsAll=array()){ - // uses ezText to add the text, and returns the height taken by the largest heading - // this page will move the headings to a new page if they will not fit completely on this one - // transaction support will be used to implement this - - if (isset($optionsAll['cols'])){ - $options = $optionsAll['cols']; - } else { - $options = array(); - } - - $mx=0; - $startPage = $this->ezPageCount; - $secondGo=0; - - // $y is the position at which the top of the table should start, so the base - // of the first text, is $y-$height-$gap-$decender, but ezText starts by dropping $height - - // the return from this function is the total cell height, including gaps, and $y is adjusted - // to be the postion of the bottom line - - // begin the transaction - $this->transaction('start'); - $ok=0; -// $y-=$gap-$decender; - $y-=$gap; - while ($ok==0){ - foreach($cols as $colName=>$colHeading){ - $this->ezSetY($y); - if (isset($options[$colName]) && isset($options[$colName]['justification'])){ - $justification = $options[$colName]['justification']; - } else { - $justification = 'left'; - } - $this->ezText($colHeading,$size,array('aleft'=> $pos[$colName],'aright'=>($maxWidth[$colName]+$pos[$colName]),'justification'=>$justification)); - $dy = $y-$this->y; - if ($dy>$mx){ - $mx=$dy; - } - } - $y = $y - $mx - $gap + $decender; -// $y -= $mx-$gap+$decender; - - // now, if this has moved to a new page, then abort the transaction, move to a new page, and put it there - // do not check on the second time around, to avoid an infinite loop - if ($this->ezPageCount != $startPage && $secondGo==0){ - $this->transaction('rewind'); - $this->ezNewPage(); - $y = $this->y - $gap-$decender; - $ok=0; - $secondGo=1; -// $y = $store_y; - $mx=0; - - } else { - $this->transaction('commit'); - $ok=1; - } - } - - return $mx+$gap*2-$decender; -} - -// ------------------------------------------------------------------------------ - -function ezPrvtGetTextWidth($size,$text){ - // will calculate the maximum width, taking into account that the text may be broken - // by line breaks. - $mx=0; - $lines = explode("\n",$text); - foreach ($lines as $line){ - $w = $this->getTextWidth($size,$line); - if ($w>$mx){ - $mx=$w; - } - } - return $mx; -} - -// ------------------------------------------------------------------------------ - -function ezTable(&$data,$cols='',$title='',$options=''){ - // add a table of information to the pdf document - // $data is a two dimensional array - // $cols (optional) is an associative array, the keys are the names of the columns from $data - // to be presented (and in that order), the values are the titles to be given to the columns - // $title (optional) is the title to be put on the top of the table - // - // $options is an associative array which can contain: - // 'showLines'=> 0,1,2, default is 1 (show outside and top lines only), 2=> lines on each row - // 'showHeadings' => 0 or 1 - // 'shaded'=> 0,1,2,3 default is 1 (1->alternate lines are shaded, 0->no shading, 2-> both shaded, second uses shadeCol2) - // 'shadeCol' => (r,g,b) array, defining the colour of the shading, default is (0.8,0.8,0.8) - // 'shadeCol2' => (r,g,b) array, defining the colour of the shading of the other blocks, default is (0.7,0.7,0.7) - // 'fontSize' => 10 - // 'textCol' => (r,g,b) array, text colour - // 'titleFontSize' => 12 - // 'rowGap' => 2 , the space added at the top and bottom of each row, between the text and the lines - // 'colGap' => 5 , the space on the left and right sides of each cell - // 'lineCol' => (r,g,b) array, defining the colour of the lines, default, black. - // 'xPos' => 'left','right','center','centre',or coordinate, reference coordinate in the x-direction - // 'xOrientation' => 'left','right','center','centre', position of the table w.r.t 'xPos' - // 'width'=> which will specify the width of the table, if it turns out to not be this - // wide, then it will stretch the table to fit, if it is wider then each cell will be made - // proportionalty smaller, and the content may have to wrap. - // 'maxWidth'=> similar to 'width', but will only make table smaller than it wants to be - // 'options' => array(=>array('justification'=>'left','width'=>100,'link'=>linkDataName),=>....) - // allow the setting of other paramaters for the individual columns - // 'minRowSpace'=> the minimum space between the bottom of each row and the bottom margin, in which a new row will be started - // if it is less, then a new page would be started, default=-100 - // 'innerLineThickness'=>1 - // 'outerLineThickness'=>1 - // 'splitRows'=>0, 0 or 1, whether or not to allow the rows to be split across page boundaries - // 'protectRows'=>number, the number of rows to hold with the heading on page, ie, if there less than this number of - // rows on the page, then move the whole lot onto the next page, default=1 - // - // note that the user will have had to make a font selection already or this will not - // produce a valid pdf file. - - if (!is_array($data)){ - return; - } - - if (!is_array($cols)){ - // take the columns from the first row of the data set - reset($data); - list($k,$v)=each($data); - if (!is_array($v)){ - return; - } - $cols=array(); - foreach($v as $k1=>$v1){ - $cols[$k1]=$k1; - } - } - - if (!is_array($options)){ - $options=array(); - } - - $defaults = array( - 'shaded'=>1,'showLines'=>1,'shadeCol'=>array(0.8,0.8,0.8),'shadeCol2'=>array(0.7,0.7,0.7),'fontSize'=>10,'titleFontSize'=>12 - ,'titleGap'=>5,'lineCol'=>array(0,0,0),'gap'=>5,'xPos'=>'centre','xOrientation'=>'centre' - ,'showHeadings'=>1,'textCol'=>array(0,0,0),'width'=>0,'maxWidth'=>0,'cols'=>array(),'minRowSpace'=>-100,'rowGap'=>2,'colGap'=>5 - ,'innerLineThickness'=>1,'outerLineThickness'=>1,'splitRows'=>0,'protectRows'=>1 - ); - - foreach($defaults as $key=>$value){ - if (is_array($value)){ - if (!isset($options[$key]) || !is_array($options[$key])){ - $options[$key]=$value; - } - } else { - if (!isset($options[$key])){ - $options[$key]=$value; - } - } - } - $options['gap']=2*$options['colGap']; - - $middle = ($this->ez['pageWidth']-$this->ez['rightMargin'])/2+($this->ez['leftMargin'])/2; - // figure out the maximum widths of the text within each column - $maxWidth=array(); - foreach($cols as $colName=>$colHeading){ - $maxWidth[$colName]=0; - } - // find the maximum cell widths based on the data - foreach($data as $row){ - foreach($cols as $colName=>$colHeading){ - $w = $this->ezPrvtGetTextWidth($options['fontSize'],(string)$row[$colName])*1.01; - if ($w > $maxWidth[$colName]){ - $maxWidth[$colName]=$w; - } - } - } - // and the maximum widths to fit in the headings - foreach($cols as $colName=>$colTitle){ - $w = $this->ezPrvtGetTextWidth($options['fontSize'],(string)$colTitle)*1.01; - if ($w > $maxWidth[$colName]){ - $maxWidth[$colName]=$w; - } - } - - // calculate the start positions of each of the columns - $pos=array(); - $x=0; - $t=$x; - $adjustmentWidth=0; - $setWidth=0; - foreach($maxWidth as $colName => $w){ - $pos[$colName]=$t; - // if the column width has been specified then set that here, also total the - // width avaliable for adjustment - if (isset($options['cols'][$colName]) && isset($options['cols'][$colName]['width']) && $options['cols'][$colName]['width']>0){ - $t=$t+$options['cols'][$colName]['width']; - $maxWidth[$colName] = $options['cols'][$colName]['width']-$options['gap']; - $setWidth += $options['cols'][$colName]['width']; - } else { - $t=$t+$w+$options['gap']; - $adjustmentWidth += $w; - $setWidth += $options['gap']; - } - } - $pos['_end_']=$t; - - // if maxWidth is specified, and the table is too wide, and the width has not been set, - // then set the width. - if ($options['width']==0 && $options['maxWidth'] && ($t-$x)>$options['maxWidth']){ - // then need to make this one smaller - $options['width']=$options['maxWidth']; - } - - if ($options['width'] && $adjustmentWidth>0 && $setWidth<$options['width']){ - // first find the current widths of the columns involved in this mystery - $cols0 = array(); - $cols1 = array(); - $xq=0; - $presentWidth=0; - $last=''; - foreach($pos as $colName=>$p){ - if (!isset($options['cols'][$last]) || !isset($options['cols'][$last]['width']) || $options['cols'][$last]['width']<=0){ - if (strlen($last)){ - $cols0[$last]=$p-$xq -$options['gap']; - $presentWidth += ($p-$xq - $options['gap']); - } - } else { - $cols1[$last]=$p-$xq; - } - $last=$colName; - $xq=$p; - } - // $cols0 contains the widths of all the columns which are not set - $neededWidth = $options['width']-$setWidth; - // if needed width is negative then add it equally to each column, else get more tricky - if ($presentWidth<$neededWidth){ - foreach($cols0 as $colName=>$w){ - $cols0[$colName]+= ($neededWidth-$presentWidth)/count($cols0); - } - } else { - - $cnt=0; - while ($presentWidth>$neededWidth && $cnt<100){ - $cnt++; // insurance policy - // find the widest columns, and the next to widest width - $aWidest = array(); - $nWidest=0; - $widest=0; - foreach($cols0 as $colName=>$w){ - if ($w>$widest){ - $aWidest=array($colName); - $nWidest = $widest; - $widest=$w; - } else if ($w==$widest){ - $aWidest[]=$colName; - } - } - // then figure out what the width of the widest columns would have to be to take up all the slack - $newWidestWidth = $widest - ($presentWidth-$neededWidth)/count($aWidest); - if ($newWidestWidth > $nWidest){ - // then there is space to set them to this - foreach($aWidest as $colName){ - $cols0[$colName] = $newWidestWidth; - } - $presentWidth=$neededWidth; - } else { - // there is not space, reduce the size of the widest ones down to the next size down, and we - // will go round again - foreach($aWidest as $colName){ - $cols0[$colName] = $nWidest; - } - $presentWidth=$presentWidth-($widest-$nWidest)*count($aWidest); - } - } - } - // $cols0 now contains the new widths of the constrained columns. - // now need to update the $pos and $maxWidth arrays - $xq=0; - foreach($pos as $colName=>$p){ - $pos[$colName]=$xq; - if (!isset($options['cols'][$colName]) || !isset($options['cols'][$colName]['width']) || $options['cols'][$colName]['width']<=0){ - if (isset($cols0[$colName])){ - $xq += $cols0[$colName] + $options['gap']; - $maxWidth[$colName]=$cols0[$colName]; - } - } else { - if (isset($cols1[$colName])){ - $xq += $cols1[$colName]; - } - } - } - - $t=$x+$options['width']; - $pos['_end_']=$t; - } - - // now adjust the table to the correct location across the page - switch ($options['xPos']){ - case 'left': - $xref = $this->ez['leftMargin']; - break; - case 'right': - $xref = $this->ez['pageWidth'] - $this->ez['rightMargin']; - break; - case 'centre': - case 'center': - $xref = $middle; - break; - default: - $xref = $options['xPos']; - break; - } - switch ($options['xOrientation']){ - case 'left': - $dx = $xref-$t; - break; - case 'right': - $dx = $xref; - break; - case 'centre': - case 'center': - $dx = $xref-$t/2; - break; - } - - - foreach($pos as $k=>$v){ - $pos[$k]=$v+$dx; - } - $x0=$x+$dx; - $x1=$t+$dx; - - $baseLeftMargin = $this->ez['leftMargin']; - $basePos = $pos; - $baseX0 = $x0; - $baseX1 = $x1; - - // ok, just about ready to make me a table - $this->setColor($options['textCol'][0],$options['textCol'][1],$options['textCol'][2]); - $this->setStrokeColor($options['shadeCol'][0],$options['shadeCol'][1],$options['shadeCol'][2]); - - $middle = ($x1+$x0)/2; - - // start a transaction which will be used to regress the table, if there are not enough rows protected - if ($options['protectRows']>0){ - $this->transaction('start'); - $movedOnce=0; - } - $abortTable = 1; - while ($abortTable){ - $abortTable=0; - - $dm = $this->ez['leftMargin']-$baseLeftMargin; - foreach($basePos as $k=>$v){ - $pos[$k]=$v+$dm; - } - $x0=$baseX0+$dm; - $x1=$baseX1+$dm; - $middle = ($x1+$x0)/2; - - - // if the title is set, then do that - if (strlen($title)){ - $w = $this->getTextWidth($options['titleFontSize'],$title); - $this->y -= $this->getFontHeight($options['titleFontSize']); - if ($this->y < $this->ez['bottomMargin']){ - $this->ezNewPage(); - // margins may have changed on the newpage - $dm = $this->ez['leftMargin']-$baseLeftMargin; - foreach($basePos as $k=>$v){ - $pos[$k]=$v+$dm; - } - $x0=$baseX0+$dm; - $x1=$baseX1+$dm; - $middle = ($x1+$x0)/2; - $this->y -= $this->getFontHeight($options['titleFontSize']); - } - $this->addText($middle-$w/2,$this->y,$options['titleFontSize'],$title); - $this->y -= $options['titleGap']; - } - - // margins may have changed on the newpage - $dm = $this->ez['leftMargin']-$baseLeftMargin; - foreach($basePos as $k=>$v){ - $pos[$k]=$v+$dm; - } - $x0=$baseX0+$dm; - $x1=$baseX1+$dm; - - $y=$this->y; // to simplify the code a bit - - // make the table - $height = $this->getFontHeight($options['fontSize']); - $decender = $this->getFontDecender($options['fontSize']); - - - - $y0=$y+$decender; - $dy=0; - if ($options['showHeadings']){ - // this function will move the start of the table to a new page if it does not fit on this one - $headingHeight = $this->ezPrvtTableColumnHeadings($cols,$pos,$maxWidth,$height,$decender,$options['rowGap'],$options['fontSize'],$y,$options); - $y0 = $y+$headingHeight; - $y1 = $y; - - - $dm = $this->ez['leftMargin']-$baseLeftMargin; - foreach($basePos as $k=>$v){ - $pos[$k]=$v+$dm; - } - $x0=$baseX0+$dm; - $x1=$baseX1+$dm; - - } else { - $y1 = $y0; - } - $firstLine=1; - - - // open an object here so that the text can be put in over the shading - if ($options['shaded']){ - $this->saveState(); - $textObjectId = $this->openObject(); - $this->closeObject(); - $this->addObject($textObjectId); - $this->reopenObject($textObjectId); - } - - $cnt=0; - $newPage=0; - foreach($data as $row){ - $cnt++; - // the transaction support will be used to prevent rows being split - if ($options['splitRows']==0){ - $pageStart = $this->ezPageCount; - if (isset($this->ez['columns']) && $this->ez['columns']['on']==1){ - $columnStart = $this->ez['columns']['colNum']; - } - $this->transaction('start'); - $row_orig = $row; - $y_orig = $y; - $y0_orig = $y0; - $y1_orig = $y1; - } - $ok=0; - $secondTurn=0; - while(!$abortTable && $ok == 0){ - - $mx=0; - $newRow=1; - while(!$abortTable && ($newPage || $newRow)){ - - $y-=$height; - if ($newPage || $y<$this->ez['bottomMargin'] || (isset($options['minRowSpace']) && $y<($this->ez['bottomMargin']+$options['minRowSpace'])) ){ - // check that enough rows are with the heading - if ($options['protectRows']>0 && $movedOnce==0 && $cnt<=$options['protectRows']){ - // then we need to move the whole table onto the next page - $movedOnce = 1; - $abortTable = 1; - } - - $y2=$y-$mx+2*$height+$decender-$newRow*$height; - if ($options['showLines']){ - if (!$options['showHeadings']){ - $y0=$y1; - } - $this->ezPrvtTableDrawLines($pos,$options['gap'],$x0,$x1,$y0,$y1,$y2,$options['lineCol'],$options['innerLineThickness'],$options['outerLineThickness'],$options['showLines']); - } - if ($options['shaded']){ - $this->closeObject(); - $this->restoreState(); - } - $this->ezNewPage(); - // and the margins may have changed, this is due to the possibility of the columns being turned on - // as the columns are managed by manipulating the margins - - $dm = $this->ez['leftMargin']-$baseLeftMargin; - foreach($basePos as $k=>$v){ - $pos[$k]=$v+$dm; - } -// $x0=$x0+$dm; -// $x1=$x1+$dm; - $x0=$baseX0+$dm; - $x1=$baseX1+$dm; - - if ($options['shaded']){ - $this->saveState(); - $textObjectId = $this->openObject(); - $this->closeObject(); - $this->addObject($textObjectId); - $this->reopenObject($textObjectId); - } - $this->setColor($options['textCol'][0],$options['textCol'][1],$options['textCol'][2],1); - $y = $this->ez['pageHeight']-$this->ez['topMargin']; - $y0=$y+$decender; - $mx=0; - if ($options['showHeadings']){ - $this->ezPrvtTableColumnHeadings($cols,$pos,$maxWidth,$height,$decender,$options['rowGap'],$options['fontSize'],$y,$options); - $y1=$y; - } else { - $y1=$y0; - } - $firstLine=1; - $y -= $height; - } - $newRow=0; - // write the actual data - // if these cells need to be split over a page, then $newPage will be set, and the remaining - // text will be placed in $leftOvers - $newPage=0; - $leftOvers=array(); - - foreach($cols as $colName=>$colTitle){ - $this->ezSetY($y+$height); - $colNewPage=0; - if (isset($row[$colName])){ - if (isset($options['cols'][$colName]) && isset($options['cols'][$colName]['link']) && strlen($options['cols'][$colName]['link'])){ - - $lines = explode("\n",$row[$colName]); - if (isset($row[$options['cols'][$colName]['link']]) && strlen($row[$options['cols'][$colName]['link']])){ - foreach($lines as $k=>$v){ - $lines[$k]=''.$v.''; - } - } - } else { - $lines = explode("\n",$row[$colName]); - } - } else { - $lines = array(); - } - $this->y -= $options['rowGap']; - foreach ($lines as $line){ - $line = $this->ezProcessText($line); - $start=1; - - while (strlen($line) || $start){ - $start=0; - if (!$colNewPage){ - $this->y=$this->y-$height; - } - if ($this->y < $this->ez['bottomMargin']){ - // $this->ezNewPage(); - $newPage=1; // whether a new page is required for any of the columns - $colNewPage=1; // whether a new page is required for this column - } - if ($colNewPage){ - if (isset($leftOvers[$colName])){ - $leftOvers[$colName].="\n".$line; - } else { - $leftOvers[$colName] = $line; - } - $line=''; - } else { - if (isset($options['cols'][$colName]) && isset($options['cols'][$colName]['justification']) ){ - $just = $options['cols'][$colName]['justification']; - } else { - $just='left'; - } - - $line=$this->addTextWrap($pos[$colName],$this->y,$maxWidth[$colName],$options['fontSize'],$line,$just); - } - } - } - - $dy=$y+$height-$this->y+$options['rowGap']; - if ($dy-$height*$newPage>$mx){ - $mx=$dy-$height*$newPage; - } - } - // set $row to $leftOvers so that they will be processed onto the new page - $row = $leftOvers; - // now add the shading underneath - if ($options['shaded'] && $cnt%2==0){ - $this->closeObject(); - $this->setColor($options['shadeCol'][0],$options['shadeCol'][1],$options['shadeCol'][2],1); - $this->filledRectangle($x0-$options['gap']/2,$y+$decender+$height-$mx,$x1-$x0,$mx); - $this->reopenObject($textObjectId); - } - - if ($options['shaded']==2 && $cnt%2==1){ - $this->closeObject(); - $this->setColor($options['shadeCol2'][0],$options['shadeCol2'][1],$options['shadeCol2'][2],1); - $this->filledRectangle($x0-$options['gap']/2,$y+$decender+$height-$mx,$x1-$x0,$mx); - $this->reopenObject($textObjectId); - } - - if ($options['showLines']>1){ - // then draw a line on the top of each block -// $this->closeObject(); - $this->saveState(); - $this->setStrokeColor($options['lineCol'][0],$options['lineCol'][1],$options['lineCol'][2],1); -// $this->line($x0-$options['gap']/2,$y+$decender+$height-$mx,$x1-$x0,$mx); - if ($firstLine){ - $this->setLineStyle($options['outerLineThickness']); - $firstLine=0; - } else { - $this->setLineStyle($options['innerLineThickness']); - } - $this->line($x0-$options['gap']/2,$y+$decender+$height,$x1-$options['gap']/2,$y+$decender+$height); - $this->restoreState(); -// $this->reopenObject($textObjectId); - } - } // end of while - $y=$y-$mx+$height; - - // checking row split over pages - if ($options['splitRows']==0){ - if ( ( ($this->ezPageCount != $pageStart) || (isset($this->ez['columns']) && $this->ez['columns']['on']==1 && $columnStart != $this->ez['columns']['colNum'] )) && $secondTurn==0){ - // then we need to go back and try that again ! - $newPage=1; - $secondTurn=1; - $this->transaction('rewind'); - $row = $row_orig; - $y = $y_orig; - $y0 = $y0_orig; - $y1 = $y1_orig; - $ok=0; - - $dm = $this->ez['leftMargin']-$baseLeftMargin; - foreach($basePos as $k=>$v){ - $pos[$k]=$v+$dm; - } - $x0=$baseX0+$dm; - $x1=$baseX1+$dm; - - } else { - $this->transaction('commit'); - $ok=1; - } - } else { - $ok=1; // don't go round the loop if splitting rows is allowed - } - - } // end of while to check for row splitting - if ($abortTable){ - if ($ok==0){ - $this->transaction('abort'); - } - // only the outer transaction should be operational - $this->transaction('rewind'); - $this->ezNewPage(); - break; - } - - } // end of foreach ($data as $row) - - } // end of while ($abortTable) - - // table has been put on the page, the rows guarded as required, commit. - $this->transaction('commit'); - - $y2=$y+$decender; - if ($options['showLines']){ - if (!$options['showHeadings']){ - $y0=$y1; - } - $this->ezPrvtTableDrawLines($pos,$options['gap'],$x0,$x1,$y0,$y1,$y2,$options['lineCol'],$options['innerLineThickness'],$options['outerLineThickness'],$options['showLines']); - } - - // close the object for drawing the text on top - if ($options['shaded']){ - $this->closeObject(); - $this->restoreState(); - } - - $this->y=$y; - return $y; -} - -// ------------------------------------------------------------------------------ -function ezProcessText($text){ - // this function will intially be used to implement underlining support, but could be used for a range of other - // purposes - $search = array('','','',''); - $replace = array('','','',''); - return str_replace($search,$replace,$text); -} - -// ------------------------------------------------------------------------------ - -function ezText($text,$size=0,$options=array(),$test=0){ - // this will add a string of text to the document, starting at the current drawing - // position. - // it will wrap to keep within the margins, including optional offsets from the left - // and the right, if $size is not specified, then it will be the last one used, or - // the default value (12 I think). - // the text will go to the start of the next line when a return code "\n" is found. - // possible options are: - // 'left'=> number, gap to leave from the left margin - // 'right'=> number, gap to leave from the right margin - // 'aleft'=> number, absolute left position (overrides 'left') - // 'aright'=> number, absolute right position (overrides 'right') - // 'justification' => 'left','right','center','centre','full' - - // only set one of the next two items (leading overrides spacing) - // 'leading' => number, defines the total height taken by the line, independent of the font height. - // 'spacing' => a real number, though usually set to one of 1, 1.5, 2 (line spacing as used in word processing) - - // if $test is set then this should just check if the text is going to flow onto a new page or not, returning true or false - - // apply the filtering which will make the underlining function. - $text = $this->ezProcessText($text); - - $newPage=false; - $store_y = $this->y; - - if (is_array($options) && isset($options['aleft'])){ - $left=$options['aleft']; - } else { - $left = $this->ez['leftMargin'] + ((is_array($options) && isset($options['left']))?$options['left']:0); - } - if (is_array($options) && isset($options['aright'])){ - $right=$options['aright']; - } else { - $right = $this->ez['pageWidth'] - $this->ez['rightMargin'] - ((is_array($options) && isset($options['right']))?$options['right']:0); - } - if ($size<=0){ - $size = $this->ez['fontSize']; - } else { - $this->ez['fontSize']=$size; - } - - if (is_array($options) && isset($options['justification'])){ - $just = $options['justification']; - } else { - $just = 'left'; - } - - // modifications to give leading and spacing based on those given by Craig Heydenburg 1/1/02 - if (is_array($options) && isset($options['leading'])) { ## use leading instead of spacing - $height = $options['leading']; - } else if (is_array($options) && isset($options['spacing'])) { - $height = $this->getFontHeight($size) * $options['spacing']; - } else { - $height = $this->getFontHeight($size); - } - - - $lines = explode("\n",$text); - foreach ($lines as $line){ - $start=1; - while (strlen($line) || $start){ - $start=0; - $this->y=$this->y-$height; - if ($this->y < $this->ez['bottomMargin']){ - if ($test){ - $newPage=true; - } else { - $this->ezNewPage(); - // and then re-calc the left and right, in case they have changed due to columns - } - } - if (is_array($options) && isset($options['aleft'])){ - $left=$options['aleft']; - } else { - $left = $this->ez['leftMargin'] + ((is_array($options) && isset($options['left']))?$options['left']:0); - } - if (is_array($options) && isset($options['aright'])){ - $right=$options['aright']; - } else { - $right = $this->ez['pageWidth'] - $this->ez['rightMargin'] - ((is_array($options) && isset($options['right']))?$options['right']:0); - } - $line=$this->addTextWrap($left,$this->y,$right-$left,$size,$line,$just,0,$test); - } - } - - if ($test){ - $this->y=$store_y; - return $newPage; - } else { - return $this->y; - } -} - -// ------------------------------------------------------------------------------ - -function ezImage($image,$pad = 5,$width = 0,$resize = 'full',$just = 'center',$border = ''){ - //beta ezimage function - if (stristr($image,'://'))//copy to temp file - { - $fp = @fopen($image,"rb"); - while(!feof($fp)) - { - $cont.= fread($fp,1024); - } - fclose($fp); - $image = tempnam ("/tmp", "php-pdf"); - $fp2 = @fopen($image,"w"); - fwrite($fp2,$cont); - fclose($fp2); - $temp = true; - } - - if (!(file_exists($image))) return false; //return immediately if image file does not exist - $imageInfo = getimagesize($image); - switch ($imageInfo[2]){ - case 2: - $type = "jpeg"; - break; - case 3: - $type = "png"; - break; - default: - return false; //return if file is not jpg or png - } - if ($width == 0) $width = $imageInfo[0]; //set width - $ratio = $imageInfo[0]/$imageInfo[1]; - - //get maximum width of image - if (isset($this->ez['columns']) && $this->ez['columns']['on'] == 1) - { - $bigwidth = $this->ez['columns']['width'] - ($pad * 2); - } - else - { - $bigwidth = $this->ez['pageWidth'] - ($pad * 2); - } - //fix width if larger than maximum or if $resize=full - if ($resize == 'full' || $resize == 'width' || $width > $bigwidth) - { - $width = $bigwidth; - - } - - $height = ($width/$ratio); //set height - - //fix size if runs off page - if ($height > ($this->y - $this->ez['bottomMargin'] - ($pad * 2))) - { - if ($resize != 'full') - { - $this->ezNewPage(); - } - else - { - $height = ($this->y - $this->ez['bottomMargin'] - ($pad * 2)); //shrink height - $width = ($height*$ratio); //fix width - } - } - - //fix x-offset if image smaller than bigwidth - if ($width < $bigwidth) - { - //center if justification=center - if ($just == 'center') - { - $offset = ($bigwidth - $width) / 2; - } - //move to right if justification=right - if ($just == 'right') - { - $offset = ($bigwidth - $width); - } - //leave at left if justification=left - if ($just == 'left') - { - $offset = 0; - } - } - - - //call appropriate function - if ($type == "jpeg"){ - $this->addJpegFromFile($image,$this->ez['leftMargin'] + $pad + $offset, $this->y + $this->getFontHeight($this->ez['fontSize']) - $pad - $height,$width); - } - - if ($type == "png"){ - $this->addPngFromFile($image,$this->ez['leftMargin'] + $pad + $offset, $this->y + $this->getFontHeight($this->ez['fontSize']) - $pad - $height,$width); - } - //draw border - if ($border != '') - { - if (!(isset($border['color']))) - { - $border['color']['red'] = .5; - $border['color']['blue'] = .5; - $border['color']['green'] = .5; - } - if (!(isset($border['width']))) $border['width'] = 1; - if (!(isset($border['cap']))) $border['cap'] = 'round'; - if (!(isset($border['join']))) $border['join'] = 'round'; - - - $this->setStrokeColor($border['color']['red'],$border['color']['green'],$border['color']['blue']); - $this->setLineStyle($border['width'],$border['cap'],$border['join']); - $this->rectangle($this->ez['leftMargin'] + $pad + $offset, $this->y + $this->getFontHeight($this->ez['fontSize']) - $pad - $height,$width,$height); - - } - // move y below image - $this->y = $this->y - $pad - $height; - //remove tempfile for remote images - if ($temp == true) unlink($image); - -} -// ------------------------------------------------------------------------------ - -// note that templating code is still considered developmental - have not really figured -// out a good way of doing this yet. -function loadTemplate($templateFile){ - // this function will load the requested template ($file includes full or relative pathname) - // the code for the template will be modified to make it name safe, and then stored in - // an array for later use - // The id of the template will be returned for the user to operate on it later - if (!file_exists($templateFile)){ - return -1; - } - - $code = implode('',file($templateFile)); - if (!strlen($code)){ - return; - } - - $code = trim($code); - if (substr($code,0,5)==''){ - $code = substr($code,0,strlen($code)-2); - } - if (isset($this->ez['numTemplates'])){ - $newNum = $this->ez['numTemplates']; - $this->ez['numTemplates']++; - } else { - $newNum=0; - $this->ez['numTemplates']=1; - $this->ez['templates']=array(); - } - - $this->ez['templates'][$newNum]['code']=$code; - - return $newNum; -} - -// ------------------------------------------------------------------------------ - -function execTemplate($id,$data=array(),$options=array()){ - // execute the given template on the current document. - if (!isset($this->ez['templates'][$id])){ - return; - } - eval($this->ez['templates'][$id]['code']); -} - -// ------------------------------------------------------------------------------ -function ilink($info){ - $this->alink($info,1); -} - -function alink($info,$internal=0){ - // a callback function to support the formation of clickable links within the document - $lineFactor=0.05; // the thickness of the line as a proportion of the height. also the drop of the line. - switch($info['status']){ - case 'start': - case 'sol': - // the beginning of the link - // this should contain the URl for the link as the 'p' entry, and will also contain the value of 'nCallback' - if (!isset($this->ez['links'])){ - $this->ez['links']=array(); - } - $i = $info['nCallback']; - $this->ez['links'][$i] = array('x'=>$info['x'],'y'=>$info['y'],'angle'=>$info['angle'],'decender'=>$info['decender'],'height'=>$info['height'],'url'=>$info['p']); - if ($internal==0){ - $this->saveState(); - $this->setColor(0,0,1); - $this->setStrokeColor(0,0,1); - $thick = $info['height']*$lineFactor; - $this->setLineStyle($thick); - } - break; - case 'end': - case 'eol': - // the end of the link - // assume that it is the most recent opening which has closed - $i = $info['nCallback']; - $start = $this->ez['links'][$i]; - // add underlining - if ($internal){ - $this->addInternalLink($start['url'],$start['x'],$start['y']+$start['decender'],$info['x'],$start['y']+$start['decender']+$start['height']); - } else { - $a = deg2rad((float)$start['angle']-90.0); - $drop = $start['height']*$lineFactor*1.5; - $dropx = cos($a)*$drop; - $dropy = -sin($a)*$drop; - $this->line($start['x']-$dropx,$start['y']-$dropy,$info['x']-$dropx,$info['y']-$dropy); - $this->addLink($start['url'],$start['x'],$start['y']+$start['decender'],$info['x'],$start['y']+$start['decender']+$start['height']); - $this->restoreState(); - } - break; - } -} - -// ------------------------------------------------------------------------------ - -function uline($info){ - // a callback function to support underlining - $lineFactor=0.05; // the thickness of the line as a proportion of the height. also the drop of the line. - switch($info['status']){ - case 'start': - case 'sol': - - // the beginning of the underline zone - if (!isset($this->ez['links'])){ - $this->ez['links']=array(); - } - $i = $info['nCallback']; - $this->ez['links'][$i] = array('x'=>$info['x'],'y'=>$info['y'],'angle'=>$info['angle'],'decender'=>$info['decender'],'height'=>$info['height']); - $this->saveState(); - $thick = $info['height']*$lineFactor; - $this->setLineStyle($thick); - break; - case 'end': - case 'eol': - // the end of the link - // assume that it is the most recent opening which has closed - $i = $info['nCallback']; - $start = $this->ez['links'][$i]; - // add underlining - $a = deg2rad((float)$start['angle']-90.0); - $drop = $start['height']*$lineFactor*1.5; - $dropx = cos($a)*$drop; - $dropy = -sin($a)*$drop; - $this->line($start['x']-$dropx,$start['y']-$dropy,$info['x']-$dropx,$info['y']-$dropy); - $this->restoreState(); - break; - } -} - -// ------------------------------------------------------------------------------ - -} -?> \ No newline at end of file diff --git a/mods/pdf_converter/class.pdf.php b/mods/pdf_converter/class.pdf.php deleted file mode 100644 index d8b720c62..000000000 --- a/mods/pdf_converter/class.pdf.php +++ /dev/null @@ -1,3077 +0,0 @@ - -* @version 009 -* @package Cpdf -*/ -class Cpdf { - -/** -* the current number of pdf objects in the document -*/ -var $numObj=0; -/** -* this array contains all of the pdf objects, ready for final assembly -*/ -var $objects = array(); -/** -* the objectId (number within the objects array) of the document catalog -*/ -var $catalogId; -/** -* array carrying information about the fonts that the system currently knows about -* used to ensure that a font is not loaded twice, among other things -*/ -var $fonts=array(); -/** -* a record of the current font -*/ -var $currentFont=''; -/** -* the current base font -*/ -var $currentBaseFont=''; -/** -* the number of the current font within the font array -*/ -var $currentFontNum=0; -/** -* -*/ -var $currentNode; -/** -* object number of the current page -*/ -var $currentPage; -/** -* object number of the currently active contents block -*/ -var $currentContents; -/** -* number of fonts within the system -*/ -var $numFonts=0; -/** -* current colour for fill operations, defaults to inactive value, all three components should be between 0 and 1 inclusive when active -*/ -var $currentColour=array('r'=>-1,'g'=>-1,'b'=>-1); -/** -* current colour for stroke operations (lines etc.) -*/ -var $currentStrokeColour=array('r'=>-1,'g'=>-1,'b'=>-1); -/** -* current style that lines are drawn in -*/ -var $currentLineStyle=''; -/** -* an array which is used to save the state of the document, mainly the colours and styles -* it is used to temporarily change to another state, the change back to what it was before -*/ -var $stateStack = array(); -/** -* number of elements within the state stack -*/ -var $nStateStack = 0; -/** -* number of page objects within the document -*/ -var $numPages=0; -/** -* object Id storage stack -*/ -var $stack=array(); -/** -* number of elements within the object Id storage stack -*/ -var $nStack=0; -/** -* an array which contains information about the objects which are not firmly attached to pages -* these have been added with the addObject function -*/ -var $looseObjects=array(); -/** -* array contains infomation about how the loose objects are to be added to the document -*/ -var $addLooseObjects=array(); -/** -* the objectId of the information object for the document -* this contains authorship, title etc. -*/ -var $infoObject=0; -/** -* number of images being tracked within the document -*/ -var $numImages=0; -/** -* an array containing options about the document -* it defaults to turning on the compression of the objects -*/ -var $options=array('compression'=>1); -/** -* the objectId of the first page of the document -*/ -var $firstPageId; -/** -* used to track the last used value of the inter-word spacing, this is so that it is known -* when the spacing is changed. -*/ -var $wordSpaceAdjust=0; -/** -* the object Id of the procset object -*/ -var $procsetObjectId; -/** -* store the information about the relationship between font families -* this used so that the code knows which font is the bold version of another font, etc. -* the value of this array is initialised in the constuctor function. -*/ -var $fontFamilies = array(); -/** -* track if the current font is bolded or italicised -*/ -var $currentTextState = ''; -/** -* messages are stored here during processing, these can be selected afterwards to give some useful debug information -*/ -var $messages=''; -/** -* the ancryption array for the document encryption is stored here -*/ -var $arc4=''; -/** -* the object Id of the encryption information -*/ -var $arc4_objnum=0; -/** -* the file identifier, used to uniquely identify a pdf document -*/ -var $fileIdentifier=''; -/** -* a flag to say if a document is to be encrypted or not -*/ -var $encrypted=0; -/** -* the ancryption key for the encryption of all the document content (structure is not encrypted) -*/ -var $encryptionKey=''; -/** -* array which forms a stack to keep track of nested callback functions -*/ -var $callback = array(); -/** -* the number of callback functions in the callback array -*/ -var $nCallback = 0; -/** -* store label->id pairs for named destinations, these will be used to replace internal links -* done this way so that destinations can be defined after the location that links to them -*/ -var $destinations = array(); -/** -* store the stack for the transaction commands, each item in here is a record of the values of all the -* variables within the class, so that the user can rollback at will (from each 'start' command) -* note that this includes the objects array, so these can be large. -*/ -var $checkpoint = ''; -/** -* class constructor -* this will start a new document -* @var array array of 4 numbers, defining the bottom left and upper right corner of the page. first two are normally zero. -*/ -function Cpdf ($pageSize=array(0,0,612,792)){ - $this->newDocument($pageSize); - - // also initialize the font families that are known about already - $this->setFontFamily('init'); -// $this->fileIdentifier = md5('xxxxxxxx'.time()); - -} - -/** -* Document object methods (internal use only) -* -* There is about one object method for each type of object in the pdf document -* Each function has the same call list ($id,$action,$options). -* $id = the object ID of the object, or what it is to be if it is being created -* $action = a string specifying the action to be performed, though ALL must support: -* 'new' - create the object with the id $id -* 'out' - produce the output for the pdf object -* $options = optional, a string or array containing the various parameters for the object -* -* These, in conjunction with the output function are the ONLY way for output to be produced -* within the pdf 'file'. -*/ - -/** -*destination object, used to specify the location for the user to jump to, presently on opening -*/ -function o_destination($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch($action){ - case 'new': - $this->objects[$id]=array('t'=>'destination','info'=>array()); - $tmp = ''; - switch ($options['type']){ - case 'XYZ': - case 'FitR': - $tmp = ' '.$options['p3'].$tmp; - case 'FitH': - case 'FitV': - case 'FitBH': - case 'FitBV': - $tmp = ' '.$options['p1'].' '.$options['p2'].$tmp; - case 'Fit': - case 'FitB': - $tmp = $options['type'].$tmp; - $this->objects[$id]['info']['string']=$tmp; - $this->objects[$id]['info']['page']=$options['page']; - } - break; - case 'out': - $tmp = $o['info']; - $res="\n".$id." 0 obj\n".'['.$tmp['page'].' 0 R /'.$tmp['string']."]\nendobj\n"; - return $res; - break; - } -} - -/** -* set the viewer preferences -*/ -function o_viewerPreferences($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - $this->objects[$id]=array('t'=>'viewerPreferences','info'=>array()); - break; - case 'add': - foreach($options as $k=>$v){ - switch ($k){ - case 'HideToolbar': - case 'HideMenubar': - case 'HideWindowUI': - case 'FitWindow': - case 'CenterWindow': - case 'NonFullScreenPageMode': - case 'Direction': - $o['info'][$k]=$v; - break; - } - } - break; - case 'out': - - $res="\n".$id." 0 obj\n".'<< '; - foreach($o['info'] as $k=>$v){ - $res.="\n/".$k.' '.$v; - } - $res.="\n>>\n"; - return $res; - break; - } -} - -/** -* define the document catalog, the overall controller for the document -*/ -function o_catalog($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - $this->objects[$id]=array('t'=>'catalog','info'=>array()); - $this->catalogId=$id; - break; - case 'outlines': - case 'pages': - case 'openHere': - $o['info'][$action]=$options; - break; - case 'viewerPreferences': - if (!isset($o['info']['viewerPreferences'])){ - $this->numObj++; - $this->o_viewerPreferences($this->numObj,'new'); - $o['info']['viewerPreferences']=$this->numObj; - } - $vp = $o['info']['viewerPreferences']; - $this->o_viewerPreferences($vp,'add',$options); - break; - case 'out': - $res="\n".$id." 0 obj\n".'<< /Type /Catalog'; - foreach($o['info'] as $k=>$v){ - switch($k){ - case 'outlines': - $res.="\n".'/Outlines '.$v.' 0 R'; - break; - case 'pages': - $res.="\n".'/Pages '.$v.' 0 R'; - break; - case 'viewerPreferences': - $res.="\n".'/ViewerPreferences '.$o['info']['viewerPreferences'].' 0 R'; - break; - case 'openHere': - $res.="\n".'/OpenAction '.$o['info']['openHere'].' 0 R'; - break; - } - } - $res.=" >>\nendobj"; - return $res; - break; - } -} - -/** -* object which is a parent to the pages in the document -*/ -function o_pages($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - $this->objects[$id]=array('t'=>'pages','info'=>array()); - $this->o_catalog($this->catalogId,'pages',$id); - break; - case 'page': - if (!is_array($options)){ - // then it will just be the id of the new page - $o['info']['pages'][]=$options; - } else { - // then it should be an array having 'id','rid','pos', where rid=the page to which this one will be placed relative - // and pos is either 'before' or 'after', saying where this page will fit. - if (isset($options['id']) && isset($options['rid']) && isset($options['pos'])){ - $i = array_search($options['rid'],$o['info']['pages']); - if (isset($o['info']['pages'][$i]) && $o['info']['pages'][$i]==$options['rid']){ - // then there is a match - // make a space - switch ($options['pos']){ - case 'before': - $k = $i; - break; - case 'after': - $k=$i+1; - break; - default: - $k=-1; - break; - } - if ($k>=0){ - for ($j=count($o['info']['pages'])-1;$j>=$k;$j--){ - $o['info']['pages'][$j+1]=$o['info']['pages'][$j]; - } - $o['info']['pages'][$k]=$options['id']; - } - } - } - } - break; - case 'procset': - $o['info']['procset']=$options; - break; - case 'mediaBox': - $o['info']['mediaBox']=$options; // which should be an array of 4 numbers - break; - case 'font': - $o['info']['fonts'][]=array('objNum'=>$options['objNum'],'fontNum'=>$options['fontNum']); - break; - case 'xObject': - $o['info']['xObjects'][]=array('objNum'=>$options['objNum'],'label'=>$options['label']); - break; - case 'out': - if (count($o['info']['pages'])){ - $res="\n".$id." 0 obj\n<< /Type /Pages\n/Kids ["; - foreach($o['info']['pages'] as $k=>$v){ - $res.=$v." 0 R\n"; - } - $res.="]\n/Count ".count($this->objects[$id]['info']['pages']); - if ((isset($o['info']['fonts']) && count($o['info']['fonts'])) || isset($o['info']['procset'])){ - $res.="\n/Resources <<"; - if (isset($o['info']['procset'])){ - $res.="\n/ProcSet ".$o['info']['procset']." 0 R"; - } - if (isset($o['info']['fonts']) && count($o['info']['fonts'])){ - $res.="\n/Font << "; - foreach($o['info']['fonts'] as $finfo){ - $res.="\n/F".$finfo['fontNum']." ".$finfo['objNum']." 0 R"; - } - $res.=" >>"; - } - if (isset($o['info']['xObjects']) && count($o['info']['xObjects'])){ - $res.="\n/XObject << "; - foreach($o['info']['xObjects'] as $finfo){ - $res.="\n/".$finfo['label']." ".$finfo['objNum']." 0 R"; - } - $res.=" >>"; - } - $res.="\n>>"; - if (isset($o['info']['mediaBox'])){ - $tmp=$o['info']['mediaBox']; - $res.="\n/MediaBox [".sprintf('%.3f',$tmp[0]).' '.sprintf('%.3f',$tmp[1]).' '.sprintf('%.3f',$tmp[2]).' '.sprintf('%.3f',$tmp[3]).']'; - } - } - $res.="\n >>\nendobj"; - } else { - $res="\n".$id." 0 obj\n<< /Type /Pages\n/Count 0\n>>\nendobj"; - } - return $res; - break; - } -} - -/** -* define the outlines in the doc, empty for now -*/ -function o_outlines($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - $this->objects[$id]=array('t'=>'outlines','info'=>array('outlines'=>array())); - $this->o_catalog($this->catalogId,'outlines',$id); - break; - case 'outline': - $o['info']['outlines'][]=$options; - break; - case 'out': - if (count($o['info']['outlines'])){ - $res="\n".$id." 0 obj\n<< /Type /Outlines /Kids ["; - foreach($o['info']['outlines'] as $k=>$v){ - $res.=$v." 0 R "; - } - $res.="] /Count ".count($o['info']['outlines'])." >>\nendobj"; - } else { - $res="\n".$id." 0 obj\n<< /Type /Outlines /Count 0 >>\nendobj"; - } - return $res; - break; - } -} - -/** -* an object to hold the font description -*/ -function o_font($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - $this->objects[$id]=array('t'=>'font','info'=>array('name'=>$options['name'],'SubType'=>'Type1')); - $fontNum=$this->numFonts; - $this->objects[$id]['info']['fontNum']=$fontNum; - // deal with the encoding and the differences - if (isset($options['differences'])){ - // then we'll need an encoding dictionary - $this->numObj++; - $this->o_fontEncoding($this->numObj,'new',$options); - $this->objects[$id]['info']['encodingDictionary']=$this->numObj; - } else if (isset($options['encoding'])){ - // we can specify encoding here - switch($options['encoding']){ - case 'WinAnsiEncoding': - case 'MacRomanEncoding': - case 'MacExpertEncoding': - $this->objects[$id]['info']['encoding']=$options['encoding']; - break; - case 'none': - break; - default: - $this->objects[$id]['info']['encoding']='WinAnsiEncoding'; - break; - } - } else { - $this->objects[$id]['info']['encoding']='WinAnsiEncoding'; - } - // also tell the pages node about the new font - $this->o_pages($this->currentNode,'font',array('fontNum'=>$fontNum,'objNum'=>$id)); - break; - case 'add': - foreach ($options as $k=>$v){ - switch ($k){ - case 'BaseFont': - $o['info']['name'] = $v; - break; - case 'FirstChar': - case 'LastChar': - case 'Widths': - case 'FontDescriptor': - case 'SubType': - $this->addMessage('o_font '.$k." : ".$v); - $o['info'][$k] = $v; - break; - } - } - break; - case 'out': - $res="\n".$id." 0 obj\n<< /Type /Font\n/Subtype /".$o['info']['SubType']."\n"; - $res.="/Name /F".$o['info']['fontNum']."\n"; - $res.="/BaseFont /".$o['info']['name']."\n"; - if (isset($o['info']['encodingDictionary'])){ - // then place a reference to the dictionary - $res.="/Encoding ".$o['info']['encodingDictionary']." 0 R\n"; - } else if (isset($o['info']['encoding'])){ - // use the specified encoding - $res.="/Encoding /".$o['info']['encoding']."\n"; - } - if (isset($o['info']['FirstChar'])){ - $res.="/FirstChar ".$o['info']['FirstChar']."\n"; - } - if (isset($o['info']['LastChar'])){ - $res.="/LastChar ".$o['info']['LastChar']."\n"; - } - if (isset($o['info']['Widths'])){ - $res.="/Widths ".$o['info']['Widths']." 0 R\n"; - } - if (isset($o['info']['FontDescriptor'])){ - $res.="/FontDescriptor ".$o['info']['FontDescriptor']." 0 R\n"; - } - $res.=">>\nendobj"; - return $res; - break; - } -} - -/** -* a font descriptor, needed for including additional fonts -*/ -function o_fontDescriptor($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - $this->objects[$id]=array('t'=>'fontDescriptor','info'=>$options); - break; - case 'out': - $res="\n".$id." 0 obj\n<< /Type /FontDescriptor\n"; - foreach ($o['info'] as $label => $value){ - switch ($label){ - case 'Ascent': - case 'CapHeight': - case 'Descent': - case 'Flags': - case 'ItalicAngle': - case 'StemV': - case 'AvgWidth': - case 'Leading': - case 'MaxWidth': - case 'MissingWidth': - case 'StemH': - case 'XHeight': - case 'CharSet': - if (strlen($value)){ - $res.='/'.$label.' '.$value."\n"; - } - break; - case 'FontFile': - case 'FontFile2': - case 'FontFile3': - $res.='/'.$label.' '.$value." 0 R\n"; - break; - case 'FontBBox': - $res.='/'.$label.' ['.$value[0].' '.$value[1].' '.$value[2].' '.$value[3]."]\n"; - break; - case 'FontName': - $res.='/'.$label.' /'.$value."\n"; - break; - } - } - $res.=">>\nendobj"; - return $res; - break; - } -} - -/** -* the font encoding -*/ -function o_fontEncoding($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - // the options array should contain 'differences' and maybe 'encoding' - $this->objects[$id]=array('t'=>'fontEncoding','info'=>$options); - break; - case 'out': - $res="\n".$id." 0 obj\n<< /Type /Encoding\n"; - if (!isset($o['info']['encoding'])){ - $o['info']['encoding']='WinAnsiEncoding'; - } - if ($o['info']['encoding']!='none'){ - $res.="/BaseEncoding /".$o['info']['encoding']."\n"; - } - $res.="/Differences \n["; - $onum=-100; - foreach($o['info']['differences'] as $num=>$label){ - if ($num!=$onum+1){ - // we cannot make use of consecutive numbering - $res.= "\n".$num." /".$label; - } else { - $res.= " /".$label; - } - $onum=$num; - } - $res.="\n]\n>>\nendobj"; - return $res; - break; - } -} - -/** -* the document procset, solves some problems with printing to old PS printers -*/ -function o_procset($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - $this->objects[$id]=array('t'=>'procset','info'=>array('PDF'=>1,'Text'=>1)); - $this->o_pages($this->currentNode,'procset',$id); - $this->procsetObjectId=$id; - break; - case 'add': - // this is to add new items to the procset list, despite the fact that this is considered - // obselete, the items are required for printing to some postscript printers - switch ($options) { - case 'ImageB': - case 'ImageC': - case 'ImageI': - $o['info'][$options]=1; - break; - } - break; - case 'out': - $res="\n".$id." 0 obj\n["; - foreach ($o['info'] as $label=>$val){ - $res.='/'.$label.' '; - } - $res.="]\nendobj"; - return $res; - break; - } -} - -/** -* define the document information -*/ -function o_info($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - $this->infoObject=$id; - $date='D:'.date('Ymd'); - $this->objects[$id]=array('t'=>'info','info'=>array('Creator'=>'R and OS php pdf writer, http://www.ros.co.nz','CreationDate'=>$date)); - break; - case 'Title': - case 'Author': - case 'Subject': - case 'Keywords': - case 'Creator': - case 'Producer': - case 'CreationDate': - case 'ModDate': - case 'Trapped': - $o['info'][$action]=$options; - break; - case 'out': - if ($this->encrypted){ - $this->encryptInit($id); - } - $res="\n".$id." 0 obj\n<<\n"; - foreach ($o['info'] as $k=>$v){ - $res.='/'.$k.' ('; - if ($this->encrypted){ - $res.=$this->filterText($this->ARC4($v)); - } else { - $res.=$this->filterText($v); - } - $res.=")\n"; - } - $res.=">>\nendobj"; - return $res; - break; - } -} - -/** -* an action object, used to link to URLS initially -*/ -function o_action($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - if (is_array($options)){ - $this->objects[$id]=array('t'=>'action','info'=>$options,'type'=>$options['type']); - } else { - // then assume a URI action - $this->objects[$id]=array('t'=>'action','info'=>$options,'type'=>'URI'); - } - break; - case 'out': - if ($this->encrypted){ - $this->encryptInit($id); - } - $res="\n".$id." 0 obj\n<< /Type /Action"; - switch($o['type']){ - case 'ilink': - // there will be an 'label' setting, this is the name of the destination - $res.="\n/S /GoTo\n/D ".$this->destinations[(string)$o['info']['label']]." 0 R"; - break; - case 'URI': - $res.="\n/S /URI\n/URI ("; - if ($this->encrypted){ - $res.=$this->filterText($this->ARC4($o['info'])); - } else { - $res.=$this->filterText($o['info']); - } - $res.=")"; - break; - } - $res.="\n>>\nendobj"; - return $res; - break; - } -} - -/** -* an annotation object, this will add an annotation to the current page. -* initially will support just link annotations -*/ -function o_annotation($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - // add the annotation to the current page - $pageId = $this->currentPage; - $this->o_page($pageId,'annot',$id); - // and add the action object which is going to be required - switch($options['type']){ - case 'link': - $this->objects[$id]=array('t'=>'annotation','info'=>$options); - $this->numObj++; - $this->o_action($this->numObj,'new',$options['url']); - $this->objects[$id]['info']['actionId']=$this->numObj; - break; - case 'ilink': - // this is to a named internal link - $label = $options['label']; - $this->objects[$id]=array('t'=>'annotation','info'=>$options); - $this->numObj++; - $this->o_action($this->numObj,'new',array('type'=>'ilink','label'=>$label)); - $this->objects[$id]['info']['actionId']=$this->numObj; - break; - } - break; - case 'out': - $res="\n".$id." 0 obj\n<< /Type /Annot"; - switch($o['info']['type']){ - case 'link': - case 'ilink': - $res.= "\n/Subtype /Link"; - break; - } - $res.="\n/A ".$o['info']['actionId']." 0 R"; - $res.="\n/Border [0 0 0]"; - $res.="\n/H /I"; - $res.="\n/Rect [ "; - foreach($o['info']['rect'] as $v){ - $res.= sprintf("%.4f ",$v); - } - $res.="]"; - $res.="\n>>\nendobj"; - return $res; - break; - } -} - -/** -* a page object, it also creates a contents object to hold its contents -*/ -function o_page($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - $this->numPages++; - $this->objects[$id]=array('t'=>'page','info'=>array('parent'=>$this->currentNode,'pageNum'=>$this->numPages)); - if (is_array($options)){ - // then this must be a page insertion, array shoudl contain 'rid','pos'=[before|after] - $options['id']=$id; - $this->o_pages($this->currentNode,'page',$options); - } else { - $this->o_pages($this->currentNode,'page',$id); - } - $this->currentPage=$id; - //make a contents object to go with this page - $this->numObj++; - $this->o_contents($this->numObj,'new',$id); - $this->currentContents=$this->numObj; - $this->objects[$id]['info']['contents']=array(); - $this->objects[$id]['info']['contents'][]=$this->numObj; - $match = ($this->numPages%2 ? 'odd' : 'even'); - foreach($this->addLooseObjects as $oId=>$target){ - if ($target=='all' || $match==$target){ - $this->objects[$id]['info']['contents'][]=$oId; - } - } - break; - case 'content': - $o['info']['contents'][]=$options; - break; - case 'annot': - // add an annotation to this page - if (!isset($o['info']['annot'])){ - $o['info']['annot']=array(); - } - // $options should contain the id of the annotation dictionary - $o['info']['annot'][]=$options; - break; - case 'out': - $res="\n".$id." 0 obj\n<< /Type /Page"; - $res.="\n/Parent ".$o['info']['parent']." 0 R"; - if (isset($o['info']['annot'])){ - $res.="\n/Annots ["; - foreach($o['info']['annot'] as $aId){ - $res.=" ".$aId." 0 R"; - } - $res.=" ]"; - } - $count = count($o['info']['contents']); - if ($count==1){ - $res.="\n/Contents ".$o['info']['contents'][0]." 0 R"; - } else if ($count>1){ - $res.="\n/Contents [\n"; - foreach ($o['info']['contents'] as $cId){ - $res.=$cId." 0 R\n"; - } - $res.="]"; - } - $res.="\n>>\nendobj"; - return $res; - break; - } -} - -/** -* the contents objects hold all of the content which appears on pages -*/ -function o_contents($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch ($action){ - case 'new': - $this->objects[$id]=array('t'=>'contents','c'=>'','info'=>array()); - if (strlen($options) && intval($options)){ - // then this contents is the primary for a page - $this->objects[$id]['onPage']=$options; - } else if ($options=='raw'){ - // then this page contains some other type of system object - $this->objects[$id]['raw']=1; - } - break; - case 'add': - // add more options to the decleration - foreach ($options as $k=>$v){ - $o['info'][$k]=$v; - } - case 'out': - $tmp=$o['c']; - $res= "\n".$id." 0 obj\n"; - if (isset($this->objects[$id]['raw'])){ - $res.=$tmp; - } else { - $res.= "<<"; - if (function_exists('gzcompress') && $this->options['compression']){ - // then implement ZLIB based compression on this content stream - $res.=" /Filter /FlateDecode"; - $tmp = gzcompress($tmp); - } - if ($this->encrypted){ - $this->encryptInit($id); - $tmp = $this->ARC4($tmp); - } - foreach($o['info'] as $k=>$v){ - $res .= "\n/".$k.' '.$v; - } - $res.="\n/Length ".strlen($tmp)." >>\nstream\n".$tmp."\nendstream"; - } - $res.="\nendobj\n"; - return $res; - break; - } -} - -/** -* an image object, will be an XObject in the document, includes description and data -*/ -function o_image($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch($action){ - case 'new': - // make the new object - $this->objects[$id]=array('t'=>'image','data'=>$options['data'],'info'=>array()); - $this->objects[$id]['info']['Type']='/XObject'; - $this->objects[$id]['info']['Subtype']='/Image'; - $this->objects[$id]['info']['Width']=$options['iw']; - $this->objects[$id]['info']['Height']=$options['ih']; - if (!isset($options['type']) || $options['type']=='jpg'){ - if (!isset($options['channels'])){ - $options['channels']=3; - } - switch($options['channels']){ - case 1: - $this->objects[$id]['info']['ColorSpace']='/DeviceGray'; - break; - default: - $this->objects[$id]['info']['ColorSpace']='/DeviceRGB'; - break; - } - $this->objects[$id]['info']['Filter']='/DCTDecode'; - $this->objects[$id]['info']['BitsPerComponent']=8; - } else if ($options['type']=='png'){ - $this->objects[$id]['info']['Filter']='/FlateDecode'; - $this->objects[$id]['info']['DecodeParms']='<< /Predictor 15 /Colors '.$options['ncolor'].' /Columns '.$options['iw'].' /BitsPerComponent '.$options['bitsPerComponent'].'>>'; - if (strlen($options['pdata'])){ - $tmp = ' [ /Indexed /DeviceRGB '.(strlen($options['pdata'])/3-1).' '; - $this->numObj++; - $this->o_contents($this->numObj,'new'); - $this->objects[$this->numObj]['c']=$options['pdata']; - $tmp.=$this->numObj.' 0 R'; - $tmp .=' ]'; - $this->objects[$id]['info']['ColorSpace'] = $tmp; - if (isset($options['transparency'])){ - switch($options['transparency']['type']){ - case 'indexed': - $tmp=' [ '.$options['transparency']['data'].' '.$options['transparency']['data'].'] '; - $this->objects[$id]['info']['Mask'] = $tmp; - break; - } - } - } else { - $this->objects[$id]['info']['ColorSpace']='/'.$options['color']; - } - $this->objects[$id]['info']['BitsPerComponent']=$options['bitsPerComponent']; - } - // assign it a place in the named resource dictionary as an external object, according to - // the label passed in with it. - $this->o_pages($this->currentNode,'xObject',array('label'=>$options['label'],'objNum'=>$id)); - // also make sure that we have the right procset object for it. - $this->o_procset($this->procsetObjectId,'add','ImageC'); - break; - case 'out': - $tmp=$o['data']; - $res= "\n".$id." 0 obj\n<<"; - foreach($o['info'] as $k=>$v){ - $res.="\n/".$k.' '.$v; - } - if ($this->encrypted){ - $this->encryptInit($id); - $tmp = $this->ARC4($tmp); - } - $res.="\n/Length ".strlen($tmp)." >>\nstream\n".$tmp."\nendstream\nendobj\n"; - return $res; - break; - } -} - -/** -* encryption object. -*/ -function o_encryption($id,$action,$options=''){ - if ($action!='new'){ - $o =& $this->objects[$id]; - } - switch($action){ - case 'new': - // make the new object - $this->objects[$id]=array('t'=>'encryption','info'=>$options); - $this->arc4_objnum=$id; - // figure out the additional paramaters required - $pad = chr(0x28).chr(0xBF).chr(0x4E).chr(0x5E).chr(0x4E).chr(0x75).chr(0x8A).chr(0x41).chr(0x64).chr(0x00).chr(0x4E).chr(0x56).chr(0xFF).chr(0xFA).chr(0x01).chr(0x08).chr(0x2E).chr(0x2E).chr(0x00).chr(0xB6).chr(0xD0).chr(0x68).chr(0x3E).chr(0x80).chr(0x2F).chr(0x0C).chr(0xA9).chr(0xFE).chr(0x64).chr(0x53).chr(0x69).chr(0x7A); - $len = strlen($options['owner']); - if ($len>32){ - $owner = substr($options['owner'],0,32); - } else if ($len<32){ - $owner = $options['owner'].substr($pad,0,32-$len); - } else { - $owner = $options['owner']; - } - $len = strlen($options['user']); - if ($len>32){ - $user = substr($options['user'],0,32); - } else if ($len<32){ - $user = $options['user'].substr($pad,0,32-$len); - } else { - $user = $options['user']; - } - $tmp = $this->md5_16($owner); - $okey = substr($tmp,0,5); - $this->ARC4_init($okey); - $ovalue=$this->ARC4($user); - $this->objects[$id]['info']['O']=$ovalue; - // now make the u value, phew. - $tmp = $this->md5_16($user.$ovalue.chr($options['p']).chr(255).chr(255).chr(255).$this->fileIdentifier); - $ukey = substr($tmp,0,5); - - $this->ARC4_init($ukey); - $this->encryptionKey = $ukey; - $this->encrypted=1; - $uvalue=$this->ARC4($pad); - - $this->objects[$id]['info']['U']=$uvalue; - $this->encryptionKey=$ukey; - - // initialize the arc4 array - break; - case 'out': - $res= "\n".$id." 0 obj\n<<"; - $res.="\n/Filter /Standard"; - $res.="\n/V 1"; - $res.="\n/R 2"; - $res.="\n/O (".$this->filterText($o['info']['O']).')'; - $res.="\n/U (".$this->filterText($o['info']['U']).')'; - // and the p-value needs to be converted to account for the twos-complement approach - $o['info']['p'] = (($o['info']['p']^255)+1)*-1; - $res.="\n/P ".($o['info']['p']); - $res.="\n>>\nendobj\n"; - - return $res; - break; - } -} - -/** -* ARC4 functions -* A series of function to implement ARC4 encoding in PHP -*/ - -/** -* calculate the 16 byte version of the 128 bit md5 digest of the string -*/ -function md5_16($string){ - $tmp = md5($string); - $out=''; - for ($i=0;$i<=30;$i=$i+2){ - $out.=chr(hexdec(substr($tmp,$i,2))); - } - return $out; -} - -/** -* initialize the encryption for processing a particular object -*/ -function encryptInit($id){ - $tmp = $this->encryptionKey; - $hex = dechex($id); - if (strlen($hex)<6){ - $hex = substr('000000',0,6-strlen($hex)).$hex; - } - $tmp.= chr(hexdec(substr($hex,4,2))).chr(hexdec(substr($hex,2,2))).chr(hexdec(substr($hex,0,2))).chr(0).chr(0); - $key = $this->md5_16($tmp); - $this->ARC4_init(substr($key,0,10)); -} - -/** -* initialize the ARC4 encryption -*/ -function ARC4_init($key=''){ - $this->arc4 = ''; - // setup the control array - if (strlen($key)==0){ - return; - } - $k = ''; - while(strlen($k)<256){ - $k.=$key; - } - $k=substr($k,0,256); - for ($i=0;$i<256;$i++){ - $this->arc4 .= chr($i); - } - $j=0; - for ($i=0;$i<256;$i++){ - $t = $this->arc4[$i]; - $j = ($j + ord($t) + ord($k[$i]))%256; - $this->arc4[$i]=$this->arc4[$j]; - $this->arc4[$j]=$t; - } -} - -/** -* ARC4 encrypt a text string -*/ -function ARC4($text){ - $len=strlen($text); - $a=0; - $b=0; - $c = $this->arc4; - $out=''; - for ($i=0;$i<$len;$i++){ - $a = ($a+1)%256; - $t= $c[$a]; - $b = ($b+ord($t))%256; - $c[$a]=$c[$b]; - $c[$b]=$t; - $k = ord($c[(ord($c[$a])+ord($c[$b]))%256]); - $out.=chr(ord($text[$i]) ^ $k); - } - - return $out; -} - -/** -* functions which can be called to adjust or add to the document -*/ - -/** -* add a link in the document to an external URL -*/ -function addLink($url,$x0,$y0,$x1,$y1){ - $this->numObj++; - $info = array('type'=>'link','url'=>$url,'rect'=>array($x0,$y0,$x1,$y1)); - $this->o_annotation($this->numObj,'new',$info); -} - -/** -* add a link in the document to an internal destination (ie. within the document) -*/ -function addInternalLink($label,$x0,$y0,$x1,$y1){ - $this->numObj++; - $info = array('type'=>'ilink','label'=>$label,'rect'=>array($x0,$y0,$x1,$y1)); - $this->o_annotation($this->numObj,'new',$info); -} - -/** -* set the encryption of the document -* can be used to turn it on and/or set the passwords which it will have. -* also the functions that the user will have are set here, such as print, modify, add -*/ -function setEncryption($userPass='',$ownerPass='',$pc=array()){ - $p=bindec(11000000); - - $options = array( - 'print'=>4 - ,'modify'=>8 - ,'copy'=>16 - ,'add'=>32 - ); - foreach($pc as $k=>$v){ - if ($v && isset($options[$k])){ - $p+=$options[$k]; - } else if (isset($options[$v])){ - $p+=$options[$v]; - } - } - // implement encryption on the document - if ($this->arc4_objnum == 0){ - // then the block does not exist already, add it. - $this->numObj++; - if (strlen($ownerPass)==0){ - $ownerPass=$userPass; - } - $this->o_encryption($this->numObj,'new',array('user'=>$userPass,'owner'=>$ownerPass,'p'=>$p)); - } -} - -/** -* should be used for internal checks, not implemented as yet -*/ -function checkAllHere(){ -} - -/** -* return the pdf stream as a string returned from the function -*/ -function output($debug=0){ - - if ($debug){ - // turn compression off - $this->options['compression']=0; - } - - if ($this->arc4_objnum){ - $this->ARC4_init($this->encryptionKey); - } - - $this->checkAllHere(); - - $xref=array(); - $content="%PDF-1.3\n%����\n"; -// $content="%PDF-1.3\n"; - $pos=strlen($content); - foreach($this->objects as $k=>$v){ - $tmp='o_'.$v['t']; - $cont=$this->$tmp($k,'out'); - $content.=$cont; - $xref[]=$pos; - $pos+=strlen($cont); - } - $content.="\nxref\n0 ".(count($xref)+1)."\n0000000000 65535 f \n"; - foreach($xref as $p){ - $content.=substr('0000000000',0,10-strlen($p)).$p." 00000 n \n"; - } - $content.="\ntrailer\n << /Size ".(count($xref)+1)."\n /Root 1 0 R\n /Info ".$this->infoObject." 0 R\n"; - // if encryption has been applied to this document then add the marker for this dictionary - if ($this->arc4_objnum > 0){ - $content .= "/Encrypt ".$this->arc4_objnum." 0 R\n"; - } - if (strlen($this->fileIdentifier)){ - $content .= "/ID[<".$this->fileIdentifier."><".$this->fileIdentifier.">]\n"; - } - $content .= " >>\nstartxref\n".$pos."\n%%EOF\n"; - return $content; -} - -/** -* intialize a new document -* if this is called on an existing document results may be unpredictable, but the existing document would be lost at minimum -* this function is called automatically by the constructor function -* -* @access private -*/ -function newDocument($pageSize=array(0,0,612,792)){ - $this->numObj=0; - $this->objects = array(); - - $this->numObj++; - $this->o_catalog($this->numObj,'new'); - - $this->numObj++; - $this->o_outlines($this->numObj,'new'); - - $this->numObj++; - $this->o_pages($this->numObj,'new'); - - $this->o_pages($this->numObj,'mediaBox',$pageSize); - $this->currentNode = 3; - - $this->numObj++; - $this->o_procset($this->numObj,'new'); - - $this->numObj++; - $this->o_info($this->numObj,'new'); - - $this->numObj++; - $this->o_page($this->numObj,'new'); - - // need to store the first page id as there is no way to get it to the user during - // startup - $this->firstPageId = $this->currentContents; -} - -/** -* open the font file and return a php structure containing it. -* first check if this one has been done before and saved in a form more suited to php -* note that if a php serialized version does not exist it will try and make one, but will -* require write access to the directory to do it... it is MUCH faster to have these serialized -* files. -* -* @access private -*/ -function openFont($font){ - // assume that $font contains both the path and perhaps the extension to the file, split them - $pos=strrpos($font,'/'); - if ($pos===false){ - $dir = './media/'; - $name = $font; - } else { - //$dir=substr($font,0,$pos+1); - $dir="./media/"; - $name=substr($font,$pos+1); - } - - if (substr($name,-4)=='.afm'){ - $name=substr($name,0,strlen($name)-4); - } - $this->addMessage('openFont: '.$font.' - '.$name); - if (file_exists($dir.'php_'.$name.'.afm')){ - $this->addMessage('openFont: php file exists '.$dir.'php_'.$name.'.afm'); - $tmp = file($dir.'php_'.$name.'.afm'); - $this->fonts[$font]=unserialize($tmp[0]); - if (!isset($this->fonts[$font]['_version_']) || $this->fonts[$font]['_version_']<1){ - // if the font file is old, then clear it out and prepare for re-creation - $this->addMessage('openFont: clear out, make way for new version.'); - unset($this->fonts[$font]); - } - } - if (!isset($this->fonts[$font]) && file_exists($dir.$name.'.afm')){ - // then rebuild the php_.afm file from the .afm file - $this->addMessage('openFont: build php file from '.$dir.$name.'.afm'); - $data = array(); - $file = file($dir.$name.'.afm'); - foreach ($file as $rowA){ - $row=trim($rowA); - $pos=strpos($row,' '); - if ($pos){ - // then there must be some keyword - $key = substr($row,0,$pos); - switch ($key){ - case 'FontName': - case 'FullName': - case 'FamilyName': - case 'Weight': - case 'ItalicAngle': - case 'IsFixedPitch': - case 'CharacterSet': - case 'UnderlinePosition': - case 'UnderlineThickness': - case 'Version': - case 'EncodingScheme': - case 'CapHeight': - case 'XHeight': - case 'Ascender': - case 'Descender': - case 'StdHW': - case 'StdVW': - case 'StartCharMetrics': - $data[$key]=trim(substr($row,$pos)); - break; - case 'FontBBox': - $data[$key]=explode(' ',trim(substr($row,$pos))); - break; - case 'C': - //C 39 ; WX 222 ; N quoteright ; B 53 463 157 718 ; - $bits=explode(';',trim($row)); - $dtmp=array(); - foreach($bits as $bit){ - $bits2 = explode(' ',trim($bit)); - if (strlen($bits2[0])){ - if (count($bits2)>2){ - $dtmp[$bits2[0]]=array(); - for ($i=1;$i=0){ - $data['C'][$dtmp['C']]=$dtmp; - $data['C'][$dtmp['N']]=$dtmp; - } else { - $data['C'][$dtmp['N']]=$dtmp; - } - break; - case 'KPX': - //KPX Adieresis yacute -40 - $bits=explode(' ',trim($row)); - $data['KPX'][$bits[1]][$bits[2]]=$bits[3]; - break; - } - } - } - $data['_version_']=1; - $this->fonts[$font]=$data; - $fp = @fopen($dir.'php_'.$name.'.afm','w') or die ("Please make sure your \"media\" directory is writeable (CHMOD 777)."); - fwrite($fp,serialize($data)); - fclose($fp); - mosChmod($dir.'php_'.$name.'.afm'); - } else if (!isset($this->fonts[$font])){ - $this->addMessage('openFont: no font file found'); -// echo 'Font not Found '.$font; - } -} - -/** -* if the font is not loaded then load it and make the required object -* else just make it the current font -* the encoding array can contain 'encoding'=> 'none','WinAnsiEncoding','MacRomanEncoding' or 'MacExpertEncoding' -* note that encoding='none' will need to be used for symbolic fonts -* and 'differences' => an array of mappings between numbers 0->255 and character names. -* -*/ -function selectFont($fontName,$encoding='',$set=1){ - if (!isset($this->fonts[$fontName])){ - // load the file - $this->openFont($fontName); - if (isset($this->fonts[$fontName])){ - $this->numObj++; - $this->numFonts++; - $pos=strrpos($fontName,'/'); -// $dir=substr($fontName,0,$pos+1); - $name=substr($fontName,$pos+1); - if (substr($name,-4)=='.afm'){ - $name=substr($name,0,strlen($name)-4); - } - $options=array('name'=>$name); - if (is_array($encoding)){ - // then encoding and differences might be set - if (isset($encoding['encoding'])){ - $options['encoding']=$encoding['encoding']; - } - if (isset($encoding['differences'])){ - $options['differences']=$encoding['differences']; - } - } else if (strlen($encoding)){ - // then perhaps only the encoding has been set - $options['encoding']=$encoding; - } - $fontObj = $this->numObj; - $this->o_font($this->numObj,'new',$options); - $this->fonts[$fontName]['fontNum']=$this->numFonts; - // if this is a '.afm' font, and there is a '.pfa' file to go with it ( as there - // should be for all non-basic fonts), then load it into an object and put the - // references into the font object - $basefile = substr($fontName,0,strlen($fontName)-4); - if (file_exists($basefile.'.pfb')){ - $fbtype = 'pfb'; - } else if (file_exists($basefile.'.ttf')){ - $fbtype = 'ttf'; - } else { - $fbtype=''; - } - $fbfile = $basefile.'.'.$fbtype; - -// $pfbfile = substr($fontName,0,strlen($fontName)-4).'.pfb'; -// $ttffile = substr($fontName,0,strlen($fontName)-4).'.ttf'; - $this->addMessage('selectFont: checking for - '.$fbfile); - if (substr($fontName,-4)=='.afm' && strlen($fbtype) ){ - $adobeFontName = $this->fonts[$fontName]['FontName']; -// $fontObj = $this->numObj; - $this->addMessage('selectFont: adding font file - '.$fbfile.' - '.$adobeFontName); - // find the array of fond widths, and put that into an object. - $firstChar = -1; - $lastChar = 0; - $widths = array(); - foreach ($this->fonts[$fontName]['C'] as $num=>$d){ - if (intval($num)>0 || $num=='0'){ - if ($lastChar>0 && $num>$lastChar+1){ - for($i=$lastChar+1;$i<$num;$i++){ - $widths[] = 0; - } - } - $widths[] = $d['WX']; - if ($firstChar==-1){ - $firstChar = $num; - } - $lastChar = $num; - } - } - // also need to adjust the widths for the differences array - if (isset($options['differences'])){ - foreach($options['differences'] as $charNum=>$charName){ - if ($charNum>$lastChar){ - for($i=$lastChar+1;$i<=$charNum;$i++){ - $widths[]=0; - } - $lastChar=$charNum; - } - if (isset($this->fonts[$fontName]['C'][$charName])){ - $widths[$charNum-$firstChar]=$this->fonts[$fontName]['C'][$charName]['WX']; - } - } - } - $this->addMessage('selectFont: FirstChar='.$firstChar); - $this->addMessage('selectFont: LastChar='.$lastChar); - $this->numObj++; - $this->o_contents($this->numObj,'new','raw'); - $this->objects[$this->numObj]['c'].='['; - foreach($widths as $width){ - $this->objects[$this->numObj]['c'].=' '.$width; - } - $this->objects[$this->numObj]['c'].=' ]'; - $widthid = $this->numObj; - - // load the pfb file, and put that into an object too. - // note that pdf supports only binary format type 1 font files, though there is a - // simple utility to convert them from pfa to pfb. - $fp = fopen($fbfile,'rb'); - $tmp = get_magic_quotes_runtime(); - set_magic_quotes_runtime(0); - $data = fread($fp,filesize($fbfile)); - set_magic_quotes_runtime($tmp); - fclose($fp); - - // create the font descriptor - $this->numObj++; - $fontDescriptorId = $this->numObj; - $this->numObj++; - $pfbid = $this->numObj; - // determine flags (more than a little flakey, hopefully will not matter much) - $flags=0; - if ($this->fonts[$fontName]['ItalicAngle']!=0){ $flags+=pow(2,6); } - if ($this->fonts[$fontName]['IsFixedPitch']=='true'){ $flags+=1; } - $flags+=pow(2,5); // assume non-sybolic - - $list = array('Ascent'=>'Ascender','CapHeight'=>'CapHeight','Descent'=>'Descender','FontBBox'=>'FontBBox','ItalicAngle'=>'ItalicAngle'); - $fdopt = array( - 'Flags'=>$flags - ,'FontName'=>$adobeFontName - ,'StemV'=>100 // don't know what the value for this should be! - ); - foreach($list as $k=>$v){ - if (isset($this->fonts[$fontName][$v])){ - $fdopt[$k]=$this->fonts[$fontName][$v]; - } - } - - if ($fbtype=='pfb'){ - $fdopt['FontFile']=$pfbid; - } else if ($fbtype=='ttf'){ - $fdopt['FontFile2']=$pfbid; - } - $this->o_fontDescriptor($fontDescriptorId,'new',$fdopt); - - // embed the font program - $this->o_contents($this->numObj,'new'); - $this->objects[$pfbid]['c'].=$data; - // determine the cruicial lengths within this file - if ($fbtype=='pfb'){ - $l1 = strpos($data,'eexec')+6; - $l2 = strpos($data,'00000000')-$l1; - $l3 = strlen($data)-$l2-$l1; - $this->o_contents($this->numObj,'add',array('Length1'=>$l1,'Length2'=>$l2,'Length3'=>$l3)); - } else if ($fbtype=='ttf'){ - $l1 = strlen($data); - $this->o_contents($this->numObj,'add',array('Length1'=>$l1)); - } - - - // tell the font object about all this new stuff - $tmp = array('BaseFont'=>$adobeFontName,'Widths'=>$widthid - ,'FirstChar'=>$firstChar,'LastChar'=>$lastChar - ,'FontDescriptor'=>$fontDescriptorId); - if ($fbtype=='ttf'){ - $tmp['SubType']='TrueType'; - } - $this->addMessage('adding extra info to font.('.$fontObj.')'); - foreach($tmp as $fk=>$fv){ - $this->addMessage($fk." : ".$fv); - } - $this->o_font($fontObj,'add',$tmp); - - } else { - $this->addMessage('selectFont: pfb or ttf file not found, ok if this is one of the 14 standard fonts'); - } - - - // also set the differences here, note that this means that these will take effect only the - //first time that a font is selected, else they are ignored - if (isset($options['differences'])){ - $this->fonts[$fontName]['differences']=$options['differences']; - } - } - } - if ($set && isset($this->fonts[$fontName])){ - // so if for some reason the font was not set in the last one then it will not be selected - $this->currentBaseFont=$fontName; - // the next line means that if a new font is selected, then the current text state will be - // applied to it as well. - $this->setCurrentFont(); - } - return $this->currentFontNum; -} - -/** -* sets up the current font, based on the font families, and the current text state -* note that this system is quite flexible, a font can be completely different to a -* font, and even will have to be defined within the family to have meaning -* This function is to be called whenever the currentTextState is changed, it will update -* the currentFont setting to whatever the appropriatte family one is. -* If the user calls selectFont themselves then that will reset the currentBaseFont, and the currentFont -* This function will change the currentFont to whatever it should be, but will not change the -* currentBaseFont. -* -* @access private -*/ -function setCurrentFont(){ - if (strlen($this->currentBaseFont)==0){ - // then assume an initial font - $this->selectFont('./fonts/Helvetica.afm'); - } - $cf = substr($this->currentBaseFont,strrpos($this->currentBaseFont,'/')+1); - if (strlen($this->currentTextState) - && isset($this->fontFamilies[$cf]) - && isset($this->fontFamilies[$cf][$this->currentTextState])){ - // then we are in some state or another - // and this font has a family, and the current setting exists within it - // select the font, then return it - $nf = substr($this->currentBaseFont,0,strrpos($this->currentBaseFont,'/')+1).$this->fontFamilies[$cf][$this->currentTextState]; - $this->selectFont($nf,'',0); - $this->currentFont = $nf; - $this->currentFontNum = $this->fonts[$nf]['fontNum']; - } else { - // the this font must not have the right family member for the current state - // simply assume the base font - $this->currentFont = $this->currentBaseFont; - $this->currentFontNum = $this->fonts[$this->currentFont]['fontNum']; - } -} - -/** -* function for the user to find out what the ID is of the first page that was created during -* startup - useful if they wish to add something to it later. -*/ -function getFirstPageId(){ - return $this->firstPageId; -} - -/** -* add content to the currently active object -* -* @access private -*/ -function addContent($content){ - $this->objects[$this->currentContents]['c'].=$content; -} - -/** -* sets the colour for fill operations -*/ -function setColor($r,$g,$b,$force=0){ - if ($r>=0 && ($force || $r!=$this->currentColour['r'] || $g!=$this->currentColour['g'] || $b!=$this->currentColour['b'])){ - $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$r).' '.sprintf('%.3f',$g).' '.sprintf('%.3f',$b).' rg'; - $this->currentColour=array('r'=>$r,'g'=>$g,'b'=>$b); - } -} - -/** -* sets the colour for stroke operations -*/ -function setStrokeColor($r,$g,$b,$force=0){ - if ($r>=0 && ($force || $r!=$this->currentStrokeColour['r'] || $g!=$this->currentStrokeColour['g'] || $b!=$this->currentStrokeColour['b'])){ - $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$r).' '.sprintf('%.3f',$g).' '.sprintf('%.3f',$b).' RG'; - $this->currentStrokeColour=array('r'=>$r,'g'=>$g,'b'=>$b); - } -} - -/** -* draw a line from one set of coordinates to another -*/ -function line($x1,$y1,$x2,$y2){ - $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$x1).' '.sprintf('%.3f',$y1).' m '.sprintf('%.3f',$x2).' '.sprintf('%.3f',$y2).' l S'; -} - -/** -* draw a bezier curve based on 4 control points -*/ -function curve($x0,$y0,$x1,$y1,$x2,$y2,$x3,$y3){ - // in the current line style, draw a bezier curve from (x0,y0) to (x3,y3) using the other two points - // as the control points for the curve. - $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$x0).' '.sprintf('%.3f',$y0).' m '.sprintf('%.3f',$x1).' '.sprintf('%.3f',$y1); - $this->objects[$this->currentContents]['c'].= ' '.sprintf('%.3f',$x2).' '.sprintf('%.3f',$y2).' '.sprintf('%.3f',$x3).' '.sprintf('%.3f',$y3).' c S'; -} - -/** -* draw a part of an ellipse -*/ -function partEllipse($x0,$y0,$astart,$afinish,$r1,$r2=0,$angle=0,$nSeg=8){ - $this->ellipse($x0,$y0,$r1,$r2,$angle,$nSeg,$astart,$afinish,0); -} - -/** -* draw a filled ellipse -*/ -function filledEllipse($x0,$y0,$r1,$r2=0,$angle=0,$nSeg=8,$astart=0,$afinish=360){ - return $this->ellipse($x0,$y0,$r1,$r2=0,$angle,$nSeg,$astart,$afinish,1,1); -} - -/** -* draw an ellipse -* note that the part and filled ellipse are just special cases of this function -* -* draws an ellipse in the current line style -* centered at $x0,$y0, radii $r1,$r2 -* if $r2 is not set, then a circle is drawn -* nSeg is not allowed to be less than 2, as this will simply draw a line (and will even draw a -* pretty crappy shape at 2, as we are approximating with bezier curves. -*/ -function ellipse($x0,$y0,$r1,$r2=0,$angle=0,$nSeg=8,$astart=0,$afinish=360,$close=1,$fill=0){ - if ($r1==0){ - return; - } - if ($r2==0){ - $r2=$r1; - } - if ($nSeg<2){ - $nSeg=2; - } - - $astart = deg2rad((float)$astart); - $afinish = deg2rad((float)$afinish); - $totalAngle =$afinish-$astart; - - $dt = $totalAngle/$nSeg; - $dtm = $dt/3; - - if ($angle != 0){ - $a = -1*deg2rad((float)$angle); - $tmp = "\n q "; - $tmp .= sprintf('%.3f',cos($a)).' '.sprintf('%.3f',(-1.0*sin($a))).' '.sprintf('%.3f',sin($a)).' '.sprintf('%.3f',cos($a)).' '; - $tmp .= sprintf('%.3f',$x0).' '.sprintf('%.3f',$y0).' cm'; - $this->objects[$this->currentContents]['c'].= $tmp; - $x0=0; - $y0=0; - } - - $t1 = $astart; - $a0 = $x0+$r1*cos($t1); - $b0 = $y0+$r2*sin($t1); - $c0 = -$r1*sin($t1); - $d0 = $r2*cos($t1); - - $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$a0).' '.sprintf('%.3f',$b0).' m '; - for ($i=1;$i<=$nSeg;$i++){ - // draw this bit of the total curve - $t1 = $i*$dt+$astart; - $a1 = $x0+$r1*cos($t1); - $b1 = $y0+$r2*sin($t1); - $c1 = -$r1*sin($t1); - $d1 = $r2*cos($t1); - $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',($a0+$c0*$dtm)).' '.sprintf('%.3f',($b0+$d0*$dtm)); - $this->objects[$this->currentContents]['c'].= ' '.sprintf('%.3f',($a1-$c1*$dtm)).' '.sprintf('%.3f',($b1-$d1*$dtm)).' '.sprintf('%.3f',$a1).' '.sprintf('%.3f',$b1).' c'; - $a0=$a1; - $b0=$b1; - $c0=$c1; - $d0=$d1; - } - if ($fill){ - $this->objects[$this->currentContents]['c'].=' f'; - } else { - if ($close){ - $this->objects[$this->currentContents]['c'].=' s'; // small 's' signifies closing the path as well - } else { - $this->objects[$this->currentContents]['c'].=' S'; - } - } - if ($angle !=0){ - $this->objects[$this->currentContents]['c'].=' Q'; - } -} - -/** -* this sets the line drawing style. -* width, is the thickness of the line in user units -* cap is the type of cap to put on the line, values can be 'butt','round','square' -* where the diffference between 'square' and 'butt' is that 'square' projects a flat end past the -* end of the line. -* join can be 'miter', 'round', 'bevel' -* dash is an array which sets the dash pattern, is a series of length values, which are the lengths of the -* on and off dashes. -* (2) represents 2 on, 2 off, 2 on , 2 off ... -* (2,1) is 2 on, 1 off, 2 on, 1 off.. etc -* phase is a modifier on the dash pattern which is used to shift the point at which the pattern starts. -*/ -function setLineStyle($width=1,$cap='',$join='',$dash='',$phase=0){ - - // this is quite inefficient in that it sets all the parameters whenever 1 is changed, but will fix another day - $string = ''; - if ($width>0){ - $string.= $width.' w'; - } - $ca = array('butt'=>0,'round'=>1,'square'=>2); - if (isset($ca[$cap])){ - $string.= ' '.$ca[$cap].' J'; - } - $ja = array('miter'=>0,'round'=>1,'bevel'=>2); - if (isset($ja[$join])){ - $string.= ' '.$ja[$join].' j'; - } - if (is_array($dash)){ - $string.= ' ['; - foreach ($dash as $len){ - $string.=' '.$len; - } - $string.= ' ] '.$phase.' d'; - } - $this->currentLineStyle = $string; - $this->objects[$this->currentContents]['c'].="\n".$string; -} - -/** -* draw a polygon, the syntax for this is similar to the GD polygon command -*/ -function polygon($p,$np,$f=0){ - $this->objects[$this->currentContents]['c'].="\n"; - $this->objects[$this->currentContents]['c'].=sprintf('%.3f',$p[0]).' '.sprintf('%.3f',$p[1]).' m '; - for ($i=2;$i<$np*2;$i=$i+2){ - $this->objects[$this->currentContents]['c'].= sprintf('%.3f',$p[$i]).' '.sprintf('%.3f',$p[$i+1]).' l '; - } - if ($f==1){ - $this->objects[$this->currentContents]['c'].=' f'; - } else { - $this->objects[$this->currentContents]['c'].=' S'; - } -} - -/** -* a filled rectangle, note that it is the width and height of the rectangle which are the secondary paramaters, not -* the coordinates of the upper-right corner -*/ -function filledRectangle($x1,$y1,$width,$height){ - $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$x1).' '.sprintf('%.3f',$y1).' '.sprintf('%.3f',$width).' '.sprintf('%.3f',$height).' re f'; -} - -/** -* draw a rectangle, note that it is the width and height of the rectangle which are the secondary paramaters, not -* the coordinates of the upper-right corner -*/ -function rectangle($x1,$y1,$width,$height){ - $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$x1).' '.sprintf('%.3f',$y1).' '.sprintf('%.3f',$width).' '.sprintf('%.3f',$height).' re S'; -} - -/** -* add a new page to the document -* this also makes the new page the current active object -*/ -function newPage($insert=0,$id=0,$pos='after'){ - - // if there is a state saved, then go up the stack closing them - // then on the new page, re-open them with the right setings - - if ($this->nStateStack){ - for ($i=$this->nStateStack;$i>=1;$i--){ - $this->restoreState($i); - } - } - - $this->numObj++; - if ($insert){ - // the id from the ezPdf class is the od of the contents of the page, not the page object itself - // query that object to find the parent - $rid = $this->objects[$id]['onPage']; - $opt= array('rid'=>$rid,'pos'=>$pos); - $this->o_page($this->numObj,'new',$opt); - } else { - $this->o_page($this->numObj,'new'); - } - // if there is a stack saved, then put that onto the page - if ($this->nStateStack){ - for ($i=1;$i<=$this->nStateStack;$i++){ - $this->saveState($i); - } - } - // and if there has been a stroke or fill colour set, then transfer them - if ($this->currentColour['r']>=0){ - $this->setColor($this->currentColour['r'],$this->currentColour['g'],$this->currentColour['b'],1); - } - if ($this->currentStrokeColour['r']>=0){ - $this->setStrokeColor($this->currentStrokeColour['r'],$this->currentStrokeColour['g'],$this->currentStrokeColour['b'],1); - } - - // if there is a line style set, then put this in too - if (strlen($this->currentLineStyle)){ - $this->objects[$this->currentContents]['c'].="\n".$this->currentLineStyle; - } - - // the call to the o_page object set currentContents to the present page, so this can be returned as the page id - return $this->currentContents; -} - -/** -* output the pdf code, streaming it to the browser -* the relevant headers are set so that hopefully the browser will recognise it -*/ -function stream($options=''){ - // setting the options allows the adjustment of the headers - // values at the moment are: - // 'Content-Disposition'=>'filename' - sets the filename, though not too sure how well this will - // work as in my trial the browser seems to use the filename of the php file with .pdf on the end - // 'Accept-Ranges'=>1 or 0 - if this is not set to 1, then this header is not included, off by default - // this header seems to have caused some problems despite tha fact that it is supposed to solve - // them, so I am leaving it off by default. - // 'compress'=> 1 or 0 - apply content stream compression, this is on (1) by default - if (!is_array($options)){ - $options=array(); - } - if ( isset($options['compress']) && $options['compress']==0){ - $tmp = $this->output(1); - } else { - $tmp = $this->output(); - } - header("Content-type: application/pdf"); - header("Content-Length: ".strlen(ltrim($tmp))); - $fileName = (isset($options['Content-Disposition'])?$options['Content-Disposition']:'file.pdf'); - header("Content-Disposition: inline; filename=".$fileName); - if (isset($options['Accept-Ranges']) && $options['Accept-Ranges']==1){ - header("Accept-Ranges: ".strlen(ltrim($tmp))); - } - echo ltrim($tmp); -} - -/** -* return the height in units of the current font in the given size -*/ -function getFontHeight($size){ - if (!$this->numFonts){ - $this->selectFont('./fonts/Helvetica'); - } - // for the current font, and the given size, what is the height of the font in user units - $h = $this->fonts[$this->currentFont]['FontBBox'][3]-$this->fonts[$this->currentFont]['FontBBox'][1]; - return $size*$h/1000; -} - -/** -* return the font decender, this will normally return a negative number -* if you add this number to the baseline, you get the level of the bottom of the font -* it is in the pdf user units -*/ -function getFontDecender($size){ - // note that this will most likely return a negative value - if (!$this->numFonts){ - $this->selectFont('./fonts/Helvetica'); - } - $h = $this->fonts[$this->currentFont]['FontBBox'][1]; - return $size*$h/1000; -} - -/** -* filter the text, this is applied to all text just before being inserted into the pdf document -* it escapes the various things that need to be escaped, and so on -* -* @access private -*/ -function filterText($text){ - $text = str_replace('\\','\\\\',$text); - $text = str_replace('(','\(',$text); - $text = str_replace(')','\)',$text); - $text = str_replace('<','<',$text); - $text = str_replace('>','>',$text); - $text = str_replace(''','\'',$text); - $text = str_replace('"','"',$text); - $text = str_replace('&','&',$text); - - return $text; -} - -/** -* given a start position and information about how text is to be laid out, calculate where -* on the page the text will end -* -* @access private -*/ -function PRVTgetTextPosition($x,$y,$angle,$size,$wa,$text){ - // given this information return an array containing x and y for the end position as elements 0 and 1 - $w = $this->getTextWidth($size,$text); - // need to adjust for the number of spaces in this text - $words = explode(' ',$text); - $nspaces=count($words)-1; - $w += $wa*$nspaces; - $a = deg2rad((float)$angle); - return array(cos($a)*$w+$x,-sin($a)*$w+$y); -} - -/** -* wrapper function for PRVTcheckTextDirective1 -* -* @access private -*/ -function PRVTcheckTextDirective(&$text,$i,&$f){ - $x=0; - $y=0; - return $this->PRVTcheckTextDirective1($text,$i,$f,0,$x,$y); -} - -/** -* checks if the text stream contains a control directive -* if so then makes some changes and returns the number of characters involved in the directive -* this has been re-worked to include everything neccesary to fins the current writing point, so that -* the location can be sent to the callback function if required -* if the directive does not require a font change, then $f should be set to 0 -* -* @access private -*/ -function PRVTcheckTextDirective1(&$text,$i,&$f,$final,&$x,&$y,$size=0,$angle=0,$wordSpaceAdjust=0){ - $directive = 0; - $j=$i; - if ($text[$j]=='<'){ - $j++; - switch($text[$j]){ - case '/': - $j++; - if (strlen($text) <= $j){ - return $directive; - } - switch($text[$j]){ - case 'b': - case 'i': - $j++; - if ($text[$j]=='>'){ - $p = strrpos($this->currentTextState,$text[$j-1]); - if ($p !== false){ - // then there is one to remove - $this->currentTextState = substr($this->currentTextState,0,$p).substr($this->currentTextState,$p+1); - } - $directive=$j-$i+1; - } - break; - case 'c': - // this this might be a callback function - $j++; - $k = strpos($text,'>',$j); - if ($k!==false && $text[$j]==':'){ - // then this will be treated as a callback directive - $directive = $k-$i+1; - $f=0; - // split the remainder on colons to get the function name and the paramater - $tmp = substr($text,$j+1,$k-$j-1); - $b1 = strpos($tmp,':'); - if ($b1!==false){ - $func = substr($tmp,0,$b1); - $parm = substr($tmp,$b1+1); - } else { - $func=$tmp; - $parm=''; - } - if (!isset($func) || !strlen(trim($func))){ - $directive=0; - } else { - // only call the function if this is the final call - if ($final){ - // need to assess the text position, calculate the text width to this point - // can use getTextWidth to find the text width I think - $tmp = $this->PRVTgetTextPosition($x,$y,$angle,$size,$wordSpaceAdjust,substr($text,0,$i)); - $info = array('x'=>$tmp[0],'y'=>$tmp[1],'angle'=>$angle,'status'=>'end','p'=>$parm,'nCallback'=>$this->nCallback); - $x=$tmp[0]; - $y=$tmp[1]; - $ret = $this->$func($info); - if (is_array($ret)){ - // then the return from the callback function could set the position, to start with, later will do font colour, and font - foreach($ret as $rk=>$rv){ - switch($rk){ - case 'x': - case 'y': - $$rk=$rv; - break; - } - } - } - // also remove from to the stack - // for simplicity, just take from the end, fix this another day - $this->nCallback--; - if ($this->nCallback<0){ - $this->nCallBack=0; - } - } - } - } - break; - } - break; - case 'b': - case 'i': - $j++; - if ($text[$j]=='>'){ - $this->currentTextState.=$text[$j-1]; - $directive=$j-$i+1; - } - break; - case 'C': - $noClose=1; - case 'c': - // this this might be a callback function - $j++; - $k = strpos($text,'>',$j); - if ($k!==false && $text[$j]==':'){ - // then this will be treated as a callback directive - $directive = $k-$i+1; - $f=0; - // split the remainder on colons to get the function name and the paramater -// $bits = explode(':',substr($text,$j+1,$k-$j-1)); - $tmp = substr($text,$j+1,$k-$j-1); - $b1 = strpos($tmp,':'); - if ($b1!==false){ - $func = substr($tmp,0,$b1); - $parm = substr($tmp,$b1+1); - } else { - $func=$tmp; - $parm=''; - } - if (!isset($func) || !strlen(trim($func))){ - $directive=0; - } else { - // only call the function if this is the final call, ie, the one actually doing printing, not measurement - if ($final){ - // need to assess the text position, calculate the text width to this point - // can use getTextWidth to find the text width I think - // also add the text height and decender - $tmp = $this->PRVTgetTextPosition($x,$y,$angle,$size,$wordSpaceAdjust,substr($text,0,$i)); - $info = array('x'=>$tmp[0],'y'=>$tmp[1],'angle'=>$angle,'status'=>'start','p'=>$parm,'f'=>$func,'height'=>$this->getFontHeight($size),'decender'=>$this->getFontDecender($size)); - $x=$tmp[0]; - $y=$tmp[1]; - if (!isset($noClose) || !$noClose){ - // only add to the stack if this is a small 'c', therefore is a start-stop pair - $this->nCallback++; - $info['nCallback']=$this->nCallback; - $this->callback[$this->nCallback]=$info; - } - $ret = $this->$func($info); - if (is_array($ret)){ - // then the return from the callback function could set the position, to start with, later will do font colour, and font - foreach($ret as $rk=>$rv){ - switch($rk){ - case 'x': - case 'y': - $$rk=$rv; - break; - } - } - } - } - } - } - break; - } - } - return $directive; -} - -/** -* add text to the document, at a specified location, size and angle on the page -*/ -function addText($x,$y,$size,$text,$angle=0,$wordSpaceAdjust=0){ - if (!$this->numFonts){$this->selectFont('./fonts/Helvetica');} - - // if there are any open callbacks, then they should be called, to show the start of the line - if ($this->nCallback>0){ - for ($i=$this->nCallback;$i>0;$i--){ - // call each function - $info = array('x'=>$x,'y'=>$y,'angle'=>$angle,'status'=>'sol','p'=>$this->callback[$i]['p'],'nCallback'=>$this->callback[$i]['nCallback'],'height'=>$this->callback[$i]['height'],'decender'=>$this->callback[$i]['decender']); - $func = $this->callback[$i]['f']; - $this->$func($info); - } - } - if ($angle==0){ - $this->objects[$this->currentContents]['c'].="\n".'BT '.sprintf('%.3f',$x).' '.sprintf('%.3f',$y).' Td'; - } else { - $a = deg2rad((float)$angle); - $tmp = "\n".'BT '; - $tmp .= sprintf('%.3f',cos($a)).' '.sprintf('%.3f',(-1.0*sin($a))).' '.sprintf('%.3f',sin($a)).' '.sprintf('%.3f',cos($a)).' '; - $tmp .= sprintf('%.3f',$x).' '.sprintf('%.3f',$y).' Tm'; - $this->objects[$this->currentContents]['c'] .= $tmp; - } - if ($wordSpaceAdjust!=0 || $wordSpaceAdjust != $this->wordSpaceAdjust){ - $this->wordSpaceAdjust=$wordSpaceAdjust; - $this->objects[$this->currentContents]['c'].=' '.sprintf('%.3f',$wordSpaceAdjust).' Tw'; - } - $len=strlen($text); - $start=0; - for ($i=0;$i<$len;$i++){ - $f=1; - $directive = $this->PRVTcheckTextDirective($text,$i,$f); - if ($directive){ - // then we should write what we need to - if ($i>$start){ - $part = substr($text,$start,$i-$start); - $this->objects[$this->currentContents]['c'].=' /F'.$this->currentFontNum.' '.sprintf('%.1f',$size).' Tf '; - $this->objects[$this->currentContents]['c'].=' ('.$this->filterText($part).') Tj'; - } - if ($f){ - // then there was nothing drastic done here, restore the contents - $this->setCurrentFont(); - } else { - $this->objects[$this->currentContents]['c'] .= ' ET'; - $f=1; - $xp=$x; - $yp=$y; - $directive = $this->PRVTcheckTextDirective1($text,$i,$f,1,$xp,$yp,$size,$angle,$wordSpaceAdjust); - - // restart the text object - if ($angle==0){ - $this->objects[$this->currentContents]['c'].="\n".'BT '.sprintf('%.3f',$xp).' '.sprintf('%.3f',$yp).' Td'; - } else { - $a = deg2rad((float)$angle); - $tmp = "\n".'BT '; - $tmp .= sprintf('%.3f',cos($a)).' '.sprintf('%.3f',(-1.0*sin($a))).' '.sprintf('%.3f',sin($a)).' '.sprintf('%.3f',cos($a)).' '; - $tmp .= sprintf('%.3f',$xp).' '.sprintf('%.3f',$yp).' Tm'; - $this->objects[$this->currentContents]['c'] .= $tmp; - } - if ($wordSpaceAdjust!=0 || $wordSpaceAdjust != $this->wordSpaceAdjust){ - $this->wordSpaceAdjust=$wordSpaceAdjust; - $this->objects[$this->currentContents]['c'].=' '.sprintf('%.3f',$wordSpaceAdjust).' Tw'; - } - } - // and move the writing point to the next piece of text - $i=$i+$directive-1; - $start=$i+1; - } - - } - if ($start<$len){ - $part = substr($text,$start); - $this->objects[$this->currentContents]['c'].=' /F'.$this->currentFontNum.' '.sprintf('%.1f',$size).' Tf '; - $this->objects[$this->currentContents]['c'].=' ('.$this->filterText($part).') Tj'; - } - $this->objects[$this->currentContents]['c'].=' ET'; - - // if there are any open callbacks, then they should be called, to show the end of the line - if ($this->nCallback>0){ - for ($i=$this->nCallback;$i>0;$i--){ - // call each function - $tmp = $this->PRVTgetTextPosition($x,$y,$angle,$size,$wordSpaceAdjust,$text); - $info = array('x'=>$tmp[0],'y'=>$tmp[1],'angle'=>$angle,'status'=>'eol','p'=>$this->callback[$i]['p'],'nCallback'=>$this->callback[$i]['nCallback'],'height'=>$this->callback[$i]['height'],'decender'=>$this->callback[$i]['decender']); - $func = $this->callback[$i]['f']; - $this->$func($info); - } - } - -} - -/** -* calculate how wide a given text string will be on a page, at a given size. -* this can be called externally, but is alse used by the other class functions -*/ -function getTextWidth($size,$text){ - // this function should not change any of the settings, though it will need to - // track any directives which change during calculation, so copy them at the start - // and put them back at the end. - $store_currentTextState = $this->currentTextState; - - if (!$this->numFonts){ - $this->selectFont('./fonts/Helvetica'); - } - - // converts a number or a float to a string so it can get the width - $text = "$text"; - - // hmm, this is where it all starts to get tricky - use the font information to - // calculate the width of each character, add them up and convert to user units - $w=0; - $len=strlen($text); - $cf = $this->currentFont; - for ($i=0;$i<$len;$i++){ - $f=1; - $directive = $this->PRVTcheckTextDirective($text,$i,$f); - if ($directive){ - if ($f){ - $this->setCurrentFont(); - $cf = $this->currentFont; - } - $i=$i+$directive-1; - } else { - $char=ord($text[$i]); - if (isset($this->fonts[$cf]['differences'][$char])){ - // then this character is being replaced by another - $name = $this->fonts[$cf]['differences'][$char]; - if (isset($this->fonts[$cf]['C'][$name]['WX'])){ - $w+=$this->fonts[$cf]['C'][$name]['WX']; - } - } else if (isset($this->fonts[$cf]['C'][$char]['WX'])){ - $w+=$this->fonts[$cf]['C'][$char]['WX']; - } - } - } - - $this->currentTextState = $store_currentTextState; - $this->setCurrentFont(); - - return $w*$size/1000; -} - -/** -* do a part of the calculation for sorting out the justification of the text -* -* @access private -*/ -function PRVTadjustWrapText($text,$actual,$width,&$x,&$adjust,$justification){ - switch ($justification){ - case 'left': - return; - break; - case 'right': - $x+=$width-$actual; - break; - case 'center': - case 'centre': - $x+=($width-$actual)/2; - break; - case 'full': - // count the number of words - $words = explode(' ',$text); - $nspaces=count($words)-1; - if ($nspaces>0){ - $adjust = ($width-$actual)/$nspaces; - } else { - $adjust=0; - } - break; - } -} - -/** -* add text to the page, but ensure that it fits within a certain width -* if it does not fit then put in as much as possible, splitting at word boundaries -* and return the remainder. -* justification and angle can also be specified for the text -*/ -function addTextWrap($x,$y,$width,$size,$text,$justification='left',$angle=0,$test=0){ - // this will display the text, and if it goes beyond the width $width, will backtrack to the - // previous space or hyphen, and return the remainder of the text. - - // $justification can be set to 'left','right','center','centre','full' - - // need to store the initial text state, as this will change during the width calculation - // but will need to be re-set before printing, so that the chars work out right - $store_currentTextState = $this->currentTextState; - - if (!$this->numFonts){$this->selectFont('./fonts/Helvetica');} - if ($width<=0){ - // error, pretend it printed ok, otherwise risking a loop - return ''; - } - $w=0; - $break=0; - $breakWidth=0; - $len=strlen($text); - $cf = $this->currentFont; - $tw = $width/$size*1000; - for ($i=0;$i<$len;$i++){ - $f=1; - $directive = $this->PRVTcheckTextDirective($text,$i,$f); - if ($directive){ - if ($f){ - $this->setCurrentFont(); - $cf = $this->currentFont; - } - $i=$i+$directive-1; - } else { - $cOrd = ord($text[$i]); - if (isset($this->fonts[$cf]['differences'][$cOrd])){ - // then this character is being replaced by another - $cOrd2 = $this->fonts[$cf]['differences'][$cOrd]; - } else { - $cOrd2 = $cOrd; - } - - if (isset($this->fonts[$cf]['C'][$cOrd2]['WX'])){ - $w+=$this->fonts[$cf]['C'][$cOrd2]['WX']; - } - if ($w>$tw){ - // then we need to truncate this line - if ($break>0){ - // then we have somewhere that we can split :) - if ($text[$break]==' '){ - $tmp = substr($text,0,$break); - } else { - $tmp = substr($text,0,$break+1); - } - $adjust=0; - $this->PRVTadjustWrapText($tmp,$breakWidth,$width,$x,$adjust,$justification); - - // reset the text state - $this->currentTextState = $store_currentTextState; - $this->setCurrentFont(); - if (!$test){ - $this->addText($x,$y,$size,$tmp,$angle,$adjust); - } - return substr($text,$break+1); - } else { - // just split before the current character - $tmp = substr($text,0,$i); - $adjust=0; - $ctmp=ord($text[$i]); - if (isset($this->fonts[$cf]['differences'][$ctmp])){ - $ctmp=$this->fonts[$cf]['differences'][$ctmp]; - } - $tmpw=($w-$this->fonts[$cf]['C'][$ctmp]['WX'])*$size/1000; - $this->PRVTadjustWrapText($tmp,$tmpw,$width,$x,$adjust,$justification); - // reset the text state - $this->currentTextState = $store_currentTextState; - $this->setCurrentFont(); - if (!$test){ - $this->addText($x,$y,$size,$tmp,$angle,$adjust); - } - return substr($text,$i); - } - } - if ($text[$i]=='-'){ - $break=$i; - $breakWidth = $w*$size/1000; - } - if ($text[$i]==' '){ - $break=$i; - $ctmp=ord($text[$i]); - if (isset($this->fonts[$cf]['differences'][$ctmp])){ - $ctmp=$this->fonts[$cf]['differences'][$ctmp]; - } - $breakWidth = ($w-$this->fonts[$cf]['C'][$ctmp]['WX'])*$size/1000; - } - } - } - // then there was no need to break this line - if ($justification=='full'){ - $justification='left'; - } - $adjust=0; - $tmpw=$w*$size/1000; - $this->PRVTadjustWrapText($text,$tmpw,$width,$x,$adjust,$justification); - // reset the text state - $this->currentTextState = $store_currentTextState; - $this->setCurrentFont(); - if (!$test){ - $this->addText($x,$y,$size,$text,$angle,$adjust,$angle); - } - return ''; -} - -/** -* this will be called at a new page to return the state to what it was on the -* end of the previous page, before the stack was closed down -* This is to get around not being able to have open 'q' across pages -* -*/ -function saveState($pageEnd=0){ - if ($pageEnd){ - // this will be called at a new page to return the state to what it was on the - // end of the previous page, before the stack was closed down - // This is to get around not being able to have open 'q' across pages - $opt = $this->stateStack[$pageEnd]; // ok to use this as stack starts numbering at 1 - $this->setColor($opt['col']['r'],$opt['col']['g'],$opt['col']['b'],1); - $this->setStrokeColor($opt['str']['r'],$opt['str']['g'],$opt['str']['b'],1); - $this->objects[$this->currentContents]['c'].="\n".$opt['lin']; -// $this->currentLineStyle = $opt['lin']; - } else { - $this->nStateStack++; - $this->stateStack[$this->nStateStack]=array( - 'col'=>$this->currentColour - ,'str'=>$this->currentStrokeColour - ,'lin'=>$this->currentLineStyle - ); - } - $this->objects[$this->currentContents]['c'].="\nq"; -} - -/** -* restore a previously saved state -*/ -function restoreState($pageEnd=0){ - if (!$pageEnd){ - $n = $this->nStateStack; - $this->currentColour = $this->stateStack[$n]['col']; - $this->currentStrokeColour = $this->stateStack[$n]['str']; - $this->objects[$this->currentContents]['c'].="\n".$this->stateStack[$n]['lin']; - $this->currentLineStyle = $this->stateStack[$n]['lin']; - unset($this->stateStack[$n]); - $this->nStateStack--; - } - $this->objects[$this->currentContents]['c'].="\nQ"; -} - -/** -* make a loose object, the output will go into this object, until it is closed, then will revert to -* the current one. -* this object will not appear until it is included within a page. -* the function will return the object number -*/ -function openObject(){ - $this->nStack++; - $this->stack[$this->nStack]=array('c'=>$this->currentContents,'p'=>$this->currentPage); - // add a new object of the content type, to hold the data flow - $this->numObj++; - $this->o_contents($this->numObj,'new'); - $this->currentContents=$this->numObj; - $this->looseObjects[$this->numObj]=1; - - return $this->numObj; -} - -/** -* open an existing object for editing -*/ -function reopenObject($id){ - $this->nStack++; - $this->stack[$this->nStack]=array('c'=>$this->currentContents,'p'=>$this->currentPage); - $this->currentContents=$id; - // also if this object is the primary contents for a page, then set the current page to its parent - if (isset($this->objects[$id]['onPage'])){ - $this->currentPage = $this->objects[$id]['onPage']; - } -} - -/** -* close an object -*/ -function closeObject(){ - // close the object, as long as there was one open in the first place, which will be indicated by - // an objectId on the stack. - if ($this->nStack>0){ - $this->currentContents=$this->stack[$this->nStack]['c']; - $this->currentPage=$this->stack[$this->nStack]['p']; - $this->nStack--; - // easier to probably not worry about removing the old entries, they will be overwritten - // if there are new ones. - } -} - -/** -* stop an object from appearing on pages from this point on -*/ -function stopObject($id){ - // if an object has been appearing on pages up to now, then stop it, this page will - // be the last one that could contian it. - if (isset($this->addLooseObjects[$id])){ - $this->addLooseObjects[$id]=''; - } -} - -/** -* after an object has been created, it wil only show if it has been added, using this function. -*/ -function addObject($id,$options='add'){ - // add the specified object to the page - if (isset($this->looseObjects[$id]) && $this->currentContents!=$id){ - // then it is a valid object, and it is not being added to itself - switch($options){ - case 'all': - // then this object is to be added to this page (done in the next block) and - // all future new pages. - $this->addLooseObjects[$id]='all'; - case 'add': - if (isset($this->objects[$this->currentContents]['onPage'])){ - // then the destination contents is the primary for the page - // (though this object is actually added to that page) - $this->o_page($this->objects[$this->currentContents]['onPage'],'content',$id); - } - break; - case 'even': - $this->addLooseObjects[$id]='even'; - $pageObjectId=$this->objects[$this->currentContents]['onPage']; - if ($this->objects[$pageObjectId]['info']['pageNum']%2==0){ - $this->addObject($id); // hacky huh :) - } - break; - case 'odd': - $this->addLooseObjects[$id]='odd'; - $pageObjectId=$this->objects[$this->currentContents]['onPage']; - if ($this->objects[$pageObjectId]['info']['pageNum']%2==1){ - $this->addObject($id); // hacky huh :) - } - break; - case 'next': - $this->addLooseObjects[$id]='all'; - break; - case 'nexteven': - $this->addLooseObjects[$id]='even'; - break; - case 'nextodd': - $this->addLooseObjects[$id]='odd'; - break; - } - } -} - -/** -* add content to the documents info object -*/ -function addInfo($label,$value=0){ - // this will only work if the label is one of the valid ones. - // modify this so that arrays can be passed as well. - // if $label is an array then assume that it is key=>value pairs - // else assume that they are both scalar, anything else will probably error - if (is_array($label)){ - foreach ($label as $l=>$v){ - $this->o_info($this->infoObject,$l,$v); - } - } else { - $this->o_info($this->infoObject,$label,$value); - } -} - -/** -* set the viewer preferences of the document, it is up to the browser to obey these. -*/ -function setPreferences($label,$value=0){ - // this will only work if the label is one of the valid ones. - if (is_array($label)){ - foreach ($label as $l=>$v){ - $this->o_catalog($this->catalogId,'viewerPreferences',array($l=>$v)); - } - } else { - $this->o_catalog($this->catalogId,'viewerPreferences',array($label=>$value)); - } -} - -/** -* extract an integer from a position in a byte stream -* -* @access private -*/ -function PRVT_getBytes(&$data,$pos,$num){ - // return the integer represented by $num bytes from $pos within $data - $ret=0; - for ($i=0;$i<$num;$i++){ - $ret=$ret*256; - $ret+=ord($data[$pos+$i]); - } - return $ret; -} - -/** -* add a PNG image into the document, from a file -* this should work with remote files -*/ -function addPngFromFile($file,$x,$y,$w=0,$h=0){ - // read in a png file, interpret it, then add to the system - $error=0; - $tmp = get_magic_quotes_runtime(); - set_magic_quotes_runtime(0); - $fp = @fopen($file,'rb'); - if ($fp){ - $data=''; - while(!feof($fp)){ - $data .= fread($fp,1024); - } - fclose($fp); - } else { - $error = 1; - $errormsg = 'trouble opening file: '.$file; - } - set_magic_quotes_runtime($tmp); - - if (!$error){ - $header = chr(137).chr(80).chr(78).chr(71).chr(13).chr(10).chr(26).chr(10); - if (substr($data,0,8)!=$header){ - $error=1; - $errormsg = 'this file does not have a valid header'; - } - } - - if (!$error){ - // set pointer - $p = 8; - $len = strlen($data); - // cycle through the file, identifying chunks - $haveHeader=0; - $info=array(); - $idata=''; - $pdata=''; - while ($p<$len){ - $chunkLen = $this->PRVT_getBytes($data,$p,4); - $chunkType = substr($data,$p+4,4); -// echo $chunkType.' - '.$chunkLen.'
    '; - - switch($chunkType){ - case 'IHDR': - // this is where all the file information comes from - $info['width']=$this->PRVT_getBytes($data,$p+8,4); - $info['height']=$this->PRVT_getBytes($data,$p+12,4); - $info['bitDepth']=ord($data[$p+16]); - $info['colorType']=ord($data[$p+17]); - $info['compressionMethod']=ord($data[$p+18]); - $info['filterMethod']=ord($data[$p+19]); - $info['interlaceMethod']=ord($data[$p+20]); -//print_r($info); - $haveHeader=1; - if ($info['compressionMethod']!=0){ - $error=1; - $errormsg = 'unsupported compression method'; - } - if ($info['filterMethod']!=0){ - $error=1; - $errormsg = 'unsupported filter method'; - } - break; - case 'PLTE': - $pdata.=substr($data,$p+8,$chunkLen); - break; - case 'IDAT': - $idata.=substr($data,$p+8,$chunkLen); - break; - case 'tRNS': - //this chunk can only occur once and it must occur after the PLTE chunk and before IDAT chunk - //print "tRNS found, color type = ".$info['colorType']."
    "; - $transparency = array(); - if ($info['colorType'] == 3) { // indexed color, rbg - /* corresponding to entries in the plte chunk - Alpha for palette index 0: 1 byte - Alpha for palette index 1: 1 byte - ...etc... - */ - // there will be one entry for each palette entry. up until the last non-opaque entry. - // set up an array, stretching over all palette entries which will be o (opaque) or 1 (transparent) - $transparency['type']='indexed'; - $numPalette = strlen($pdata)/3; - $trans=0; - for ($i=$chunkLen;$i>=0;$i--){ - if (ord($data[$p+8+$i])==0){ - $trans=$i; - } - } - $transparency['data'] = $trans; - - } elseif($info['colorType'] == 0) { // grayscale - /* corresponding to entries in the plte chunk - Gray: 2 bytes, range 0 .. (2^bitdepth)-1 - */ -// $transparency['grayscale']=$this->PRVT_getBytes($data,$p+8,2); // g = grayscale - $transparency['type']='indexed'; - $transparency['data'] = ord($data[$p+8+1]); - - } elseif($info['colorType'] == 2) { // truecolor - /* corresponding to entries in the plte chunk - Red: 2 bytes, range 0 .. (2^bitdepth)-1 - Green: 2 bytes, range 0 .. (2^bitdepth)-1 - Blue: 2 bytes, range 0 .. (2^bitdepth)-1 - */ - $transparency['r']=$this->PRVT_getBytes($data,$p+8,2); // r from truecolor - $transparency['g']=$this->PRVT_getBytes($data,$p+10,2); // g from truecolor - $transparency['b']=$this->PRVT_getBytes($data,$p+12,2); // b from truecolor - - } else { - //unsupported transparency type - } - // KS End new code - break; - default: - break; - } - - $p += $chunkLen+12; - } - - if(!$haveHeader){ - $error = 1; - $errormsg = 'information header is missing'; - } - if (isset($info['interlaceMethod']) && $info['interlaceMethod']){ - $error = 1; - $errormsg = 'There appears to be no support for interlaced images in pdf.'; - } - } - - if (!$error && $info['bitDepth'] > 8){ - $error = 1; - $errormsg = 'only bit depth of 8 or less is supported'; - } - - if (!$error){ - if ($info['colorType']!=2 && $info['colorType']!=0 && $info['colorType']!=3){ - $error = 1; - $errormsg = 'transparancey alpha channel not supported, transparency only supported for palette images.'; - } else { - switch ($info['colorType']){ - case 3: - $color = 'DeviceRGB'; - $ncolor=1; - break; - case 2: - $color = 'DeviceRGB'; - $ncolor=3; - break; - case 0: - $color = 'DeviceGray'; - $ncolor=1; - break; - } - } - } - if ($error){ - $this->addMessage('PNG error - ('.$file.') '.$errormsg); - return; - } - if ($w==0){ - $w=$h/$info['height']*$info['width']; - } - if ($h==0){ - $h=$w*$info['height']/$info['width']; - } -//print_r($info); - // so this image is ok... add it in. - $this->numImages++; - $im=$this->numImages; - $label='I'.$im; - $this->numObj++; -// $this->o_image($this->numObj,'new',array('label'=>$label,'data'=>$idata,'iw'=>$w,'ih'=>$h,'type'=>'png','ic'=>$info['width'])); - $options = array('label'=>$label,'data'=>$idata,'bitsPerComponent'=>$info['bitDepth'],'pdata'=>$pdata - ,'iw'=>$info['width'],'ih'=>$info['height'],'type'=>'png','color'=>$color,'ncolor'=>$ncolor); - if (isset($transparency)){ - $options['transparency']=$transparency; - } - $this->o_image($this->numObj,'new',$options); - - $this->objects[$this->currentContents]['c'].="\nq"; - $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$w)." 0 0 ".sprintf('%.3f',$h)." ".sprintf('%.3f',$x)." ".sprintf('%.3f',$y)." cm"; - $this->objects[$this->currentContents]['c'].="\n/".$label.' Do'; - $this->objects[$this->currentContents]['c'].="\nQ"; -} - -/** -* add a JPEG image into the document, from a file -*/ -function addJpegFromFile($img,$x,$y,$w=0,$h=0){ - // attempt to add a jpeg image straight from a file, using no GD commands - // note that this function is unable to operate on a remote file. - - if (!file_exists($img)){ - return; - } - - $tmp=getimagesize($img); - $imageWidth=$tmp[0]; - $imageHeight=$tmp[1]; - - if (isset($tmp['channels'])){ - $channels = $tmp['channels']; - } else { - $channels = 3; - } - - if ($w<=0 && $h<=0){ - $w=$imageWidth; - } - if ($w==0){ - $w=$h/$imageHeight*$imageWidth; - } - if ($h==0){ - $h=$w*$imageHeight/$imageWidth; - } - - $fp=fopen($img,'rb'); - - $tmp = get_magic_quotes_runtime(); - set_magic_quotes_runtime(0); - $data = fread($fp,filesize($img)); - set_magic_quotes_runtime($tmp); - - fclose($fp); - - $this->addJpegImage_common($data,$x,$y,$w,$h,$imageWidth,$imageHeight,$channels); -} - -/** -* add an image into the document, from a GD object -* this function is not all that reliable, and I would probably encourage people to use -* the file based functions -*/ -function addImage(&$img,$x,$y,$w=0,$h=0,$quality=75){ - // add a new image into the current location, as an external object - // add the image at $x,$y, and with width and height as defined by $w & $h - - // note that this will only work with full colour images and makes them jpg images for display - // later versions could present lossless image formats if there is interest. - - // there seems to be some problem here in that images that have quality set above 75 do not appear - // not too sure why this is, but in the meantime I have restricted this to 75. - if ($quality>75){ - $quality=75; - } - - // if the width or height are set to zero, then set the other one based on keeping the image - // height/width ratio the same, if they are both zero, then give up :) - $imageWidth=imagesx($img); - $imageHeight=imagesy($img); - - if ($w<=0 && $h<=0){ - return; - } - if ($w==0){ - $w=$h/$imageHeight*$imageWidth; - } - if ($h==0){ - $h=$w*$imageHeight/$imageWidth; - } - - // gotta get the data out of the img.. - - // so I write to a temp file, and then read it back.. soo ugly, my apologies. - $tmpDir='/tmp'; - $tmpName=tempnam($tmpDir,'img'); - imagejpeg($img,$tmpName,$quality); - $fp=fopen($tmpName,'rb'); - - $tmp = get_magic_quotes_runtime(); - set_magic_quotes_runtime(0); - $fp = @fopen($tmpName,'rb'); - if ($fp){ - $data=''; - while(!feof($fp)){ - $data .= fread($fp,1024); - } - fclose($fp); - } else { - $error = 1; - $errormsg = 'trouble opening file'; - } -// $data = fread($fp,filesize($tmpName)); - set_magic_quotes_runtime($tmp); -// fclose($fp); - unlink($tmpName); - $this->addJpegImage_common($data,$x,$y,$w,$h,$imageWidth,$imageHeight); -} - -/** -* common code used by the two JPEG adding functions -* -* @access private -*/ -function addJpegImage_common(&$data,$x,$y,$w=0,$h=0,$imageWidth,$imageHeight,$channels=3){ - // note that this function is not to be called externally - // it is just the common code between the GD and the file options - $this->numImages++; - $im=$this->numImages; - $label='I'.$im; - $this->numObj++; - $this->o_image($this->numObj,'new',array('label'=>$label,'data'=>$data,'iw'=>$imageWidth,'ih'=>$imageHeight,'channels'=>$channels)); - - $this->objects[$this->currentContents]['c'].="\nq"; - $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$w)." 0 0 ".sprintf('%.3f',$h)." ".sprintf('%.3f',$x)." ".sprintf('%.3f',$y)." cm"; - $this->objects[$this->currentContents]['c'].="\n/".$label.' Do'; - $this->objects[$this->currentContents]['c'].="\nQ"; -} - -/** -* specify where the document should open when it first starts -*/ -function openHere($style,$a=0,$b=0,$c=0){ - // this function will open the document at a specified page, in a specified style - // the values for style, and the required paramters are: - // 'XYZ' left, top, zoom - // 'Fit' - // 'FitH' top - // 'FitV' left - // 'FitR' left,bottom,right - // 'FitB' - // 'FitBH' top - // 'FitBV' left - $this->numObj++; - $this->o_destination($this->numObj,'new',array('page'=>$this->currentPage,'type'=>$style,'p1'=>$a,'p2'=>$b,'p3'=>$c)); - $id = $this->catalogId; - $this->o_catalog($id,'openHere',$this->numObj); -} - -/** -* create a labelled destination within the document -*/ -function addDestination($label,$style,$a=0,$b=0,$c=0){ - // associates the given label with the destination, it is done this way so that a destination can be specified after - // it has been linked to - // styles are the same as the 'openHere' function - $this->numObj++; - $this->o_destination($this->numObj,'new',array('page'=>$this->currentPage,'type'=>$style,'p1'=>$a,'p2'=>$b,'p3'=>$c)); - $id = $this->numObj; - // store the label->idf relationship, note that this means that labels can be used only once - $this->destinations["$label"]=$id; -} - -/** -* define font families, this is used to initialize the font families for the default fonts -* and for the user to add new ones for their fonts. The default bahavious can be overridden should -* that be desired. -*/ -function setFontFamily($family,$options=''){ - if (!is_array($options)){ - if ($family=='init'){ - // set the known family groups - // these font families will be used to enable bold and italic markers to be included - // within text streams. html forms will be used... - $this->fontFamilies['Helvetica.afm']=array( - 'b'=>'Helvetica-Bold.afm' - ,'i'=>'Helvetica-Oblique.afm' - ,'bi'=>'Helvetica-BoldOblique.afm' - ,'ib'=>'Helvetica-BoldOblique.afm' - ); - $this->fontFamilies['Courier.afm']=array( - 'b'=>'Courier-Bold.afm' - ,'i'=>'Courier-Oblique.afm' - ,'bi'=>'Courier-BoldOblique.afm' - ,'ib'=>'Courier-BoldOblique.afm' - ); - $this->fontFamilies['Times-Roman.afm']=array( - 'b'=>'Times-Bold.afm' - ,'i'=>'Times-Italic.afm' - ,'bi'=>'Times-BoldItalic.afm' - ,'ib'=>'Times-BoldItalic.afm' - ); - } - } else { - // the user is trying to set a font family - // note that this can also be used to set the base ones to something else - if (strlen($family)){ - $this->fontFamilies[$family] = $options; - } - } -} - -/** -* used to add messages for use in debugging -*/ -function addMessage($message){ - $this->messages.=$message."\n"; -} - -/** -* a few functions which should allow the document to be treated transactionally. -*/ -function transaction($action){ - switch ($action){ - case 'start': - // store all the data away into the checkpoint variable - $data = get_object_vars($this); - $this->checkpoint = $data; - unset($data); - break; - case 'commit': - if (is_array($this->checkpoint) && isset($this->checkpoint['checkpoint'])){ - $tmp = $this->checkpoint['checkpoint']; - $this->checkpoint = $tmp; - unset($tmp); - } else { - $this->checkpoint=''; - } - break; - case 'rewind': - // do not destroy the current checkpoint, but move us back to the state then, so that we can try again - if (is_array($this->checkpoint)){ - // can only abort if were inside a checkpoint - $tmp = $this->checkpoint; - foreach ($tmp as $k=>$v){ - if ($k != 'checkpoint'){ - $this->$k=$v; - } - } - unset($tmp); - } - break; - case 'abort': - if (is_array($this->checkpoint)){ - // can only abort if were inside a checkpoint - $tmp = $this->checkpoint; - foreach ($tmp as $k=>$v){ - $this->$k=$v; - } - unset($tmp); - } - break; - } - -} - -} // end of class - -?> \ No newline at end of file diff --git a/mods/pdf_converter/font/courier.php b/mods/pdf_converter/font/courier.php deleted file mode 100644 index 913f9a453..000000000 --- a/mods/pdf_converter/font/courier.php +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/mods/pdf_converter/font/helvetica.php b/mods/pdf_converter/font/helvetica.php deleted file mode 100644 index ca94cdf21..000000000 --- a/mods/pdf_converter/font/helvetica.php +++ /dev/null @@ -1,15 +0,0 @@ -278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278, - chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>278,'"'=>355,'#'=>556,'$'=>556,'%'=>889,'&'=>667,'\''=>191,'('=>333,')'=>333,'*'=>389,'+'=>584, - ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>278,';'=>278,'<'=>584,'='=>584,'>'=>584,'?'=>556,'@'=>1015,'A'=>667, - 'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>500,'K'=>667,'L'=>556,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944, - 'X'=>667,'Y'=>667,'Z'=>611,'['=>278,'\\'=>278,']'=>278,'^'=>469,'_'=>556,'`'=>333,'a'=>556,'b'=>556,'c'=>500,'d'=>556,'e'=>556,'f'=>278,'g'=>556,'h'=>556,'i'=>222,'j'=>222,'k'=>500,'l'=>222,'m'=>833, - 'n'=>556,'o'=>556,'p'=>556,'q'=>556,'r'=>333,'s'=>500,'t'=>278,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>500,'{'=>334,'|'=>260,'}'=>334,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>222,chr(131)=>556, - chr(132)=>333,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>222,chr(146)=>222,chr(147)=>333,chr(148)=>333,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000, - chr(154)=>500,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>260,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333, - chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>556,chr(182)=>537,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667, - chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, - chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>500,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>556,chr(241)=>556, - chr(242)=>556,chr(243)=>556,chr(244)=>556,chr(245)=>556,chr(246)=>556,chr(247)=>584,chr(248)=>611,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500); -?> diff --git a/mods/pdf_converter/font/helveticab.php b/mods/pdf_converter/font/helveticab.php deleted file mode 100644 index 276cfa8cb..000000000 --- a/mods/pdf_converter/font/helveticab.php +++ /dev/null @@ -1,15 +0,0 @@ -278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278, - chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>333,'"'=>474,'#'=>556,'$'=>556,'%'=>889,'&'=>722,'\''=>238,'('=>333,')'=>333,'*'=>389,'+'=>584, - ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>333,';'=>333,'<'=>584,'='=>584,'>'=>584,'?'=>611,'@'=>975,'A'=>722, - 'B'=>722,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>556,'K'=>722,'L'=>611,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944, - 'X'=>667,'Y'=>667,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>584,'_'=>556,'`'=>333,'a'=>556,'b'=>611,'c'=>556,'d'=>611,'e'=>556,'f'=>333,'g'=>611,'h'=>611,'i'=>278,'j'=>278,'k'=>556,'l'=>278,'m'=>889, - 'n'=>611,'o'=>611,'p'=>611,'q'=>611,'r'=>389,'s'=>556,'t'=>333,'u'=>611,'v'=>556,'w'=>778,'x'=>556,'y'=>556,'z'=>500,'{'=>389,'|'=>280,'}'=>389,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>278,chr(131)=>556, - chr(132)=>500,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>278,chr(146)=>278,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000, - chr(154)=>556,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>280,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333, - chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>611,chr(182)=>556,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722, - chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, - chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>556,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>611,chr(241)=>611, - chr(242)=>611,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>584,chr(248)=>611,chr(249)=>611,chr(250)=>611,chr(251)=>611,chr(252)=>611,chr(253)=>556,chr(254)=>611,chr(255)=>556); -?> diff --git a/mods/pdf_converter/font/helveticabi.php b/mods/pdf_converter/font/helveticabi.php deleted file mode 100644 index 8d2177432..000000000 --- a/mods/pdf_converter/font/helveticabi.php +++ /dev/null @@ -1,15 +0,0 @@ -278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278, - chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>333,'"'=>474,'#'=>556,'$'=>556,'%'=>889,'&'=>722,'\''=>238,'('=>333,')'=>333,'*'=>389,'+'=>584, - ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>333,';'=>333,'<'=>584,'='=>584,'>'=>584,'?'=>611,'@'=>975,'A'=>722, - 'B'=>722,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>556,'K'=>722,'L'=>611,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944, - 'X'=>667,'Y'=>667,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>584,'_'=>556,'`'=>333,'a'=>556,'b'=>611,'c'=>556,'d'=>611,'e'=>556,'f'=>333,'g'=>611,'h'=>611,'i'=>278,'j'=>278,'k'=>556,'l'=>278,'m'=>889, - 'n'=>611,'o'=>611,'p'=>611,'q'=>611,'r'=>389,'s'=>556,'t'=>333,'u'=>611,'v'=>556,'w'=>778,'x'=>556,'y'=>556,'z'=>500,'{'=>389,'|'=>280,'}'=>389,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>278,chr(131)=>556, - chr(132)=>500,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>278,chr(146)=>278,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000, - chr(154)=>556,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>280,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333, - chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>611,chr(182)=>556,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722, - chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, - chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>556,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>611,chr(241)=>611, - chr(242)=>611,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>584,chr(248)=>611,chr(249)=>611,chr(250)=>611,chr(251)=>611,chr(252)=>611,chr(253)=>556,chr(254)=>611,chr(255)=>556); -?> diff --git a/mods/pdf_converter/font/helveticai.php b/mods/pdf_converter/font/helveticai.php deleted file mode 100644 index 88bf4371b..000000000 --- a/mods/pdf_converter/font/helveticai.php +++ /dev/null @@ -1,15 +0,0 @@ -278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278, - chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>278,'"'=>355,'#'=>556,'$'=>556,'%'=>889,'&'=>667,'\''=>191,'('=>333,')'=>333,'*'=>389,'+'=>584, - ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>278,';'=>278,'<'=>584,'='=>584,'>'=>584,'?'=>556,'@'=>1015,'A'=>667, - 'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>500,'K'=>667,'L'=>556,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944, - 'X'=>667,'Y'=>667,'Z'=>611,'['=>278,'\\'=>278,']'=>278,'^'=>469,'_'=>556,'`'=>333,'a'=>556,'b'=>556,'c'=>500,'d'=>556,'e'=>556,'f'=>278,'g'=>556,'h'=>556,'i'=>222,'j'=>222,'k'=>500,'l'=>222,'m'=>833, - 'n'=>556,'o'=>556,'p'=>556,'q'=>556,'r'=>333,'s'=>500,'t'=>278,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>500,'{'=>334,'|'=>260,'}'=>334,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>222,chr(131)=>556, - chr(132)=>333,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>222,chr(146)=>222,chr(147)=>333,chr(148)=>333,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000, - chr(154)=>500,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>260,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333, - chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>556,chr(182)=>537,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667, - chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, - chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>500,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>556,chr(241)=>556, - chr(242)=>556,chr(243)=>556,chr(244)=>556,chr(245)=>556,chr(246)=>556,chr(247)=>584,chr(248)=>611,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500); -?> diff --git a/mods/pdf_converter/font/makefont/cp1250.map b/mods/pdf_converter/font/makefont/cp1250.map deleted file mode 100644 index ec110af06..000000000 --- a/mods/pdf_converter/font/makefont/cp1250.map +++ /dev/null @@ -1,251 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+20AC Euro -!82 U+201A quotesinglbase -!84 U+201E quotedblbase -!85 U+2026 ellipsis -!86 U+2020 dagger -!87 U+2021 daggerdbl -!89 U+2030 perthousand -!8A U+0160 Scaron -!8B U+2039 guilsinglleft -!8C U+015A Sacute -!8D U+0164 Tcaron -!8E U+017D Zcaron -!8F U+0179 Zacute -!91 U+2018 quoteleft -!92 U+2019 quoteright -!93 U+201C quotedblleft -!94 U+201D quotedblright -!95 U+2022 bullet -!96 U+2013 endash -!97 U+2014 emdash -!99 U+2122 trademark -!9A U+0161 scaron -!9B U+203A guilsinglright -!9C U+015B sacute -!9D U+0165 tcaron -!9E U+017E zcaron -!9F U+017A zacute -!A0 U+00A0 space -!A1 U+02C7 caron -!A2 U+02D8 breve -!A3 U+0141 Lslash -!A4 U+00A4 currency -!A5 U+0104 Aogonek -!A6 U+00A6 brokenbar -!A7 U+00A7 section -!A8 U+00A8 dieresis -!A9 U+00A9 copyright -!AA U+015E Scedilla -!AB U+00AB guillemotleft -!AC U+00AC logicalnot -!AD U+00AD hyphen -!AE U+00AE registered -!AF U+017B Zdotaccent -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+02DB ogonek -!B3 U+0142 lslash -!B4 U+00B4 acute -!B5 U+00B5 mu -!B6 U+00B6 paragraph -!B7 U+00B7 periodcentered -!B8 U+00B8 cedilla -!B9 U+0105 aogonek -!BA U+015F scedilla -!BB U+00BB guillemotright -!BC U+013D Lcaron -!BD U+02DD hungarumlaut -!BE U+013E lcaron -!BF U+017C zdotaccent -!C0 U+0154 Racute -!C1 U+00C1 Aacute -!C2 U+00C2 Acircumflex -!C3 U+0102 Abreve -!C4 U+00C4 Adieresis -!C5 U+0139 Lacute -!C6 U+0106 Cacute -!C7 U+00C7 Ccedilla -!C8 U+010C Ccaron -!C9 U+00C9 Eacute -!CA U+0118 Eogonek -!CB U+00CB Edieresis -!CC U+011A Ecaron -!CD U+00CD Iacute -!CE U+00CE Icircumflex -!CF U+010E Dcaron -!D0 U+0110 Dcroat -!D1 U+0143 Nacute -!D2 U+0147 Ncaron -!D3 U+00D3 Oacute -!D4 U+00D4 Ocircumflex -!D5 U+0150 Ohungarumlaut -!D6 U+00D6 Odieresis -!D7 U+00D7 multiply -!D8 U+0158 Rcaron -!D9 U+016E Uring -!DA U+00DA Uacute -!DB U+0170 Uhungarumlaut -!DC U+00DC Udieresis -!DD U+00DD Yacute -!DE U+0162 Tcommaaccent -!DF U+00DF germandbls -!E0 U+0155 racute -!E1 U+00E1 aacute -!E2 U+00E2 acircumflex -!E3 U+0103 abreve -!E4 U+00E4 adieresis -!E5 U+013A lacute -!E6 U+0107 cacute -!E7 U+00E7 ccedilla -!E8 U+010D ccaron -!E9 U+00E9 eacute -!EA U+0119 eogonek -!EB U+00EB edieresis -!EC U+011B ecaron -!ED U+00ED iacute -!EE U+00EE icircumflex -!EF U+010F dcaron -!F0 U+0111 dcroat -!F1 U+0144 nacute -!F2 U+0148 ncaron -!F3 U+00F3 oacute -!F4 U+00F4 ocircumflex -!F5 U+0151 ohungarumlaut -!F6 U+00F6 odieresis -!F7 U+00F7 divide -!F8 U+0159 rcaron -!F9 U+016F uring -!FA U+00FA uacute -!FB U+0171 uhungarumlaut -!FC U+00FC udieresis -!FD U+00FD yacute -!FE U+0163 tcommaaccent -!FF U+02D9 dotaccent diff --git a/mods/pdf_converter/font/makefont/cp1251.map b/mods/pdf_converter/font/makefont/cp1251.map deleted file mode 100644 index de6a198d9..000000000 --- a/mods/pdf_converter/font/makefont/cp1251.map +++ /dev/null @@ -1,255 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+0402 afii10051 -!81 U+0403 afii10052 -!82 U+201A quotesinglbase -!83 U+0453 afii10100 -!84 U+201E quotedblbase -!85 U+2026 ellipsis -!86 U+2020 dagger -!87 U+2021 daggerdbl -!88 U+20AC Euro -!89 U+2030 perthousand -!8A U+0409 afii10058 -!8B U+2039 guilsinglleft -!8C U+040A afii10059 -!8D U+040C afii10061 -!8E U+040B afii10060 -!8F U+040F afii10145 -!90 U+0452 afii10099 -!91 U+2018 quoteleft -!92 U+2019 quoteright -!93 U+201C quotedblleft -!94 U+201D quotedblright -!95 U+2022 bullet -!96 U+2013 endash -!97 U+2014 emdash -!99 U+2122 trademark -!9A U+0459 afii10106 -!9B U+203A guilsinglright -!9C U+045A afii10107 -!9D U+045C afii10109 -!9E U+045B afii10108 -!9F U+045F afii10193 -!A0 U+00A0 space -!A1 U+040E afii10062 -!A2 U+045E afii10110 -!A3 U+0408 afii10057 -!A4 U+00A4 currency -!A5 U+0490 afii10050 -!A6 U+00A6 brokenbar -!A7 U+00A7 section -!A8 U+0401 afii10023 -!A9 U+00A9 copyright -!AA U+0404 afii10053 -!AB U+00AB guillemotleft -!AC U+00AC logicalnot -!AD U+00AD hyphen -!AE U+00AE registered -!AF U+0407 afii10056 -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+0406 afii10055 -!B3 U+0456 afii10103 -!B4 U+0491 afii10098 -!B5 U+00B5 mu -!B6 U+00B6 paragraph -!B7 U+00B7 periodcentered -!B8 U+0451 afii10071 -!B9 U+2116 afii61352 -!BA U+0454 afii10101 -!BB U+00BB guillemotright -!BC U+0458 afii10105 -!BD U+0405 afii10054 -!BE U+0455 afii10102 -!BF U+0457 afii10104 -!C0 U+0410 afii10017 -!C1 U+0411 afii10018 -!C2 U+0412 afii10019 -!C3 U+0413 afii10020 -!C4 U+0414 afii10021 -!C5 U+0415 afii10022 -!C6 U+0416 afii10024 -!C7 U+0417 afii10025 -!C8 U+0418 afii10026 -!C9 U+0419 afii10027 -!CA U+041A afii10028 -!CB U+041B afii10029 -!CC U+041C afii10030 -!CD U+041D afii10031 -!CE U+041E afii10032 -!CF U+041F afii10033 -!D0 U+0420 afii10034 -!D1 U+0421 afii10035 -!D2 U+0422 afii10036 -!D3 U+0423 afii10037 -!D4 U+0424 afii10038 -!D5 U+0425 afii10039 -!D6 U+0426 afii10040 -!D7 U+0427 afii10041 -!D8 U+0428 afii10042 -!D9 U+0429 afii10043 -!DA U+042A afii10044 -!DB U+042B afii10045 -!DC U+042C afii10046 -!DD U+042D afii10047 -!DE U+042E afii10048 -!DF U+042F afii10049 -!E0 U+0430 afii10065 -!E1 U+0431 afii10066 -!E2 U+0432 afii10067 -!E3 U+0433 afii10068 -!E4 U+0434 afii10069 -!E5 U+0435 afii10070 -!E6 U+0436 afii10072 -!E7 U+0437 afii10073 -!E8 U+0438 afii10074 -!E9 U+0439 afii10075 -!EA U+043A afii10076 -!EB U+043B afii10077 -!EC U+043C afii10078 -!ED U+043D afii10079 -!EE U+043E afii10080 -!EF U+043F afii10081 -!F0 U+0440 afii10082 -!F1 U+0441 afii10083 -!F2 U+0442 afii10084 -!F3 U+0443 afii10085 -!F4 U+0444 afii10086 -!F5 U+0445 afii10087 -!F6 U+0446 afii10088 -!F7 U+0447 afii10089 -!F8 U+0448 afii10090 -!F9 U+0449 afii10091 -!FA U+044A afii10092 -!FB U+044B afii10093 -!FC U+044C afii10094 -!FD U+044D afii10095 -!FE U+044E afii10096 -!FF U+044F afii10097 diff --git a/mods/pdf_converter/font/makefont/cp1252.map b/mods/pdf_converter/font/makefont/cp1252.map deleted file mode 100644 index dd490e596..000000000 --- a/mods/pdf_converter/font/makefont/cp1252.map +++ /dev/null @@ -1,251 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+20AC Euro -!82 U+201A quotesinglbase -!83 U+0192 florin -!84 U+201E quotedblbase -!85 U+2026 ellipsis -!86 U+2020 dagger -!87 U+2021 daggerdbl -!88 U+02C6 circumflex -!89 U+2030 perthousand -!8A U+0160 Scaron -!8B U+2039 guilsinglleft -!8C U+0152 OE -!8E U+017D Zcaron -!91 U+2018 quoteleft -!92 U+2019 quoteright -!93 U+201C quotedblleft -!94 U+201D quotedblright -!95 U+2022 bullet -!96 U+2013 endash -!97 U+2014 emdash -!98 U+02DC tilde -!99 U+2122 trademark -!9A U+0161 scaron -!9B U+203A guilsinglright -!9C U+0153 oe -!9E U+017E zcaron -!9F U+0178 Ydieresis -!A0 U+00A0 space -!A1 U+00A1 exclamdown -!A2 U+00A2 cent -!A3 U+00A3 sterling -!A4 U+00A4 currency -!A5 U+00A5 yen -!A6 U+00A6 brokenbar -!A7 U+00A7 section -!A8 U+00A8 dieresis -!A9 U+00A9 copyright -!AA U+00AA ordfeminine -!AB U+00AB guillemotleft -!AC U+00AC logicalnot -!AD U+00AD hyphen -!AE U+00AE registered -!AF U+00AF macron -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+00B2 twosuperior -!B3 U+00B3 threesuperior -!B4 U+00B4 acute -!B5 U+00B5 mu -!B6 U+00B6 paragraph -!B7 U+00B7 periodcentered -!B8 U+00B8 cedilla -!B9 U+00B9 onesuperior -!BA U+00BA ordmasculine -!BB U+00BB guillemotright -!BC U+00BC onequarter -!BD U+00BD onehalf -!BE U+00BE threequarters -!BF U+00BF questiondown -!C0 U+00C0 Agrave -!C1 U+00C1 Aacute -!C2 U+00C2 Acircumflex -!C3 U+00C3 Atilde -!C4 U+00C4 Adieresis -!C5 U+00C5 Aring -!C6 U+00C6 AE -!C7 U+00C7 Ccedilla -!C8 U+00C8 Egrave -!C9 U+00C9 Eacute -!CA U+00CA Ecircumflex -!CB U+00CB Edieresis -!CC U+00CC Igrave -!CD U+00CD Iacute -!CE U+00CE Icircumflex -!CF U+00CF Idieresis -!D0 U+00D0 Eth -!D1 U+00D1 Ntilde -!D2 U+00D2 Ograve -!D3 U+00D3 Oacute -!D4 U+00D4 Ocircumflex -!D5 U+00D5 Otilde -!D6 U+00D6 Odieresis -!D7 U+00D7 multiply -!D8 U+00D8 Oslash -!D9 U+00D9 Ugrave -!DA U+00DA Uacute -!DB U+00DB Ucircumflex -!DC U+00DC Udieresis -!DD U+00DD Yacute -!DE U+00DE Thorn -!DF U+00DF germandbls -!E0 U+00E0 agrave -!E1 U+00E1 aacute -!E2 U+00E2 acircumflex -!E3 U+00E3 atilde -!E4 U+00E4 adieresis -!E5 U+00E5 aring -!E6 U+00E6 ae -!E7 U+00E7 ccedilla -!E8 U+00E8 egrave -!E9 U+00E9 eacute -!EA U+00EA ecircumflex -!EB U+00EB edieresis -!EC U+00EC igrave -!ED U+00ED iacute -!EE U+00EE icircumflex -!EF U+00EF idieresis -!F0 U+00F0 eth -!F1 U+00F1 ntilde -!F2 U+00F2 ograve -!F3 U+00F3 oacute -!F4 U+00F4 ocircumflex -!F5 U+00F5 otilde -!F6 U+00F6 odieresis -!F7 U+00F7 divide -!F8 U+00F8 oslash -!F9 U+00F9 ugrave -!FA U+00FA uacute -!FB U+00FB ucircumflex -!FC U+00FC udieresis -!FD U+00FD yacute -!FE U+00FE thorn -!FF U+00FF ydieresis diff --git a/mods/pdf_converter/font/makefont/cp1253.map b/mods/pdf_converter/font/makefont/cp1253.map deleted file mode 100644 index 4bd826fb2..000000000 --- a/mods/pdf_converter/font/makefont/cp1253.map +++ /dev/null @@ -1,239 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+20AC Euro -!82 U+201A quotesinglbase -!83 U+0192 florin -!84 U+201E quotedblbase -!85 U+2026 ellipsis -!86 U+2020 dagger -!87 U+2021 daggerdbl -!89 U+2030 perthousand -!8B U+2039 guilsinglleft -!91 U+2018 quoteleft -!92 U+2019 quoteright -!93 U+201C quotedblleft -!94 U+201D quotedblright -!95 U+2022 bullet -!96 U+2013 endash -!97 U+2014 emdash -!99 U+2122 trademark -!9B U+203A guilsinglright -!A0 U+00A0 space -!A1 U+0385 dieresistonos -!A2 U+0386 Alphatonos -!A3 U+00A3 sterling -!A4 U+00A4 currency -!A5 U+00A5 yen -!A6 U+00A6 brokenbar -!A7 U+00A7 section -!A8 U+00A8 dieresis -!A9 U+00A9 copyright -!AB U+00AB guillemotleft -!AC U+00AC logicalnot -!AD U+00AD hyphen -!AE U+00AE registered -!AF U+2015 afii00208 -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+00B2 twosuperior -!B3 U+00B3 threesuperior -!B4 U+0384 tonos -!B5 U+00B5 mu -!B6 U+00B6 paragraph -!B7 U+00B7 periodcentered -!B8 U+0388 Epsilontonos -!B9 U+0389 Etatonos -!BA U+038A Iotatonos -!BB U+00BB guillemotright -!BC U+038C Omicrontonos -!BD U+00BD onehalf -!BE U+038E Upsilontonos -!BF U+038F Omegatonos -!C0 U+0390 iotadieresistonos -!C1 U+0391 Alpha -!C2 U+0392 Beta -!C3 U+0393 Gamma -!C4 U+0394 Delta -!C5 U+0395 Epsilon -!C6 U+0396 Zeta -!C7 U+0397 Eta -!C8 U+0398 Theta -!C9 U+0399 Iota -!CA U+039A Kappa -!CB U+039B Lambda -!CC U+039C Mu -!CD U+039D Nu -!CE U+039E Xi -!CF U+039F Omicron -!D0 U+03A0 Pi -!D1 U+03A1 Rho -!D3 U+03A3 Sigma -!D4 U+03A4 Tau -!D5 U+03A5 Upsilon -!D6 U+03A6 Phi -!D7 U+03A7 Chi -!D8 U+03A8 Psi -!D9 U+03A9 Omega -!DA U+03AA Iotadieresis -!DB U+03AB Upsilondieresis -!DC U+03AC alphatonos -!DD U+03AD epsilontonos -!DE U+03AE etatonos -!DF U+03AF iotatonos -!E0 U+03B0 upsilondieresistonos -!E1 U+03B1 alpha -!E2 U+03B2 beta -!E3 U+03B3 gamma -!E4 U+03B4 delta -!E5 U+03B5 epsilon -!E6 U+03B6 zeta -!E7 U+03B7 eta -!E8 U+03B8 theta -!E9 U+03B9 iota -!EA U+03BA kappa -!EB U+03BB lambda -!EC U+03BC mu -!ED U+03BD nu -!EE U+03BE xi -!EF U+03BF omicron -!F0 U+03C0 pi -!F1 U+03C1 rho -!F2 U+03C2 sigma1 -!F3 U+03C3 sigma -!F4 U+03C4 tau -!F5 U+03C5 upsilon -!F6 U+03C6 phi -!F7 U+03C7 chi -!F8 U+03C8 psi -!F9 U+03C9 omega -!FA U+03CA iotadieresis -!FB U+03CB upsilondieresis -!FC U+03CC omicrontonos -!FD U+03CD upsilontonos -!FE U+03CE omegatonos diff --git a/mods/pdf_converter/font/makefont/cp1254.map b/mods/pdf_converter/font/makefont/cp1254.map deleted file mode 100644 index 829473b28..000000000 --- a/mods/pdf_converter/font/makefont/cp1254.map +++ /dev/null @@ -1,249 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+20AC Euro -!82 U+201A quotesinglbase -!83 U+0192 florin -!84 U+201E quotedblbase -!85 U+2026 ellipsis -!86 U+2020 dagger -!87 U+2021 daggerdbl -!88 U+02C6 circumflex -!89 U+2030 perthousand -!8A U+0160 Scaron -!8B U+2039 guilsinglleft -!8C U+0152 OE -!91 U+2018 quoteleft -!92 U+2019 quoteright -!93 U+201C quotedblleft -!94 U+201D quotedblright -!95 U+2022 bullet -!96 U+2013 endash -!97 U+2014 emdash -!98 U+02DC tilde -!99 U+2122 trademark -!9A U+0161 scaron -!9B U+203A guilsinglright -!9C U+0153 oe -!9F U+0178 Ydieresis -!A0 U+00A0 space -!A1 U+00A1 exclamdown -!A2 U+00A2 cent -!A3 U+00A3 sterling -!A4 U+00A4 currency -!A5 U+00A5 yen -!A6 U+00A6 brokenbar -!A7 U+00A7 section -!A8 U+00A8 dieresis -!A9 U+00A9 copyright -!AA U+00AA ordfeminine -!AB U+00AB guillemotleft -!AC U+00AC logicalnot -!AD U+00AD hyphen -!AE U+00AE registered -!AF U+00AF macron -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+00B2 twosuperior -!B3 U+00B3 threesuperior -!B4 U+00B4 acute -!B5 U+00B5 mu -!B6 U+00B6 paragraph -!B7 U+00B7 periodcentered -!B8 U+00B8 cedilla -!B9 U+00B9 onesuperior -!BA U+00BA ordmasculine -!BB U+00BB guillemotright -!BC U+00BC onequarter -!BD U+00BD onehalf -!BE U+00BE threequarters -!BF U+00BF questiondown -!C0 U+00C0 Agrave -!C1 U+00C1 Aacute -!C2 U+00C2 Acircumflex -!C3 U+00C3 Atilde -!C4 U+00C4 Adieresis -!C5 U+00C5 Aring -!C6 U+00C6 AE -!C7 U+00C7 Ccedilla -!C8 U+00C8 Egrave -!C9 U+00C9 Eacute -!CA U+00CA Ecircumflex -!CB U+00CB Edieresis -!CC U+00CC Igrave -!CD U+00CD Iacute -!CE U+00CE Icircumflex -!CF U+00CF Idieresis -!D0 U+011E Gbreve -!D1 U+00D1 Ntilde -!D2 U+00D2 Ograve -!D3 U+00D3 Oacute -!D4 U+00D4 Ocircumflex -!D5 U+00D5 Otilde -!D6 U+00D6 Odieresis -!D7 U+00D7 multiply -!D8 U+00D8 Oslash -!D9 U+00D9 Ugrave -!DA U+00DA Uacute -!DB U+00DB Ucircumflex -!DC U+00DC Udieresis -!DD U+0130 Idotaccent -!DE U+015E Scedilla -!DF U+00DF germandbls -!E0 U+00E0 agrave -!E1 U+00E1 aacute -!E2 U+00E2 acircumflex -!E3 U+00E3 atilde -!E4 U+00E4 adieresis -!E5 U+00E5 aring -!E6 U+00E6 ae -!E7 U+00E7 ccedilla -!E8 U+00E8 egrave -!E9 U+00E9 eacute -!EA U+00EA ecircumflex -!EB U+00EB edieresis -!EC U+00EC igrave -!ED U+00ED iacute -!EE U+00EE icircumflex -!EF U+00EF idieresis -!F0 U+011F gbreve -!F1 U+00F1 ntilde -!F2 U+00F2 ograve -!F3 U+00F3 oacute -!F4 U+00F4 ocircumflex -!F5 U+00F5 otilde -!F6 U+00F6 odieresis -!F7 U+00F7 divide -!F8 U+00F8 oslash -!F9 U+00F9 ugrave -!FA U+00FA uacute -!FB U+00FB ucircumflex -!FC U+00FC udieresis -!FD U+0131 dotlessi -!FE U+015F scedilla -!FF U+00FF ydieresis diff --git a/mods/pdf_converter/font/makefont/cp1255.map b/mods/pdf_converter/font/makefont/cp1255.map deleted file mode 100644 index 079e10c61..000000000 --- a/mods/pdf_converter/font/makefont/cp1255.map +++ /dev/null @@ -1,233 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+20AC Euro -!82 U+201A quotesinglbase -!83 U+0192 florin -!84 U+201E quotedblbase -!85 U+2026 ellipsis -!86 U+2020 dagger -!87 U+2021 daggerdbl -!88 U+02C6 circumflex -!89 U+2030 perthousand -!8B U+2039 guilsinglleft -!91 U+2018 quoteleft -!92 U+2019 quoteright -!93 U+201C quotedblleft -!94 U+201D quotedblright -!95 U+2022 bullet -!96 U+2013 endash -!97 U+2014 emdash -!98 U+02DC tilde -!99 U+2122 trademark -!9B U+203A guilsinglright -!A0 U+00A0 space -!A1 U+00A1 exclamdown -!A2 U+00A2 cent -!A3 U+00A3 sterling -!A4 U+20AA afii57636 -!A5 U+00A5 yen -!A6 U+00A6 brokenbar -!A7 U+00A7 section -!A8 U+00A8 dieresis -!A9 U+00A9 copyright -!AA U+00D7 multiply -!AB U+00AB guillemotleft -!AC U+00AC logicalnot -!AD U+00AD sfthyphen -!AE U+00AE registered -!AF U+00AF macron -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+00B2 twosuperior -!B3 U+00B3 threesuperior -!B4 U+00B4 acute -!B5 U+00B5 mu -!B6 U+00B6 paragraph -!B7 U+00B7 middot -!B8 U+00B8 cedilla -!B9 U+00B9 onesuperior -!BA U+00F7 divide -!BB U+00BB guillemotright -!BC U+00BC onequarter -!BD U+00BD onehalf -!BE U+00BE threequarters -!BF U+00BF questiondown -!C0 U+05B0 afii57799 -!C1 U+05B1 afii57801 -!C2 U+05B2 afii57800 -!C3 U+05B3 afii57802 -!C4 U+05B4 afii57793 -!C5 U+05B5 afii57794 -!C6 U+05B6 afii57795 -!C7 U+05B7 afii57798 -!C8 U+05B8 afii57797 -!C9 U+05B9 afii57806 -!CB U+05BB afii57796 -!CC U+05BC afii57807 -!CD U+05BD afii57839 -!CE U+05BE afii57645 -!CF U+05BF afii57841 -!D0 U+05C0 afii57842 -!D1 U+05C1 afii57804 -!D2 U+05C2 afii57803 -!D3 U+05C3 afii57658 -!D4 U+05F0 afii57716 -!D5 U+05F1 afii57717 -!D6 U+05F2 afii57718 -!D7 U+05F3 gereshhebrew -!D8 U+05F4 gershayimhebrew -!E0 U+05D0 afii57664 -!E1 U+05D1 afii57665 -!E2 U+05D2 afii57666 -!E3 U+05D3 afii57667 -!E4 U+05D4 afii57668 -!E5 U+05D5 afii57669 -!E6 U+05D6 afii57670 -!E7 U+05D7 afii57671 -!E8 U+05D8 afii57672 -!E9 U+05D9 afii57673 -!EA U+05DA afii57674 -!EB U+05DB afii57675 -!EC U+05DC afii57676 -!ED U+05DD afii57677 -!EE U+05DE afii57678 -!EF U+05DF afii57679 -!F0 U+05E0 afii57680 -!F1 U+05E1 afii57681 -!F2 U+05E2 afii57682 -!F3 U+05E3 afii57683 -!F4 U+05E4 afii57684 -!F5 U+05E5 afii57685 -!F6 U+05E6 afii57686 -!F7 U+05E7 afii57687 -!F8 U+05E8 afii57688 -!F9 U+05E9 afii57689 -!FA U+05EA afii57690 -!FD U+200E afii299 -!FE U+200F afii300 diff --git a/mods/pdf_converter/font/makefont/cp1257.map b/mods/pdf_converter/font/makefont/cp1257.map deleted file mode 100644 index 2f2ecfa21..000000000 --- a/mods/pdf_converter/font/makefont/cp1257.map +++ /dev/null @@ -1,244 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+20AC Euro -!82 U+201A quotesinglbase -!84 U+201E quotedblbase -!85 U+2026 ellipsis -!86 U+2020 dagger -!87 U+2021 daggerdbl -!89 U+2030 perthousand -!8B U+2039 guilsinglleft -!8D U+00A8 dieresis -!8E U+02C7 caron -!8F U+00B8 cedilla -!91 U+2018 quoteleft -!92 U+2019 quoteright -!93 U+201C quotedblleft -!94 U+201D quotedblright -!95 U+2022 bullet -!96 U+2013 endash -!97 U+2014 emdash -!99 U+2122 trademark -!9B U+203A guilsinglright -!9D U+00AF macron -!9E U+02DB ogonek -!A0 U+00A0 space -!A2 U+00A2 cent -!A3 U+00A3 sterling -!A4 U+00A4 currency -!A6 U+00A6 brokenbar -!A7 U+00A7 section -!A8 U+00D8 Oslash -!A9 U+00A9 copyright -!AA U+0156 Rcommaaccent -!AB U+00AB guillemotleft -!AC U+00AC logicalnot -!AD U+00AD hyphen -!AE U+00AE registered -!AF U+00C6 AE -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+00B2 twosuperior -!B3 U+00B3 threesuperior -!B4 U+00B4 acute -!B5 U+00B5 mu -!B6 U+00B6 paragraph -!B7 U+00B7 periodcentered -!B8 U+00F8 oslash -!B9 U+00B9 onesuperior -!BA U+0157 rcommaaccent -!BB U+00BB guillemotright -!BC U+00BC onequarter -!BD U+00BD onehalf -!BE U+00BE threequarters -!BF U+00E6 ae -!C0 U+0104 Aogonek -!C1 U+012E Iogonek -!C2 U+0100 Amacron -!C3 U+0106 Cacute -!C4 U+00C4 Adieresis -!C5 U+00C5 Aring -!C6 U+0118 Eogonek -!C7 U+0112 Emacron -!C8 U+010C Ccaron -!C9 U+00C9 Eacute -!CA U+0179 Zacute -!CB U+0116 Edotaccent -!CC U+0122 Gcommaaccent -!CD U+0136 Kcommaaccent -!CE U+012A Imacron -!CF U+013B Lcommaaccent -!D0 U+0160 Scaron -!D1 U+0143 Nacute -!D2 U+0145 Ncommaaccent -!D3 U+00D3 Oacute -!D4 U+014C Omacron -!D5 U+00D5 Otilde -!D6 U+00D6 Odieresis -!D7 U+00D7 multiply -!D8 U+0172 Uogonek -!D9 U+0141 Lslash -!DA U+015A Sacute -!DB U+016A Umacron -!DC U+00DC Udieresis -!DD U+017B Zdotaccent -!DE U+017D Zcaron -!DF U+00DF germandbls -!E0 U+0105 aogonek -!E1 U+012F iogonek -!E2 U+0101 amacron -!E3 U+0107 cacute -!E4 U+00E4 adieresis -!E5 U+00E5 aring -!E6 U+0119 eogonek -!E7 U+0113 emacron -!E8 U+010D ccaron -!E9 U+00E9 eacute -!EA U+017A zacute -!EB U+0117 edotaccent -!EC U+0123 gcommaaccent -!ED U+0137 kcommaaccent -!EE U+012B imacron -!EF U+013C lcommaaccent -!F0 U+0161 scaron -!F1 U+0144 nacute -!F2 U+0146 ncommaaccent -!F3 U+00F3 oacute -!F4 U+014D omacron -!F5 U+00F5 otilde -!F6 U+00F6 odieresis -!F7 U+00F7 divide -!F8 U+0173 uogonek -!F9 U+0142 lslash -!FA U+015B sacute -!FB U+016B umacron -!FC U+00FC udieresis -!FD U+017C zdotaccent -!FE U+017E zcaron -!FF U+02D9 dotaccent diff --git a/mods/pdf_converter/font/makefont/cp1258.map b/mods/pdf_converter/font/makefont/cp1258.map deleted file mode 100644 index fed915f71..000000000 --- a/mods/pdf_converter/font/makefont/cp1258.map +++ /dev/null @@ -1,247 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+20AC Euro -!82 U+201A quotesinglbase -!83 U+0192 florin -!84 U+201E quotedblbase -!85 U+2026 ellipsis -!86 U+2020 dagger -!87 U+2021 daggerdbl -!88 U+02C6 circumflex -!89 U+2030 perthousand -!8B U+2039 guilsinglleft -!8C U+0152 OE -!91 U+2018 quoteleft -!92 U+2019 quoteright -!93 U+201C quotedblleft -!94 U+201D quotedblright -!95 U+2022 bullet -!96 U+2013 endash -!97 U+2014 emdash -!98 U+02DC tilde -!99 U+2122 trademark -!9B U+203A guilsinglright -!9C U+0153 oe -!9F U+0178 Ydieresis -!A0 U+00A0 space -!A1 U+00A1 exclamdown -!A2 U+00A2 cent -!A3 U+00A3 sterling -!A4 U+00A4 currency -!A5 U+00A5 yen -!A6 U+00A6 brokenbar -!A7 U+00A7 section -!A8 U+00A8 dieresis -!A9 U+00A9 copyright -!AA U+00AA ordfeminine -!AB U+00AB guillemotleft -!AC U+00AC logicalnot -!AD U+00AD hyphen -!AE U+00AE registered -!AF U+00AF macron -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+00B2 twosuperior -!B3 U+00B3 threesuperior -!B4 U+00B4 acute -!B5 U+00B5 mu -!B6 U+00B6 paragraph -!B7 U+00B7 periodcentered -!B8 U+00B8 cedilla -!B9 U+00B9 onesuperior -!BA U+00BA ordmasculine -!BB U+00BB guillemotright -!BC U+00BC onequarter -!BD U+00BD onehalf -!BE U+00BE threequarters -!BF U+00BF questiondown -!C0 U+00C0 Agrave -!C1 U+00C1 Aacute -!C2 U+00C2 Acircumflex -!C3 U+0102 Abreve -!C4 U+00C4 Adieresis -!C5 U+00C5 Aring -!C6 U+00C6 AE -!C7 U+00C7 Ccedilla -!C8 U+00C8 Egrave -!C9 U+00C9 Eacute -!CA U+00CA Ecircumflex -!CB U+00CB Edieresis -!CC U+0300 gravecomb -!CD U+00CD Iacute -!CE U+00CE Icircumflex -!CF U+00CF Idieresis -!D0 U+0110 Dcroat -!D1 U+00D1 Ntilde -!D2 U+0309 hookabovecomb -!D3 U+00D3 Oacute -!D4 U+00D4 Ocircumflex -!D5 U+01A0 Ohorn -!D6 U+00D6 Odieresis -!D7 U+00D7 multiply -!D8 U+00D8 Oslash -!D9 U+00D9 Ugrave -!DA U+00DA Uacute -!DB U+00DB Ucircumflex -!DC U+00DC Udieresis -!DD U+01AF Uhorn -!DE U+0303 tildecomb -!DF U+00DF germandbls -!E0 U+00E0 agrave -!E1 U+00E1 aacute -!E2 U+00E2 acircumflex -!E3 U+0103 abreve -!E4 U+00E4 adieresis -!E5 U+00E5 aring -!E6 U+00E6 ae -!E7 U+00E7 ccedilla -!E8 U+00E8 egrave -!E9 U+00E9 eacute -!EA U+00EA ecircumflex -!EB U+00EB edieresis -!EC U+0301 acutecomb -!ED U+00ED iacute -!EE U+00EE icircumflex -!EF U+00EF idieresis -!F0 U+0111 dcroat -!F1 U+00F1 ntilde -!F2 U+0323 dotbelowcomb -!F3 U+00F3 oacute -!F4 U+00F4 ocircumflex -!F5 U+01A1 ohorn -!F6 U+00F6 odieresis -!F7 U+00F7 divide -!F8 U+00F8 oslash -!F9 U+00F9 ugrave -!FA U+00FA uacute -!FB U+00FB ucircumflex -!FC U+00FC udieresis -!FD U+01B0 uhorn -!FE U+20AB dong -!FF U+00FF ydieresis diff --git a/mods/pdf_converter/font/makefont/cp874.map b/mods/pdf_converter/font/makefont/cp874.map deleted file mode 100644 index 1006e6b17..000000000 --- a/mods/pdf_converter/font/makefont/cp874.map +++ /dev/null @@ -1,225 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+20AC Euro -!85 U+2026 ellipsis -!91 U+2018 quoteleft -!92 U+2019 quoteright -!93 U+201C quotedblleft -!94 U+201D quotedblright -!95 U+2022 bullet -!96 U+2013 endash -!97 U+2014 emdash -!A0 U+00A0 space -!A1 U+0E01 kokaithai -!A2 U+0E02 khokhaithai -!A3 U+0E03 khokhuatthai -!A4 U+0E04 khokhwaithai -!A5 U+0E05 khokhonthai -!A6 U+0E06 khorakhangthai -!A7 U+0E07 ngonguthai -!A8 U+0E08 chochanthai -!A9 U+0E09 chochingthai -!AA U+0E0A chochangthai -!AB U+0E0B sosothai -!AC U+0E0C chochoethai -!AD U+0E0D yoyingthai -!AE U+0E0E dochadathai -!AF U+0E0F topatakthai -!B0 U+0E10 thothanthai -!B1 U+0E11 thonangmonthothai -!B2 U+0E12 thophuthaothai -!B3 U+0E13 nonenthai -!B4 U+0E14 dodekthai -!B5 U+0E15 totaothai -!B6 U+0E16 thothungthai -!B7 U+0E17 thothahanthai -!B8 U+0E18 thothongthai -!B9 U+0E19 nonuthai -!BA U+0E1A bobaimaithai -!BB U+0E1B poplathai -!BC U+0E1C phophungthai -!BD U+0E1D fofathai -!BE U+0E1E phophanthai -!BF U+0E1F fofanthai -!C0 U+0E20 phosamphaothai -!C1 U+0E21 momathai -!C2 U+0E22 yoyakthai -!C3 U+0E23 roruathai -!C4 U+0E24 ruthai -!C5 U+0E25 lolingthai -!C6 U+0E26 luthai -!C7 U+0E27 wowaenthai -!C8 U+0E28 sosalathai -!C9 U+0E29 sorusithai -!CA U+0E2A sosuathai -!CB U+0E2B hohipthai -!CC U+0E2C lochulathai -!CD U+0E2D oangthai -!CE U+0E2E honokhukthai -!CF U+0E2F paiyannoithai -!D0 U+0E30 saraathai -!D1 U+0E31 maihanakatthai -!D2 U+0E32 saraaathai -!D3 U+0E33 saraamthai -!D4 U+0E34 saraithai -!D5 U+0E35 saraiithai -!D6 U+0E36 sarauethai -!D7 U+0E37 saraueethai -!D8 U+0E38 sarauthai -!D9 U+0E39 sarauuthai -!DA U+0E3A phinthuthai -!DF U+0E3F bahtthai -!E0 U+0E40 saraethai -!E1 U+0E41 saraaethai -!E2 U+0E42 saraothai -!E3 U+0E43 saraaimaimuanthai -!E4 U+0E44 saraaimaimalaithai -!E5 U+0E45 lakkhangyaothai -!E6 U+0E46 maiyamokthai -!E7 U+0E47 maitaikhuthai -!E8 U+0E48 maiekthai -!E9 U+0E49 maithothai -!EA U+0E4A maitrithai -!EB U+0E4B maichattawathai -!EC U+0E4C thanthakhatthai -!ED U+0E4D nikhahitthai -!EE U+0E4E yamakkanthai -!EF U+0E4F fongmanthai -!F0 U+0E50 zerothai -!F1 U+0E51 onethai -!F2 U+0E52 twothai -!F3 U+0E53 threethai -!F4 U+0E54 fourthai -!F5 U+0E55 fivethai -!F6 U+0E56 sixthai -!F7 U+0E57 seventhai -!F8 U+0E58 eightthai -!F9 U+0E59 ninethai -!FA U+0E5A angkhankhuthai -!FB U+0E5B khomutthai diff --git a/mods/pdf_converter/font/makefont/iso-8859-1.map b/mods/pdf_converter/font/makefont/iso-8859-1.map deleted file mode 100644 index 61740a38f..000000000 --- a/mods/pdf_converter/font/makefont/iso-8859-1.map +++ /dev/null @@ -1,256 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+0080 .notdef -!81 U+0081 .notdef -!82 U+0082 .notdef -!83 U+0083 .notdef -!84 U+0084 .notdef -!85 U+0085 .notdef -!86 U+0086 .notdef -!87 U+0087 .notdef -!88 U+0088 .notdef -!89 U+0089 .notdef -!8A U+008A .notdef -!8B U+008B .notdef -!8C U+008C .notdef -!8D U+008D .notdef -!8E U+008E .notdef -!8F U+008F .notdef -!90 U+0090 .notdef -!91 U+0091 .notdef -!92 U+0092 .notdef -!93 U+0093 .notdef -!94 U+0094 .notdef -!95 U+0095 .notdef -!96 U+0096 .notdef -!97 U+0097 .notdef -!98 U+0098 .notdef -!99 U+0099 .notdef -!9A U+009A .notdef -!9B U+009B .notdef -!9C U+009C .notdef -!9D U+009D .notdef -!9E U+009E .notdef -!9F U+009F .notdef -!A0 U+00A0 space -!A1 U+00A1 exclamdown -!A2 U+00A2 cent -!A3 U+00A3 sterling -!A4 U+00A4 currency -!A5 U+00A5 yen -!A6 U+00A6 brokenbar -!A7 U+00A7 section -!A8 U+00A8 dieresis -!A9 U+00A9 copyright -!AA U+00AA ordfeminine -!AB U+00AB guillemotleft -!AC U+00AC logicalnot -!AD U+00AD hyphen -!AE U+00AE registered -!AF U+00AF macron -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+00B2 twosuperior -!B3 U+00B3 threesuperior -!B4 U+00B4 acute -!B5 U+00B5 mu -!B6 U+00B6 paragraph -!B7 U+00B7 periodcentered -!B8 U+00B8 cedilla -!B9 U+00B9 onesuperior -!BA U+00BA ordmasculine -!BB U+00BB guillemotright -!BC U+00BC onequarter -!BD U+00BD onehalf -!BE U+00BE threequarters -!BF U+00BF questiondown -!C0 U+00C0 Agrave -!C1 U+00C1 Aacute -!C2 U+00C2 Acircumflex -!C3 U+00C3 Atilde -!C4 U+00C4 Adieresis -!C5 U+00C5 Aring -!C6 U+00C6 AE -!C7 U+00C7 Ccedilla -!C8 U+00C8 Egrave -!C9 U+00C9 Eacute -!CA U+00CA Ecircumflex -!CB U+00CB Edieresis -!CC U+00CC Igrave -!CD U+00CD Iacute -!CE U+00CE Icircumflex -!CF U+00CF Idieresis -!D0 U+00D0 Eth -!D1 U+00D1 Ntilde -!D2 U+00D2 Ograve -!D3 U+00D3 Oacute -!D4 U+00D4 Ocircumflex -!D5 U+00D5 Otilde -!D6 U+00D6 Odieresis -!D7 U+00D7 multiply -!D8 U+00D8 Oslash -!D9 U+00D9 Ugrave -!DA U+00DA Uacute -!DB U+00DB Ucircumflex -!DC U+00DC Udieresis -!DD U+00DD Yacute -!DE U+00DE Thorn -!DF U+00DF germandbls -!E0 U+00E0 agrave -!E1 U+00E1 aacute -!E2 U+00E2 acircumflex -!E3 U+00E3 atilde -!E4 U+00E4 adieresis -!E5 U+00E5 aring -!E6 U+00E6 ae -!E7 U+00E7 ccedilla -!E8 U+00E8 egrave -!E9 U+00E9 eacute -!EA U+00EA ecircumflex -!EB U+00EB edieresis -!EC U+00EC igrave -!ED U+00ED iacute -!EE U+00EE icircumflex -!EF U+00EF idieresis -!F0 U+00F0 eth -!F1 U+00F1 ntilde -!F2 U+00F2 ograve -!F3 U+00F3 oacute -!F4 U+00F4 ocircumflex -!F5 U+00F5 otilde -!F6 U+00F6 odieresis -!F7 U+00F7 divide -!F8 U+00F8 oslash -!F9 U+00F9 ugrave -!FA U+00FA uacute -!FB U+00FB ucircumflex -!FC U+00FC udieresis -!FD U+00FD yacute -!FE U+00FE thorn -!FF U+00FF ydieresis diff --git a/mods/pdf_converter/font/makefont/iso-8859-11.map b/mods/pdf_converter/font/makefont/iso-8859-11.map deleted file mode 100644 index 916881206..000000000 --- a/mods/pdf_converter/font/makefont/iso-8859-11.map +++ /dev/null @@ -1,248 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+0080 .notdef -!81 U+0081 .notdef -!82 U+0082 .notdef -!83 U+0083 .notdef -!84 U+0084 .notdef -!85 U+0085 .notdef -!86 U+0086 .notdef -!87 U+0087 .notdef -!88 U+0088 .notdef -!89 U+0089 .notdef -!8A U+008A .notdef -!8B U+008B .notdef -!8C U+008C .notdef -!8D U+008D .notdef -!8E U+008E .notdef -!8F U+008F .notdef -!90 U+0090 .notdef -!91 U+0091 .notdef -!92 U+0092 .notdef -!93 U+0093 .notdef -!94 U+0094 .notdef -!95 U+0095 .notdef -!96 U+0096 .notdef -!97 U+0097 .notdef -!98 U+0098 .notdef -!99 U+0099 .notdef -!9A U+009A .notdef -!9B U+009B .notdef -!9C U+009C .notdef -!9D U+009D .notdef -!9E U+009E .notdef -!9F U+009F .notdef -!A0 U+00A0 space -!A1 U+0E01 kokaithai -!A2 U+0E02 khokhaithai -!A3 U+0E03 khokhuatthai -!A4 U+0E04 khokhwaithai -!A5 U+0E05 khokhonthai -!A6 U+0E06 khorakhangthai -!A7 U+0E07 ngonguthai -!A8 U+0E08 chochanthai -!A9 U+0E09 chochingthai -!AA U+0E0A chochangthai -!AB U+0E0B sosothai -!AC U+0E0C chochoethai -!AD U+0E0D yoyingthai -!AE U+0E0E dochadathai -!AF U+0E0F topatakthai -!B0 U+0E10 thothanthai -!B1 U+0E11 thonangmonthothai -!B2 U+0E12 thophuthaothai -!B3 U+0E13 nonenthai -!B4 U+0E14 dodekthai -!B5 U+0E15 totaothai -!B6 U+0E16 thothungthai -!B7 U+0E17 thothahanthai -!B8 U+0E18 thothongthai -!B9 U+0E19 nonuthai -!BA U+0E1A bobaimaithai -!BB U+0E1B poplathai -!BC U+0E1C phophungthai -!BD U+0E1D fofathai -!BE U+0E1E phophanthai -!BF U+0E1F fofanthai -!C0 U+0E20 phosamphaothai -!C1 U+0E21 momathai -!C2 U+0E22 yoyakthai -!C3 U+0E23 roruathai -!C4 U+0E24 ruthai -!C5 U+0E25 lolingthai -!C6 U+0E26 luthai -!C7 U+0E27 wowaenthai -!C8 U+0E28 sosalathai -!C9 U+0E29 sorusithai -!CA U+0E2A sosuathai -!CB U+0E2B hohipthai -!CC U+0E2C lochulathai -!CD U+0E2D oangthai -!CE U+0E2E honokhukthai -!CF U+0E2F paiyannoithai -!D0 U+0E30 saraathai -!D1 U+0E31 maihanakatthai -!D2 U+0E32 saraaathai -!D3 U+0E33 saraamthai -!D4 U+0E34 saraithai -!D5 U+0E35 saraiithai -!D6 U+0E36 sarauethai -!D7 U+0E37 saraueethai -!D8 U+0E38 sarauthai -!D9 U+0E39 sarauuthai -!DA U+0E3A phinthuthai -!DF U+0E3F bahtthai -!E0 U+0E40 saraethai -!E1 U+0E41 saraaethai -!E2 U+0E42 saraothai -!E3 U+0E43 saraaimaimuanthai -!E4 U+0E44 saraaimaimalaithai -!E5 U+0E45 lakkhangyaothai -!E6 U+0E46 maiyamokthai -!E7 U+0E47 maitaikhuthai -!E8 U+0E48 maiekthai -!E9 U+0E49 maithothai -!EA U+0E4A maitrithai -!EB U+0E4B maichattawathai -!EC U+0E4C thanthakhatthai -!ED U+0E4D nikhahitthai -!EE U+0E4E yamakkanthai -!EF U+0E4F fongmanthai -!F0 U+0E50 zerothai -!F1 U+0E51 onethai -!F2 U+0E52 twothai -!F3 U+0E53 threethai -!F4 U+0E54 fourthai -!F5 U+0E55 fivethai -!F6 U+0E56 sixthai -!F7 U+0E57 seventhai -!F8 U+0E58 eightthai -!F9 U+0E59 ninethai -!FA U+0E5A angkhankhuthai -!FB U+0E5B khomutthai diff --git a/mods/pdf_converter/font/makefont/iso-8859-15.map b/mods/pdf_converter/font/makefont/iso-8859-15.map deleted file mode 100644 index 6c2b57127..000000000 --- a/mods/pdf_converter/font/makefont/iso-8859-15.map +++ /dev/null @@ -1,256 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+0080 .notdef -!81 U+0081 .notdef -!82 U+0082 .notdef -!83 U+0083 .notdef -!84 U+0084 .notdef -!85 U+0085 .notdef -!86 U+0086 .notdef -!87 U+0087 .notdef -!88 U+0088 .notdef -!89 U+0089 .notdef -!8A U+008A .notdef -!8B U+008B .notdef -!8C U+008C .notdef -!8D U+008D .notdef -!8E U+008E .notdef -!8F U+008F .notdef -!90 U+0090 .notdef -!91 U+0091 .notdef -!92 U+0092 .notdef -!93 U+0093 .notdef -!94 U+0094 .notdef -!95 U+0095 .notdef -!96 U+0096 .notdef -!97 U+0097 .notdef -!98 U+0098 .notdef -!99 U+0099 .notdef -!9A U+009A .notdef -!9B U+009B .notdef -!9C U+009C .notdef -!9D U+009D .notdef -!9E U+009E .notdef -!9F U+009F .notdef -!A0 U+00A0 space -!A1 U+00A1 exclamdown -!A2 U+00A2 cent -!A3 U+00A3 sterling -!A4 U+20AC Euro -!A5 U+00A5 yen -!A6 U+0160 Scaron -!A7 U+00A7 section -!A8 U+0161 scaron -!A9 U+00A9 copyright -!AA U+00AA ordfeminine -!AB U+00AB guillemotleft -!AC U+00AC logicalnot -!AD U+00AD hyphen -!AE U+00AE registered -!AF U+00AF macron -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+00B2 twosuperior -!B3 U+00B3 threesuperior -!B4 U+017D Zcaron -!B5 U+00B5 mu -!B6 U+00B6 paragraph -!B7 U+00B7 periodcentered -!B8 U+017E zcaron -!B9 U+00B9 onesuperior -!BA U+00BA ordmasculine -!BB U+00BB guillemotright -!BC U+0152 OE -!BD U+0153 oe -!BE U+0178 Ydieresis -!BF U+00BF questiondown -!C0 U+00C0 Agrave -!C1 U+00C1 Aacute -!C2 U+00C2 Acircumflex -!C3 U+00C3 Atilde -!C4 U+00C4 Adieresis -!C5 U+00C5 Aring -!C6 U+00C6 AE -!C7 U+00C7 Ccedilla -!C8 U+00C8 Egrave -!C9 U+00C9 Eacute -!CA U+00CA Ecircumflex -!CB U+00CB Edieresis -!CC U+00CC Igrave -!CD U+00CD Iacute -!CE U+00CE Icircumflex -!CF U+00CF Idieresis -!D0 U+00D0 Eth -!D1 U+00D1 Ntilde -!D2 U+00D2 Ograve -!D3 U+00D3 Oacute -!D4 U+00D4 Ocircumflex -!D5 U+00D5 Otilde -!D6 U+00D6 Odieresis -!D7 U+00D7 multiply -!D8 U+00D8 Oslash -!D9 U+00D9 Ugrave -!DA U+00DA Uacute -!DB U+00DB Ucircumflex -!DC U+00DC Udieresis -!DD U+00DD Yacute -!DE U+00DE Thorn -!DF U+00DF germandbls -!E0 U+00E0 agrave -!E1 U+00E1 aacute -!E2 U+00E2 acircumflex -!E3 U+00E3 atilde -!E4 U+00E4 adieresis -!E5 U+00E5 aring -!E6 U+00E6 ae -!E7 U+00E7 ccedilla -!E8 U+00E8 egrave -!E9 U+00E9 eacute -!EA U+00EA ecircumflex -!EB U+00EB edieresis -!EC U+00EC igrave -!ED U+00ED iacute -!EE U+00EE icircumflex -!EF U+00EF idieresis -!F0 U+00F0 eth -!F1 U+00F1 ntilde -!F2 U+00F2 ograve -!F3 U+00F3 oacute -!F4 U+00F4 ocircumflex -!F5 U+00F5 otilde -!F6 U+00F6 odieresis -!F7 U+00F7 divide -!F8 U+00F8 oslash -!F9 U+00F9 ugrave -!FA U+00FA uacute -!FB U+00FB ucircumflex -!FC U+00FC udieresis -!FD U+00FD yacute -!FE U+00FE thorn -!FF U+00FF ydieresis diff --git a/mods/pdf_converter/font/makefont/iso-8859-16.map b/mods/pdf_converter/font/makefont/iso-8859-16.map deleted file mode 100644 index 202c8fe59..000000000 --- a/mods/pdf_converter/font/makefont/iso-8859-16.map +++ /dev/null @@ -1,256 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+0080 .notdef -!81 U+0081 .notdef -!82 U+0082 .notdef -!83 U+0083 .notdef -!84 U+0084 .notdef -!85 U+0085 .notdef -!86 U+0086 .notdef -!87 U+0087 .notdef -!88 U+0088 .notdef -!89 U+0089 .notdef -!8A U+008A .notdef -!8B U+008B .notdef -!8C U+008C .notdef -!8D U+008D .notdef -!8E U+008E .notdef -!8F U+008F .notdef -!90 U+0090 .notdef -!91 U+0091 .notdef -!92 U+0092 .notdef -!93 U+0093 .notdef -!94 U+0094 .notdef -!95 U+0095 .notdef -!96 U+0096 .notdef -!97 U+0097 .notdef -!98 U+0098 .notdef -!99 U+0099 .notdef -!9A U+009A .notdef -!9B U+009B .notdef -!9C U+009C .notdef -!9D U+009D .notdef -!9E U+009E .notdef -!9F U+009F .notdef -!A0 U+00A0 space -!A1 U+0104 Aogonek -!A2 U+0105 aogonek -!A3 U+0141 Lslash -!A4 U+20AC Euro -!A5 U+201E quotedblbase -!A6 U+0160 Scaron -!A7 U+00A7 section -!A8 U+0161 scaron -!A9 U+00A9 copyright -!AA U+0218 Scommaaccent -!AB U+00AB guillemotleft -!AC U+0179 Zacute -!AD U+00AD hyphen -!AE U+017A zacute -!AF U+017B Zdotaccent -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+010C Ccaron -!B3 U+0142 lslash -!B4 U+017D Zcaron -!B5 U+201D quotedblright -!B6 U+00B6 paragraph -!B7 U+00B7 periodcentered -!B8 U+017E zcaron -!B9 U+010D ccaron -!BA U+0219 scommaaccent -!BB U+00BB guillemotright -!BC U+0152 OE -!BD U+0153 oe -!BE U+0178 Ydieresis -!BF U+017C zdotaccent -!C0 U+00C0 Agrave -!C1 U+00C1 Aacute -!C2 U+00C2 Acircumflex -!C3 U+0102 Abreve -!C4 U+00C4 Adieresis -!C5 U+0106 Cacute -!C6 U+00C6 AE -!C7 U+00C7 Ccedilla -!C8 U+00C8 Egrave -!C9 U+00C9 Eacute -!CA U+00CA Ecircumflex -!CB U+00CB Edieresis -!CC U+00CC Igrave -!CD U+00CD Iacute -!CE U+00CE Icircumflex -!CF U+00CF Idieresis -!D0 U+0110 Dcroat -!D1 U+0143 Nacute -!D2 U+00D2 Ograve -!D3 U+00D3 Oacute -!D4 U+00D4 Ocircumflex -!D5 U+0150 Ohungarumlaut -!D6 U+00D6 Odieresis -!D7 U+015A Sacute -!D8 U+0170 Uhungarumlaut -!D9 U+00D9 Ugrave -!DA U+00DA Uacute -!DB U+00DB Ucircumflex -!DC U+00DC Udieresis -!DD U+0118 Eogonek -!DE U+021A Tcommaaccent -!DF U+00DF germandbls -!E0 U+00E0 agrave -!E1 U+00E1 aacute -!E2 U+00E2 acircumflex -!E3 U+0103 abreve -!E4 U+00E4 adieresis -!E5 U+0107 cacute -!E6 U+00E6 ae -!E7 U+00E7 ccedilla -!E8 U+00E8 egrave -!E9 U+00E9 eacute -!EA U+00EA ecircumflex -!EB U+00EB edieresis -!EC U+00EC igrave -!ED U+00ED iacute -!EE U+00EE icircumflex -!EF U+00EF idieresis -!F0 U+0111 dcroat -!F1 U+0144 nacute -!F2 U+00F2 ograve -!F3 U+00F3 oacute -!F4 U+00F4 ocircumflex -!F5 U+0151 ohungarumlaut -!F6 U+00F6 odieresis -!F7 U+015B sacute -!F8 U+0171 uhungarumlaut -!F9 U+00F9 ugrave -!FA U+00FA uacute -!FB U+00FB ucircumflex -!FC U+00FC udieresis -!FD U+0119 eogonek -!FE U+021B tcommaaccent -!FF U+00FF ydieresis diff --git a/mods/pdf_converter/font/makefont/iso-8859-2.map b/mods/pdf_converter/font/makefont/iso-8859-2.map deleted file mode 100644 index 65ae09f95..000000000 --- a/mods/pdf_converter/font/makefont/iso-8859-2.map +++ /dev/null @@ -1,256 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+0080 .notdef -!81 U+0081 .notdef -!82 U+0082 .notdef -!83 U+0083 .notdef -!84 U+0084 .notdef -!85 U+0085 .notdef -!86 U+0086 .notdef -!87 U+0087 .notdef -!88 U+0088 .notdef -!89 U+0089 .notdef -!8A U+008A .notdef -!8B U+008B .notdef -!8C U+008C .notdef -!8D U+008D .notdef -!8E U+008E .notdef -!8F U+008F .notdef -!90 U+0090 .notdef -!91 U+0091 .notdef -!92 U+0092 .notdef -!93 U+0093 .notdef -!94 U+0094 .notdef -!95 U+0095 .notdef -!96 U+0096 .notdef -!97 U+0097 .notdef -!98 U+0098 .notdef -!99 U+0099 .notdef -!9A U+009A .notdef -!9B U+009B .notdef -!9C U+009C .notdef -!9D U+009D .notdef -!9E U+009E .notdef -!9F U+009F .notdef -!A0 U+00A0 space -!A1 U+0104 Aogonek -!A2 U+02D8 breve -!A3 U+0141 Lslash -!A4 U+00A4 currency -!A5 U+013D Lcaron -!A6 U+015A Sacute -!A7 U+00A7 section -!A8 U+00A8 dieresis -!A9 U+0160 Scaron -!AA U+015E Scedilla -!AB U+0164 Tcaron -!AC U+0179 Zacute -!AD U+00AD hyphen -!AE U+017D Zcaron -!AF U+017B Zdotaccent -!B0 U+00B0 degree -!B1 U+0105 aogonek -!B2 U+02DB ogonek -!B3 U+0142 lslash -!B4 U+00B4 acute -!B5 U+013E lcaron -!B6 U+015B sacute -!B7 U+02C7 caron -!B8 U+00B8 cedilla -!B9 U+0161 scaron -!BA U+015F scedilla -!BB U+0165 tcaron -!BC U+017A zacute -!BD U+02DD hungarumlaut -!BE U+017E zcaron -!BF U+017C zdotaccent -!C0 U+0154 Racute -!C1 U+00C1 Aacute -!C2 U+00C2 Acircumflex -!C3 U+0102 Abreve -!C4 U+00C4 Adieresis -!C5 U+0139 Lacute -!C6 U+0106 Cacute -!C7 U+00C7 Ccedilla -!C8 U+010C Ccaron -!C9 U+00C9 Eacute -!CA U+0118 Eogonek -!CB U+00CB Edieresis -!CC U+011A Ecaron -!CD U+00CD Iacute -!CE U+00CE Icircumflex -!CF U+010E Dcaron -!D0 U+0110 Dcroat -!D1 U+0143 Nacute -!D2 U+0147 Ncaron -!D3 U+00D3 Oacute -!D4 U+00D4 Ocircumflex -!D5 U+0150 Ohungarumlaut -!D6 U+00D6 Odieresis -!D7 U+00D7 multiply -!D8 U+0158 Rcaron -!D9 U+016E Uring -!DA U+00DA Uacute -!DB U+0170 Uhungarumlaut -!DC U+00DC Udieresis -!DD U+00DD Yacute -!DE U+0162 Tcommaaccent -!DF U+00DF germandbls -!E0 U+0155 racute -!E1 U+00E1 aacute -!E2 U+00E2 acircumflex -!E3 U+0103 abreve -!E4 U+00E4 adieresis -!E5 U+013A lacute -!E6 U+0107 cacute -!E7 U+00E7 ccedilla -!E8 U+010D ccaron -!E9 U+00E9 eacute -!EA U+0119 eogonek -!EB U+00EB edieresis -!EC U+011B ecaron -!ED U+00ED iacute -!EE U+00EE icircumflex -!EF U+010F dcaron -!F0 U+0111 dcroat -!F1 U+0144 nacute -!F2 U+0148 ncaron -!F3 U+00F3 oacute -!F4 U+00F4 ocircumflex -!F5 U+0151 ohungarumlaut -!F6 U+00F6 odieresis -!F7 U+00F7 divide -!F8 U+0159 rcaron -!F9 U+016F uring -!FA U+00FA uacute -!FB U+0171 uhungarumlaut -!FC U+00FC udieresis -!FD U+00FD yacute -!FE U+0163 tcommaaccent -!FF U+02D9 dotaccent diff --git a/mods/pdf_converter/font/makefont/iso-8859-4.map b/mods/pdf_converter/font/makefont/iso-8859-4.map deleted file mode 100644 index a7d87bf3e..000000000 --- a/mods/pdf_converter/font/makefont/iso-8859-4.map +++ /dev/null @@ -1,256 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+0080 .notdef -!81 U+0081 .notdef -!82 U+0082 .notdef -!83 U+0083 .notdef -!84 U+0084 .notdef -!85 U+0085 .notdef -!86 U+0086 .notdef -!87 U+0087 .notdef -!88 U+0088 .notdef -!89 U+0089 .notdef -!8A U+008A .notdef -!8B U+008B .notdef -!8C U+008C .notdef -!8D U+008D .notdef -!8E U+008E .notdef -!8F U+008F .notdef -!90 U+0090 .notdef -!91 U+0091 .notdef -!92 U+0092 .notdef -!93 U+0093 .notdef -!94 U+0094 .notdef -!95 U+0095 .notdef -!96 U+0096 .notdef -!97 U+0097 .notdef -!98 U+0098 .notdef -!99 U+0099 .notdef -!9A U+009A .notdef -!9B U+009B .notdef -!9C U+009C .notdef -!9D U+009D .notdef -!9E U+009E .notdef -!9F U+009F .notdef -!A0 U+00A0 space -!A1 U+0104 Aogonek -!A2 U+0138 kgreenlandic -!A3 U+0156 Rcommaaccent -!A4 U+00A4 currency -!A5 U+0128 Itilde -!A6 U+013B Lcommaaccent -!A7 U+00A7 section -!A8 U+00A8 dieresis -!A9 U+0160 Scaron -!AA U+0112 Emacron -!AB U+0122 Gcommaaccent -!AC U+0166 Tbar -!AD U+00AD hyphen -!AE U+017D Zcaron -!AF U+00AF macron -!B0 U+00B0 degree -!B1 U+0105 aogonek -!B2 U+02DB ogonek -!B3 U+0157 rcommaaccent -!B4 U+00B4 acute -!B5 U+0129 itilde -!B6 U+013C lcommaaccent -!B7 U+02C7 caron -!B8 U+00B8 cedilla -!B9 U+0161 scaron -!BA U+0113 emacron -!BB U+0123 gcommaaccent -!BC U+0167 tbar -!BD U+014A Eng -!BE U+017E zcaron -!BF U+014B eng -!C0 U+0100 Amacron -!C1 U+00C1 Aacute -!C2 U+00C2 Acircumflex -!C3 U+00C3 Atilde -!C4 U+00C4 Adieresis -!C5 U+00C5 Aring -!C6 U+00C6 AE -!C7 U+012E Iogonek -!C8 U+010C Ccaron -!C9 U+00C9 Eacute -!CA U+0118 Eogonek -!CB U+00CB Edieresis -!CC U+0116 Edotaccent -!CD U+00CD Iacute -!CE U+00CE Icircumflex -!CF U+012A Imacron -!D0 U+0110 Dcroat -!D1 U+0145 Ncommaaccent -!D2 U+014C Omacron -!D3 U+0136 Kcommaaccent -!D4 U+00D4 Ocircumflex -!D5 U+00D5 Otilde -!D6 U+00D6 Odieresis -!D7 U+00D7 multiply -!D8 U+00D8 Oslash -!D9 U+0172 Uogonek -!DA U+00DA Uacute -!DB U+00DB Ucircumflex -!DC U+00DC Udieresis -!DD U+0168 Utilde -!DE U+016A Umacron -!DF U+00DF germandbls -!E0 U+0101 amacron -!E1 U+00E1 aacute -!E2 U+00E2 acircumflex -!E3 U+00E3 atilde -!E4 U+00E4 adieresis -!E5 U+00E5 aring -!E6 U+00E6 ae -!E7 U+012F iogonek -!E8 U+010D ccaron -!E9 U+00E9 eacute -!EA U+0119 eogonek -!EB U+00EB edieresis -!EC U+0117 edotaccent -!ED U+00ED iacute -!EE U+00EE icircumflex -!EF U+012B imacron -!F0 U+0111 dcroat -!F1 U+0146 ncommaaccent -!F2 U+014D omacron -!F3 U+0137 kcommaaccent -!F4 U+00F4 ocircumflex -!F5 U+00F5 otilde -!F6 U+00F6 odieresis -!F7 U+00F7 divide -!F8 U+00F8 oslash -!F9 U+0173 uogonek -!FA U+00FA uacute -!FB U+00FB ucircumflex -!FC U+00FC udieresis -!FD U+0169 utilde -!FE U+016B umacron -!FF U+02D9 dotaccent diff --git a/mods/pdf_converter/font/makefont/iso-8859-5.map b/mods/pdf_converter/font/makefont/iso-8859-5.map deleted file mode 100644 index f9cd4edcf..000000000 --- a/mods/pdf_converter/font/makefont/iso-8859-5.map +++ /dev/null @@ -1,256 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+0080 .notdef -!81 U+0081 .notdef -!82 U+0082 .notdef -!83 U+0083 .notdef -!84 U+0084 .notdef -!85 U+0085 .notdef -!86 U+0086 .notdef -!87 U+0087 .notdef -!88 U+0088 .notdef -!89 U+0089 .notdef -!8A U+008A .notdef -!8B U+008B .notdef -!8C U+008C .notdef -!8D U+008D .notdef -!8E U+008E .notdef -!8F U+008F .notdef -!90 U+0090 .notdef -!91 U+0091 .notdef -!92 U+0092 .notdef -!93 U+0093 .notdef -!94 U+0094 .notdef -!95 U+0095 .notdef -!96 U+0096 .notdef -!97 U+0097 .notdef -!98 U+0098 .notdef -!99 U+0099 .notdef -!9A U+009A .notdef -!9B U+009B .notdef -!9C U+009C .notdef -!9D U+009D .notdef -!9E U+009E .notdef -!9F U+009F .notdef -!A0 U+00A0 space -!A1 U+0401 afii10023 -!A2 U+0402 afii10051 -!A3 U+0403 afii10052 -!A4 U+0404 afii10053 -!A5 U+0405 afii10054 -!A6 U+0406 afii10055 -!A7 U+0407 afii10056 -!A8 U+0408 afii10057 -!A9 U+0409 afii10058 -!AA U+040A afii10059 -!AB U+040B afii10060 -!AC U+040C afii10061 -!AD U+00AD hyphen -!AE U+040E afii10062 -!AF U+040F afii10145 -!B0 U+0410 afii10017 -!B1 U+0411 afii10018 -!B2 U+0412 afii10019 -!B3 U+0413 afii10020 -!B4 U+0414 afii10021 -!B5 U+0415 afii10022 -!B6 U+0416 afii10024 -!B7 U+0417 afii10025 -!B8 U+0418 afii10026 -!B9 U+0419 afii10027 -!BA U+041A afii10028 -!BB U+041B afii10029 -!BC U+041C afii10030 -!BD U+041D afii10031 -!BE U+041E afii10032 -!BF U+041F afii10033 -!C0 U+0420 afii10034 -!C1 U+0421 afii10035 -!C2 U+0422 afii10036 -!C3 U+0423 afii10037 -!C4 U+0424 afii10038 -!C5 U+0425 afii10039 -!C6 U+0426 afii10040 -!C7 U+0427 afii10041 -!C8 U+0428 afii10042 -!C9 U+0429 afii10043 -!CA U+042A afii10044 -!CB U+042B afii10045 -!CC U+042C afii10046 -!CD U+042D afii10047 -!CE U+042E afii10048 -!CF U+042F afii10049 -!D0 U+0430 afii10065 -!D1 U+0431 afii10066 -!D2 U+0432 afii10067 -!D3 U+0433 afii10068 -!D4 U+0434 afii10069 -!D5 U+0435 afii10070 -!D6 U+0436 afii10072 -!D7 U+0437 afii10073 -!D8 U+0438 afii10074 -!D9 U+0439 afii10075 -!DA U+043A afii10076 -!DB U+043B afii10077 -!DC U+043C afii10078 -!DD U+043D afii10079 -!DE U+043E afii10080 -!DF U+043F afii10081 -!E0 U+0440 afii10082 -!E1 U+0441 afii10083 -!E2 U+0442 afii10084 -!E3 U+0443 afii10085 -!E4 U+0444 afii10086 -!E5 U+0445 afii10087 -!E6 U+0446 afii10088 -!E7 U+0447 afii10089 -!E8 U+0448 afii10090 -!E9 U+0449 afii10091 -!EA U+044A afii10092 -!EB U+044B afii10093 -!EC U+044C afii10094 -!ED U+044D afii10095 -!EE U+044E afii10096 -!EF U+044F afii10097 -!F0 U+2116 afii61352 -!F1 U+0451 afii10071 -!F2 U+0452 afii10099 -!F3 U+0453 afii10100 -!F4 U+0454 afii10101 -!F5 U+0455 afii10102 -!F6 U+0456 afii10103 -!F7 U+0457 afii10104 -!F8 U+0458 afii10105 -!F9 U+0459 afii10106 -!FA U+045A afii10107 -!FB U+045B afii10108 -!FC U+045C afii10109 -!FD U+00A7 section -!FE U+045E afii10110 -!FF U+045F afii10193 diff --git a/mods/pdf_converter/font/makefont/iso-8859-7.map b/mods/pdf_converter/font/makefont/iso-8859-7.map deleted file mode 100644 index e163796b1..000000000 --- a/mods/pdf_converter/font/makefont/iso-8859-7.map +++ /dev/null @@ -1,250 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+0080 .notdef -!81 U+0081 .notdef -!82 U+0082 .notdef -!83 U+0083 .notdef -!84 U+0084 .notdef -!85 U+0085 .notdef -!86 U+0086 .notdef -!87 U+0087 .notdef -!88 U+0088 .notdef -!89 U+0089 .notdef -!8A U+008A .notdef -!8B U+008B .notdef -!8C U+008C .notdef -!8D U+008D .notdef -!8E U+008E .notdef -!8F U+008F .notdef -!90 U+0090 .notdef -!91 U+0091 .notdef -!92 U+0092 .notdef -!93 U+0093 .notdef -!94 U+0094 .notdef -!95 U+0095 .notdef -!96 U+0096 .notdef -!97 U+0097 .notdef -!98 U+0098 .notdef -!99 U+0099 .notdef -!9A U+009A .notdef -!9B U+009B .notdef -!9C U+009C .notdef -!9D U+009D .notdef -!9E U+009E .notdef -!9F U+009F .notdef -!A0 U+00A0 space -!A1 U+2018 quoteleft -!A2 U+2019 quoteright -!A3 U+00A3 sterling -!A6 U+00A6 brokenbar -!A7 U+00A7 section -!A8 U+00A8 dieresis -!A9 U+00A9 copyright -!AB U+00AB guillemotleft -!AC U+00AC logicalnot -!AD U+00AD hyphen -!AF U+2015 afii00208 -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+00B2 twosuperior -!B3 U+00B3 threesuperior -!B4 U+0384 tonos -!B5 U+0385 dieresistonos -!B6 U+0386 Alphatonos -!B7 U+00B7 periodcentered -!B8 U+0388 Epsilontonos -!B9 U+0389 Etatonos -!BA U+038A Iotatonos -!BB U+00BB guillemotright -!BC U+038C Omicrontonos -!BD U+00BD onehalf -!BE U+038E Upsilontonos -!BF U+038F Omegatonos -!C0 U+0390 iotadieresistonos -!C1 U+0391 Alpha -!C2 U+0392 Beta -!C3 U+0393 Gamma -!C4 U+0394 Delta -!C5 U+0395 Epsilon -!C6 U+0396 Zeta -!C7 U+0397 Eta -!C8 U+0398 Theta -!C9 U+0399 Iota -!CA U+039A Kappa -!CB U+039B Lambda -!CC U+039C Mu -!CD U+039D Nu -!CE U+039E Xi -!CF U+039F Omicron -!D0 U+03A0 Pi -!D1 U+03A1 Rho -!D3 U+03A3 Sigma -!D4 U+03A4 Tau -!D5 U+03A5 Upsilon -!D6 U+03A6 Phi -!D7 U+03A7 Chi -!D8 U+03A8 Psi -!D9 U+03A9 Omega -!DA U+03AA Iotadieresis -!DB U+03AB Upsilondieresis -!DC U+03AC alphatonos -!DD U+03AD epsilontonos -!DE U+03AE etatonos -!DF U+03AF iotatonos -!E0 U+03B0 upsilondieresistonos -!E1 U+03B1 alpha -!E2 U+03B2 beta -!E3 U+03B3 gamma -!E4 U+03B4 delta -!E5 U+03B5 epsilon -!E6 U+03B6 zeta -!E7 U+03B7 eta -!E8 U+03B8 theta -!E9 U+03B9 iota -!EA U+03BA kappa -!EB U+03BB lambda -!EC U+03BC mu -!ED U+03BD nu -!EE U+03BE xi -!EF U+03BF omicron -!F0 U+03C0 pi -!F1 U+03C1 rho -!F2 U+03C2 sigma1 -!F3 U+03C3 sigma -!F4 U+03C4 tau -!F5 U+03C5 upsilon -!F6 U+03C6 phi -!F7 U+03C7 chi -!F8 U+03C8 psi -!F9 U+03C9 omega -!FA U+03CA iotadieresis -!FB U+03CB upsilondieresis -!FC U+03CC omicrontonos -!FD U+03CD upsilontonos -!FE U+03CE omegatonos diff --git a/mods/pdf_converter/font/makefont/iso-8859-9.map b/mods/pdf_converter/font/makefont/iso-8859-9.map deleted file mode 100644 index 48c123ae6..000000000 --- a/mods/pdf_converter/font/makefont/iso-8859-9.map +++ /dev/null @@ -1,256 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+0080 .notdef -!81 U+0081 .notdef -!82 U+0082 .notdef -!83 U+0083 .notdef -!84 U+0084 .notdef -!85 U+0085 .notdef -!86 U+0086 .notdef -!87 U+0087 .notdef -!88 U+0088 .notdef -!89 U+0089 .notdef -!8A U+008A .notdef -!8B U+008B .notdef -!8C U+008C .notdef -!8D U+008D .notdef -!8E U+008E .notdef -!8F U+008F .notdef -!90 U+0090 .notdef -!91 U+0091 .notdef -!92 U+0092 .notdef -!93 U+0093 .notdef -!94 U+0094 .notdef -!95 U+0095 .notdef -!96 U+0096 .notdef -!97 U+0097 .notdef -!98 U+0098 .notdef -!99 U+0099 .notdef -!9A U+009A .notdef -!9B U+009B .notdef -!9C U+009C .notdef -!9D U+009D .notdef -!9E U+009E .notdef -!9F U+009F .notdef -!A0 U+00A0 space -!A1 U+00A1 exclamdown -!A2 U+00A2 cent -!A3 U+00A3 sterling -!A4 U+00A4 currency -!A5 U+00A5 yen -!A6 U+00A6 brokenbar -!A7 U+00A7 section -!A8 U+00A8 dieresis -!A9 U+00A9 copyright -!AA U+00AA ordfeminine -!AB U+00AB guillemotleft -!AC U+00AC logicalnot -!AD U+00AD hyphen -!AE U+00AE registered -!AF U+00AF macron -!B0 U+00B0 degree -!B1 U+00B1 plusminus -!B2 U+00B2 twosuperior -!B3 U+00B3 threesuperior -!B4 U+00B4 acute -!B5 U+00B5 mu -!B6 U+00B6 paragraph -!B7 U+00B7 periodcentered -!B8 U+00B8 cedilla -!B9 U+00B9 onesuperior -!BA U+00BA ordmasculine -!BB U+00BB guillemotright -!BC U+00BC onequarter -!BD U+00BD onehalf -!BE U+00BE threequarters -!BF U+00BF questiondown -!C0 U+00C0 Agrave -!C1 U+00C1 Aacute -!C2 U+00C2 Acircumflex -!C3 U+00C3 Atilde -!C4 U+00C4 Adieresis -!C5 U+00C5 Aring -!C6 U+00C6 AE -!C7 U+00C7 Ccedilla -!C8 U+00C8 Egrave -!C9 U+00C9 Eacute -!CA U+00CA Ecircumflex -!CB U+00CB Edieresis -!CC U+00CC Igrave -!CD U+00CD Iacute -!CE U+00CE Icircumflex -!CF U+00CF Idieresis -!D0 U+011E Gbreve -!D1 U+00D1 Ntilde -!D2 U+00D2 Ograve -!D3 U+00D3 Oacute -!D4 U+00D4 Ocircumflex -!D5 U+00D5 Otilde -!D6 U+00D6 Odieresis -!D7 U+00D7 multiply -!D8 U+00D8 Oslash -!D9 U+00D9 Ugrave -!DA U+00DA Uacute -!DB U+00DB Ucircumflex -!DC U+00DC Udieresis -!DD U+0130 Idotaccent -!DE U+015E Scedilla -!DF U+00DF germandbls -!E0 U+00E0 agrave -!E1 U+00E1 aacute -!E2 U+00E2 acircumflex -!E3 U+00E3 atilde -!E4 U+00E4 adieresis -!E5 U+00E5 aring -!E6 U+00E6 ae -!E7 U+00E7 ccedilla -!E8 U+00E8 egrave -!E9 U+00E9 eacute -!EA U+00EA ecircumflex -!EB U+00EB edieresis -!EC U+00EC igrave -!ED U+00ED iacute -!EE U+00EE icircumflex -!EF U+00EF idieresis -!F0 U+011F gbreve -!F1 U+00F1 ntilde -!F2 U+00F2 ograve -!F3 U+00F3 oacute -!F4 U+00F4 ocircumflex -!F5 U+00F5 otilde -!F6 U+00F6 odieresis -!F7 U+00F7 divide -!F8 U+00F8 oslash -!F9 U+00F9 ugrave -!FA U+00FA uacute -!FB U+00FB ucircumflex -!FC U+00FC udieresis -!FD U+0131 dotlessi -!FE U+015F scedilla -!FF U+00FF ydieresis diff --git a/mods/pdf_converter/font/makefont/koi8-r.map b/mods/pdf_converter/font/makefont/koi8-r.map deleted file mode 100644 index 6ad5d05d0..000000000 --- a/mods/pdf_converter/font/makefont/koi8-r.map +++ /dev/null @@ -1,256 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+2500 SF100000 -!81 U+2502 SF110000 -!82 U+250C SF010000 -!83 U+2510 SF030000 -!84 U+2514 SF020000 -!85 U+2518 SF040000 -!86 U+251C SF080000 -!87 U+2524 SF090000 -!88 U+252C SF060000 -!89 U+2534 SF070000 -!8A U+253C SF050000 -!8B U+2580 upblock -!8C U+2584 dnblock -!8D U+2588 block -!8E U+258C lfblock -!8F U+2590 rtblock -!90 U+2591 ltshade -!91 U+2592 shade -!92 U+2593 dkshade -!93 U+2320 integraltp -!94 U+25A0 filledbox -!95 U+2219 periodcentered -!96 U+221A radical -!97 U+2248 approxequal -!98 U+2264 lessequal -!99 U+2265 greaterequal -!9A U+00A0 space -!9B U+2321 integralbt -!9C U+00B0 degree -!9D U+00B2 twosuperior -!9E U+00B7 periodcentered -!9F U+00F7 divide -!A0 U+2550 SF430000 -!A1 U+2551 SF240000 -!A2 U+2552 SF510000 -!A3 U+0451 afii10071 -!A4 U+2553 SF520000 -!A5 U+2554 SF390000 -!A6 U+2555 SF220000 -!A7 U+2556 SF210000 -!A8 U+2557 SF250000 -!A9 U+2558 SF500000 -!AA U+2559 SF490000 -!AB U+255A SF380000 -!AC U+255B SF280000 -!AD U+255C SF270000 -!AE U+255D SF260000 -!AF U+255E SF360000 -!B0 U+255F SF370000 -!B1 U+2560 SF420000 -!B2 U+2561 SF190000 -!B3 U+0401 afii10023 -!B4 U+2562 SF200000 -!B5 U+2563 SF230000 -!B6 U+2564 SF470000 -!B7 U+2565 SF480000 -!B8 U+2566 SF410000 -!B9 U+2567 SF450000 -!BA U+2568 SF460000 -!BB U+2569 SF400000 -!BC U+256A SF540000 -!BD U+256B SF530000 -!BE U+256C SF440000 -!BF U+00A9 copyright -!C0 U+044E afii10096 -!C1 U+0430 afii10065 -!C2 U+0431 afii10066 -!C3 U+0446 afii10088 -!C4 U+0434 afii10069 -!C5 U+0435 afii10070 -!C6 U+0444 afii10086 -!C7 U+0433 afii10068 -!C8 U+0445 afii10087 -!C9 U+0438 afii10074 -!CA U+0439 afii10075 -!CB U+043A afii10076 -!CC U+043B afii10077 -!CD U+043C afii10078 -!CE U+043D afii10079 -!CF U+043E afii10080 -!D0 U+043F afii10081 -!D1 U+044F afii10097 -!D2 U+0440 afii10082 -!D3 U+0441 afii10083 -!D4 U+0442 afii10084 -!D5 U+0443 afii10085 -!D6 U+0436 afii10072 -!D7 U+0432 afii10067 -!D8 U+044C afii10094 -!D9 U+044B afii10093 -!DA U+0437 afii10073 -!DB U+0448 afii10090 -!DC U+044D afii10095 -!DD U+0449 afii10091 -!DE U+0447 afii10089 -!DF U+044A afii10092 -!E0 U+042E afii10048 -!E1 U+0410 afii10017 -!E2 U+0411 afii10018 -!E3 U+0426 afii10040 -!E4 U+0414 afii10021 -!E5 U+0415 afii10022 -!E6 U+0424 afii10038 -!E7 U+0413 afii10020 -!E8 U+0425 afii10039 -!E9 U+0418 afii10026 -!EA U+0419 afii10027 -!EB U+041A afii10028 -!EC U+041B afii10029 -!ED U+041C afii10030 -!EE U+041D afii10031 -!EF U+041E afii10032 -!F0 U+041F afii10033 -!F1 U+042F afii10049 -!F2 U+0420 afii10034 -!F3 U+0421 afii10035 -!F4 U+0422 afii10036 -!F5 U+0423 afii10037 -!F6 U+0416 afii10024 -!F7 U+0412 afii10019 -!F8 U+042C afii10046 -!F9 U+042B afii10045 -!FA U+0417 afii10025 -!FB U+0428 afii10042 -!FC U+042D afii10047 -!FD U+0429 afii10043 -!FE U+0427 afii10041 -!FF U+042A afii10044 diff --git a/mods/pdf_converter/font/makefont/koi8-u.map b/mods/pdf_converter/font/makefont/koi8-u.map deleted file mode 100644 index 40a7e4fd7..000000000 --- a/mods/pdf_converter/font/makefont/koi8-u.map +++ /dev/null @@ -1,256 +0,0 @@ -!00 U+0000 .notdef -!01 U+0001 .notdef -!02 U+0002 .notdef -!03 U+0003 .notdef -!04 U+0004 .notdef -!05 U+0005 .notdef -!06 U+0006 .notdef -!07 U+0007 .notdef -!08 U+0008 .notdef -!09 U+0009 .notdef -!0A U+000A .notdef -!0B U+000B .notdef -!0C U+000C .notdef -!0D U+000D .notdef -!0E U+000E .notdef -!0F U+000F .notdef -!10 U+0010 .notdef -!11 U+0011 .notdef -!12 U+0012 .notdef -!13 U+0013 .notdef -!14 U+0014 .notdef -!15 U+0015 .notdef -!16 U+0016 .notdef -!17 U+0017 .notdef -!18 U+0018 .notdef -!19 U+0019 .notdef -!1A U+001A .notdef -!1B U+001B .notdef -!1C U+001C .notdef -!1D U+001D .notdef -!1E U+001E .notdef -!1F U+001F .notdef -!20 U+0020 space -!21 U+0021 exclam -!22 U+0022 quotedbl -!23 U+0023 numbersign -!24 U+0024 dollar -!25 U+0025 percent -!26 U+0026 ampersand -!27 U+0027 quotesingle -!28 U+0028 parenleft -!29 U+0029 parenright -!2A U+002A asterisk -!2B U+002B plus -!2C U+002C comma -!2D U+002D hyphen -!2E U+002E period -!2F U+002F slash -!30 U+0030 zero -!31 U+0031 one -!32 U+0032 two -!33 U+0033 three -!34 U+0034 four -!35 U+0035 five -!36 U+0036 six -!37 U+0037 seven -!38 U+0038 eight -!39 U+0039 nine -!3A U+003A colon -!3B U+003B semicolon -!3C U+003C less -!3D U+003D equal -!3E U+003E greater -!3F U+003F question -!40 U+0040 at -!41 U+0041 A -!42 U+0042 B -!43 U+0043 C -!44 U+0044 D -!45 U+0045 E -!46 U+0046 F -!47 U+0047 G -!48 U+0048 H -!49 U+0049 I -!4A U+004A J -!4B U+004B K -!4C U+004C L -!4D U+004D M -!4E U+004E N -!4F U+004F O -!50 U+0050 P -!51 U+0051 Q -!52 U+0052 R -!53 U+0053 S -!54 U+0054 T -!55 U+0055 U -!56 U+0056 V -!57 U+0057 W -!58 U+0058 X -!59 U+0059 Y -!5A U+005A Z -!5B U+005B bracketleft -!5C U+005C backslash -!5D U+005D bracketright -!5E U+005E asciicircum -!5F U+005F underscore -!60 U+0060 grave -!61 U+0061 a -!62 U+0062 b -!63 U+0063 c -!64 U+0064 d -!65 U+0065 e -!66 U+0066 f -!67 U+0067 g -!68 U+0068 h -!69 U+0069 i -!6A U+006A j -!6B U+006B k -!6C U+006C l -!6D U+006D m -!6E U+006E n -!6F U+006F o -!70 U+0070 p -!71 U+0071 q -!72 U+0072 r -!73 U+0073 s -!74 U+0074 t -!75 U+0075 u -!76 U+0076 v -!77 U+0077 w -!78 U+0078 x -!79 U+0079 y -!7A U+007A z -!7B U+007B braceleft -!7C U+007C bar -!7D U+007D braceright -!7E U+007E asciitilde -!7F U+007F .notdef -!80 U+2500 SF100000 -!81 U+2502 SF110000 -!82 U+250C SF010000 -!83 U+2510 SF030000 -!84 U+2514 SF020000 -!85 U+2518 SF040000 -!86 U+251C SF080000 -!87 U+2524 SF090000 -!88 U+252C SF060000 -!89 U+2534 SF070000 -!8A U+253C SF050000 -!8B U+2580 upblock -!8C U+2584 dnblock -!8D U+2588 block -!8E U+258C lfblock -!8F U+2590 rtblock -!90 U+2591 ltshade -!91 U+2592 shade -!92 U+2593 dkshade -!93 U+2320 integraltp -!94 U+25A0 filledbox -!95 U+2022 bullet -!96 U+221A radical -!97 U+2248 approxequal -!98 U+2264 lessequal -!99 U+2265 greaterequal -!9A U+00A0 space -!9B U+2321 integralbt -!9C U+00B0 degree -!9D U+00B2 twosuperior -!9E U+00B7 periodcentered -!9F U+00F7 divide -!A0 U+2550 SF430000 -!A1 U+2551 SF240000 -!A2 U+2552 SF510000 -!A3 U+0451 afii10071 -!A4 U+0454 afii10101 -!A5 U+2554 SF390000 -!A6 U+0456 afii10103 -!A7 U+0457 afii10104 -!A8 U+2557 SF250000 -!A9 U+2558 SF500000 -!AA U+2559 SF490000 -!AB U+255A SF380000 -!AC U+255B SF280000 -!AD U+0491 afii10098 -!AE U+255D SF260000 -!AF U+255E SF360000 -!B0 U+255F SF370000 -!B1 U+2560 SF420000 -!B2 U+2561 SF190000 -!B3 U+0401 afii10023 -!B4 U+0404 afii10053 -!B5 U+2563 SF230000 -!B6 U+0406 afii10055 -!B7 U+0407 afii10056 -!B8 U+2566 SF410000 -!B9 U+2567 SF450000 -!BA U+2568 SF460000 -!BB U+2569 SF400000 -!BC U+256A SF540000 -!BD U+0490 afii10050 -!BE U+256C SF440000 -!BF U+00A9 copyright -!C0 U+044E afii10096 -!C1 U+0430 afii10065 -!C2 U+0431 afii10066 -!C3 U+0446 afii10088 -!C4 U+0434 afii10069 -!C5 U+0435 afii10070 -!C6 U+0444 afii10086 -!C7 U+0433 afii10068 -!C8 U+0445 afii10087 -!C9 U+0438 afii10074 -!CA U+0439 afii10075 -!CB U+043A afii10076 -!CC U+043B afii10077 -!CD U+043C afii10078 -!CE U+043D afii10079 -!CF U+043E afii10080 -!D0 U+043F afii10081 -!D1 U+044F afii10097 -!D2 U+0440 afii10082 -!D3 U+0441 afii10083 -!D4 U+0442 afii10084 -!D5 U+0443 afii10085 -!D6 U+0436 afii10072 -!D7 U+0432 afii10067 -!D8 U+044C afii10094 -!D9 U+044B afii10093 -!DA U+0437 afii10073 -!DB U+0448 afii10090 -!DC U+044D afii10095 -!DD U+0449 afii10091 -!DE U+0447 afii10089 -!DF U+044A afii10092 -!E0 U+042E afii10048 -!E1 U+0410 afii10017 -!E2 U+0411 afii10018 -!E3 U+0426 afii10040 -!E4 U+0414 afii10021 -!E5 U+0415 afii10022 -!E6 U+0424 afii10038 -!E7 U+0413 afii10020 -!E8 U+0425 afii10039 -!E9 U+0418 afii10026 -!EA U+0419 afii10027 -!EB U+041A afii10028 -!EC U+041B afii10029 -!ED U+041C afii10030 -!EE U+041D afii10031 -!EF U+041E afii10032 -!F0 U+041F afii10033 -!F1 U+042F afii10049 -!F2 U+0420 afii10034 -!F3 U+0421 afii10035 -!F4 U+0422 afii10036 -!F5 U+0423 afii10037 -!F6 U+0416 afii10024 -!F7 U+0412 afii10019 -!F8 U+042C afii10046 -!F9 U+042B afii10045 -!FA U+0417 afii10025 -!FB U+0428 afii10042 -!FC U+042D afii10047 -!FD U+0429 afii10043 -!FE U+0427 afii10041 -!FF U+042A afii10044 diff --git a/mods/pdf_converter/font/makefont/makefont.php b/mods/pdf_converter/font/makefont/makefont.php deleted file mode 100644 index 178e9e239..000000000 --- a/mods/pdf_converter/font/makefont/makefont.php +++ /dev/null @@ -1,416 +0,0 @@ -Error:
    encoding not found: '.$enc); - $cc2gn=array(); - foreach($a as $l) - { - if($l{0}=='!') - { - $e=preg_split('/[ \\t]+/',rtrim($l)); - $cc=hexdec(substr($e[0],1)); - $gn=$e[2]; - $cc2gn[$cc]=$gn; - } - } - for($i=0;$i<=255;$i++) - { - if(!isset($cc2gn[$i])) - $cc2gn[$i]='.notdef'; - } - return $cc2gn; -} - -function ReadAFM($file,&$map) -{ - //Read a font metric file - $a=file($file); - if(empty($a)) - die('File not found'); - $widths=array(); - $fm=array(); - $fix=array('Edot'=>'Edotaccent','edot'=>'edotaccent','Idot'=>'Idotaccent','Zdot'=>'Zdotaccent','zdot'=>'zdotaccent', - 'Odblacute'=>'Ohungarumlaut','odblacute'=>'ohungarumlaut','Udblacute'=>'Uhungarumlaut','udblacute'=>'uhungarumlaut', - 'Gcedilla'=>'Gcommaaccent','gcedilla'=>'gcommaaccent','Kcedilla'=>'Kcommaaccent','kcedilla'=>'kcommaaccent', - 'Lcedilla'=>'Lcommaaccent','lcedilla'=>'lcommaaccent','Ncedilla'=>'Ncommaaccent','ncedilla'=>'ncommaaccent', - 'Rcedilla'=>'Rcommaaccent','rcedilla'=>'rcommaaccent','Scedilla'=>'Scommaaccent','scedilla'=>'scommaaccent', - 'Tcedilla'=>'Tcommaaccent','tcedilla'=>'tcommaaccent','Dslash'=>'Dcroat','dslash'=>'dcroat','Dmacron'=>'Dcroat','dmacron'=>'dcroat', - 'combininggraveaccent'=>'gravecomb','combininghookabove'=>'hookabovecomb','combiningtildeaccent'=>'tildecomb', - 'combiningacuteaccent'=>'acutecomb','combiningdotbelow'=>'dotbelowcomb','dongsign'=>'dong'); - foreach($a as $l) - { - $e=explode(' ',rtrim($l)); - if(count($e)<2) - continue; - $code=$e[0]; - $param=$e[1]; - if($code=='C') - { - //Character metrics - $cc=(int)$e[1]; - $w=$e[4]; - $gn=$e[7]; - if(substr($gn,-4)=='20AC') - $gn='Euro'; - if(isset($fix[$gn])) - { - //Fix incorrect glyph name - foreach($map as $c=>$n) - { - if($n==$fix[$gn]) - $map[$c]=$gn; - } - } - if(empty($map)) - { - //Symbolic font: use built-in encoding - $widths[$cc]=$w; - } - else - { - $widths[$gn]=$w; - if($gn=='X') - $fm['CapXHeight']=$e[13]; - } - if($gn=='.notdef') - $fm['MissingWidth']=$w; - } - elseif($code=='FontName') - $fm['FontName']=$param; - elseif($code=='Weight') - $fm['Weight']=$param; - elseif($code=='ItalicAngle') - $fm['ItalicAngle']=(double)$param; - elseif($code=='Ascender') - $fm['Ascender']=(int)$param; - elseif($code=='Descender') - $fm['Descender']=(int)$param; - elseif($code=='UnderlineThickness') - $fm['UnderlineThickness']=(int)$param; - elseif($code=='UnderlinePosition') - $fm['UnderlinePosition']=(int)$param; - elseif($code=='IsFixedPitch') - $fm['IsFixedPitch']=($param=='true'); - elseif($code=='FontBBox') - $fm['FontBBox']=array($e[1],$e[2],$e[3],$e[4]); - elseif($code=='CapHeight') - $fm['CapHeight']=(int)$param; - elseif($code=='StdVW') - $fm['StdVW']=(int)$param; - } - if(!isset($fm['FontName'])) - die('FontName not found'); - if(!empty($map)) - { - if(!isset($widths['.notdef'])) - $widths['.notdef']=600; - if(!isset($widths['Delta']) and isset($widths['increment'])) - $widths['Delta']=$widths['increment']; - //Order widths according to map - for($i=0;$i<=255;$i++) - { - if(!isset($widths[$map[$i]])) - { - echo 'Warning: character '.$map[$i].' is missing
    '; - $widths[$i]=$widths['.notdef']; - } - else - $widths[$i]=$widths[$map[$i]]; - } - } - $fm['Widths']=$widths; - return $fm; -} - -function MakeFontDescriptor($fm,$symbolic) -{ - //Ascent - $asc=(isset($fm['Ascender']) ? $fm['Ascender'] : 1000); - $fd="array('Ascent'=>".$asc; - //Descent - $desc=(isset($fm['Descender']) ? $fm['Descender'] : -200); - $fd.=",'Descent'=>".$desc; - //CapHeight - if(isset($fm['CapHeight'])) - $ch=$fm['CapHeight']; - elseif(isset($fm['CapXHeight'])) - $ch=$fm['CapXHeight']; - else - $ch=$asc; - $fd.=",'CapHeight'=>".$ch; - //Flags - $flags=0; - if(isset($fm['IsFixedPitch']) and $fm['IsFixedPitch']) - $flags+=1<<0; - if($symbolic) - $flags+=1<<2; - if(!$symbolic) - $flags+=1<<5; - if(isset($fm['ItalicAngle']) and $fm['ItalicAngle']!=0) - $flags+=1<<6; - $fd.=",'Flags'=>".$flags; - //FontBBox - if(isset($fm['FontBBox'])) - $fbb=$fm['FontBBox']; - else - $fbb=array(0,$des-100,1000,$asc+100); - $fd.=",'FontBBox'=>'[".$fbb[0].' '.$fbb[1].' '.$fbb[2].' '.$fbb[3]."]'"; - //ItalicAngle - $ia=(isset($fm['ItalicAngle']) ? $fm['ItalicAngle'] : 0); - $fd.=",'ItalicAngle'=>".$ia; - //StemV - if(isset($fm['StdVW'])) - $stemv=$fm['StdVW']; - elseif(isset($fm['Weight']) and eregi('(bold|black)',$fm['Weight'])) - $stemv=120; - else - $stemv=70; - $fd.=",'StemV'=>".$stemv; - //MissingWidth - if(isset($fm['MissingWidth'])) - $fd.=",'MissingWidth'=>".$fm['MissingWidth']; - $fd.=')'; - return $fd; -} - -function MakeWidthArray($fm) -{ - //Make character width array - $s="array(\n\t"; - $cw=$fm['Widths']; - for($i=0;$i<=255;$i++) - { - if(chr($i)=="'") - $s.="'\\''"; - elseif(chr($i)=="\\") - $s.="'\\\\'"; - elseif($i>=32 and $i<=126) - $s.="'".chr($i)."'"; - else - $s.="chr($i)"; - $s.='=>'.$fm['Widths'][$i]; - if($i<255) - $s.=','; - if(($i+1)%22==0) - $s.="\n\t"; - } - $s.=')'; - return $s; -} - -function MakeFontEncoding($map) -{ - //Build differences from reference encoding - $ref=ReadMap('cp1252'); - $s=''; - $last=0; - for($i=32;$i<=255;$i++) - { - if($map[$i]!=$ref[$i]) - { - if($i!=$last+1) - $s.=$i.' '; - $last=$i; - $s.='/'.$map[$i].' '; - } - } - return rtrim($s); -} - -function SaveToFile($file,$s,$mode='t') -{ - $f=fopen($file,'w'.$mode); - if(!$f) - die('Can\'t write to file '.$file); - fwrite($f,$s,strlen($s)); - fclose($f); -} - -function ReadShort($f) -{ - $a=unpack('n1n',fread($f,2)); - return $a['n']; -} - -function ReadLong($f) -{ - $a=unpack('N1N',fread($f,4)); - return $a['N']; -} - -function CheckTTF($file) -{ - //Check if font license allows embedding - $f=fopen($file,'rb'); - if(!$f) - die('Error: Can\'t open '.$file); - //Extract number of tables - fseek($f,4,SEEK_CUR); - $nb=ReadShort($f); - fseek($f,6,SEEK_CUR); - //Seek OS/2 table - $found=false; - for($i=0;$i<$nb;$i++) - { - if(fread($f,4)=='OS/2') - { - $found=true; - break; - } - fseek($f,12,SEEK_CUR); - } - if(!$found) - { - fclose($f); - return; - } - fseek($f,4,SEEK_CUR); - $offset=ReadLong($f); - fseek($f,$offset,SEEK_SET); - //Extract fsType flags - fseek($f,8,SEEK_CUR); - $fsType=ReadShort($f); - $rl=($fsType & 0x02)!=0; - $pp=($fsType & 0x04)!=0; - $e=($fsType & 0x08)!=0; - fclose($f); - if($rl and !$pp and !$e) - echo 'Warning: font license does not allow embedding'; -} - -/******************************************************************************* -* $fontfile : chemin du fichier TTF (ou chaîne vide si pas d'incorporation) * -* $afmfile : chemin du fichier AFM * -* $enc : encodage (ou chaîne vide si la police est symbolique) * -* $patch : patch optionnel pour l'encodage * -* $type : type de la police si $fontfile est vide * -*******************************************************************************/ -function MakeFont($fontfile,$afmfile,$enc='cp1252',$patch=array(),$type='TrueType') -{ - //Generate a font definition file - set_magic_quotes_runtime(0); - ini_set('auto_detect_line_endings','1'); - if($enc) - { - $map=ReadMap($enc); - foreach($patch as $cc=>$gn) - $map[$cc]=$gn; - } - else - $map=array(); - if(!file_exists($afmfile)) - die('Error: AFM file not found: '.$afmfile); - $fm=ReadAFM($afmfile,$map); - if($enc) - $diff=MakeFontEncoding($map); - else - $diff=''; - $fd=MakeFontDescriptor($fm,empty($map)); - //Find font type - if($fontfile) - { - $ext=strtolower(substr($fontfile,-3)); - if($ext=='ttf') - $type='TrueType'; - elseif($ext=='pfb') - $type='Type1'; - else - die('Error: unrecognized font file extension: '.$ext); - } - else - { - if($type!='TrueType' and $type!='Type1') - die('Error: incorrect font type: '.$type); - } - //Start generation - $s='Error:
    font file not found: '.$fontfile); - if($type=='TrueType') - CheckTTF($fontfile); - $f=fopen($fontfile,'rb'); - if(!$f) - die('Error: Can\'t open '.$fontfile); - $file=fread($f,filesize($fontfile)); - fclose($f); - if($type=='Type1') - { - //Find first two sections and discard third one - $header=(ord($file{0})==128); - if($header) - { - //Strip first binary header - $file=substr($file,6); - } - $pos=strpos($file,'eexec'); - if(!$pos) - die('Error: font file does not seem to be valid Type1'); - $size1=$pos+6; - if($header and ord($file{$size1})==128) - { - //Strip second binary header - $file=substr($file,0,$size1).substr($file,$size1+6); - } - $pos=strpos($file,'00000000'); - if(!$pos) - die('Error: font file does not seem to be valid Type1'); - $size2=$pos-$size1; - $file=substr($file,0,$size1+$size2); - } - if(function_exists('gzcompress')) - { - $cmp=$basename.'.z'; - SaveToFile($cmp,gzcompress($file),'b'); - $s.='$file=\''.$cmp."';\n"; - echo 'Font file compressed ('.$cmp.')
    '; - } - else - { - $s.='$file=\''.basename($fontfile)."';\n"; - echo 'Notice: font file could not be compressed (zlib extension not available)
    '; - } - if($type=='Type1') - { - $s.='$size1='.$size1.";\n"; - $s.='$size2='.$size2.";\n"; - } - else - $s.='$originalsize='.filesize($fontfile).";\n"; - } - else - { - //Not embedded font - $s.='$file='."'';\n"; - } - $s.="?>\n"; - SaveToFile($basename.'.php',$s); - echo 'Font definition file generated ('.$basename.'.php'.')
    '; -} -?> diff --git a/mods/pdf_converter/font/symbol.php b/mods/pdf_converter/font/symbol.php deleted file mode 100644 index 43b50e451..000000000 --- a/mods/pdf_converter/font/symbol.php +++ /dev/null @@ -1,15 +0,0 @@ -250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250, - chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>713,'#'=>500,'$'=>549,'%'=>833,'&'=>778,'\''=>439,'('=>333,')'=>333,'*'=>500,'+'=>549, - ','=>250,'-'=>549,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>278,';'=>278,'<'=>549,'='=>549,'>'=>549,'?'=>444,'@'=>549,'A'=>722, - 'B'=>667,'C'=>722,'D'=>612,'E'=>611,'F'=>763,'G'=>603,'H'=>722,'I'=>333,'J'=>631,'K'=>722,'L'=>686,'M'=>889,'N'=>722,'O'=>722,'P'=>768,'Q'=>741,'R'=>556,'S'=>592,'T'=>611,'U'=>690,'V'=>439,'W'=>768, - 'X'=>645,'Y'=>795,'Z'=>611,'['=>333,'\\'=>863,']'=>333,'^'=>658,'_'=>500,'`'=>500,'a'=>631,'b'=>549,'c'=>549,'d'=>494,'e'=>439,'f'=>521,'g'=>411,'h'=>603,'i'=>329,'j'=>603,'k'=>549,'l'=>549,'m'=>576, - 'n'=>521,'o'=>549,'p'=>549,'q'=>521,'r'=>549,'s'=>603,'t'=>439,'u'=>576,'v'=>713,'w'=>686,'x'=>493,'y'=>686,'z'=>494,'{'=>480,'|'=>200,'}'=>480,'~'=>549,chr(127)=>0,chr(128)=>0,chr(129)=>0,chr(130)=>0,chr(131)=>0, - chr(132)=>0,chr(133)=>0,chr(134)=>0,chr(135)=>0,chr(136)=>0,chr(137)=>0,chr(138)=>0,chr(139)=>0,chr(140)=>0,chr(141)=>0,chr(142)=>0,chr(143)=>0,chr(144)=>0,chr(145)=>0,chr(146)=>0,chr(147)=>0,chr(148)=>0,chr(149)=>0,chr(150)=>0,chr(151)=>0,chr(152)=>0,chr(153)=>0, - chr(154)=>0,chr(155)=>0,chr(156)=>0,chr(157)=>0,chr(158)=>0,chr(159)=>0,chr(160)=>750,chr(161)=>620,chr(162)=>247,chr(163)=>549,chr(164)=>167,chr(165)=>713,chr(166)=>500,chr(167)=>753,chr(168)=>753,chr(169)=>753,chr(170)=>753,chr(171)=>1042,chr(172)=>987,chr(173)=>603,chr(174)=>987,chr(175)=>603, - chr(176)=>400,chr(177)=>549,chr(178)=>411,chr(179)=>549,chr(180)=>549,chr(181)=>713,chr(182)=>494,chr(183)=>460,chr(184)=>549,chr(185)=>549,chr(186)=>549,chr(187)=>549,chr(188)=>1000,chr(189)=>603,chr(190)=>1000,chr(191)=>658,chr(192)=>823,chr(193)=>686,chr(194)=>795,chr(195)=>987,chr(196)=>768,chr(197)=>768, - chr(198)=>823,chr(199)=>768,chr(200)=>768,chr(201)=>713,chr(202)=>713,chr(203)=>713,chr(204)=>713,chr(205)=>713,chr(206)=>713,chr(207)=>713,chr(208)=>768,chr(209)=>713,chr(210)=>790,chr(211)=>790,chr(212)=>890,chr(213)=>823,chr(214)=>549,chr(215)=>250,chr(216)=>713,chr(217)=>603,chr(218)=>603,chr(219)=>1042, - chr(220)=>987,chr(221)=>603,chr(222)=>987,chr(223)=>603,chr(224)=>494,chr(225)=>329,chr(226)=>790,chr(227)=>790,chr(228)=>786,chr(229)=>713,chr(230)=>384,chr(231)=>384,chr(232)=>384,chr(233)=>384,chr(234)=>384,chr(235)=>384,chr(236)=>494,chr(237)=>494,chr(238)=>494,chr(239)=>494,chr(240)=>0,chr(241)=>329, - chr(242)=>274,chr(243)=>686,chr(244)=>686,chr(245)=>686,chr(246)=>384,chr(247)=>384,chr(248)=>384,chr(249)=>384,chr(250)=>384,chr(251)=>384,chr(252)=>494,chr(253)=>494,chr(254)=>494,chr(255)=>0); -?> diff --git a/mods/pdf_converter/font/times.php b/mods/pdf_converter/font/times.php deleted file mode 100644 index 837c706e0..000000000 --- a/mods/pdf_converter/font/times.php +++ /dev/null @@ -1,15 +0,0 @@ -250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250, - chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>408,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>180,'('=>333,')'=>333,'*'=>500,'+'=>564, - ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>278,';'=>278,'<'=>564,'='=>564,'>'=>564,'?'=>444,'@'=>921,'A'=>722, - 'B'=>667,'C'=>667,'D'=>722,'E'=>611,'F'=>556,'G'=>722,'H'=>722,'I'=>333,'J'=>389,'K'=>722,'L'=>611,'M'=>889,'N'=>722,'O'=>722,'P'=>556,'Q'=>722,'R'=>667,'S'=>556,'T'=>611,'U'=>722,'V'=>722,'W'=>944, - 'X'=>722,'Y'=>722,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>469,'_'=>500,'`'=>333,'a'=>444,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>333,'g'=>500,'h'=>500,'i'=>278,'j'=>278,'k'=>500,'l'=>278,'m'=>778, - 'n'=>500,'o'=>500,'p'=>500,'q'=>500,'r'=>333,'s'=>389,'t'=>278,'u'=>500,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>444,'{'=>480,'|'=>200,'}'=>480,'~'=>541,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500, - chr(132)=>444,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>889,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>444,chr(148)=>444,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>980, - chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>444,chr(159)=>722,chr(160)=>250,chr(161)=>333,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>200,chr(167)=>500,chr(168)=>333,chr(169)=>760,chr(170)=>276,chr(171)=>500,chr(172)=>564,chr(173)=>333,chr(174)=>760,chr(175)=>333, - chr(176)=>400,chr(177)=>564,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>500,chr(182)=>453,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>310,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>444,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722, - chr(198)=>889,chr(199)=>667,chr(200)=>611,chr(201)=>611,chr(202)=>611,chr(203)=>611,chr(204)=>333,chr(205)=>333,chr(206)=>333,chr(207)=>333,chr(208)=>722,chr(209)=>722,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>564,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722, - chr(220)=>722,chr(221)=>722,chr(222)=>556,chr(223)=>500,chr(224)=>444,chr(225)=>444,chr(226)=>444,chr(227)=>444,chr(228)=>444,chr(229)=>444,chr(230)=>667,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>500, - chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>564,chr(248)=>500,chr(249)=>500,chr(250)=>500,chr(251)=>500,chr(252)=>500,chr(253)=>500,chr(254)=>500,chr(255)=>500); -?> diff --git a/mods/pdf_converter/font/timesb.php b/mods/pdf_converter/font/timesb.php deleted file mode 100644 index 09cff86ac..000000000 --- a/mods/pdf_converter/font/timesb.php +++ /dev/null @@ -1,15 +0,0 @@ -250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250, - chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>555,'#'=>500,'$'=>500,'%'=>1000,'&'=>833,'\''=>278,'('=>333,')'=>333,'*'=>500,'+'=>570, - ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>570,'='=>570,'>'=>570,'?'=>500,'@'=>930,'A'=>722, - 'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>778,'I'=>389,'J'=>500,'K'=>778,'L'=>667,'M'=>944,'N'=>722,'O'=>778,'P'=>611,'Q'=>778,'R'=>722,'S'=>556,'T'=>667,'U'=>722,'V'=>722,'W'=>1000, - 'X'=>722,'Y'=>722,'Z'=>667,'['=>333,'\\'=>278,']'=>333,'^'=>581,'_'=>500,'`'=>333,'a'=>500,'b'=>556,'c'=>444,'d'=>556,'e'=>444,'f'=>333,'g'=>500,'h'=>556,'i'=>278,'j'=>333,'k'=>556,'l'=>278,'m'=>833, - 'n'=>556,'o'=>500,'p'=>556,'q'=>556,'r'=>444,'s'=>389,'t'=>333,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>444,'{'=>394,'|'=>220,'}'=>394,'~'=>520,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500, - chr(132)=>500,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>667,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>1000, - chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>444,chr(159)=>722,chr(160)=>250,chr(161)=>333,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>220,chr(167)=>500,chr(168)=>333,chr(169)=>747,chr(170)=>300,chr(171)=>500,chr(172)=>570,chr(173)=>333,chr(174)=>747,chr(175)=>333, - chr(176)=>400,chr(177)=>570,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>556,chr(182)=>540,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>330,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722, - chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>389,chr(205)=>389,chr(206)=>389,chr(207)=>389,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>570,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, - chr(220)=>722,chr(221)=>722,chr(222)=>611,chr(223)=>556,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>722,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>556, - chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>570,chr(248)=>500,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500); -?> diff --git a/mods/pdf_converter/font/timesbi.php b/mods/pdf_converter/font/timesbi.php deleted file mode 100644 index b4e38d763..000000000 --- a/mods/pdf_converter/font/timesbi.php +++ /dev/null @@ -1,15 +0,0 @@ -250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250, - chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>389,'"'=>555,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>278,'('=>333,')'=>333,'*'=>500,'+'=>570, - ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>570,'='=>570,'>'=>570,'?'=>500,'@'=>832,'A'=>667, - 'B'=>667,'C'=>667,'D'=>722,'E'=>667,'F'=>667,'G'=>722,'H'=>778,'I'=>389,'J'=>500,'K'=>667,'L'=>611,'M'=>889,'N'=>722,'O'=>722,'P'=>611,'Q'=>722,'R'=>667,'S'=>556,'T'=>611,'U'=>722,'V'=>667,'W'=>889, - 'X'=>667,'Y'=>611,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>570,'_'=>500,'`'=>333,'a'=>500,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>333,'g'=>500,'h'=>556,'i'=>278,'j'=>278,'k'=>500,'l'=>278,'m'=>778, - 'n'=>556,'o'=>500,'p'=>500,'q'=>500,'r'=>389,'s'=>389,'t'=>278,'u'=>556,'v'=>444,'w'=>667,'x'=>500,'y'=>444,'z'=>389,'{'=>348,'|'=>220,'}'=>348,'~'=>570,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500, - chr(132)=>500,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>944,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>1000, - chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>389,chr(159)=>611,chr(160)=>250,chr(161)=>389,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>220,chr(167)=>500,chr(168)=>333,chr(169)=>747,chr(170)=>266,chr(171)=>500,chr(172)=>606,chr(173)=>333,chr(174)=>747,chr(175)=>333, - chr(176)=>400,chr(177)=>570,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>576,chr(182)=>500,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>300,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667, - chr(198)=>944,chr(199)=>667,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>389,chr(205)=>389,chr(206)=>389,chr(207)=>389,chr(208)=>722,chr(209)=>722,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>570,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722, - chr(220)=>722,chr(221)=>611,chr(222)=>611,chr(223)=>500,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>722,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>556, - chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>570,chr(248)=>500,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>444,chr(254)=>500,chr(255)=>444); -?> diff --git a/mods/pdf_converter/font/timesi.php b/mods/pdf_converter/font/timesi.php deleted file mode 100644 index 0ba2b7773..000000000 --- a/mods/pdf_converter/font/timesi.php +++ /dev/null @@ -1,15 +0,0 @@ -250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250, - chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>420,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>214,'('=>333,')'=>333,'*'=>500,'+'=>675, - ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>675,'='=>675,'>'=>675,'?'=>500,'@'=>920,'A'=>611, - 'B'=>611,'C'=>667,'D'=>722,'E'=>611,'F'=>611,'G'=>722,'H'=>722,'I'=>333,'J'=>444,'K'=>667,'L'=>556,'M'=>833,'N'=>667,'O'=>722,'P'=>611,'Q'=>722,'R'=>611,'S'=>500,'T'=>556,'U'=>722,'V'=>611,'W'=>833, - 'X'=>611,'Y'=>556,'Z'=>556,'['=>389,'\\'=>278,']'=>389,'^'=>422,'_'=>500,'`'=>333,'a'=>500,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>278,'g'=>500,'h'=>500,'i'=>278,'j'=>278,'k'=>444,'l'=>278,'m'=>722, - 'n'=>500,'o'=>500,'p'=>500,'q'=>500,'r'=>389,'s'=>389,'t'=>278,'u'=>500,'v'=>444,'w'=>667,'x'=>444,'y'=>444,'z'=>389,'{'=>400,'|'=>275,'}'=>400,'~'=>541,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500, - chr(132)=>556,chr(133)=>889,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>500,chr(139)=>333,chr(140)=>944,chr(141)=>350,chr(142)=>556,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>556,chr(148)=>556,chr(149)=>350,chr(150)=>500,chr(151)=>889,chr(152)=>333,chr(153)=>980, - chr(154)=>389,chr(155)=>333,chr(156)=>667,chr(157)=>350,chr(158)=>389,chr(159)=>556,chr(160)=>250,chr(161)=>389,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>275,chr(167)=>500,chr(168)=>333,chr(169)=>760,chr(170)=>276,chr(171)=>500,chr(172)=>675,chr(173)=>333,chr(174)=>760,chr(175)=>333, - chr(176)=>400,chr(177)=>675,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>500,chr(182)=>523,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>310,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>611,chr(193)=>611,chr(194)=>611,chr(195)=>611,chr(196)=>611,chr(197)=>611, - chr(198)=>889,chr(199)=>667,chr(200)=>611,chr(201)=>611,chr(202)=>611,chr(203)=>611,chr(204)=>333,chr(205)=>333,chr(206)=>333,chr(207)=>333,chr(208)=>722,chr(209)=>667,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>675,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722, - chr(220)=>722,chr(221)=>556,chr(222)=>611,chr(223)=>500,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>667,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>500, - chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>675,chr(248)=>500,chr(249)=>500,chr(250)=>500,chr(251)=>500,chr(252)=>500,chr(253)=>444,chr(254)=>500,chr(255)=>444); -?> diff --git a/mods/pdf_converter/font/zapfdingbats.php b/mods/pdf_converter/font/zapfdingbats.php deleted file mode 100644 index 1f926a8c3..000000000 --- a/mods/pdf_converter/font/zapfdingbats.php +++ /dev/null @@ -1,15 +0,0 @@ -0,chr(1)=>0,chr(2)=>0,chr(3)=>0,chr(4)=>0,chr(5)=>0,chr(6)=>0,chr(7)=>0,chr(8)=>0,chr(9)=>0,chr(10)=>0,chr(11)=>0,chr(12)=>0,chr(13)=>0,chr(14)=>0,chr(15)=>0,chr(16)=>0,chr(17)=>0,chr(18)=>0,chr(19)=>0,chr(20)=>0,chr(21)=>0, - chr(22)=>0,chr(23)=>0,chr(24)=>0,chr(25)=>0,chr(26)=>0,chr(27)=>0,chr(28)=>0,chr(29)=>0,chr(30)=>0,chr(31)=>0,' '=>278,'!'=>974,'"'=>961,'#'=>974,'$'=>980,'%'=>719,'&'=>789,'\''=>790,'('=>791,')'=>690,'*'=>960,'+'=>939, - ','=>549,'-'=>855,'.'=>911,'/'=>933,'0'=>911,'1'=>945,'2'=>974,'3'=>755,'4'=>846,'5'=>762,'6'=>761,'7'=>571,'8'=>677,'9'=>763,':'=>760,';'=>759,'<'=>754,'='=>494,'>'=>552,'?'=>537,'@'=>577,'A'=>692, - 'B'=>786,'C'=>788,'D'=>788,'E'=>790,'F'=>793,'G'=>794,'H'=>816,'I'=>823,'J'=>789,'K'=>841,'L'=>823,'M'=>833,'N'=>816,'O'=>831,'P'=>923,'Q'=>744,'R'=>723,'S'=>749,'T'=>790,'U'=>792,'V'=>695,'W'=>776, - 'X'=>768,'Y'=>792,'Z'=>759,'['=>707,'\\'=>708,']'=>682,'^'=>701,'_'=>826,'`'=>815,'a'=>789,'b'=>789,'c'=>707,'d'=>687,'e'=>696,'f'=>689,'g'=>786,'h'=>787,'i'=>713,'j'=>791,'k'=>785,'l'=>791,'m'=>873, - 'n'=>761,'o'=>762,'p'=>762,'q'=>759,'r'=>759,'s'=>892,'t'=>892,'u'=>788,'v'=>784,'w'=>438,'x'=>138,'y'=>277,'z'=>415,'{'=>392,'|'=>392,'}'=>668,'~'=>668,chr(127)=>0,chr(128)=>390,chr(129)=>390,chr(130)=>317,chr(131)=>317, - chr(132)=>276,chr(133)=>276,chr(134)=>509,chr(135)=>509,chr(136)=>410,chr(137)=>410,chr(138)=>234,chr(139)=>234,chr(140)=>334,chr(141)=>334,chr(142)=>0,chr(143)=>0,chr(144)=>0,chr(145)=>0,chr(146)=>0,chr(147)=>0,chr(148)=>0,chr(149)=>0,chr(150)=>0,chr(151)=>0,chr(152)=>0,chr(153)=>0, - chr(154)=>0,chr(155)=>0,chr(156)=>0,chr(157)=>0,chr(158)=>0,chr(159)=>0,chr(160)=>0,chr(161)=>732,chr(162)=>544,chr(163)=>544,chr(164)=>910,chr(165)=>667,chr(166)=>760,chr(167)=>760,chr(168)=>776,chr(169)=>595,chr(170)=>694,chr(171)=>626,chr(172)=>788,chr(173)=>788,chr(174)=>788,chr(175)=>788, - chr(176)=>788,chr(177)=>788,chr(178)=>788,chr(179)=>788,chr(180)=>788,chr(181)=>788,chr(182)=>788,chr(183)=>788,chr(184)=>788,chr(185)=>788,chr(186)=>788,chr(187)=>788,chr(188)=>788,chr(189)=>788,chr(190)=>788,chr(191)=>788,chr(192)=>788,chr(193)=>788,chr(194)=>788,chr(195)=>788,chr(196)=>788,chr(197)=>788, - chr(198)=>788,chr(199)=>788,chr(200)=>788,chr(201)=>788,chr(202)=>788,chr(203)=>788,chr(204)=>788,chr(205)=>788,chr(206)=>788,chr(207)=>788,chr(208)=>788,chr(209)=>788,chr(210)=>788,chr(211)=>788,chr(212)=>894,chr(213)=>838,chr(214)=>1016,chr(215)=>458,chr(216)=>748,chr(217)=>924,chr(218)=>748,chr(219)=>918, - chr(220)=>927,chr(221)=>928,chr(222)=>928,chr(223)=>834,chr(224)=>873,chr(225)=>828,chr(226)=>924,chr(227)=>924,chr(228)=>917,chr(229)=>930,chr(230)=>931,chr(231)=>463,chr(232)=>883,chr(233)=>836,chr(234)=>836,chr(235)=>867,chr(236)=>867,chr(237)=>696,chr(238)=>696,chr(239)=>874,chr(240)=>0,chr(241)=>874, - chr(242)=>760,chr(243)=>946,chr(244)=>771,chr(245)=>865,chr(246)=>771,chr(247)=>888,chr(248)=>967,chr(249)=>888,chr(250)=>831,chr(251)=>873,chr(252)=>927,chr(253)=>970,chr(254)=>918,chr(255)=>0); -?> diff --git a/mods/pdf_converter/fpdf.css b/mods/pdf_converter/fpdf.css deleted file mode 100644 index 580b144e9..000000000 --- a/mods/pdf_converter/fpdf.css +++ /dev/null @@ -1,23 +0,0 @@ -body {font-family:"Times New Roman",serif} -h1 {font-size:150%; color:#4000A0} -h2 {color:#4000A0} -h3 {font-size:100%; margin-top:1.2em} -dl.param dt {text-decoration:underline} -dl.param dd {margin-top:1em; margin-bottom:1em} -dl.param ul {margin-top:1em; margin-bottom:1em} -tt, code, kbd {font-family:"Courier New",Courier,monospace; font-size:82%} -div.source {margin-top:1.4em; margin-bottom:1.3em} -div.source pre {display:table; border:1px solid #24246A; width:100%; margin:0em; font-family:inherited; font-size:100%} -div.source code {display:block; border:1px solid #C5C5EC; background-color:#F0F5FF; padding:6px; color:#000000} -div.doc-source {margin-top:1.4em; margin-bottom:1.3em} -div.doc-source pre {display:table; width:100%; margin:0em; font-family:inherited; font-size:100%} -div.doc-source code {display:block; background-color:#E0E0E0; padding:4px} -.st {font-weight:bold; color:#900000} -.kw {color:#000080; font-weight:bold} -.str {color:#CC0000} -.cmt {color:#008000} -p.demo {text-align:center; margin-top:-0.9em} -a.demo {text-decoration:none; font-weight:bold; color:#0000CC} -a.demo:link {text-decoration:none; font-weight:bold; color:#0000CC} -a.demo:hover {text-decoration:none; font-weight:bold; color:#0000FF} -a.demo:active {text-decoration:none; font-weight:bold; color:#0000FF} diff --git a/mods/pdf_converter/fpdf.php b/mods/pdf_converter/fpdf.php deleted file mode 100644 index f0a3e45ef..000000000 --- a/mods/pdf_converter/fpdf.php +++ /dev/null @@ -1,1647 +0,0 @@ -_dochecks(); - //Initialization of properties - $this->page=0; - $this->n=2; - $this->buffer=''; - $this->pages=array(); - $this->OrientationChanges=array(); - $this->state=0; - $this->fonts=array(); - $this->FontFiles=array(); - $this->diffs=array(); - $this->images=array(); - $this->links=array(); - $this->InFooter=false; - $this->lasth=0; - $this->FontFamily=''; - $this->FontStyle=''; - $this->FontSizePt=12; - $this->underline=false; - $this->DrawColor='0 G'; - $this->FillColor='0 g'; - $this->TextColor='0 g'; - $this->ColorFlag=false; - $this->ws=0; - //Standard fonts - $this->CoreFonts=array('courier'=>'Courier','courierB'=>'Courier-Bold','courierI'=>'Courier-Oblique','courierBI'=>'Courier-BoldOblique', - 'helvetica'=>'Helvetica','helveticaB'=>'Helvetica-Bold','helveticaI'=>'Helvetica-Oblique','helveticaBI'=>'Helvetica-BoldOblique', - 'times'=>'Times-Roman','timesB'=>'Times-Bold','timesI'=>'Times-Italic','timesBI'=>'Times-BoldItalic', - 'symbol'=>'Symbol','zapfdingbats'=>'ZapfDingbats'); - //Scale factor - if($unit=='pt') - $this->k=1; - elseif($unit=='mm') - $this->k=72/25.4; - elseif($unit=='cm') - $this->k=72/2.54; - elseif($unit=='in') - $this->k=72; - else - $this->Error('Incorrect unit: '.$unit); - //Page format - if(is_string($format)) - { - $format=strtolower($format); - if($format=='a3') - $format=array(841.89,1190.55); - elseif($format=='a4') - $format=array(595.28,841.89); - elseif($format=='a5') - $format=array(420.94,595.28); - elseif($format=='letter') - $format=array(612,792); - elseif($format=='legal') - $format=array(612,1008); - else - $this->Error('Unknown page format: '.$format); - $this->fwPt=$format[0]; - $this->fhPt=$format[1]; - } - else - { - $this->fwPt=$format[0]*$this->k; - $this->fhPt=$format[1]*$this->k; - } - $this->fw=$this->fwPt/$this->k; - $this->fh=$this->fhPt/$this->k; - //Page orientation - $orientation=strtolower($orientation); - if($orientation=='p' || $orientation=='portrait') - { - $this->DefOrientation='P'; - $this->wPt=$this->fwPt; - $this->hPt=$this->fhPt; - } - elseif($orientation=='l' || $orientation=='landscape') - { - $this->DefOrientation='L'; - $this->wPt=$this->fhPt; - $this->hPt=$this->fwPt; - } - else - $this->Error('Incorrect orientation: '.$orientation); - $this->CurOrientation=$this->DefOrientation; - $this->w=$this->wPt/$this->k; - $this->h=$this->hPt/$this->k; - //Page margins (1 cm) - $margin=28.35/$this->k; - $this->SetMargins($margin,$margin); - //Interior cell margin (1 mm) - $this->cMargin=$margin/10; - //Line width (0.2 mm) - $this->LineWidth=.567/$this->k; - //Automatic page break - $this->SetAutoPageBreak(true,2*$margin); - //Full width display mode - $this->SetDisplayMode('fullwidth'); - //Enable compression - $this->SetCompression(true); - //Set default PDF version number - $this->PDFVersion='1.3'; -} - -function SetMargins($left,$top,$right=-1) -{ - //Set left, top and right margins - $this->lMargin=$left; - $this->tMargin=$top; - if($right==-1) - $right=$left; - $this->rMargin=$right; -} - -function SetLeftMargin($margin) -{ - //Set left margin - $this->lMargin=$margin; - if($this->page>0 && $this->x<$margin) - $this->x=$margin; -} - -function SetTopMargin($margin) -{ - //Set top margin - $this->tMargin=$margin; -} - -function SetRightMargin($margin) -{ - //Set right margin - $this->rMargin=$margin; -} - -function SetAutoPageBreak($auto,$margin=0) -{ - //Set auto page break mode and triggering margin - $this->AutoPageBreak=$auto; - $this->bMargin=$margin; - $this->PageBreakTrigger=$this->h-$margin; -} - -function SetDisplayMode($zoom,$layout='continuous') -{ - //Set display mode in viewer - if($zoom=='fullpage' || $zoom=='fullwidth' || $zoom=='real' || $zoom=='default' || !is_string($zoom)) - $this->ZoomMode=$zoom; - else - $this->Error('Incorrect zoom display mode: '.$zoom); - if($layout=='single' || $layout=='continuous' || $layout=='two' || $layout=='default') - $this->LayoutMode=$layout; - else - $this->Error('Incorrect layout display mode: '.$layout); -} - -function SetCompression($compress) -{ - //Set page compression - if(function_exists('gzcompress')) - $this->compress=$compress; - else - $this->compress=false; -} - -function SetTitle($title) -{ - //Title of document - $this->title=$title; -} - -function SetSubject($subject) -{ - //Subject of document - $this->subject=$subject; -} - -function SetAuthor($author) -{ - //Author of document - $this->author=$author; -} - -function SetKeywords($keywords) -{ - //Keywords of document - $this->keywords=$keywords; -} - -function SetCreator($creator) -{ - //Creator of document - $this->creator=$creator; -} - -function AliasNbPages($alias='{nb}') -{ - //Define an alias for total number of pages - $this->AliasNbPages=$alias; -} - -function Error($msg) -{ - //Fatal error - die('FPDF error: '.$msg); -} - -function Open() -{ - //Begin document - $this->state=1; -} - -function Close() -{ - //Terminate document - if($this->state==3) - return; - if($this->page==0) - $this->AddPage(); - //Page footer - $this->InFooter=true; - $this->Footer(); - $this->InFooter=false; - //Close page - $this->_endpage(); - //Close document - $this->_enddoc(); -} - -function AddPage($orientation='') -{ - //Start a new page - if($this->state==0) - $this->Open(); - $family=$this->FontFamily; - $style=$this->FontStyle.($this->underline ? 'U' : ''); - $size=$this->FontSizePt; - $lw=$this->LineWidth; - $dc=$this->DrawColor; - $fc=$this->FillColor; - $tc=$this->TextColor; - $cf=$this->ColorFlag; - if($this->page>0) - { - //Page footer - $this->InFooter=true; - $this->Footer(); - $this->InFooter=false; - //Close page - $this->_endpage(); - } - //Start new page - $this->_beginpage($orientation); - //Set line cap style to square - $this->_out('2 J'); - //Set line width - $this->LineWidth=$lw; - $this->_out(sprintf('%.2f w',$lw*$this->k)); - //Set font - if($family) - $this->SetFont($family,$style,$size); - //Set colors - $this->DrawColor=$dc; - if($dc!='0 G') - $this->_out($dc); - $this->FillColor=$fc; - if($fc!='0 g') - $this->_out($fc); - $this->TextColor=$tc; - $this->ColorFlag=$cf; - //Page header - $this->Header(); - //Restore line width - if($this->LineWidth!=$lw) - { - $this->LineWidth=$lw; - $this->_out(sprintf('%.2f w',$lw*$this->k)); - } - //Restore font - if($family) - $this->SetFont($family,$style,$size); - //Restore colors - if($this->DrawColor!=$dc) - { - $this->DrawColor=$dc; - $this->_out($dc); - } - if($this->FillColor!=$fc) - { - $this->FillColor=$fc; - $this->_out($fc); - } - $this->TextColor=$tc; - $this->ColorFlag=$cf; -} - -function Header() -{ - //To be implemented in your own inherited class -} - -function Footer() -{ - //To be implemented in your own inherited class -} - -function PageNo() -{ - //Get current page number - return $this->page; -} - -function SetDrawColor($r,$g=-1,$b=-1) -{ - //Set color for all stroking operations - if(($r==0 && $g==0 && $b==0) || $g==-1) - $this->DrawColor=sprintf('%.3f G',$r/255); - else - $this->DrawColor=sprintf('%.3f %.3f %.3f RG',$r/255,$g/255,$b/255); - if($this->page>0) - $this->_out($this->DrawColor); -} - -function SetFillColor($r,$g=-1,$b=-1) -{ - //Set color for all filling operations - if(($r==0 && $g==0 && $b==0) || $g==-1) - $this->FillColor=sprintf('%.3f g',$r/255); - else - $this->FillColor=sprintf('%.3f %.3f %.3f rg',$r/255,$g/255,$b/255); - $this->ColorFlag=($this->FillColor!=$this->TextColor); - if($this->page>0) - $this->_out($this->FillColor); -} - -function SetTextColor($r,$g=-1,$b=-1) -{ - //Set color for text - if(($r==0 && $g==0 && $b==0) || $g==-1) - $this->TextColor=sprintf('%.3f g',$r/255); - else - $this->TextColor=sprintf('%.3f %.3f %.3f rg',$r/255,$g/255,$b/255); - $this->ColorFlag=($this->FillColor!=$this->TextColor); -} - -function GetStringWidth($s) -{ - //Get width of a string in the current font - $s=(string)$s; - $cw=&$this->CurrentFont['cw']; - $w=0; - $l=strlen($s); - for($i=0;$i<$l;$i++) - $w+=$cw[$s{$i}]; - return $w*$this->FontSize/1000; -} - -function SetLineWidth($width) -{ - //Set line width - $this->LineWidth=$width; - if($this->page>0) - $this->_out(sprintf('%.2f w',$width*$this->k)); -} - -function Line($x1,$y1,$x2,$y2) -{ - //Draw a line - $this->_out(sprintf('%.2f %.2f m %.2f %.2f l S',$x1*$this->k,($this->h-$y1)*$this->k,$x2*$this->k,($this->h-$y2)*$this->k)); -} - -function Rect($x,$y,$w,$h,$style='') -{ - //Draw a rectangle - if($style=='F') - $op='f'; - elseif($style=='FD' || $style=='DF') - $op='B'; - else - $op='S'; - $this->_out(sprintf('%.2f %.2f %.2f %.2f re %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op)); -} - -function AddFont($family,$style='',$file='') -{ - //Add a TrueType or Type1 font - $family=strtolower($family); - if($file=='') - $file=str_replace(' ','',$family).strtolower($style).'.php'; - if($family=='arial') - $family='helvetica'; - $style=strtoupper($style); - if($style=='IB') - $style='BI'; - $fontkey=$family.$style; - if(isset($this->fonts[$fontkey])) - $this->Error('Font already added: '.$family.' '.$style); - include($this->_getfontpath().$file); - if(!isset($name)) - $this->Error('Could not include font definition file'); - $i=count($this->fonts)+1; - $this->fonts[$fontkey]=array('i'=>$i,'type'=>$type,'name'=>$name,'desc'=>$desc,'up'=>$up,'ut'=>$ut,'cw'=>$cw,'enc'=>$enc,'file'=>$file); - if($diff) - { - //Search existing encodings - $d=0; - $nb=count($this->diffs); - for($i=1;$i<=$nb;$i++) - { - if($this->diffs[$i]==$diff) - { - $d=$i; - break; - } - } - if($d==0) - { - $d=$nb+1; - $this->diffs[$d]=$diff; - } - $this->fonts[$fontkey]['diff']=$d; - } - if($file) - { - if($type=='TrueType') - $this->FontFiles[$file]=array('length1'=>$originalsize); - else - $this->FontFiles[$file]=array('length1'=>$size1,'length2'=>$size2); - } -} - -function SetFont($family,$style='',$size=0) -{ - //Select a font; size given in points - global $fpdf_charwidths; - - $family=strtolower($family); - if($family=='') - $family=$this->FontFamily; - if($family=='arial') - $family='helvetica'; - elseif($family=='symbol' || $family=='zapfdingbats') - $style=''; - $style=strtoupper($style); - if(strpos($style,'U')!==false) - { - $this->underline=true; - $style=str_replace('U','',$style); - } - else - $this->underline=false; - if($style=='IB') - $style='BI'; - if($size==0) - $size=$this->FontSizePt; - //Test if font is already selected - if($this->FontFamily==$family && $this->FontStyle==$style && $this->FontSizePt==$size) - return; - //Test if used for the first time - $fontkey=$family.$style; - if(!isset($this->fonts[$fontkey])) - { - //Check if one of the standard fonts - if(isset($this->CoreFonts[$fontkey])) - { - if(!isset($fpdf_charwidths[$fontkey])) - { - //Load metric file - $file=$family; - if($family=='times' || $family=='helvetica') - $file.=strtolower($style); - include($this->_getfontpath().$file.'.php'); - if(!isset($fpdf_charwidths[$fontkey])) - $this->Error('Could not include font metric file'); - } - $i=count($this->fonts)+1; - $this->fonts[$fontkey]=array('i'=>$i,'type'=>'core','name'=>$this->CoreFonts[$fontkey],'up'=>-100,'ut'=>50,'cw'=>$fpdf_charwidths[$fontkey]); - } - else - $this->Error('Undefined font: '.$family.' '.$style); - } - //Select it - $this->FontFamily=$family; - $this->FontStyle=$style; - $this->FontSizePt=$size; - $this->FontSize=$size/$this->k; - $this->CurrentFont=&$this->fonts[$fontkey]; - if($this->page>0) - $this->_out(sprintf('BT /F%d %.2f Tf ET',$this->CurrentFont['i'],$this->FontSizePt)); -} - -function SetFontSize($size) -{ - //Set font size in points - if($this->FontSizePt==$size) - return; - $this->FontSizePt=$size; - $this->FontSize=$size/$this->k; - if($this->page>0) - $this->_out(sprintf('BT /F%d %.2f Tf ET',$this->CurrentFont['i'],$this->FontSizePt)); -} - -function AddLink() -{ - //Create a new internal link - $n=count($this->links)+1; - $this->links[$n]=array(0,0); - return $n; -} - -function SetLink($link,$y=0,$page=-1) -{ - //Set destination of internal link - if($y==-1) - $y=$this->y; - if($page==-1) - $page=$this->page; - $this->links[$link]=array($page,$y); -} - -function Link($x,$y,$w,$h,$link) -{ - //Put a link on the page - $this->PageLinks[$this->page][]=array($x*$this->k,$this->hPt-$y*$this->k,$w*$this->k,$h*$this->k,$link); -} - -function Text($x,$y,$txt) -{ - //Output a string - $s=sprintf('BT %.2f %.2f Td (%s) Tj ET',$x*$this->k,($this->h-$y)*$this->k,$this->_escape($txt)); - if($this->underline && $txt!='') - $s.=' '.$this->_dounderline($x,$y,$txt); - if($this->ColorFlag) - $s='q '.$this->TextColor.' '.$s.' Q'; - $this->_out($s); -} - -function AcceptPageBreak() -{ - //Accept automatic page break or not - return $this->AutoPageBreak; -} - -function Cell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='') -{ - //Output a cell - $k=$this->k; - if($this->y+$h>$this->PageBreakTrigger && !$this->InFooter && $this->AcceptPageBreak()) - { - //Automatic page break - $x=$this->x; - $ws=$this->ws; - if($ws>0) - { - $this->ws=0; - $this->_out('0 Tw'); - } - $this->AddPage($this->CurOrientation); - $this->x=$x; - if($ws>0) - { - $this->ws=$ws; - $this->_out(sprintf('%.3f Tw',$ws*$k)); - } - } - if($w==0) - $w=$this->w-$this->rMargin-$this->x; - $s=''; - if($fill==1 || $border==1) - { - if($fill==1) - $op=($border==1) ? 'B' : 'f'; - else - $op='S'; - $s=sprintf('%.2f %.2f %.2f %.2f re %s ',$this->x*$k,($this->h-$this->y)*$k,$w*$k,-$h*$k,$op); - } - if(is_string($border)) - { - $x=$this->x; - $y=$this->y; - if(strpos($border,'L')!==false) - $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,$x*$k,($this->h-($y+$h))*$k); - if(strpos($border,'T')!==false) - $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-$y)*$k); - if(strpos($border,'R')!==false) - $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',($x+$w)*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-($y+$h))*$k); - if(strpos($border,'B')!==false) - $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-($y+$h))*$k,($x+$w)*$k,($this->h-($y+$h))*$k); - } - if($txt!=='') - { - if($align=='R') - $dx=$w-$this->cMargin-$this->GetStringWidth($txt); - elseif($align=='C') - $dx=($w-$this->GetStringWidth($txt))/2; - else - $dx=$this->cMargin; - if($this->ColorFlag) - $s.='q '.$this->TextColor.' '; - $txt2=str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$txt))); - $s.=sprintf('BT %.2f %.2f Td (%s) Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$txt2); - if($this->underline) - $s.=' '.$this->_dounderline($this->x+$dx,$this->y+.5*$h+.3*$this->FontSize,$txt); - if($this->ColorFlag) - $s.=' Q'; - if($link) - $this->Link($this->x+$dx,$this->y+.5*$h-.5*$this->FontSize,$this->GetStringWidth($txt),$this->FontSize,$link); - } - if($s) - $this->_out($s); - $this->lasth=$h; - if($ln>0) - { - //Go to next line - $this->y+=$h; - if($ln==1) - $this->x=$this->lMargin; - } - else - $this->x+=$w; -} - -function MultiCell($w,$h,$txt,$border=0,$align='J',$fill=0) -{ - //Output text with automatic or explicit line breaks - $cw=&$this->CurrentFont['cw']; - if($w==0) - $w=$this->w-$this->rMargin-$this->x; - $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; - $s=str_replace("\r",'',$txt); - $nb=strlen($s); - if($nb>0 && $s[$nb-1]=="\n") - $nb--; - $b=0; - if($border) - { - if($border==1) - { - $border='LTRB'; - $b='LRT'; - $b2='LR'; - } - else - { - $b2=''; - if(strpos($border,'L')!==false) - $b2.='L'; - if(strpos($border,'R')!==false) - $b2.='R'; - $b=(strpos($border,'T')!==false) ? $b2.'T' : $b2; - } - } - $sep=-1; - $i=0; - $j=0; - $l=0; - $ns=0; - $nl=1; - while($i<$nb) - { - //Get next character - $c=$s{$i}; - if($c=="\n") - { - //Explicit line break - if($this->ws>0) - { - $this->ws=0; - $this->_out('0 Tw'); - } - $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); - $i++; - $sep=-1; - $j=$i; - $l=0; - $ns=0; - $nl++; - if($border && $nl==2) - $b=$b2; - continue; - } - if($c==' ') - { - $sep=$i; - $ls=$l; - $ns++; - } - $l+=$cw[$c]; - if($l>$wmax) - { - //Automatic line break - if($sep==-1) - { - if($i==$j) - $i++; - if($this->ws>0) - { - $this->ws=0; - $this->_out('0 Tw'); - } - $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); - } - else - { - if($align=='J') - { - $this->ws=($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0; - $this->_out(sprintf('%.3f Tw',$this->ws*$this->k)); - } - $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill); - $i=$sep+1; - } - $sep=-1; - $j=$i; - $l=0; - $ns=0; - $nl++; - if($border && $nl==2) - $b=$b2; - } - else - $i++; - } - //Last chunk - if($this->ws>0) - { - $this->ws=0; - $this->_out('0 Tw'); - } - if($border && strpos($border,'B')!==false) - $b.='B'; - $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); - $this->x=$this->lMargin; -} - -function Write($h,$txt,$link='') -{ - //Output text in flowing mode - $cw=&$this->CurrentFont['cw']; - $w=$this->w-$this->rMargin-$this->x; - $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; - $s=str_replace("\r",'',$txt); - $nb=strlen($s); - $sep=-1; - $i=0; - $j=0; - $l=0; - $nl=1; - while($i<$nb) - { - //Get next character - $c=$s{$i}; - if($c=="\n") - { - //Explicit line break - $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link); - $i++; - $sep=-1; - $j=$i; - $l=0; - if($nl==1) - { - $this->x=$this->lMargin; - $w=$this->w-$this->rMargin-$this->x; - $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; - } - $nl++; - continue; - } - if($c==' ') - $sep=$i; - $l+=$cw[$c]; - if($l>$wmax) - { - //Automatic line break - if($sep==-1) - { - if($this->x>$this->lMargin) - { - //Move to next line - $this->x=$this->lMargin; - $this->y+=$h; - $w=$this->w-$this->rMargin-$this->x; - $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; - $i++; - $nl++; - continue; - } - if($i==$j) - $i++; - $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link); - } - else - { - $this->Cell($w,$h,substr($s,$j,$sep-$j),0,2,'',0,$link); - $i=$sep+1; - } - $sep=-1; - $j=$i; - $l=0; - if($nl==1) - { - $this->x=$this->lMargin; - $w=$this->w-$this->rMargin-$this->x; - $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; - } - $nl++; - } - else - $i++; - } - //Last chunk - if($i!=$j) - $this->Cell($l/1000*$this->FontSize,$h,substr($s,$j),0,0,'',0,$link); -} - -function Image($file,$x,$y,$w=0,$h=0,$type='',$link='') -{ - //Put an image on the page - if(!isset($this->images[$file])) - { - //First use of image, get info - if($type=='') - { - $pos=strrpos($file,'.'); - if(!$pos) - $this->Error('Image file has no extension and no type was specified: '.$file); - $type=substr($file,$pos+1); - } - $type=strtolower($type); - $mqr=get_magic_quotes_runtime(); - set_magic_quotes_runtime(0); - if($type=='jpg' || $type=='jpeg') - $info=$this->_parsejpg($file); - elseif($type=='png') - $info=$this->_parsepng($file); - else - { - //Allow for additional formats - $mtd='_parse'.$type; - if(!method_exists($this,$mtd)) - $this->Error('Unsupported image type: '.$type); - $info=$this->$mtd($file); - } - set_magic_quotes_runtime($mqr); - $info['i']=count($this->images)+1; - $this->images[$file]=$info; - } - else - $info=$this->images[$file]; - //Automatic width and height calculation if needed - if($w==0 && $h==0) - { - //Put image at 72 dpi - $w=$info['w']/$this->k; - $h=$info['h']/$this->k; - } - if($w==0) - $w=$h*$info['w']/$info['h']; - if($h==0) - $h=$w*$info['h']/$info['w']; - $this->_out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q',$w*$this->k,$h*$this->k,$x*$this->k,($this->h-($y+$h))*$this->k,$info['i'])); - if($link) - $this->Link($x,$y,$w,$h,$link); -} - -function Ln($h='') -{ - //Line feed; default value is last cell height - $this->x=$this->lMargin; - if(is_string($h)) - $this->y+=$this->lasth; - else - $this->y+=$h; -} - -function GetX() -{ - //Get x position - return $this->x; -} - -function SetX($x) -{ - //Set x position - if($x>=0) - $this->x=$x; - else - $this->x=$this->w+$x; -} - -function GetY() -{ - //Get y position - return $this->y; -} - -function SetY($y) -{ - //Set y position and reset x - $this->x=$this->lMargin; - if($y>=0) - $this->y=$y; - else - $this->y=$this->h+$y; -} - -function SetXY($x,$y) -{ - //Set x and y positions - $this->SetY($y); - $this->SetX($x); -} - -function Output($name='',$dest='') -{ - //Output PDF to some destination - //Finish document if necessary - if($this->state<3) - $this->Close(); - //Normalize parameters - if(is_bool($dest)) - $dest=$dest ? 'D' : 'F'; - $dest=strtoupper($dest); - if($dest=='') - { - if($name=='') - { - $name='doc.pdf'; - $dest='I'; - } - else - $dest='F'; - } - switch($dest) - { - case 'I': - //Send to standard output - if(ob_get_contents()) - $this->Error('Some data has already been output, can\'t send PDF file'); - if(php_sapi_name()!='cli') - { - //We send to a browser - header('Content-Type: application/pdf'); - if(headers_sent()) - $this->Error('Some data has already been output to browser, can\'t send PDF file'); - header('Content-Length: '.strlen($this->buffer)); - header('Content-disposition: inline; filename="'.$name.'"'); - } - echo $this->buffer; - break; - case 'D': - //Download file - if(ob_get_contents()) - $this->Error('Some data has already been output, can\'t send PDF file'); - if(isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'],'MSIE')) - header('Content-Type: application/force-download'); - else - header('Content-Type: application/octet-stream'); - if(headers_sent()) - $this->Error('Some data has already been output to browser, can\'t send PDF file'); - header('Content-Length: '.strlen($this->buffer)); - header('Content-disposition: attachment; filename="'.$name.'"'); - echo $this->buffer; - break; - case 'F': - //Save to local file - $f=fopen($name,'wb'); - if(!$f) - $this->Error('Unable to create output file: '.$name); - fwrite($f,$this->buffer,strlen($this->buffer)); - fclose($f); - break; - case 'S': - //Return as a string - return $this->buffer; - default: - $this->Error('Incorrect output destination: '.$dest); - } - return ''; -} - -/******************************************************************************* -* * -* Protected methods * -* * -*******************************************************************************/ -function _dochecks() -{ - //Check for locale-related bug - if(1.1==1) - $this->Error('Don\'t alter the locale before including class file'); - //Check for decimal separator - if(sprintf('%.1f',1.0)!='1.0') - setlocale(LC_NUMERIC,'C'); -} - -function _getfontpath() -{ - if(!defined('FPDF_FONTPATH') && is_dir(dirname(__FILE__).'/font')) - define('FPDF_FONTPATH',dirname(__FILE__).'/font/'); - return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : ''; -} - -function _putpages() -{ - $nb=$this->page; - if(!empty($this->AliasNbPages)) - { - //Replace number of pages - for($n=1;$n<=$nb;$n++) - $this->pages[$n]=str_replace($this->AliasNbPages,$nb,$this->pages[$n]); - } - if($this->DefOrientation=='P') - { - $wPt=$this->fwPt; - $hPt=$this->fhPt; - } - else - { - $wPt=$this->fhPt; - $hPt=$this->fwPt; - } - $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; - for($n=1;$n<=$nb;$n++) - { - //Page - $this->_newobj(); - $this->_out('<_out('/Parent 1 0 R'); - if(isset($this->OrientationChanges[$n])) - $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',$hPt,$wPt)); - $this->_out('/Resources 2 0 R'); - if(isset($this->PageLinks[$n])) - { - //Links - $annots='/Annots ['; - foreach($this->PageLinks[$n] as $pl) - { - $rect=sprintf('%.2f %.2f %.2f %.2f',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]); - $annots.='<_textstring($pl[4]).'>>>>'; - else - { - $l=$this->links[$pl[4]]; - $h=isset($this->OrientationChanges[$l[0]]) ? $wPt : $hPt; - $annots.=sprintf('/Dest [%d 0 R /XYZ 0 %.2f null]>>',1+2*$l[0],$h-$l[1]*$this->k); - } - } - $this->_out($annots.']'); - } - $this->_out('/Contents '.($this->n+1).' 0 R>>'); - $this->_out('endobj'); - //Page content - $p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n]; - $this->_newobj(); - $this->_out('<<'.$filter.'/Length '.strlen($p).'>>'); - $this->_putstream($p); - $this->_out('endobj'); - } - //Pages root - $this->offsets[1]=strlen($this->buffer); - $this->_out('1 0 obj'); - $this->_out('<_out($kids.']'); - $this->_out('/Count '.$nb); - $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',$wPt,$hPt)); - $this->_out('>>'); - $this->_out('endobj'); -} - -function _putfonts() -{ - $nf=$this->n; - foreach($this->diffs as $diff) - { - //Encodings - $this->_newobj(); - $this->_out('<>'); - $this->_out('endobj'); - } - $mqr=get_magic_quotes_runtime(); - set_magic_quotes_runtime(0); - foreach($this->FontFiles as $file=>$info) - { - //Font file embedding - $this->_newobj(); - $this->FontFiles[$file]['n']=$this->n; - $font=''; - $f=fopen($this->_getfontpath().$file,'rb',1); - if(!$f) - $this->Error('Font file not found'); - while(!feof($f)) - $font.=fread($f,8192); - fclose($f); - $compressed=(substr($file,-2)=='.z'); - if(!$compressed && isset($info['length2'])) - { - $header=(ord($font{0})==128); - if($header) - { - //Strip first binary header - $font=substr($font,6); - } - if($header && ord($font{$info['length1']})==128) - { - //Strip second binary header - $font=substr($font,0,$info['length1']).substr($font,$info['length1']+6); - } - } - $this->_out('<_out('/Filter /FlateDecode'); - $this->_out('/Length1 '.$info['length1']); - if(isset($info['length2'])) - $this->_out('/Length2 '.$info['length2'].' /Length3 0'); - $this->_out('>>'); - $this->_putstream($font); - $this->_out('endobj'); - } - set_magic_quotes_runtime($mqr); - foreach($this->fonts as $k=>$font) - { - //Font objects - $this->fonts[$k]['n']=$this->n+1; - $type=$font['type']; - $name=$font['name']; - if($type=='core') - { - //Standard font - $this->_newobj(); - $this->_out('<_out('/BaseFont /'.$name); - $this->_out('/Subtype /Type1'); - if($name!='Symbol' && $name!='ZapfDingbats') - $this->_out('/Encoding /WinAnsiEncoding'); - $this->_out('>>'); - $this->_out('endobj'); - } - elseif($type=='Type1' || $type=='TrueType') - { - //Additional Type1 or TrueType font - $this->_newobj(); - $this->_out('<_out('/BaseFont /'.$name); - $this->_out('/Subtype /'.$type); - $this->_out('/FirstChar 32 /LastChar 255'); - $this->_out('/Widths '.($this->n+1).' 0 R'); - $this->_out('/FontDescriptor '.($this->n+2).' 0 R'); - if($font['enc']) - { - if(isset($font['diff'])) - $this->_out('/Encoding '.($nf+$font['diff']).' 0 R'); - else - $this->_out('/Encoding /WinAnsiEncoding'); - } - $this->_out('>>'); - $this->_out('endobj'); - //Widths - $this->_newobj(); - $cw=&$font['cw']; - $s='['; - for($i=32;$i<=255;$i++) - $s.=$cw[chr($i)].' '; - $this->_out($s.']'); - $this->_out('endobj'); - //Descriptor - $this->_newobj(); - $s='<$v) - $s.=' /'.$k.' '.$v; - $file=$font['file']; - if($file) - $s.=' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->FontFiles[$file]['n'].' 0 R'; - $this->_out($s.'>>'); - $this->_out('endobj'); - } - else - { - //Allow for additional types - $mtd='_put'.strtolower($type); - if(!method_exists($this,$mtd)) - $this->Error('Unsupported font type: '.$type); - $this->$mtd($font); - } - } -} - -function _putimages() -{ - $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; - reset($this->images); - while(list($file,$info)=each($this->images)) - { - $this->_newobj(); - $this->images[$file]['n']=$this->n; - $this->_out('<_out('/Subtype /Image'); - $this->_out('/Width '.$info['w']); - $this->_out('/Height '.$info['h']); - if($info['cs']=='Indexed') - $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]'); - else - { - $this->_out('/ColorSpace /'.$info['cs']); - if($info['cs']=='DeviceCMYK') - $this->_out('/Decode [1 0 1 0 1 0 1 0]'); - } - $this->_out('/BitsPerComponent '.$info['bpc']); - if(isset($info['f'])) - $this->_out('/Filter /'.$info['f']); - if(isset($info['parms'])) - $this->_out($info['parms']); - if(isset($info['trns']) && is_array($info['trns'])) - { - $trns=''; - for($i=0;$i_out('/Mask ['.$trns.']'); - } - $this->_out('/Length '.strlen($info['data']).'>>'); - $this->_putstream($info['data']); - unset($this->images[$file]['data']); - $this->_out('endobj'); - //Palette - if($info['cs']=='Indexed') - { - $this->_newobj(); - $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal']; - $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>'); - $this->_putstream($pal); - $this->_out('endobj'); - } - } -} - -function _putxobjectdict() -{ - foreach($this->images as $image) - $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R'); -} - -function _putresourcedict() -{ - $this->_out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'); - $this->_out('/Font <<'); - foreach($this->fonts as $font) - $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R'); - $this->_out('>>'); - $this->_out('/XObject <<'); - $this->_putxobjectdict(); - $this->_out('>>'); -} - -function _putresources() -{ - $this->_putfonts(); - $this->_putimages(); - //Resource dictionary - $this->offsets[2]=strlen($this->buffer); - $this->_out('2 0 obj'); - $this->_out('<<'); - $this->_putresourcedict(); - $this->_out('>>'); - $this->_out('endobj'); -} - -function _putinfo() -{ - $this->_out('/Producer '.$this->_textstring('FPDF '.FPDF_VERSION)); - if(!empty($this->title)) - $this->_out('/Title '.$this->_textstring($this->title)); - if(!empty($this->subject)) - $this->_out('/Subject '.$this->_textstring($this->subject)); - if(!empty($this->author)) - $this->_out('/Author '.$this->_textstring($this->author)); - if(!empty($this->keywords)) - $this->_out('/Keywords '.$this->_textstring($this->keywords)); - if(!empty($this->creator)) - $this->_out('/Creator '.$this->_textstring($this->creator)); - $this->_out('/CreationDate '.$this->_textstring('D:'.date('YmdHis'))); -} - -function _putcatalog() -{ - $this->_out('/Type /Catalog'); - $this->_out('/Pages 1 0 R'); - if($this->ZoomMode=='fullpage') - $this->_out('/OpenAction [3 0 R /Fit]'); - elseif($this->ZoomMode=='fullwidth') - $this->_out('/OpenAction [3 0 R /FitH null]'); - elseif($this->ZoomMode=='real') - $this->_out('/OpenAction [3 0 R /XYZ null null 1]'); - elseif(!is_string($this->ZoomMode)) - $this->_out('/OpenAction [3 0 R /XYZ null null '.($this->ZoomMode/100).']'); - if($this->LayoutMode=='single') - $this->_out('/PageLayout /SinglePage'); - elseif($this->LayoutMode=='continuous') - $this->_out('/PageLayout /OneColumn'); - elseif($this->LayoutMode=='two') - $this->_out('/PageLayout /TwoColumnLeft'); -} - -function _putheader() -{ - $this->_out('%PDF-'.$this->PDFVersion); -} - -function _puttrailer() -{ - $this->_out('/Size '.($this->n+1)); - $this->_out('/Root '.$this->n.' 0 R'); - $this->_out('/Info '.($this->n-1).' 0 R'); -} - -function _enddoc() -{ - $this->_putheader(); - $this->_putpages(); - $this->_putresources(); - //Info - $this->_newobj(); - $this->_out('<<'); - $this->_putinfo(); - $this->_out('>>'); - $this->_out('endobj'); - //Catalog - $this->_newobj(); - $this->_out('<<'); - $this->_putcatalog(); - $this->_out('>>'); - $this->_out('endobj'); - //Cross-ref - $o=strlen($this->buffer); - $this->_out('xref'); - $this->_out('0 '.($this->n+1)); - $this->_out('0000000000 65535 f '); - for($i=1;$i<=$this->n;$i++) - $this->_out(sprintf('%010d 00000 n ',$this->offsets[$i])); - //Trailer - $this->_out('trailer'); - $this->_out('<<'); - $this->_puttrailer(); - $this->_out('>>'); - $this->_out('startxref'); - $this->_out($o); - $this->_out('%%EOF'); - $this->state=3; -} - -function _beginpage($orientation) -{ - $this->page++; - $this->pages[$this->page]=''; - $this->state=2; - $this->x=$this->lMargin; - $this->y=$this->tMargin; - $this->FontFamily=''; - //Page orientation - if(!$orientation) - $orientation=$this->DefOrientation; - else - { - $orientation=strtoupper($orientation{0}); - if($orientation!=$this->DefOrientation) - $this->OrientationChanges[$this->page]=true; - } - if($orientation!=$this->CurOrientation) - { - //Change orientation - if($orientation=='P') - { - $this->wPt=$this->fwPt; - $this->hPt=$this->fhPt; - $this->w=$this->fw; - $this->h=$this->fh; - } - else - { - $this->wPt=$this->fhPt; - $this->hPt=$this->fwPt; - $this->w=$this->fh; - $this->h=$this->fw; - } - $this->PageBreakTrigger=$this->h-$this->bMargin; - $this->CurOrientation=$orientation; - } -} - -function _endpage() -{ - //End of page contents - $this->state=1; -} - -function _newobj() -{ - //Begin a new object - $this->n++; - $this->offsets[$this->n]=strlen($this->buffer); - $this->_out($this->n.' 0 obj'); -} - -function _dounderline($x,$y,$txt) -{ - //Underline text - $up=$this->CurrentFont['up']; - $ut=$this->CurrentFont['ut']; - $w=$this->GetStringWidth($txt)+$this->ws*substr_count($txt,' '); - return sprintf('%.2f %.2f %.2f %.2f re f',$x*$this->k,($this->h-($y-$up/1000*$this->FontSize))*$this->k,$w*$this->k,-$ut/1000*$this->FontSizePt); -} - -function _parsejpg($file) -{ - //Extract info from a JPEG file - $a=GetImageSize($file); - if(!$a) - $this->Error('Missing or incorrect image file: '.$file); - if($a[2]!=2) - $this->Error('Not a JPEG file: '.$file); - if(!isset($a['channels']) || $a['channels']==3) - $colspace='DeviceRGB'; - elseif($a['channels']==4) - $colspace='DeviceCMYK'; - else - $colspace='DeviceGray'; - $bpc=isset($a['bits']) ? $a['bits'] : 8; - //Read whole file - $f=fopen($file,'rb'); - $data=''; - while(!feof($f)) - $data.=fread($f,4096); - fclose($f); - return array('w'=>$a[0],'h'=>$a[1],'cs'=>$colspace,'bpc'=>$bpc,'f'=>'DCTDecode','data'=>$data); -} - -function _parsepng($file) -{ - //Extract info from a PNG file - $f=fopen($file,'rb'); - if(!$f) - $this->Error('Can\'t open image file: '.$file); - //Check signature - if(fread($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) - $this->Error('Not a PNG file: '.$file); - //Read header chunk - fread($f,4); - if(fread($f,4)!='IHDR') - $this->Error('Incorrect PNG file: '.$file); - $w=$this->_freadint($f); - $h=$this->_freadint($f); - $bpc=ord(fread($f,1)); - if($bpc>8) - $this->Error('16-bit depth not supported: '.$file); - $ct=ord(fread($f,1)); - if($ct==0) - $colspace='DeviceGray'; - elseif($ct==2) - $colspace='DeviceRGB'; - elseif($ct==3) - $colspace='Indexed'; - else - $this->Error('Alpha channel not supported: '.$file); - if(ord(fread($f,1))!=0) - $this->Error('Unknown compression method: '.$file); - if(ord(fread($f,1))!=0) - $this->Error('Unknown filter method: '.$file); - if(ord(fread($f,1))!=0) - $this->Error('Interlacing not supported: '.$file); - fread($f,4); - $parms='/DecodeParms <>'; - //Scan chunks looking for palette, transparency and image data - $pal=''; - $trns=''; - $data=''; - do - { - $n=$this->_freadint($f); - $type=fread($f,4); - if($type=='PLTE') - { - //Read palette - $pal=fread($f,$n); - fread($f,4); - } - elseif($type=='tRNS') - { - //Read transparency info - $t=fread($f,$n); - if($ct==0) - $trns=array(ord(substr($t,1,1))); - elseif($ct==2) - $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1))); - else - { - $pos=strpos($t,chr(0)); - if($pos!==false) - $trns=array($pos); - } - fread($f,4); - } - elseif($type=='IDAT') - { - //Read image data block - $data.=fread($f,$n); - fread($f,4); - } - elseif($type=='IEND') - break; - else - fread($f,$n+4); - } - while($n); - if($colspace=='Indexed' && empty($pal)) - $this->Error('Missing palette in '.$file); - fclose($f); - return array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$data); -} - -function _freadint($f) -{ - //Read a 4-byte integer from file - $a=unpack('Ni',fread($f,4)); - return $a['i']; -} - -function _textstring($s) -{ - //Format a text string - return '('.$this->_escape($s).')'; -} - -function _escape($s) -{ - //Add \ before \, ( and ) - return str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$s))); -} - -function _putstream($s) -{ - $this->_out('stream'); - $this->_out($s); - $this->_out('endstream'); -} - -function _out($s) -{ - //Add a line to the document - if($this->state==2) - $this->pages[$this->page].=$s."\n"; - else - $this->buffer.=$s."\n"; -} -//End of class -} - -//Handle special IE contype request -if(isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT']=='contype') -{ - header('Content-Type: application/pdf'); - exit; -} - -} -?> diff --git a/mods/pdf_converter/index.php b/mods/pdf_converter/index.php deleted file mode 100644 index 111bd831f..000000000 --- a/mods/pdf_converter/index.php +++ /dev/null @@ -1,12 +0,0 @@ - - -
    - Hello Student!! :) -
    - - \ No newline at end of file diff --git a/mods/pdf_converter/module.php b/mods/pdf_converter/module.php deleted file mode 100644 index 9c0dd36b5..000000000 --- a/mods/pdf_converter/module.php +++ /dev/null @@ -1,26 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_PDF_CONVERTER', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -$this->_stacks['pdf_converter'] = array('title_var'=>'pdf_converter', 'file'=>'mods/pdf_converter/side_menu.inc.php'); - -$this->_pages['mods/pdf_converter/index.php']['img'] = 'mods/pdf_converter/pdf_icon.jpg'; - - -?> \ No newline at end of file diff --git a/mods/pdf_converter/module.sql b/mods/pdf_converter/module.sql deleted file mode 100644 index 6f535390c..000000000 --- a/mods/pdf_converter/module.sql +++ /dev/null @@ -1,4 +0,0 @@ -# sql file for hello world module - -INSERT INTO `language_text` VALUES ('en', '_module','pdf_converter','PDF Converter',NOW(),''); -INSERT INTO `language_text` VALUES ('es-es', '_module','pdf_converter','Convertidor a PDF',NOW(),''); diff --git a/mods/pdf_converter/module.xml b/mods/pdf_converter/module.xml deleted file mode 100644 index 374006a48..000000000 --- a/mods/pdf_converter/module.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - PDF Converter - This is a module that can be used to convert content files from content navigation to pdf format files - - - arbolsistemas - info@arbolsistemas.com.ar - - - http://arbolsistemas.com.ar - GNU - - 0.2 - 2010-10-25 - beta - Convert course content to a pdf document. This module creates a side menu block with a link that when clicked generates the page being viewd as a PDF file. -Note: After installing, make for file muestra_pdf.txt writable, if it is not already. This is an extra module - - \ No newline at end of file diff --git a/mods/pdf_converter/module_install.php b/mods/pdf_converter/module_install.php deleted file mode 100644 index 9a828118f..000000000 --- a/mods/pdf_converter/module_install.php +++ /dev/null @@ -1,67 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/pdf_converter/module_uninstall.php b/mods/pdf_converter/module_uninstall.php deleted file mode 100644 index 52d8f8129..000000000 --- a/mods/pdf_converter/module_uninstall.php +++ /dev/null @@ -1,31 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/pdf_converter/muestra_pdf.txt b/mods/pdf_converter/muestra_pdf.txt deleted file mode 100644 index 2e73700bb..000000000 --- a/mods/pdf_converter/muestra_pdf.txt +++ /dev/null @@ -1,3 +0,0 @@ -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. - -We are testing pdf converter \ No newline at end of file diff --git a/mods/pdf_converter/pdf.php b/mods/pdf_converter/pdf.php deleted file mode 100644 index 1ab380833..000000000 --- a/mods/pdf_converter/pdf.php +++ /dev/null @@ -1,212 +0,0 @@ -gid; - $now = _CURRENT_SERVER_TIME; - $nullDate = $database->getNullDate(); - - // query to check for state and access levels - $query = "SELECT a.*, cc.name AS category, s.name AS section, s.published AS sec_pub, cc.published AS cat_pub," - . "\n s.access AS sec_access, cc.access AS cat_access, s.id AS sec_id, cc.id as cat_id" - . "\n FROM #__content AS a" - . "\n LEFT JOIN #__categories AS cc ON cc.id = a.catid" - . "\n LEFT JOIN #__sections AS s ON s.id = cc.section AND s.scope = 'content'" - . "\n WHERE a.id = $id" - . "\n AND a.state = 1" - . "\n AND a.access <= $gid" - . "\n AND ( a.publish_up = '$nullDate' OR a.publish_up <= '$now' )" - . "\n AND ( a.publish_down = '$nullDate' OR a.publish_down >= '$now' )" - ; - $database->setQuery( $query ); - $row = NULL; - - if ( $database->loadObject( $row ) ) { - /* - * check whether category is published - */ - if ( !$row->cat_pub && $row->catid ) { - mosNotAuth(); - return; - } - /* - * check whether section is published - */ - if ( !$row->sec_pub && $row->sectionid ) { - mosNotAuth(); - return; - } - /* - * check whether category access level allows access - */ - if ( ($row->cat_access > $gid) && $row->catid ) { - mosNotAuth(); - return; - } - /* - * check whether section access level allows access - */ - if ( ($row->sec_access > $gid) && $row->sectionid ) { - mosNotAuth(); - return; - } - - include( 'includes/class.ezpdf.php' ); - - $params = new mosParameters( $row->attribs ); - $params->def( 'author', !$mainframe->getCfg( 'hideAuthor' ) ); - $params->def( 'createdate', !$mainframe->getCfg( 'hideCreateDate' ) ); - $params->def( 'modifydate', !$mainframe->getCfg( 'hideModifyDate' ) ); - - $row->fulltext = pdfCleaner( $row->fulltext ); - $row->introtext = pdfCleaner( $row->introtext ); - - $pdf = new Cezpdf( 'a4', 'P' ); //A4 Portrait - $pdf -> ezSetCmMargins( 2, 1.5, 1, 1); - $pdf->selectFont( './fonts/Helvetica.afm' ); //choose font - - $all = $pdf->openObject(); - $pdf->saveState(); - $pdf->setStrokeColor( 0, 0, 0, 1 ); - - // footer - $pdf->addText( 250, 822, 6, $mosConfig_sitename ); - $pdf->line( 10, 40, 578, 40 ); - $pdf->line( 10, 818, 578, 818 ); - $pdf->addText( 30, 34, 6, $mosConfig_live_site ); - $pdf->addText( 250, 34, 6, _PDF_POWERED ); - $pdf->addText( 450, 34, 6, _PDF_GENERATED .' '. date( 'j F, Y, H:i', time() + $mosConfig_offset * 60 * 60 ) ); - - $pdf->restoreState(); - $pdf->closeObject(); - $pdf->addObject( $all, 'all' ); - $pdf->ezSetDy( 30 ); - - $txt1 = $row->title; - $pdf->ezText( $txt1, 14 ); - - $txt2 = AuthorDateLine( $row, $params ); - - $pdf->ezText( $txt2, 8 ); - - $txt3 = $row->introtext ."\n". $row->fulltext; - $pdf->ezText( $txt3, 10 ); - - $pdf->ezStream(); - } else { - mosNotAuth(); - return; - } -} - -function decodeHTML( $string ) { - $string = strtr( $string, array_flip(get_html_translation_table( HTML_ENTITIES ) ) ); - $string = preg_replace( "/&#([0-9]+);/me", "chr('\\1')", $string ); - - return $string; -} - -function get_php_setting ($val ) { - $r = ( ini_get( $val ) == '1' ? 1 : 0 ); - - return $r ? 'ON' : 'OFF'; -} - -function pdfCleaner( $text ) { - // Ugly but needed to get rid of all the stuff the PDF class cant handle - - $text = str_replace( '

    ', "\n\n", $text ); - $text = str_replace( '

    ', "\n\n", $text ); - $text = str_replace( '
    ', "\n", $text ); - $text = str_replace( '
    ', "\n", $text ); - $text = str_replace( '
    ', "\n", $text ); - $text = str_replace( '
    ', "\n", $text ); - $text = str_replace( '

  • ', "\n - ", $text ); - $text = str_replace( '
  • ', "\n - ", $text ); - $text = str_replace( '{mosimage}', '', $text ); - $text = str_replace( '{mospagebreak}', '', $text ); - - $text = strip_tags( $text ); - $text = decodeHTML( $text ); - - return $text; -} - -function AuthorDateLine( &$row, &$params ) { - global $database; - - $text = ''; - - if ( $params->get( 'author' ) ) { - // Display Author name - - //Find Author Name - $users_rows = new mosUser( $database ); - $users_rows->load( $row->created_by ); - $row->author = $users_rows->name; - $row->usertype = $users_rows->usertype; - - if ($row->usertype == 'administrator' || $row->usertype == 'superadministrator') { - $text .= "\n"; - $text .= _WRITTEN_BY .' '. ( $row->created_by_alias ? $row->created_by_alias : $row->author ); - } else { - $text .= "\n"; - $text .= _AUTHOR_BY .' '. ( $row->created_by_alias ? $row->created_by_alias : $row->author ); - } - } - - if ( $params->get( 'createdate' ) && $params->get( 'author' ) ) { - // Display Separator - $text .= "\n"; - } - - if ( $params->get( 'createdate' ) ) { - // Display Created Date - if ( intval( $row->created ) ) { - $create_date = mosFormatDate( $row->created ); - $text .= $create_date; - } - } - - if ( $params->get( 'modifydate' ) && ( $params->get( 'author' ) || $params->get( 'createdate' ) ) ) { - // Display Separator - $text .= "\n"; - } - - if ( $params->get( 'modifydate' ) ) { - // Display Modified Date - if ( intval( $row->modified ) ) { - $mod_date = mosFormatDate( $row->modified ); - $text .= _LAST_UPDATED .' '. $mod_date; - - } - } - - $text .= "\n\n"; - - return $text; -} - -dofreePDF(); -?> \ No newline at end of file diff --git a/mods/pdf_converter/pdf_converter.php b/mods/pdf_converter/pdf_converter.php deleted file mode 100644 index 9c9ab7d4a..000000000 --- a/mods/pdf_converter/pdf_converter.php +++ /dev/null @@ -1,127 +0,0 @@ -attribs ); - //$params->def( 'author', !$mainframe->getCfg( 'hideAuthor' ) ); - //$params->def( 'createdate', !$mainframe->getCfg( 'hideCreateDate' ) ); - //$params->def( 'modifydate', !$mainframe->getCfg( 'hideModifyDate' ) ); - - $titulo = strip_tags(pdfCleaner( $titulo )); - $contenido = trim(strip_tags(pdfCleaner( $contenido ))); - - - $pdf = new Cezpdf( 'a4', 'P' ); //A4 Portrait - $pdf -> ezSetCmMargins( 2, 1.5, 1, 1); - $pdf->selectFont( './fonts/Helvetica.afm' ); //choose font - - $all = $pdf->openObject(); - $pdf->saveState(); - $pdf->setStrokeColor( 0, 0, 0, 1 ); - - // footer - //$pdf->addText( 250, 822, 6, $mosConfig_sitename ); - $pdf->line( 10, 40, 578, 40 ); - $pdf->line( 10, 818, 578, 818 ); - //$pdf->addText( 30, 34, 6, $mosConfig_live_site ); - //$pdf->addText( 250, 34, 6, _PDF_POWERED ); - //$pdf->addText( 450, 34, 6, _PDF_GENERATED .' '. date( 'j F, Y, H:i', time() + $mosConfig_offset * 60 * 60 ) ); - - $pdf->restoreState(); - $pdf->closeObject(); - $pdf->addObject( $all, 'all' ); - $pdf->ezSetDy( 30 ); - - $txt1 = $titulo; - $pdf->ezText( $txt1, 14 ); - - //$txt2 = AuthorDateLine( $row, $params ); - $txt2 = $contenido; - - $pdf->ezText( $txt2, 8 ); - - //$txt3 = $row->introtext ."\n". $row->fulltext; - //$pdf->ezText( $txt3, 10 ); - - $pdf->ezStream(); - - //FIN JOOMLA -*/ - $titulo = strip_tags(pdfCleaner( $titulo )); - $contenido = trim(strip_tags(pdfCleaner( $contenido ))); - //$contenido = str_word_count($contenido,1); - //$contenido = implode(" ",$contenido); - - //Leemos el fichero - $muestra_pdf = 'muestra_pdf.txt'; - $f=fopen($muestra_pdf,'w'); - fwrite($f,$contenido); - fclose($f); - $f=fopen($muestra_pdf,'r+'); - $pdf=new FPDF(); - $pdf->AddPage(); - $pdf->SetFont('Arial','',10); - fclose($f); - //$pdf->Cell(0,5,$titulo); - //$pdf->Ln(10); - $pdf->MultiCell(0,3,$contenido); - $pdf->Output(); - } - else{ - echo(_AT('error')); - - } -} - -function decodeHTML( $string ) { - $string = strtr( $string, array_flip(get_html_translation_table( HTML_ENTITIES ) ) ); - $string = preg_replace( "/&#([0-9]+);/me", "chr('\\1')", $string ); - - return $string; -} - - -function pdfCleaner( $text ) { - // Ugly but needed to get rid of all the stuff the PDF class cant handle - - $text = str_replace( '

    ', "\n\n", $text ); - $text = str_replace( '

    ', "\n\n", $text ); - $text = str_replace( '
    ', "\n", $text ); - $text = str_replace( '
    ', "\n", $text ); - $text = str_replace( '
    ', "\n", $text ); - $text = str_replace( '
    ', "\n", $text ); - $text = str_replace( '

  • ', "\n - ", $text ); - $text = str_replace( '
  • ', "\n - ", $text ); - $text = str_replace( '{mosimage}', '', $text ); - $text = str_replace( '{mospagebreak}', '', $text ); - $text = str_replace( '','',$text ); - $text = str_replace( '
    ','',$text ); - $text = str_replace( '
    ','',$text ); - $text = str_replace( '','',$text ); - $text = str_replace( '','',$text ); - $text = str_replace( '','',$text ); - $text = str_replace( '','',$text ); - $text = str_replace( '','',$text ); - $text = str_replace( ' ','',$text ); - - - - $text = strip_tags( $text ); - $text = decodeHTML( $text ); - - return $text; -} -?> \ No newline at end of file diff --git a/mods/pdf_converter/pdf_icon.jpg b/mods/pdf_converter/pdf_icon.jpg deleted file mode 100644 index c005ed142289bb3595e09e56288a42d7f23ff57c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1095 zcmex=^lOiET&UP@Y7ModgWM?qOlT~kX_QeM|USHnP6LsJ7}2qQZ?I~NC+Fc+7w zhLo6;2Fc+60R}-11|tR|W=16jCP7AKLB{__7-Se2n3x%u85s}&=vsD0CT0$xtc?Hz zBQrA-6B{cBH$(wYf`x%qkWEO@kX_iwF|bfXDY0>~sJKc<(Z)>&l}(&nLz5;>nzHaB zP`4y75SW1&2>^AovH_)31Q{4vm>8K^;j)ZCcL=g53b8r{3L6$K+<5W-Ee0N-yO;!- z1sUuae)Yxd_%Ku7r*@eXyY$@%ui|H!UcUdB?na7NEJ%4QB>ecfx2^rX@U-^SQk92( zI}G36viSR-;o1bLmuk{sKXi87kN9-kBmBk1ty-`BLc(vIyVz5-=KP$kPxp!EOD{Ex zDf7wsq!REp{7=-S_Xhp%r`ezM|GUEfbXwG|9orL@`={!jJZa}3b>82ja8~WnGhdPx zEWdI+Xxd5Mw_lB{Rhm!R{aVnu_Il}+f+(ly8(;RcymJbw&V1+3_-@5+g>7qN#oba4 z9$oSx_C^2EFMQK>dSz)z@7%Fmz|$)(@Fa^&!u)fyUP?Jnj_O#Z+{Rt0e%(>Mf8Vkf zt508=Q+40aqH^L+_M>*9Yb&4JbQK8{dbjOT!PXqM#ePAzb=I%RJyPs>Oxq@Z;SVk@ zdyNwh7Flz?QwcjA`cZg__S@ATr8<-SPJ|n)MI0BiX#BM4{LB;bM^fsOvRAzLb$D5t z%Z|HxemTyESMxClg`Y`hzB#`%`=IFDlFO2Qw{mxfO#HH7p1O>eZ@2f|e6>$lzF-_E#Kezr!)}bl)_D3%`S=kvZnR#Vxq}LTj8DBv|d({wEG-a6;J|RYq_7t#gWG?}g^Bf9|yZw(`;TvW|x7P1i&o z9BN>n8Dp0Ayf2WrJ0@jomE9fN8T=$cHF%|K^zwy8e$content_row[title]"); - //echo ($content_row['title']); -} - -$savant->assign('dropdown_contents', ob_get_contents()); -ob_end_clean(); - -$savant->assign('title', _AT('pdf_converter')); // the box title -$savant->display('include/box.tmpl.php'); -?> \ No newline at end of file diff --git a/mods/photo_album/HTML/Template/IT.php b/mods/photo_album/HTML/Template/IT.php deleted file mode 100644 index d715f46dc..000000000 --- a/mods/photo_album/HTML/Template/IT.php +++ /dev/null @@ -1,990 +0,0 @@ - | -// | Pierre-Alain Joye | -// +----------------------------------------------------------------------+ -// -// $Id: IT.php,v 1.14 2005/11/01 10:14:19 pajoye Exp $ -// - -require_once 'PEAR.php'; - -define('IT_OK', 1); -define('IT_ERROR', -1); -define('IT_TPL_NOT_FOUND', -2); -define('IT_BLOCK_NOT_FOUND', -3); -define('IT_BLOCK_DUPLICATE', -4); -define('IT_UNKNOWN_OPTION', -6); -/** - * Integrated Template - IT - * - * Well there's not much to say about it. I needed a template class that - * supports a single template file with multiple (nested) blocks inside and - * a simple block API. - * - * The Isotemplate API is somewhat tricky for a beginner although it is the best - * one you can build. template::parse() [phplib template = Isotemplate] requests - * you to name a source and a target where the current block gets parsed into. - * Source and target can be block names or even handler names. This API gives you - * a maximum of fexibility but you always have to know what you do which is - * quite unusual for php skripter like me. - * - * I noticed that I do not any control on which block gets parsed into which one. - * If all blocks are within one file, the script knows how they are nested and in - * which way you have to parse them. IT knows that inner1 is a child of block2, there's - * no need to tell him about this. - * - * - * - * - * - * - * - * - * - *
    - * __global__ - *

    - * (hidden and automatically added) - *

    block1 - * - * - * - * - * - * - * - * - *
    block2
    inner1inner2
    - *
    - * - * To add content to block1 you simply type: - * $tpl->setCurrentBlock("block1"); - * and repeat this as often as needed: - * - * $tpl->setVariable(...); - * $tpl->parseCurrentBlock(); - * - * - * To add content to block2 you would type something like: - * - * $tpl->setCurrentBlock("inner1"); - * $tpl->setVariable(...); - * $tpl->parseCurrentBlock(); - * - * $tpl->setVariable(...); - * $tpl->parseCurrentBlock(); - * - * $tpl->parse("block1"); - * - * - * This will result in one repition of block1 which contains two repitions - * of inner1. inner2 will be removed if $removeEmptyBlock is set to true which is the default. - * - * Usage: - * - * $tpl = new HTML_Template_IT( [string filerootdir] ); - * - * // load a template or set it with setTemplate() - * $tpl->loadTemplatefile( string filename [, boolean removeUnknownVariables, boolean removeEmptyBlocks] ) - * - * // set "global" Variables meaning variables not beeing within a (inner) block - * $tpl->setVariable( string variablename, mixed value ); - * - * // like with the Isotemplates there's a second way to use setVariable() - * $tpl->setVariable( array ( string varname => mixed value ) ); - * - * // Let's use any block, even a deeply nested one - * $tpl->setCurrentBlock( string blockname ); - * - * // repeat this as often as you need it. - * $tpl->setVariable( array ( string varname => mixed value ) ); - * $tpl->parseCurrentBlock(); - * - * // get the parsed template or print it: $tpl->show() - * $tpl->get(); - * - * - * @author Ulf Wendel - * @version $Id: IT.php,v 1.14 2005/11/01 10:14:19 pajoye Exp $ - * @access public - * @package HTML_Template_IT - */ -class HTML_Template_IT -{ - /** - * Contains the error objects - * @var array - * @access public - * @see halt(), $printError, $haltOnError - */ - var $err = array(); - - /** - * Clear cache on get()? - * @var boolean - */ - var $clearCache = false; - - /** - * First character of a variable placeholder ( _{_VARIABLE} ). - * @var string - * @access public - * @see $closingDelimiter, $blocknameRegExp, $variablenameRegExp - */ - var $openingDelimiter = '{'; - - /** - * Last character of a variable placeholder ( {VARIABLE_}_ ). - * @var string - * @access public - * @see $openingDelimiter, $blocknameRegExp, $variablenameRegExp - */ - var $closingDelimiter = '}'; - - /** - * RegExp matching a block in the template. - * Per default "sm" is used as the regexp modifier, "i" is missing. - * That means a case sensitive search is done. - * @var string - * @access public - * @see $variablenameRegExp, $openingDelimiter, $closingDelimiter - */ - var $blocknameRegExp = '[0-9A-Za-z_-]+'; - - /** - * RegExp matching a variable placeholder in the template. - * Per default "sm" is used as the regexp modifier, "i" is missing. - * That means a case sensitive search is done. - * @var string - * @access public - * @see $blocknameRegExp, $openingDelimiter, $closingDelimiter - */ - var $variablenameRegExp = '[0-9A-Za-z_-]+'; - - /** - * RegExp used to find variable placeholder, filled by the constructor. - * @var string Looks somewhat like @(delimiter varname delimiter)@ - * @access public - * @see IntegratedTemplate() - */ - var $variablesRegExp = ''; - - /** - * RegExp used to strip unused variable placeholder. - * @brother $variablesRegExp - */ - var $removeVariablesRegExp = ''; - - /** - * Controls the handling of unknown variables, default is remove. - * @var boolean - * @access public - */ - var $removeUnknownVariables = true; - - /** - * Controls the handling of empty blocks, default is remove. - * @var boolean - * @access public - */ - var $removeEmptyBlocks = true; - - /** - * RegExp used to find blocks an their content, filled by the constructor. - * @var string - * @see IntegratedTemplate() - */ - var $blockRegExp = ''; - - /** - * Name of the current block. - * @var string - */ - var $currentBlock = '__global__'; - - /** - * Content of the template. - * @var string - */ - var $template = ''; - - /** - * Array of all blocks and their content. - * - * @var array - * @see findBlocks() - */ - var $blocklist = array(); - - /** - * Array with the parsed content of a block. - * - * @var array - */ - var $blockdata = array(); - - /** - * Array of variables in a block. - * @var array - */ - var $blockvariables = array(); - - /** - * Array of inner blocks of a block. - * @var array - */ - var $blockinner = array(); - - /** - * List of blocks to preverse even if they are "empty". - * - * This is something special. Sometimes you have blocks that - * should be preserved although they are empty (no placeholder replaced). - * Think of a shopping basket. If it's empty you have to drop a message to - * the user. If it's filled you have to show the contents of - * the shopping baseket. Now where do you place the message that the basket - * is empty? It's no good idea to place it in you applications as customers - * tend to like unecessary minor text changes. Having another template file - * for an empty basket means that it's very likely that one fine day - * the filled and empty basket templates have different layout. I decided - * to introduce blocks that to not contain any placeholder but only - * text such as the message "Your shopping basked is empty". - * - * Now if there is no replacement done in such a block the block will - * be recognized as "empty" and by default ($removeEmptyBlocks = true) be - * stripped off. To avoid thisyou can now call touchBlock() to avoid this. - * - * The array $touchedBlocks stores a list of touched block which must not - * be removed even if they are empty. - * - * @var array $touchedBlocks - * @see touchBlock(), $removeEmptyBlocks - */ - var $touchedBlocks = array(); - - /** - * List of blocks which should not be shown even if not "empty" - * @var array $_hiddenBlocks - * @see hideBlock(), $removeEmptyBlocks - */ - var $_hiddenBlocks = array(); - - /** - * Variable cache. - * - * Variables get cached before any replacement is done. - * Advantage: empty blocks can be removed automatically. - * Disadvantage: might take some more memory - * - * @var array - * @see setVariable(), $clearCacheOnParse - */ - var $variableCache = array(); - - /** - * Clear the variable cache on parse? - * - * If you're not an expert just leave the default false. - * True reduces memory consumption somewhat if you tend to - * add lots of values for unknown placeholder. - * - * @var boolean - */ - var $clearCacheOnParse = false; - - /** - * Root directory for all file operations. - * The string gets prefixed to all filenames given. - * @var string - * @see HTML_Template_IT(), setRoot() - */ - var $fileRoot = ''; - - /** - * Internal flag indicating that a blockname was used multiple times. - * @var boolean - */ - var $flagBlocktrouble = false; - - /** - * Flag indicating that the global block was parsed. - * @var boolean - */ - var $flagGlobalParsed = false; - - /** - * EXPERIMENTAL! FIXME! - * Flag indication that a template gets cached. - * - * Complex templates require some times to be preparsed - * before the replacement can take place. Often I use - * one template file over and over again but I don't know - * before that I will use the same template file again. - * Now IT could notice this and skip the preparse. - * - * @var boolean - */ - var $flagCacheTemplatefile = true; - - /** - * EXPERIMENTAL! FIXME! - */ - var $lastTemplatefile = ''; - - /** - * $_options['preserve_data'] Whether to substitute variables and remove - * empty placeholders in data passed through setVariable - * (see also bugs #20199, #21951). - * $_options['use_preg'] Whether to use preg_replace instead of - * str_replace in parse() - * (this is a backwards compatibility feature, see also bugs #21951, #20392) - */ - var $_options = array( - 'preserve_data' => false, - 'use_preg' => true - ); - - /** - * Builds some complex regular expressions and optinally sets the - * file root directory. - * - * Make sure that you call this constructor if you derive your template - * class from this one. - * - * @param string File root directory, prefix for all filenames - * given to the object. - * @see setRoot() - */ - function HTML_Template_IT($root = '', $options = null) - { - if (!is_null($options)) { - $this->setOptions($options); - } - $this->variablesRegExp = '@' . $this->openingDelimiter . - '(' . $this->variablenameRegExp . ')' . - $this->closingDelimiter . '@sm'; - $this->removeVariablesRegExp = '@' . $this->openingDelimiter . - "\s*(" . $this->variablenameRegExp . - ")\s*" . $this->closingDelimiter .'@sm'; - - $this->blockRegExp = '@(.*)@sm'; - - $this->setRoot($root); - } // end constructor - - - /** - * Sets the option for the template class - * - * @access public - * @param string option name - * @param mixed option value - * @return mixed IT_OK on success, error object on failure - */ - function setOption($option, $value) - { - if (array_key_exists($option, $this->_options)) { - $this->_options[$option] = $value; - return IT_OK; - } - - return PEAR::raiseError( - $this->errorMessage(IT_UNKNOWN_OPTION) . ": '{$option}'", - IT_UNKNOWN_OPTION - ); - } - - /** - * Sets the options for the template class - * - * @access public - * @param string options array of options - * default value: - * 'preserve_data' => false, - * 'use_preg' => true - * @param mixed option value - * @return mixed IT_OK on success, error object on failure - * @see $options - */ - function setOptions($options) - { - if (is_array($options)) { - foreach ($options as $option => $value) { - $error = $this->setOption($option, $value); - if (PEAR::isError($error)) { - return $error; - } - } - } - - return IT_OK; - } - - /** - * Print a certain block with all replacements done. - * @brother get() - */ - function show($block = '__global__') - { - print $this->get($block); - } // end func show - - /** - * Returns a block with all replacements done. - * - * @param string name of the block - * @return string - * @throws PEAR_Error - * @access public - * @see show() - */ - function get($block = '__global__') - { - if ($block == '__global__' && !$this->flagGlobalParsed) { - $this->parse('__global__'); - } - - if (!isset($this->blocklist[$block])) { - $this->err[] = PEAR::raiseError( - $this->errorMessage(IT_BLOCK_NOT_FOUND) . - '"' . $block . "'", - IT_BLOCK_NOT_FOUND - ); - return ''; - } - - if (isset($this->blockdata[$block])) { - $ret = $this->blockdata[$block]; - if ($this->clearCache) { - unset($this->blockdata[$block]); - } - if ($this->_options['preserve_data']) { - $ret = str_replace( - $this->openingDelimiter . - '%preserved%' . $this->closingDelimiter, - $this->openingDelimiter, - $ret - ); - } - return $ret; - } - - return ''; - } // end func get() - - /** - * Parses the given block. - * - * @param string name of the block to be parsed - * @access public - * @see parseCurrentBlock() - * @throws PEAR_Error - */ - function parse($block = '__global__', $flag_recursion = false) - { - static $regs, $values; - - if (!isset($this->blocklist[$block])) { - return PEAR::raiseError( - $this->errorMessage( IT_BLOCK_NOT_FOUND ) . '"' . $block . "'", - IT_BLOCK_NOT_FOUND - ); - } - - if ($block == '__global__') { - $this->flagGlobalParsed = true; - } - - if (!$flag_recursion) { - $regs = array(); - $values = array(); - } - $outer = $this->blocklist[$block]; - $empty = true; - - if ($this->clearCacheOnParse) { - foreach ($this->variableCache as $name => $value) { - $regs[] = $this->openingDelimiter . - $name . $this->closingDelimiter; - $values[] = $value; - $empty = false; - } - $this->variableCache = array(); - } else { - foreach ($this->blockvariables[$block] as $allowedvar => $v) { - - if (isset($this->variableCache[$allowedvar])) { - $regs[] = $this->openingDelimiter . - $allowedvar . $this->closingDelimiter; - $values[] = $this->variableCache[$allowedvar]; - unset($this->variableCache[$allowedvar]); - $empty = false; - } - } - } - - if (isset($this->blockinner[$block])) { - foreach ($this->blockinner[$block] as $k => $innerblock) { - - $this->parse($innerblock, true); - if ($this->blockdata[$innerblock] != '') { - $empty = false; - } - - $placeholder = $this->openingDelimiter . "__" . - $innerblock . "__" . $this->closingDelimiter; - $outer = str_replace( - $placeholder, - $this->blockdata[$innerblock], $outer - ); - $this->blockdata[$innerblock] = ""; - } - - } - - if (!$flag_recursion && 0 != count($values)) { - if ($this->_options['use_preg']) { - $regs = array_map(array( - &$this, '_addPregDelimiters'), - $regs - ); - $funcReplace = 'preg_replace'; - } else { - $funcReplace = 'str_replace'; - } - - if ($this->_options['preserve_data']) { - $values = array_map( - array(&$this, '_preserveOpeningDelimiter'), $values - ); - } - - $outer = $funcReplace($regs, $values, $outer); - - if ($this->removeUnknownVariables) { - $outer = preg_replace($this->removeVariablesRegExp, "", $outer); - } - } - - if ($empty) { - if (!$this->removeEmptyBlocks) { - $this->blockdata[$block ].= $outer; - } else { - if (isset($this->touchedBlocks[$block])) { - $this->blockdata[$block] .= $outer; - unset($this->touchedBlocks[$block]); - } - } - } else { - $this->blockdata[$block] .= $outer; - } - - return $empty; - } // end func parse - - /** - * Parses the current block - * @see parse(), setCurrentBlock(), $currentBlock - * @access public - */ - function parseCurrentBlock() - { - return $this->parse($this->currentBlock); - } // end func parseCurrentBlock - - /** - * Sets a variable value. - * - * The function can be used eighter like setVariable( "varname", "value") - * or with one array $variables["varname"] = "value" - * given setVariable($variables) quite like phplib templates set_var(). - * - * @param mixed string with the variable name or an array - * %variables["varname"] = "value" - * @param string value of the variable or empty if $variable - * is an array. - * @param string prefix for variable names - * @access public - */ - function setVariable($variable, $value = '') - { - if (is_array($variable)) { - $this->variableCache = array_merge( - $this->variableCache, $variable - ); - } else { - $this->variableCache[$variable] = $value; - } - } // end func setVariable - - /** - * Sets the name of the current block that is the block where variables - * are added. - * - * @param string name of the block - * @return boolean false on failure, otherwise true - * @throws PEAR_Error - * @access public - */ - function setCurrentBlock($block = '__global__') - { - - if (!isset($this->blocklist[$block])) { - return PEAR::raiseError( - $this->errorMessage( IT_BLOCK_NOT_FOUND ) . - '"' . $block . "'", IT_BLOCK_NOT_FOUND - ); - } - - $this->currentBlock = $block; - - return true; - } // end func setCurrentBlock - - /** - * Preserves an empty block even if removeEmptyBlocks is true. - * - * @param string name of the block - * @return boolean false on false, otherwise true - * @throws PEAR_Error - * @access public - * @see $removeEmptyBlocks - */ - function touchBlock($block) - { - if (!isset($this->blocklist[$block])) { - return PEAR::raiseError( - $this->errorMessage(IT_BLOCK_NOT_FOUND) . - '"' . $block . "'", IT_BLOCK_NOT_FOUND); - } - - $this->touchedBlocks[$block] = true; - - return true; - } // end func touchBlock - - /** - * Clears all datafields of the object and rebuild the internal blocklist - * - * LoadTemplatefile() and setTemplate() automatically call this function - * when a new template is given. Don't use this function - * unless you know what you're doing. - * - * @access public - * @see free() - */ - function init() - { - $this->free(); - $this->findBlocks($this->template); - // we don't need it any more - $this->template = ''; - $this->buildBlockvariablelist(); - } // end func init - - /** - * Clears all datafields of the object. - * - * Don't use this function unless you know what you're doing. - * - * @access public - * @see init() - */ - function free() - { - $this->err = array(); - - $this->currentBlock = '__global__'; - - $this->variableCache = array(); - $this->blocklookup = array(); - $this->touchedBlocks = array(); - - $this->flagBlocktrouble = false; - $this->flagGlobalParsed = false; - } // end func free - - /** - * Sets the template. - * - * You can eighter load a template file from disk with - * LoadTemplatefile() or set the template manually using this function. - * - * @param string template content - * @param boolean remove unknown/unused variables? - * @param boolean remove empty blocks? - * @see LoadTemplatefile(), $template - * @access public - */ - function setTemplate( $template, $removeUnknownVariables = true, - $removeEmptyBlocks = true) - { - $this->removeUnknownVariables = $removeUnknownVariables; - $this->removeEmptyBlocks = $removeEmptyBlocks; - - if ($template == '' && $this->flagCacheTemplatefile) { - $this->variableCache = array(); - $this->blockdata = array(); - $this->touchedBlocks = array(); - $this->currentBlock = '__global__'; - } else { - $this->template = '' . $template . - ''; - $this->init(); - } - - if ($this->flagBlocktrouble) { - return false; - } - - return true; - } // end func setTemplate - - /** - * Reads a template file from the disk. - * - * @param string name of the template file - * @param bool how to handle unknown variables. - * @param bool how to handle empty blocks. - * @access public - * @return boolean false on failure, otherwise true - * @see $template, setTemplate(), $removeUnknownVariables, - * $removeEmptyBlocks - */ - function loadTemplatefile( $filename, - $removeUnknownVariables = true, - $removeEmptyBlocks = true ) - { - $template = ''; - if (!$this->flagCacheTemplatefile || - $this->lastTemplatefile != $filename - ) { - $template = $this->getFile($filename); - } - $this->lastTemplatefile = $filename; - - return $template != '' ? - $this->setTemplate( - $template,$removeUnknownVariables, $removeEmptyBlocks - ) : false; - } // end func LoadTemplatefile - - /** - * Sets the file root. The file root gets prefixed to all filenames passed - * to the object. - * - * Make sure that you override this function when using the class - * on windows. - * - * @param string - * @see IntegratedTemplate() - * @access public - */ - function setRoot($root) - { - if ($root != '' && substr($root, -1) != '/') { - $root .= '/'; - } - - $this->fileRoot = $root; - } // end func setRoot - - /** - * Build a list of all variables within of a block - */ - function buildBlockvariablelist() - { - foreach ($this->blocklist as $name => $content) { - preg_match_all($this->variablesRegExp, $content, $regs); - - if (count($regs[1]) != 0) { - foreach ($regs[1] as $k => $var) { - $this->blockvariables[$name][$var] = true; - } - } else { - $this->blockvariables[$name] = array(); - } - } - } // end func buildBlockvariablelist - - /** - * Returns a list of all global variables - */ - function getGlobalvariables() - { - $regs = array(); - $values = array(); - - foreach ($this->blockvariables['__global__'] as $allowedvar => $v) { - if (isset($this->variableCache[$allowedvar])) { - $regs[] = '@' . $this->openingDelimiter . - $allowedvar . $this->closingDelimiter . '@'; - $values[] = $this->variableCache[$allowedvar]; - unset($this->variableCache[$allowedvar]); - } - } - - return array($regs, $values); - } // end func getGlobalvariables - - /** - * Recusively builds a list of all blocks within the template. - * - * @param string string that gets scanned - * @see $blocklist - */ - function findBlocks($string) - { - $blocklist = array(); - - if (preg_match_all($this->blockRegExp, $string, $regs, PREG_SET_ORDER)) { - foreach ($regs as $k => $match) { - $blockname = $match[1]; - $blockcontent = $match[2]; - - if (isset($this->blocklist[$blockname])) { - $this->err[] = PEAR::raiseError( - $this->errorMessage( - IT_BLOCK_DUPLICATE, $blockname), - IT_BLOCK_DUPLICATE - ); - $this->flagBlocktrouble = true; - } - - $this->blocklist[$blockname] = $blockcontent; - $this->blockdata[$blockname] = ""; - - $blocklist[] = $blockname; - - $inner = $this->findBlocks($blockcontent); - foreach ($inner as $k => $name) { - $pattern = sprintf( - '@(.*)@sm', - $name, - $name - ); - - $this->blocklist[$blockname] = preg_replace( - $pattern, - $this->openingDelimiter . - '__' . $name . '__' . - $this->closingDelimiter, - $this->blocklist[$blockname] - ); - $this->blockinner[$blockname][] = $name; - $this->blockparents[$name] = $blockname; - } - } - } - - return $blocklist; - } // end func findBlocks - - /** - * Reads a file from disk and returns its content. - * @param string Filename - * @return string Filecontent - */ - function getFile($filename) - { - if ($filename{0} == '/' && substr($this->fileRoot, -1) == '/') { - $filename = substr($filename, 1); - } - - $filename = $this->fileRoot . $filename; - - if (!($fh = @fopen($filename, 'r'))) { - $this->err[] = PEAR::raiseError( - $this->errorMessage(IT_TPL_NOT_FOUND) . - ': "' .$filename .'"', - IT_TPL_NOT_FOUND - ); - return ""; - } - - $content = fread($fh, filesize($filename)); - fclose($fh); - - return preg_replace( - "##ime", "\$this->getFile('\\1')", $content - ); - } // end func getFile - - /** - * Adds delimiters to a string, so it can be used as a pattern - * in preg_* functions - * - * @param string - * @return string - */ - function _addPregDelimiters($str) - { - return '@' . $str . '@'; - } - - /** - * Replaces an opening delimiter by a special string - * - * @param string - * @return string - */ - function _preserveOpeningDelimiter($str) - { - return (false === strpos($str, $this->openingDelimiter))? - $str: - str_replace( - $this->openingDelimiter, - $this->openingDelimiter . - '%preserved%' . $this->closingDelimiter, - $str - ); - } - - /** - * Return a textual error message for a IT error code - * - * @param integer $value error code - * - * @return string error message, or false if the error code was - * not recognized - */ - function errorMessage($value, $blockname = '') - { - static $errorMessages; - if (!isset($errorMessages)) { - $errorMessages = array( - IT_OK => '', - IT_ERROR => 'unknown error', - IT_TPL_NOT_FOUND => 'Cannot read the template file', - IT_BLOCK_NOT_FOUND => 'Cannot find this block', - IT_BLOCK_DUPLICATE => 'The name of a block must be'. - ' uniquewithin a template.'. - ' Found "' . $blockname . '" twice.'. - 'Unpredictable results '. - 'may appear.', - IT_UNKNOWN_OPTION => 'Unknown option' - ); - } - - if (PEAR::isError($value)) { - $value = $value->getCode(); - } - - return isset($errorMessages[$value]) ? - $errorMessages[$value] : $errorMessages[IT_ERROR]; - } -} // end class IntegratedTemplate -?> diff --git a/mods/photo_album/HTML/Template/ITX.php b/mods/photo_album/HTML/Template/ITX.php deleted file mode 100644 index 41d5c9bb3..000000000 --- a/mods/photo_album/HTML/Template/ITX.php +++ /dev/null @@ -1,809 +0,0 @@ - | -// | Pierre-Alain Joye | -// +----------------------------------------------------------------------+ -// -// $Id: ITX.php,v 1.14 2005/11/01 10:14:19 pajoye Exp $ -// - -require_once 'IT.php'; -require_once 'IT_Error.php'; - -/** -* Integrated Template Extension - ITX -* -* With this class you get the full power of the phplib template class. -* You may have one file with blocks in it but you have as well one main file -* and multiple files one for each block. This is quite usefull when you have -* user configurable websites. Using blocks not in the main template allows -* you to modify some parts of your layout easily. -* -* Note that you can replace an existing block and add new blocks at runtime. -* Adding new blocks means changing a variable placeholder to a block. -* -* @author Ulf Wendel -* @access public -* @version $Id: ITX.php,v 1.14 2005/11/01 10:14:19 pajoye Exp $ -* @package IT[X] -*/ -class HTML_Template_ITX extends HTML_Template_IT -{ - /** - * Array with all warnings. - * @var array - * @access public - * @see $printWarning, $haltOnWarning, warning() - */ - var $warn = array(); - - /** - * Print warnings? - * @var array - * @access public - * @see $haltOnWarning, $warn, warning() - */ - var $printWarning = false; - - /** - * Call die() on warning? - * @var boolean - * @access public - * @see $warn, $printWarning, warning() - */ - var $haltOnWarning = false; - - /** - * RegExp used to test for a valid blockname. - * @var string - */ - var $checkblocknameRegExp = ''; - - /** - * Functionnameprefix used when searching function calls in the template. - * @var string - */ - var $functionPrefix = 'func_'; - - /** - * Functionname RegExp. - * @var string - */ - var $functionnameRegExp = '[_a-zA-Z]+[A-Za-z_0-9]*'; - - /** - * RegExp used to grep function calls in the template. - * - * The variable gets set by the constructor. - * - * @var string - * @see HTML_Template_IT() - */ - var $functionRegExp = ''; - - /** - * List of functions found in the template. - * - * @var array - */ - var $functions = array(); - - /** - * List of callback functions specified by the user. - * - * @var array - */ - var $callback = array(); - - /** - * Builds some complex regexps and calls the constructor - * of the parent class. - * - * Make sure that you call this constructor if you derive your own - * template class from this one. - * - * @see HTML_Template_IT() - */ - function HTML_Template_ITX($root = '') - { - - $this->checkblocknameRegExp = '@' . $this->blocknameRegExp . '@'; - $this->functionRegExp = '@' . $this->functionPrefix . '(' . - $this->functionnameRegExp . ')\s*\(@sm'; - - $this->HTML_Template_IT($root); - } // end func constructor - - function init() - { - $this->free(); - $this->buildFunctionlist(); - $this->findBlocks($this->template); - // we don't need it any more - $this->template = ''; - $this->buildBlockvariablelist(); - - } // end func init - - /** - * Replaces an existing block with new content. - * - * This function will replace a block of the template and all blocks - * contained in the replaced block and add a new block insted, means - * you can dynamically change your template. - * - * Note that changing the template structure violates one of the IT[X] - * development goals. I've tried to write a simple to use template engine - * supporting blocks. In contrast to other systems IT[X] analyses the way - * you've nested blocks and knows which block belongs into another block. - * The nesting information helps to make the API short and simple. Replacing - * blocks does not only mean that IT[X] has to update the nesting - * information (relatively time consumpting task) but you have to make sure - * that you do not get confused due to the template change itself. - * - * @param string Blockname - * @param string Blockcontent - * @param boolean true if the new block inherits the content - * of the old block - * @return boolean - * @throws IT_Error - * @see replaceBlockfile(), addBlock(), addBlockfile() - * @access public - */ - function replaceBlock($block, $template, $keep_content = false) - { - if (!isset($this->blocklist[$block])) { - return new IT_Error( - "The block "."'$block'". - " does not exist in the template and thus it can't be replaced.", - __FILE__, __LINE__ - ); - } - - if ($template == '') { - return new IT_Error('No block content given.', __FILE__, __LINE__); - } - - if ($keep_content) { - $blockdata = $this->blockdata[$block]; - } - - // remove all kinds of links to the block / data of the block - $this->removeBlockData($block); - - $template = "" . $template . ""; - $parents = $this->blockparents[$block]; - $this->findBlocks($template); - $this->blockparents[$block] = $parents; - - // KLUDGE: rebuild the list for all block - could be done faster - $this->buildBlockvariablelist(); - - if ($keep_content) { - $this->blockdata[$block] = $blockdata; - } - - // old TODO - I'm not sure if we need this - // update caches - - return true; - } // end func replaceBlock - - /** - * Replaces an existing block with new content from a file. - * - * @brother replaceBlock() - * @param string Blockname - * @param string Name of the file that contains the blockcontent - * @param boolean true if the new block inherits the content of the old block - */ - function replaceBlockfile($block, $filename, $keep_content = false) - { - return $this->replaceBlock($block, $this->getFile($filename), $keep_content); - } // end func replaceBlockfile - - /** - * Adds a block to the template changing a variable placeholder - * to a block placeholder. - * - * Add means "replace a variable placeholder by a new block". - * This is different to PHPLibs templates. The function loads a - * block, creates a handle for it and assigns it to a certain - * variable placeholder. To to the same with PHPLibs templates you would - * call set_file() to create the handle and parse() to assign the - * parsed block to a variable. By this PHPLibs templates assume - * that you tend to assign a block to more than one one placeholder. - * To assign a parsed block to more than only the placeholder you specify - * in this function you have to use a combination of getBlock() - * and setVariable(). - * - * As no updates to cached data is necessary addBlock() and addBlockfile() - * are rather "cheap" meaning quick operations. - * - * The block content must not start with - * and end with this would cause overhead and - * produce an error. - * - * @param string Name of the variable placeholder, the name must be unique - * within the template. - * @param string Name of the block to be added - * @param string Content of the block - * @return boolean - * @throws IT_Error - * @see addBlockfile() - * @access public - */ - function addBlock($placeholder, $blockname, $template) - { - // Don't trust any user even if it's a programmer or yourself... - if ($placeholder == '') { - return new IT_Error('No variable placeholder given.', - __FILE__, __LINE__ - ); - } elseif ($blockname == '' || - !preg_match($this->checkblocknameRegExp, $blockname) - ) { - return new IT_Error("No or invalid blockname '$blockname' given.", - __FILE__, __LINE__ - ); - } elseif ($template == '') { - return new IT_Error('No block content given.', __FILE__, __LINE__); - } elseif (isset($this->blocklist[$blockname])) { - return new IT_Error('The block already exists.', - __FILE__, __LINE__ - ); - } - - // find out where to insert the new block - $parents = $this->findPlaceholderBlocks($placeholder); - if (count($parents) == 0) { - - return new IT_Error( - "The variable placeholder". - " '$placeholder' was not found in the template.", - __FILE__, __LINE__ - ); - - } elseif (count($parents) > 1) { - - reset($parents); - while (list($k, $parent) = each($parents)) { - $msg .= "$parent, "; - } - $msg = substr($parent, -2); - - return new IT_Error("The variable placeholder "."'$placeholder'". - " must be unique, found in multiple blocks '$msg'.", - __FILE__, __LINE__ - ); - } - - $template = "" . $template . ""; - $this->findBlocks($template); - if ($this->flagBlocktrouble) { - return false; // findBlocks() already throws an exception - } - $this->blockinner[$parents[0]][] = $blockname; - $this->blocklist[$parents[0]] = preg_replace( - '@' . $this->openingDelimiter . $placeholder . - $this->closingDelimiter . '@', - - $this->openingDelimiter . '__' . $blockname . '__' . - $this->closingDelimiter, - - $this->blocklist[$parents[0]] - ); - - $this->deleteFromBlockvariablelist($parents[0], $placeholder); - $this->updateBlockvariablelist($blockname); - /* - // check if any inner blocks were found - if(is_array($this->blockinner[$blockname]) and count($this->blockinner[$blockname]) > 0) { - // loop through inner blocks, registering the variable placeholders in each - foreach($this->blockinner[$blockname] as $childBlock) { - $this->updateBlockvariablelist($childBlock); - } - } - */ - return true; - } // end func addBlock - - /** - * Adds a block taken from a file to the template changing a variable - * placeholder to a block placeholder. - * - * @param string Name of the variable placeholder to be converted - * @param string Name of the block to be added - * @param string File that contains the block - * @brother addBlock() - */ - function addBlockfile($placeholder, $blockname, $filename) - { - return $this->addBlock($placeholder, $blockname, $this->getFile($filename)); - } // end func addBlockfile - - /** - * Returns the name of the (first) block that contains - * the specified placeholder. - * - * @param string Name of the placeholder you're searching - * @param string Name of the block to scan. If left out (default) - * all blocks are scanned. - * @return string Name of the (first) block that contains - * the specified placeholder. - * If the placeholder was not found or an error occured - * an empty string is returned. - * @throws IT_Error - * @access public - */ - function placeholderExists($placeholder, $block = '') - { - if ($placeholder == '') { - new IT_Error('No placeholder name given.', __FILE__, __LINE__); - return ''; - } - - if ($block != '' && !isset($this->blocklist[$block])) { - new IT_Error("Unknown block '$block'.", __FILE__, __LINE__); - return ''; - } - - // name of the block where the given placeholder was found - $found = ''; - - if ($block != '') { - if (is_array($variables = $this->blockvariables[$block])) { - // search the value in the list of blockvariables - reset($variables); - while (list($k, $variable) = each($variables)) { - if ($k == $placeholder) { - $found = $block; - break; - } - } - } - } else { - - // search all blocks and return the name of the first block that - // contains the placeholder - reset($this->blockvariables); - while (list($blockname, $variables) = each($this->blockvariables)){ - if (is_array($variables) && isset($variables[$placeholder])) { - $found = $blockname; - break; - } - } - } - - return $found; - } // end func placeholderExists - - /** - * Checks the list of function calls in the template and - * calls their callback function. - * - * @access public - */ - function performCallback() - { - reset($this->functions); - while (list($func_id, $function) = each($this->functions)) { - if (isset($this->callback[$function['name']])) { - if ($this->callback[$function['name']]['object'] != '') { - $this->variableCache['__function' . $func_id . '__'] = - call_user_func( - array( - &$GLOBALS[$this->callback[$function['name']]['object']], - $this->callback[$function['name']]['function']), - $function['args'] - ); - } else { - $this->variableCache['__function' . $func_id . '__'] = - call_user_func( - $this->callback[$function['name']]['function'], - $function['args'] - ); - } - } - } - - } // end func performCallback - - /** - * Returns a list of all function calls in the current template. - * - * @return array - * @access public - */ - function getFunctioncalls() - { - return $this->functions; - } // end func getFunctioncalls - - /** - * Replaces a function call with the given replacement. - * - * @param int Function ID - * @param string Replacement - * @deprec - */ - function setFunctioncontent($functionID, $replacement) - { - $this->variableCache['__function' . $functionID . '__'] = $replacement; - } // end func setFunctioncontent - - /** - * Sets a callback function. - * - * IT[X] templates (note the X) can contain simple function calls. - * "function call" means that the editor of the template can add - * special placeholder to the template like 'func_h1("embedded in h1")'. - * IT[X] will grab this function calls and allow you to define a callback - * function for them. - * - * This is an absolutely evil feature. If your application makes heavy - * use of such callbacks and you're even implementing if-then etc. on - * the level of a template engine you're reiventing the wheel... - that's - * actually how PHP came into life. Anyway, sometimes it's handy. - * - * Consider also using XML/XSLT or native PHP. And please do not push - * IT[X] any further into this direction of adding logics to the template - * engine. - * - * For those of you ready for the X in IT[X]: - * - * %s', $args[0]); - * } - * - * ... - * $itx = new HTML_Template_ITX( ... ); - * ... - * $itx->setCallbackFunction('h1', 'h_one'); - * $itx->performCallback(); - * ?> - * - * template: - * func_h1('H1 Headline'); - * - * @param string Function name in the template - * @param string Name of the callback function - * @param string Name of the callback object - * @return boolean False on failure. - * @throws IT_Error - * @access public - */ - function - setCallbackFunction($tplfunction, $callbackfunction, $callbackobject = '') - { - if ($tplfunction == '' || $callbackfunction == '') { - return new IT_Error( - "No template function "."('$tplfunction')". - " and/or no callback function ('$callback') given.", - __FILE__, __LINE__ - ); - } - $this->callback[$tplfunction] = array( - 'function' => $callbackfunction, - 'object' => $callbackobject - ); - - return true; - } // end func setCallbackFunction - - /** - * Sets the Callback function lookup table - * - * @param array function table - * array[templatefunction] = - * array( - * "function" => userfunction, - * "object" => userobject - * ) - * @access public - */ - function setCallbackFuntiontable($functions) - { - $this->callback = $functions; - } // end func setCallbackFunctiontable - - /** - * Recursively removes all data assiciated with a block, including all inner blocks - * - * @param string block to be removed - */ - function removeBlockData($block) - { - if (isset($this->blockinner[$block])) { - foreach ($this->blockinner[$block] as $k => $inner) { - $this->removeBlockData($inner); - } - - unset($this->blockinner[$block]); - } - - unset($this->blocklist[$block]); - unset($this->blockdata[$block]); - unset($this->blockvariables[$block]); - unset($this->touchedBlocks[$block]); - - } // end func removeBlockinner - - /** - * Returns a list of blocknames in the template. - * - * @return array [blockname => blockname] - * @access public - * @see blockExists() - */ - function getBlocklist() - { - $blocklist = array(); - foreach ($this->blocklist as $block => $content) { - $blocklist[$block] = $block; - } - - return $blocklist; - } // end func getBlocklist - - /** - * Checks wheter a block exists. - * - * @param string - * @return boolean - * @access public - * @see getBlocklist() - */ - function blockExists($blockname) - { - return isset($this->blocklist[$blockname]); - } // end func blockExists - - /** - * Returns a list of variables of a block. - * - * @param string Blockname - * @return array [varname => varname] - * @access public - * @see BlockvariableExists() - */ - function getBlockvariables($block) - { - if (!isset($this->blockvariables[$block])) { - return array(); - } - - $variables = array(); - foreach ($this->blockvariables[$block] as $variable => $v) { - $variables[$variable] = $variable; - } - - return $variables; - } // end func getBlockvariables - - /** - * Checks wheter a block variable exists. - * - * @param string Blockname - * @param string Variablename - * @return boolean - * @access public - * @see getBlockvariables() - */ - function BlockvariableExists($block, $variable) - { - return isset($this->blockvariables[$block][$variable]); - } // end func BlockvariableExists - - /** - * Builds a functionlist from the template. - */ - function buildFunctionlist() - { - $this->functions = array(); - - $template = $this->template; - $num = 0; - - while (preg_match($this->functionRegExp, $template, $regs)) { - - $pos = strpos($template, $regs[0]); - $template = substr($template, $pos + strlen($regs[0])); - - $head = $this->getValue($template, ')'); - $args = array(); - - $search = $regs[0] . $head . ')'; - - $replace = $this->openingDelimiter . - '__function' . $num . '__' . - $this->closingDelimiter; - - $this->template = str_replace($search, $replace, $this->template); - $template = str_replace($search, $replace, $template); - - while ($head != '' && $args2 = $this->getValue($head, ',')) { - $arg2 = trim($args2); - $args[] = ('"' == $arg2{0} || "'" == $arg2{0}) ? - substr($arg2, 1, -1) : $arg2; - if ($arg2 == $head) { - break; - } - $head = substr($head, strlen($arg2) + 1); - } - - $this->functions[$num++] = array( - 'name' => $regs[1], - 'args' => $args - ); - } - - } // end func buildFunctionlist - - function getValue($code, $delimiter) { - if ($code == '') { - return ''; - } - - if (!is_array($delimiter)) { - $delimiter = array( $delimiter => true ); - } - - $len = strlen($code); - $enclosed = false; - $enclosed_by = ''; - - if (isset($delimiter[$code[0]])) { - $i = 1; - } else { - for ($i = 0; $i < $len; ++$i) { - $char = $code[$i]; - - if ( - ($char == '"' || $char = "'") && - ($char == $enclosed_by || '' == $enclosed_by) && - (0 == $i || ($i > 0 && '\\' != $code[$i - 1])) - ) { - - if (!$enclosed) { - $enclosed_by = $char; - } else { - $enclosed_by = ""; - } - $enclosed = !$enclosed; - - } - - if (!$enclosed && isset($delimiter[$char])) { - break; - } - } - } - - return substr($code, 0, $i); - } // end func getValue - - /** - * Deletes one or many variables from the block variable list. - * - * @param string Blockname - * @param mixed Name of one variable or array of variables - * ( array ( name => true ) ) to be stripped. - */ - function deleteFromBlockvariablelist($block, $variables) - { - if (!is_array($variables)) { - $variables = array($variables => true); - } - - reset($this->blockvariables[$block]); - while (list($varname, $val) = each($this->blockvariables[$block])) { - if (isset($variables[$varname])) { - unset($this->blockvariables[$block][$varname]); - } - } - } // end deleteFromBlockvariablelist - - /** - * Updates the variable list of a block. - * - * @param string Blockname - */ - function updateBlockvariablelist($block) - { - preg_match_all( $this->variablesRegExp, - $this->blocklist[$block], $regs - ); - - if (count($regs[1]) != 0) { - foreach ($regs[1] as $k => $var) { - $this->blockvariables[$block][$var] = true; - } - } else { - $this->blockvariables[$block] = array(); - } - - // check if any inner blocks were found - if (isset($this->blockinner[$block]) && - is_array($this->blockinner[$block]) && - count($this->blockinner[$block]) > 0 - ) { - /* - * loop through inner blocks, registering the variable - * placeholders in each - */ - foreach ($this->blockinner[$block] as $childBlock) { - $this->updateBlockvariablelist($childBlock); - } - } - } // end func updateBlockvariablelist - - /** - * Returns an array of blocknames where the given variable - * placeholder is used. - * - * @param string Variable placeholder - * @return array $parents parents[0..n] = blockname - */ - function findPlaceholderBlocks($variable) - { - $parents = array(); - reset($this->blocklist); - while (list($blockname, $content) = each($this->blocklist)) { - reset($this->blockvariables[$blockname]); - while ( - list($varname, $val) = each($this->blockvariables[$blockname])) - { - if ($variable == $varname) { - $parents[] = $blockname; - } - } - } - - return $parents; - } // end func findPlaceholderBlocks - - /** - * Handles warnings, saves them to $warn and prints them or - * calls die() depending on the flags - * - * @param string Warning - * @param string File where the warning occured - * @param int Linenumber where the warning occured - * @see $warn, $printWarning, $haltOnWarning - */ - function warning($message, $file = '', $line = 0) - { - $message = sprintf( - 'HTML_Template_ITX Warning: %s [File: %s, Line: %d]', - $message, - $file, - $line - ); - - $this->warn[] = $message; - - if ($this->printWarning) { - print $message; - } - - if ($this->haltOnWarning) { - die($message); - } - } // end func warning - -} // end class HTML_Template_ITX -?> diff --git a/mods/photo_album/HTML/Template/IT_Error.php b/mods/photo_album/HTML/Template/IT_Error.php deleted file mode 100644 index fedee9356..000000000 --- a/mods/photo_album/HTML/Template/IT_Error.php +++ /dev/null @@ -1,51 +0,0 @@ - | -// | Pierre-Alain Joye | -// +----------------------------------------------------------------------+ -// -// $Id: IT_Error.php,v 1.2 2005/11/01 10:14:19 pajoye Exp $ - -require_once "PEAR.php"; - -/** -* IT[X] Error class -* -* @package IT[X] -*/ -class IT_Error extends PEAR_Error { - - - /** - * Prefix of all error messages. - * - * @var string - */ - var $error_message_prefix = "IntegratedTemplate Error: "; - - /** - * Creates an cache error object. - * - * @param string error message - * @param string file where the error occured - * @param string linenumber where the error occured - */ - function IT_Error($msg, $file = __FILE__, $line = __LINE__) { - - $this->PEAR_Error(sprintf("%s [%s on line %d].", $msg, $file, $line)); - - } // end func IT_Error - -} // end class IT_Error -?> diff --git a/mods/photo_album/README.txt b/mods/photo_album/README.txt deleted file mode 100644 index 5389030a6..000000000 --- a/mods/photo_album/README.txt +++ /dev/null @@ -1,50 +0,0 @@ -Photo Album Module for ATutor 1.5.2 -=================================== - -Share photos! Share comments! - -Features - -* Add and share photos -* Share comments on class photos -* Approve and edit photos before public posting -* Moderate user submissions...or not! - -Requirements - -* You need to be running an instance of ATutor version 1.5.2 or higher -* Your PHP must have the GD Library v.2 or higher compiled into it - -Installation - -1. Download the file into the following directory: /ATutor/mods/ -2. Unzip the file using the UNIX command: tar zxvf atutor_photoa-1.0.0.tar.gz -3. A folder named photo_album is created -4. You will now install the module using ATutor's installation utility. Login to your ATutor server using an 'administrator' account. -5. From the default Administration home page, click 'Install Modules'. -6. From the list of modules, click the radio button next to the module named 'Photo Album'. -7. The next screen is a confirmation page. Read the details of the module installation and then click the 'Yes' button. -8. The next screen is a list of the modules installed on your ATutor server. By default, the Photo Album is not enabled. Before you begin using the Photo Album in your courses, you need to enable it. -9. Click the radio button next to the module named 'Photo Album'. At the bottom of the screen (you may need to scroll your browser window) is a button labelled 'Enable'; click that button. -10. A success message is displayed if there are no errors -11. Add the Photo Album to your courses using Manage | Student Tools - -Administration - -The system is set up so that both administrator and instructor can approve and delete photos. When moderation is enabled, a student adds a photo it is sent to an approval queue until an instructor or an administrator approves it. To approve photos, select Photo Album from the Manage tab and view the New Photos. Click the check box and then click the appropriate button to approve photos. - -The moderation setting is disabled by default, so you need to enable it using the Manage | Photo Album | Enable Moderation - -Errors - -Please report errors to the developers: - -support@canassist.ca - -http://bugs.canassist.ca/ - -Please provide as much information as possible (error message, actions, server settings - phpinfo) in your error reports. Thanks for your feedback! - -License - -This software is licensed under the GPL license. Copyright 2006 by Dylan Cheon and the Institute for Assistive Technology, University of Victoria. diff --git a/mods/photo_album/Template/admin_comment_list.tpl.php b/mods/photo_album/Template/admin_comment_list.tpl.php deleted file mode 100644 index 85397e9ad..000000000 --- a/mods/photo_album/Template/admin_comment_list.tpl.php +++ /dev/null @@ -1,75 +0,0 @@ - - -

    - {TITLE} -

    - -
    {CONFIG_STRING} : {CONFIG_VALUE}
    - -
    - -
    -
    - - - -
    -
    - - - - -
    - -
    - - - - - - - - - - - - -
    {COMMENT_TABLE_DATA2}{COMMENT_TABLE_DATA3}
    {COMMENT_TABLE_DATA4}
    -
    - -
    - -
    -
    - - - -
    -
    -
    - - -
    -
      - - {B_DATA} - -
    -
    \ No newline at end of file diff --git a/mods/photo_album/Template/admin_config.tpl.php b/mods/photo_album/Template/admin_config.tpl.php deleted file mode 100644 index f5f3192e0..000000000 --- a/mods/photo_album/Template/admin_config.tpl.php +++ /dev/null @@ -1,15 +0,0 @@ -

    {TITLE}

    -

    {CONFIG_NOTE}

    -
    {CONFIG_STRING} : {CONFIG_VALUE}
    - -
    -
    -
    - - -
    - -
    -
    -
    -
    diff --git a/mods/photo_album/Template/admin_image_list.tpl.php b/mods/photo_album/Template/admin_image_list.tpl.php deleted file mode 100644 index 98c131436..000000000 --- a/mods/photo_album/Template/admin_image_list.tpl.php +++ /dev/null @@ -1,91 +0,0 @@ - - -

    - {TITLE} -

    -
    {CONFIG_STRING} : {CONFIG_VALUE}
    -
    -
    - -
    - - - -
    - - - - -
    - - - -
    - -
    - - - -
    - -
    - - - - - - - - - - - - - - - - - - -
    {IMAGE_TABLE_DATA2}
    {IMAGE_TABLE_DATA3}
    {IMAGE_TABLE_DATA4}
    {IMAGE_TABLE_DATA5}
    {IMAGE_TABLE_DATA6}
    -
    - -
    - - -
    - -
    - - - -
    -
    -
    - - -
    -
      - - {B_DATA} - -
    -
    - diff --git a/mods/photo_album/Template/delete_confirm.tpl.php b/mods/photo_album/Template/delete_confirm.tpl.php deleted file mode 100644 index 8e7d0eba8..000000000 --- a/mods/photo_album/Template/delete_confirm.tpl.php +++ /dev/null @@ -1,32 +0,0 @@ -
    -

    {MESSAGE}

    - -
    - {ALT} -
    - - - - - - - - - - - -
    {DESC}
    {NAME_STRING} : {NAME}{DATE_STRING} : {DATE}
    - - -
    -
    - -
    - -
    - -
    -
    -
    - - diff --git a/mods/photo_album/Template/file_upload.tpl.php b/mods/photo_album/Template/file_upload.tpl.php deleted file mode 100644 index 4bea6f558..000000000 --- a/mods/photo_album/Template/file_upload.tpl.php +++ /dev/null @@ -1,33 +0,0 @@ - -

    - {TITLE} -

    - -
    -
    - -
    - {ALT} -
    - - - -
    -

    {MESSAGE}

    -
    - -
    - {REQUIRED_SYMBOL}
    -
    -
    - - - - - -
    -
    -
    - - - diff --git a/mods/photo_album/Template/form.tpl.php b/mods/photo_album/Template/form.tpl.php deleted file mode 100644 index 671f489da..000000000 --- a/mods/photo_album/Template/form.tpl.php +++ /dev/null @@ -1,48 +0,0 @@ - - - -
    -
    -
    - {ALT} -
    -
    {MESSAGE}
    - -
    -
    *

    -
    -
    -
    - -
    - -
    -
    *

    -
    - -
    - - -
    -
    -
    - - - -
    -
    -

    {COMMENT_MESSAGE}

    -
    -
    *

    - -
    -
    - - -
    -
    -
    - - - - diff --git a/mods/photo_album/Template/index.tpl.php b/mods/photo_album/Template/index.tpl.php deleted file mode 100644 index cdfd93da5..000000000 --- a/mods/photo_album/Template/index.tpl.php +++ /dev/null @@ -1,75 +0,0 @@ - - -

    - {IMAGE_PAGE_TITLE} -

    - - - -
    - - -
    - -
    - - -
    -
    -
    - - {IMAGE_ALT} - -
    - - - -
    -
    - - - -
    - - - - - - -
    - - - -
    -
    - -
    -
      - - {B_DATA} - -
    -
    -
    -
    - diff --git a/mods/photo_album/Template/index.tpl.php.bak b/mods/photo_album/Template/index.tpl.php.bak deleted file mode 100644 index 3bed766fa..000000000 --- a/mods/photo_album/Template/index.tpl.php.bak +++ /dev/null @@ -1,44 +0,0 @@ - -

    - {IMAGE_PAGE_TITLE} -

    - - - -
    -
    - - - -
    - - -
    -
    - - - -
    -
    - -
    - -
    -
    -
      - - {B_DATA} - -
    -
    -
    - diff --git a/mods/photo_album/Template/index_admin.tpl.php b/mods/photo_album/Template/index_admin.tpl.php deleted file mode 100644 index 136e19cb1..000000000 --- a/mods/photo_album/Template/index_admin.tpl.php +++ /dev/null @@ -1,18 +0,0 @@ -

    {TITLE}

    -
    -

    {MESSAGE}

    -
    - -
    -
    -
    -
    - - -
    -
    -
    diff --git a/mods/photo_album/Template/instructor_comment.tpl.php b/mods/photo_album/Template/instructor_comment.tpl.php deleted file mode 100644 index 67e5669ce..000000000 --- a/mods/photo_album/Template/instructor_comment.tpl.php +++ /dev/null @@ -1,76 +0,0 @@ - - -

    - {TITLE} -

    - -
    {CONFIG_STRING} : {CONFIG_VALUE}
    - -
    -
    - -
    - - - -
    - -
    - - -
    - -
    - - - - - - - - - - - - -
    {COMMENT_TABLE_DATA2}{COMMENT_TABLE_DATA3}
    {COMMENT_TABLE_DATA4}
    -
    - - -
    - -
    -
    - - - -
    -
    -
    - - -
    -
      - - {B_DATA} - -
    -
    - diff --git a/mods/photo_album/Template/instructor_config.tpl.php b/mods/photo_album/Template/instructor_config.tpl.php deleted file mode 100644 index 51316c5af..000000000 --- a/mods/photo_album/Template/instructor_config.tpl.php +++ /dev/null @@ -1,15 +0,0 @@ -

    {TITLE}

    -

    {CONFIG_NOTE}

    -
    {CONFIG_STRING} : {CONFIG_VALUE}
    - -
    -
    -
    - - -
    - -
    -
    -
    -
    diff --git a/mods/photo_album/Template/instructor_image.tpl.php b/mods/photo_album/Template/instructor_image.tpl.php deleted file mode 100644 index 2a75edee1..000000000 --- a/mods/photo_album/Template/instructor_image.tpl.php +++ /dev/null @@ -1,93 +0,0 @@ - - -

    - {TITLE} -

    - -
    {CONFIG_STRING} : {CONFIG_VALUE}
    - -
    - -
    - -
    - - - -
    - - -
    - - - -
    - -
    - - - -
    - -
    - - - - - - - - - - - - - - - - - - - -
    {IMAGE_TABLE_DATA2}
    {IMAGE_TABLE_DATA3}
    {IMAGE_TABLE_DATA4}
    {IMAGE_TABLE_DATA5}
    {IMAGE_TABLE_DATA6}
    -
    - - -
    - - -
    -
    - - - -
    -
    -
    - - -
    -
      - - {B_DATA} - -
    -
    - diff --git a/mods/photo_album/Template/my_comment.tpl.php b/mods/photo_album/Template/my_comment.tpl.php deleted file mode 100644 index 213703915..000000000 --- a/mods/photo_album/Template/my_comment.tpl.php +++ /dev/null @@ -1,44 +0,0 @@ -

    - {TITLE} -

    - - - -
    -
    - - {LINK_TEXT} - -
    - - -
    - - - - - - - - - - - -
    {COMMENT_TABLE_DATA1}
    {COMMENT_TABLE_DATA2}{COMMENT_TABLE_DATA3}
    {COMMENT_TABLE_DATA4}
    -
    - -
    - -
    -
      - - {B_DATA} - -
    -
    diff --git a/mods/photo_album/Template/my_photo.tpl.php b/mods/photo_album/Template/my_photo.tpl.php deleted file mode 100644 index 83d9f30ad..000000000 --- a/mods/photo_album/Template/my_photo.tpl.php +++ /dev/null @@ -1,48 +0,0 @@ -

    - {TITLE} -

    - - - -
    - -
    - - {LINK_TEXT} - -
    - - -
    -

    {IMAGE_DATA1}

    -

    {IMAGE_DATA2}

    -

    {IMAGE_DATA3}

    -
    - - - -
    - -
    -
    - -
    - -
    -   -
    -
    - -
    -
      - - {B_DATA} - -
    -
    diff --git a/mods/photo_album/Template/result.tpl.php b/mods/photo_album/Template/result.tpl.php deleted file mode 100644 index ffd6424a1..000000000 --- a/mods/photo_album/Template/result.tpl.php +++ /dev/null @@ -1,20 +0,0 @@ -

    - {PAGE_TITLE} -

    - -
    - {REASON}
    - Your request is denied.
    - Authorization is failed.
    - Click here to go back to beginning.
    - If you want to go back to where you were just in, press back button in the web browser. -
    - - - -
    - {MESSAGE}
    - You will be redirected to where you started in few seconds.
    - If the redirection failes, Click here to go back where you were. -
    - \ No newline at end of file diff --git a/mods/photo_album/Template/view.tpl.php b/mods/photo_album/Template/view.tpl.php deleted file mode 100644 index f04fb2450..000000000 --- a/mods/photo_album/Template/view.tpl.php +++ /dev/null @@ -1,81 +0,0 @@ -
    {RESULT}
    - -

    {IMAGE_TITLE_STRING} : {IMAGE_TITLE}

    - - -
    -
    - {ALT} -
    - - -
    -
    - - - - -
    - -
    - - - - -
    -
    - - - - - -

    {IMAGE_DISPLAY}

    -
    - - - - - - - - -
    {IMAGE_DESC}
    {IMAGE_NAME_STRING} : {IMAGE_NAME}{IMAGE_DATE_STRING} : {IMAGE_DATE}
    -
    - - -
    -
    - - - -
    -
    - -
    - - -
    -

    {COMMENT_DISPLAY}

    - - -
    - -
    -
    - - - - - - - - -
    {COMMENT_VALUE}
    Name : {COMMENT_NAME}Date : {COMMENT_DATE}
    -
    - {CONTROL_BUTTONS} - - -
    - diff --git a/mods/photo_album/admin_comment_list.php b/mods/photo_album/admin_comment_list.php deleted file mode 100644 index 5ef312c42..000000000 --- a/mods/photo_album/admin_comment_list.php +++ /dev/null @@ -1,173 +0,0 @@ - - -isError()!=true){ //no error found, display the page - $template=new HTML_Template_ITX("./Template"); - $template->loadTemplateFile("admin_comment_list.tpl.php"); - $template->setVariable("ADMIN_NUMBER_OF_COMMENT", ADMIN_NUMBER_OF_COMMENT); - $course_name=get_course_title($admin->getVariable('course_id')); - switch ($admin->getVariable('mode')){ - case POSTED_NEW: - $template->setVariable("TITLE", _AT('pa_title_administrator_new_comment')." (".$course_name.")"); - break; - case APPROVED: - $template->setVariable("TITLE", _AT('pa_title_administrator_approved_comment')." (".$course_name.")"); - break; - case DISAPPROVED: - $template->setVariable("TITLE", _AT('pa_title_administrator_disapproved_comment')." (".$course_name.")"); - break; - } - - $mode=get_config_mode($admin->getVariable('course_id')); - $template->setVariable("CONFIG_STRING", _AT('pa_tag_config_string')); - if ($mode==CONFIG_ENABLED){ - $template->setVariable("CONFIG_VALUE", _AT('pa_tag_config_enabled')); - } else { - $template->setVariable("CONFIG_VALUE", _AT('pa_tag_config_disabled')); - } - - $template->setCurrentBlock("SELECT_PART"); - $template->setVariable("SELECT_FORM_NAME", "select_form"); - $template->setVariable("SELECT_ACTION", $_SERVER['PHP_SELF']); - $template->setVariable("SELECT_NAME", "mode"); - $template->setVariable("SELECT_LABEL", _AT('pa_tag_view')); - - $template->setCurrentBlock("OPTION_PART"); - $template->setVariable("OPTION_VALUE", POSTED_NEW); - $template->setVariable("OPTION_STRING", _AT('pa_tag_new_comment')); - $template->parseCurrentBlock("OPTION_PART"); - - $template->setCurrentBlock("OPTION_PART"); - $template->setVariable("OPTION_VALUE", APPROVED); - $template->setVariable("OPTION_STRING", _AT('pa_tag_approved_comment')); - $template->parseCurrentBlock("OPTION_PART"); - - $template->setCurrentBlock("OPTION_PART"); - $template->setVariable("OPTION_VALUE", DISAPPROVED); - $template->setVariable("OPTION_STRING", _AT('pa_tag_disapproved_comment')); - $template->parseCurrentBlock("OPTION_PART"); - - $template->setVariable("SELECT_SUBMIT", "select_submit"); - $template->setVariable("SELECT_SUBMIT_VALUE", _AT('pa_tag_go')); - $template->parseCurrentBlock("SELECT_PART"); - - $template->setCurrentBlock("COMMENT_TABLE_PART"); - $template->setVariable("COMMENT_TABLE_FORM_NAME", "table_form"); - $action_string=$_SERVER['PHP_SELF']."?mode=".$admin->getVariable('mode')."&current_page=".$admin->getVariable('current_page'); - $template->setVariable("COMMENT_TABLE_ACTION", $action_string); - - /* start display comments */ - $comment_array=$admin->comment_array; - // print_r($comment_array); - //exit; - for ($i=0; $isetCurrentBlock("COMMENT_TABLE_DATA"); - $template->setVariable("CHECK_NAME", "commentId".$i); - $template->setVariable("CHECK_VALUE", $comment_array[$i]['comment_id']); - $template->setVariable("COMMENT_TABLE_DATA1", $comment_array[$i]['comment']); - $template->setVariable("COMMENT_TABLE_DATA2", _AT('login').": ".$comment_array[$i]['login']); - $template->setVariable("COMMENT_TABLE_DATA3", _AT('date').": ".$comment_array[$i]['date']); - $template->setVariable("COMMENT_TABLE_DATA4", ""._AT('pa_tag_view_comment_link').""); - $template->parseCurrentBlock("COMMENT_TABLE_DATA"); - } - $template->setCurrentBlock("COMMENT_BUTTON"); - $template->setVariable("COMMENT_BUTTON_NAME", "button_disapprove"); - $template->setVariable("COMMENT_BUTTON_VALUE", _AT('pa_button_set_disapproved_comment')); - $template->parseCurrentBlock("COMMENT_BUTTON"); - - $template->setCurrentBlock("COMMENT_BUTTON"); - $template->setVariable("COMMENT_BUTTON_NAME", "button_approve"); - $template->setVariable("COMMENT_BUTTON_VALUE", _AT('pa_button_set_approved_comment')); - $template->parseCurrentBlock("COMMENT_BUTTON"); - - $template->setCurrentBlock("COMMENT_BUTTON"); - $template->setVariable("COMMENT_BUTTON_NAME", "button_post_new"); - $template->setVariable("COMMENT_BUTTON_VALUE", _AT('pa_button_set_new_comment')); - $template->parseCurrentBlock("COMMENT_BUTTON"); - - $template->setVariable("CHECK_ALL_MSG", _AT('pa_tag_check_all_comment')); - - $template->parseCurrentBlock("COMMENT_TABLE_PART"); - - // Display page table - $page_array=$admin->getVariable('page_array'); - $current=$admin->getVariable('current_page'); - if ($admin->getVariable('show_page_left_buttons')==true){ - $first_button=_AT('pa_tag_first_page_button'); - $previous_button=_AT('pa_tag_previous_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$first_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$previous_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - for ($i=$page_array['start']; $i<=$page_array['end']; $i++){ - if ($i==$current){ - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • '.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } else { - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>'.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - } - - if ($admin->getVariable('show_page_right_buttons')==true){ - $next_button=_AT('pa_tag_next_page_button'); - $last_button=_AT('pa_tag_last_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$next_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$last_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - $template->parseCurrentBlock(); - $template->show(); - unset($_SESSION['pa']); - $_SESSION['pa']['course_id']=$admin->getVariable('course_id'); - $_SESSION['pa']['administrator_mode']=true; -} else { - $msg->addError('pa_obj_pa_admin_comment'); - redirect('index.php'); -} - -?> - \ No newline at end of file diff --git a/mods/photo_album/admin_config.php b/mods/photo_album/admin_config.php deleted file mode 100644 index 4cf15dc23..000000000 --- a/mods/photo_album/admin_config.php +++ /dev/null @@ -1,68 +0,0 @@ - - -loadTemplateFile("admin_config.tpl.php"); -$template->setVariable("TITLE", _AT('pa_title_instructor_config')); -$template->setVariable("CONFIG_NOTE", _AT('pa_note_instructor_config')); - -$mode=get_config_mode($_SESSION['pa']['course_id']); -$template->setVariable("CONFIG_STRING", _AT('pa_tag_config_string')); -if ($mode==CONFIG_ENABLED){ - $template->setVariable("CONFIG_VALUE", _AT('pa_tag_config_enabled')); - $template->setVariable("CHECKED1", "checked=\"checked\""); -} else { - $template->setVariable("CONFIG_VALUE", _AT('pa_tag_config_disabled')); - $template->setVariable("CHECKED2", "checked=\"checked\""); -} - -$template->setVariable("FORM_NAME", "config_form"); -$template->setVariable("ACTION", $_SERVER['PHP_SELF']); -$template->setVariable("RADIO_VALUE1", "make_enabled"); -$template->setVariable("RADIO_STRING1", _AT('yes')); -$template->setVariable("RADIO_VALUE2", "make_disabled"); -$template->setVariable("RADIO_STRING2", _AT('no')); -$template->setVariable("SUBMIT_VALUE", _AT('pa_button_config_change')); - -$template->show(); -?> - \ No newline at end of file diff --git a/mods/photo_album/admin_image_list.php b/mods/photo_album/admin_image_list.php deleted file mode 100644 index 9fa7b5694..000000000 --- a/mods/photo_album/admin_image_list.php +++ /dev/null @@ -1,181 +0,0 @@ - - -isError()!=true){ //no error was found, so display the page - clear_temp_folder(); - $template=new HTML_Template_ITX("./Template"); - $template->loadTemplateFile("admin_image_list.tpl.php"); - $template->setVariable("ADMIN_NUMBER_OF_IMAGE", ADMIN_NUMBER_OF_IMAGE); - $course_name=get_course_title($admin->getVariable('course_id')); - switch ($admin->getVariable('mode')){ - case POSTED_NEW: - $template->setVariable("TITLE", _AT('pa_title_administrator_new_pic')." (".$course_name.")"); - break; - case APPROVED: - $template->setVariable("TITLE", _AT('pa_title_administrator_approved_pic')." (".$course_name.")"); - break; - case DISAPPROVED: - $template->setVariable("TITLE", _AT('pa_title_administrator_disapproved_pic')." (".$course_name.")"); - break; - } - - $mode=get_config_mode($admin->getVariable('course_id')); - $template->setVariable("CONFIG_STRING", _AT('pa_tag_config_string')); - if ($mode==CONFIG_ENABLED){ - $template->setVariable("CONFIG_VALUE", _AT('pa_tag_config_enabled')); - } else { - $template->setVariable("CONFIG_VALUE", _AT('pa_tag_config_disabled')); - } - - $template->setCurrentBlock("ADD_PART"); - $template->setVariable("ADD_FORM_NAME", "add_form"); - $template->setVariable("ADD_ACTION", UPLOAD_ACTION); - $template->setVariable("ADD_VALUE", _AT('pa_button_add_image')); - $template->setVariable("ADD_HIDDEN_VALUE", IMAGE); - $template->parseCurrentBlock("ADD_PART"); - - $template->setCurrentBlock("SELECT_PART"); - $template->setVariable("SELECT_FORM_NAME", "select_form"); - $template->setVariable("SELECT_ACTION", $_SERVER['PHP_SELF']); - $template->setVariable("SELECT_NAME", "mode"); - $template->setVariable("SELECT_LABEL", _AT('pa_tag_view')); - - $template->setCurrentBlock("OPTION_PART"); - $template->setVariable("OPTION_VALUE", POSTED_NEW); - $template->setVariable("OPTION_STRING", _AT('pa_tag_new_pic')); - $template->parseCurrentBlock("OPTION_PART"); - - $template->setCurrentBlock("OPTION_PART"); - $template->setVariable("OPTION_VALUE", APPROVED); - $template->setVariable("OPTION_STRING", _AT('pa_tag_approved_pic')); - $template->parseCurrentBlock("OPTION_PART"); - - $template->setCurrentBlock("OPTION_PART"); - $template->setVariable("OPTION_VALUE", DISAPPROVED); - $template->setVariable("OPTION_STRING", _AT('pa_tag_disapproved_pic')); - $template->parseCurrentBlock("OPTION_PART"); - - $template->setVariable("SELECT_SUBMIT", "select_submit"); - $template->setVariable("SELECT_SUBMIT_VALUE", _AT('pa_tag_go')); - $template->parseCurrentBlock("SELECT_PART"); - - $template->setCurrentBlock("IMAGE_TABLE_PART"); - $template->setVariable("IMAGE_TABLE_FORM_NAME", "table_form"); - $action_string=$_SERVER['PHP_SELF']."?mode=".$admin->getVariable('mode')."&current_page=".$admin->getVariable('current_page'); - $template->setVariable("IMAGE_TABLE_ACTION", $action_string); - - /* start display images */ - $image_array=$admin->image_array; - for ($i=0; $isetCurrentBlock("IMAGE_TABLE_DATA"); - $template->setVariable("CHECK_NAME", "imageId".$i); - $template->setVariable("CHECK_VALUE", $image_array[$i]['image_id']); - $img_src=$get_file.$image_array[$i]['location'].urlencode($image_array[$i]['thumb_image_name']); - $template->setVariable("IMAGE_TABLE_DATA1", "\"".$image_array[$i]['alt']."\"/"); - $template->setVariable("IMAGE_TABLE_DATA2", _AT('title').": ".$image_array[$i]['title']); - $template->setVariable("IMAGE_TABLE_DATA3", _AT('login').": ".$image_array[$i]['login']); - $template->setVariable("IMAGE_TABLE_DATA4", _AT('pa_tag_alt').": ".$image_array[$i]['alt']); - $template->setVariable("IMAGE_TABLE_DATA5", _AT('date').": ".$image_array[$i]['date']); - $template->setVariable("IMAGE_TABLE_DATA6", ""._AT('pa_tag_view_image_link').""); - $template->parseCurrentBlock("IMAGE_TABLE_DATA"); - } - $template->setVariable("CHECK_MESSAGE", _AT('pa_tag_check_all_image')); - - $template->setCurrentBlock("IMAGE_BUTTON"); - $template->setVariable("IMAGE_BUTTON_NAME", "button_disapprove"); - $template->setVariable("IMAGE_BUTTON_VALUE", _AT('pa_button_set_disapproved_pic')); - $template->parseCurrentBlock("IMAGE_BUTTON"); - - $template->setCurrentBlock("IMAGE_BUTTON"); - $template->setVariable("IMAGE_BUTTON_NAME", "button_approve"); - $template->setVariable("IMAGE_BUTTON_VALUE", _AT('pa_button_set_approved_pic')); - $template->parseCurrentBlock("IMAGE_BUTTON"); - - $template->setCurrentBlock("IMAGE_BUTTON"); - $template->setVariable("IMAGE_BUTTON_NAME", "button_post_new"); - $template->setVariable("IMAGE_BUTTON_VALUE", _AT('pa_button_set_new_pic')); - $template->parseCurrentBlock("IMAGE_BUTTON"); - - $template->parseCurrentBlock("IMAGE_TABLE_PART"); - - // Display page table - $page_array=$admin->getVariable('page_array'); - $current=$admin->getVariable('current_page'); - $template->setCurrentBlock("PAGE_TABLE_PART"); - if ($admin->getVariable('show_page_left_buttons')==true){ - $first_button=_AT('pa_tag_first_page_button'); - $previous_button=_AT('pa_tag_previous_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$first_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$previous_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - for ($i=$page_array['start']; $i<=$page_array['end']; $i++){ - if ($i==$current){ - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • '.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } else { - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>'.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - } - - if ($admin->getVariable('show_page_right_buttons')==true){ - $last_button=_AT('pa_tag_last_page_button'); - $next_button=_AT('pa_tag_next_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$next_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$last_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - $template->parseCurrentBlock("PAGE_TABLE_PART"); - $template->parseCurrentBlock(); - $template->show(); - unset($_SESSION['pa']); - $_SESSION['pa']['course_id']=$admin->getVariable('course_id'); - $_SESSION['pa']['administrator_mode']=true; -} else { - $msg->addError('pa_obj_pa_admin_image'); - redirect('../../index.php'); -} -?> - \ No newline at end of file diff --git a/mods/photo_album/classes/image_upload.class.php b/mods/photo_album/classes/image_upload.class.php deleted file mode 100644 index c5bd9facb..000000000 --- a/mods/photo_album/classes/image_upload.class.php +++ /dev/null @@ -1,256 +0,0 @@ -setVariable('temp_folder_path', $temp_folder_path); - $this->checkImageFile($file_array); - if (($this->getVariable('user_input_error')==0) && ($this->getVariable('image_copy_required')==true)){ //no error, so process image copy operation - $this->setVariable('name', $file_array['name']); - $this->copyViewImage(); - $this->copyThumbImage(); - } - } - - /** - * @desc This function checks the given file array is properly set up - * @param Array $file file array - */ - function checkImageFile(&$file){ - $this->checkImageEmpty($file['name']); - $this->checkValidType($file['type']); - $this->checkValidNameLength($file['name']); - $this->checkValidEscape($file['name']); - $this->checkValidSize($file['size']); - $this->setVariable('file_tmp_src', $file['tmp_name']); - - } - - /** - * @desc This function checks whether the image is submitted empty or not - * @param String $file image name - */ - function checkImageEmpty(&$file){ - if (empty($file)){ - $this->storeUserError("file_empty"); - } - } - - /** - * @desc This function stores the user input error - * @param String $string error string - */ - function storeUserError($string){ - $error_count=$this->getVariable('user_input_error'); - $error_array=&$this->user_input_array; - $error_array[$error_count]=&$string; - $this->setVariable('user_input_error', $error_count+1); - } - - /** - * @desc This function checks whether the image size is valid - * @param int $file image size - */ - function checkValidSize($file){ - $max_size=get_max_file_size(PA::getVariable('course_id')); - if ($max_size==-1){ - global $_config; - $max_size=$_config['max_file_size']; - } - if ($file > $max_size){ - $this->storeUserError('file_size'); - } else { - $this->setVariable('file_size', $file); - } - } - - /** - * @desc This function checks whether the image file name uses invalid escape characters or not - * @param String $file image file name - */ - function checkValidEscape(&$file){ - if (ereg(INVALID_ESCAPE, $file)){ - $this->storeUserError('file_escape'); - } - } - - /** - * @desc This function checks whether the image file name length is valid - * @param String $file image name - */ - function checkValidNameLength(&$file){ - if (count($file)>MAX_FILENAME_LENGTH){ - $this->storeUserError('file_length'); - } - } - - /** - * @desc This function checks whether the image type is valid - * @param String $type image type string - */ - function checkValidType($type){ - global $IMAGE_TYPE; - if (in_array($type, $IMAGE_TYPE)){ - $this->setVariable('file_type', $type); - } else { - $this->storeUserError('file_type'); - } - } - - /** - * @desc This function sets the string value for the class object - * @param String $string string name to be set - * @param mixed $value string value - */ - function setVariable($string, $value){ - switch ($string){ - case 'mode_edit': - case 'image_copy_required': - if (is_bool($value)){ - $this->{$string}=$value; - } else { - parent::storeError("string ".$string." is not boolean"); - } - break; - case 'file_type': - case 'file_tmp_src': - case 'name': - case 'thumb_image_name': - case 'view_image_name': - case 'temp_folder_path': - if (is_string($value)){ - $this->{$string}=$value; - } else { - parent::storeError("string ".$string." is not string"); - } - break; - case 'user_input_error': - if (is_int($value)){ - $this->{$string}=$value; - } else { - parent::storeError("string ".$string." is not int"); - } - break; - } - } - - /** - * @desc This function creates a full-sized image of the image file and copies it to the temp folder - */ - function copyViewImage(){ - $temp_folder_path=$this->getVariable('temp_folder_path'); - $view_image_name=modify_image_name($temp_folder_path, $this->getVariable('name')); - $this->setVariable('view_image_name', $view_image_name); - image_to_this_location($view_image_name, $this->getVariable('file_tmp_src'), $temp_folder_path); - $thumb=new phpThumb(); - $view_image_path=AT_CONTENT_DIR.$temp_folder_path.$view_image_name; - $thumb->setSourceFilename($view_image_path); - $size=getimagesize($view_image_path); - /* set size for view image */ - if ($size[0]>MAX_IMAGE_WIDTH){ - $thumb->w=MAX_IMAGE_WIDTH; - } - if (defined(MAX_IMAGE_HEIGHT) && $size[1]> MAX_IMAGE_HEIGHT){ - $thumb->h=MAX_IMAGE_HEIGHT; - } - - $thumb->iar='l'; - $thumb->config_output_format='jpeg'; - - /* generate for view image */ - if ($thumb->GenerateThumbnail()){ - if ($view_image_path){ - if (!$thumb->RenderToFile($view_image_path)){ - parent::storeError("render operation failed for view image"); - } - } else { - parent::storeError("view image path does not exist"); - } - } else { - parent::storeError("View generateThumbnail operation is failed"); - } - } - - /** - * @desc This function creates a thumbnail image of the image file and stores it in the temp folder - */ - function copyThumbImage(){ - $temp_folder_path=$this->getVariable('temp_folder_path'); - $thumb_image_name=insert_into_image_name($this->getVariable('view_image_name'), THUMB_EXT); - $thumb_image_name=modify_image_name($temp_folder_path, $thumb_image_name); - $this->setVariable('thumb_image_name', $thumb_image_name); - $thumb=new phpThumb(); - $view_image_path=AT_CONTENT_DIR.$temp_folder_path.$this->getVariable('view_image_name'); - $thumb->setSourceFilename($view_image_path); - $size=getimagesize($view_image_path); - /* set size for thumb image */ - $thumb->iar='l'; - $thumb->config_output_format='jpeg'; - - /* set size for thumb image */ - $thumb->h=THUMB_IMAGE_HEIGHT; - $thumb->w=THUMB_IMAGE_WIDTH; - - /* generate for thumb image */ - $thumb_image_path=AT_CONTENT_DIR.$temp_folder_path.$thumb_image_name; - if ($thumb->GenerateThumbnail()){ - if ($view_image_path){ - if (!$thumb->RenderToFile($thumb_image_path)){ - parent::storeError("render operation failed for thumb image"); - } - } else { - parent::storeError("view image path does not exist"); - } - } else { - parent::storeError("Thumb generateThumbnail operation is failed"); - } - } -} -?> diff --git a/mods/photo_album/classes/pa.class.php b/mods/photo_album/classes/pa.class.php deleted file mode 100644 index 105c2fcdf..000000000 --- a/mods/photo_album/classes/pa.class.php +++ /dev/null @@ -1,157 +0,0 @@ - 0){ - define('PATH', $matches[1]); - } else { - define('PATH', './'); - } -} - -require_once (PATH.'define.php'); -require_once (PATH.'include/data_func.php'); -require_once (PATH.'include/general_func.php'); -require_once (PATH.'HTML/Template/ITX.php'); - -/** - * @desc This class is called Pa. This class is used by every other class - */ -class Pa { - var $course_id=-1; - var $error=0; - var $error_array=Array(); - - /** - * @desc constructor. - */ - function Pa (){ - Pa::init(); - } - - /** - * @desc This function initializes the class object - */ - function init(){ - Pa::checkGuest(); - Pa::checkEnrolled(); - Pa::setCourseId(); - } - - /** - * @desc This function checks whether the user is enrolled in the course or not - */ - function checkEnrolled(){ - if ($_SESSION['privileges']>0){ - Pa::setVariable('show_modification_buttons', true); - } else if (isset($_SESSION['enroll']) && ($_SESSION['enroll']==true)){ - Pa::setVariable('show_modification_buttons', true); - } - } - - /** - * @desc This function checks whether the user is guest. If the user is guest, it redirects the user to login page - */ - function checkGuest(){ - if (isset($_SESSION['is_guest']) && ($_SESSION['is_guest']==true)){ - redirect('../../'.PATH.'login.php'); - } - } - - /** - * @desc This function sets the course id - */ - function setCourseId(){ - if (isset($_POST['course_id']) && course_exist($_POST['course_id'])){ - Pa::setVariable('course_id', intval($_POST['course_id'])); - } else if ($_SESSION['course_id']==-1){ - Pa::setVariable('course_id', intval($_SESSION['pa']['course_id'])); - } else { - Pa::setVariable('course_id', intval($_SESSION['course_id'])); - } - } - - /** - * @desc This function sets the given input string for the class object variable - * @param String $string string name to be set - * @param mixed $value string value - */ - function setVariable($string, $value){ - switch ($string){ - case 'course_id': - if (is_int($value) && ($value > 0) && course_exist($value)){ - $this->{$string}=$value; - } else { - $this->storeError("course value is not valid"); - } - break; - case 'error': - if (is_int($value) && ($value > 0)){ - $this->{$string}=$value; - } else { - $this->storeError("value ".$value." is not int"); - } - break; - case 'show_modification_buttons': - if (is_bool($value)){ - $this->{$string}=$value; - } else { - $this->storeError("value ".$value." is not boolean"); - } - break; - } - } - - /** - * @desc This function returns the given variable value - * @param String $string name of string to be returned - * @return mixed the required variable value - */ - function getVariable($string){ - return $this->{$string}; - } - - - /** - * @desc This function stores the fatal error for the class object. This function is only called when a fatal error is occured. - * @param String $string error string to be stored - */ - function storeError($string){ - $error=&Pa::getVariable('error'); - $array=&$this->error_array; - $array[$error]=$string; - Pa::setVariable('error', $error+1); - } - - /** - * @desc This function checks if a fatal error has occurred or not in the class object - * @return boolean true if there is fatal error - */ - function isError(){ - if (Pa::getVariable('error')==0){ - return false; - } else { - return true; - } - } -} \ No newline at end of file diff --git a/mods/photo_album/classes/pa_admin_comment.class.php b/mods/photo_album/classes/pa_admin_comment.class.php deleted file mode 100644 index 7f507c7eb..000000000 --- a/mods/photo_album/classes/pa_admin_comment.class.php +++ /dev/null @@ -1,180 +0,0 @@ -checkAuthority(); - parent::init(); - $this->checkRequest(); - $this->setMode(); - $this->checkCurrentPage(); - $this->setComments(); - $this->setPages(); - - } - - /** - * @desc This function checks requests to change the comment status. The request could be one of make approved, make disapproved, or make new - */ - function checkRequest(){ - if (isset($_POST['button_disapprove'])){ - for ($i=0; $i < ADMIN_NUMBER_OF_COMMENT; $i++){ - $string="commentId".$i; - if (isset($_POST[$string])){ - modify_comment_status($_POST[$string], $this->getVariable('course_id'), DISAPPROVED); - } - } - } else if (isset($_POST['button_approve'])){ - for ($i=0; $i< ADMIN_NUMBER_OF_COMMENT; $i++){ - $string="commentId".$i; - if (isset($_POST[$string])){ - modify_comment_status($_POST[$string], $this->getVariable('course_id'), APPROVED); - } - } - } else if (isset($_POST['button_post_new'])){ - for ($i=0; $i < ADMIN_NUMBER_OF_COMMENT; $i++){ - $string="commentId".$i; - if (isset($_POST[$string])){ - modify_comment_status($_POST[$string], $this->getVariable('course_id'), POSTED_NEW); - } - } - } - } - - /** - * @desc This function checks whether the user is instructor or administrator. If the user is neither instructor nor administrator, it redirects the user to the index page - */ - function checkAuthority(){ - if (is_admin_for_course()!=true){ - redirect('index.php'); - } - } - - /** - * @desc This function decides whether to display left arrow and right arrow buttons in the page table - */ - function setPages(){ - $temp=get_page_array(ADMIN_NUMBER_OF_COMMENT,ADMIN_NUMBER_OF_COMMENT_PAGE, $this->getVariable('current_page'), $this->getVariable('last_page')); - $current=$this->getVariable('current_page'); - if ($current > 1){ - $this->setVariable('show_page_left_buttons', true); - } - if ($current < $temp['last_page']){ - $this->setVariable('show_page_right_buttons', true); - } - $this->page_array=&$temp; - - } - - /** - * @desc This function sets the mode value for the comment display. The mode value can be one of POSTED_NEW, APPROVED, DISAPPROVED - */ - function setMode(){ - if (isset($_GET['mode'])){ - $this->setVariable('mode', intval($_GET['mode'])); - } - } - - /** - * @desc This function checks if the current page is valid. Otherwise, the current page is set to 1 - */ - function checkCurrentPage(){ - $total=get_total_comment_number(ADMIN_PANEL, $this->getVariable('course_id'), $this->getVariable('mode')); - $last_page=get_last_page(ADMIN_NUMBER_OF_COMMENT, $total); - $this->setVariable('total', $total); - $this->setVariable('last_page', $last_page); - - if (!isset($_GET['current_page'])){ - $this->setVariable('current_page', FIRST_PAGE); - } else { - $current_page=to_pos_int($_GET['current_page']); - if ($current_page > $last_page){ - $this->setVariable('current_page',$last_page); - } else { - $this->setVariable('current_page', $current_page); - } - } - } - - /** - * @desc This function sets the data for the comment array - */ - function setComments(){ - $temp=get_comment_array(ADMIN_PANEL, parent::getVariable('course_id'), $this->getVariable('mode'), NOT_SET, ADMIN_NUMBER_OF_COMMENT, $this->getVariable('current_page')); - $this->comment_array=&$temp; - } - - /** - * @desc This function sets the given string value for the class object - * @param String $string string name to be set - * @param mixed $value string value - */ - function setVariable($string, $value){ - switch ($string){ - case 'mode': - if ($value==APPROVED || $value==DISAPPROVED || $value==POSTED_NEW){ - $this->{$string}=$value; - } - break; - case 'current_page': - case 'total': - case 'last_page': - if (is_int($value)){ - $this->{$string}=$value; - } else { - parent::storeError("value ".$string." is not integer"); - } - break; - case 'show_page_left_buttons': - case 'show_page_right_buttons': - if (is_bool($value)){ - $this->{$string}=$value; - } else { - parent::storeError("value ".$string." is not boolean"); - } - break; - } - } -} \ No newline at end of file diff --git a/mods/photo_album/classes/pa_admin_image.class.php b/mods/photo_album/classes/pa_admin_image.class.php deleted file mode 100644 index 4468ecc33..000000000 --- a/mods/photo_album/classes/pa_admin_image.class.php +++ /dev/null @@ -1,178 +0,0 @@ -checkAuthority(); - parent::init(); - $this->checkRequest(); - $this->setMode(); - $this->checkCurrentPage(); - $this->setImages(); - $this->setPages(); - - } - - /** - * @desc This function checks the request to change the image status. The request could be make approved, make disapproved, or make new - */ - function checkRequest(){ - if (isset($_POST['button_disapprove'])){ - for ($i=0; $i < ADMIN_NUMBER_OF_IMAGE_PAGE; $i++){ - $string="imageId".$i; - if (isset($_POST[$string])){ - modify_image_status($_POST[$string], $this->getVariable('course_id'), DISAPPROVED); - } - } - } else if (isset($_POST['button_approve'])){ - for ($i=0; $i< ADMIN_NUMBER_OF_IMAGE_PAGE; $i++){ - $string="imageId".$i; - if (isset($_POST[$string])){ - modify_image_status($_POST[$string], $this->getVariable('course_id'), APPROVED); - } - } - } else if (isset($_POST['button_post_new'])){ - for ($i=0; $i < ADMIN_NUMBER_OF_IMAGE_PAGE; $i++){ - $string="imageId".$i; - if (isset($_POST[$string])){ - modify_image_status($_POST[$string], $this->getVariable('course_id'), POSTED_NEW); - } - } - } - } - - /** - * @desc This function checks if the user is an instructor or an administrator. If the user is neither instructor nor administrator, it redirects the user to the index page - */ - function checkAuthority(){ - if (is_admin_for_course()!=true){ - redirect('index.php'); - } - } - - /** - * @desc This function decides whether to display left arrow and right arrow buttons on the page table - */ - function setPages(){ - $temp=get_page_array(ADMIN_NUMBER_OF_IMAGE, ADMIN_NUMBER_OF_IMAGE_PAGE, $this->getVariable('current_page'), $this->getVariable('last_page')); - $current=$this->getVariable('current_page'); - if ($current > 1){ - $this->setVariable('show_page_left_buttons', true); - } - if ($current < $temp['last_page']){ - $this->setVariable('show_page_right_buttons', true); - } - $this->page_array=&$temp; - - } - - /** - * @desc This function sets the mode value for the image display. The mode value can be POSTED_NEW, APPROVED, or DISAPPROVED - */ - function setMode(){ - if (isset($_GET['mode'])){ - $this->setVariable('mode', intval($_GET['mode'])); - } - } - - /** - * @desc This function checks if the current page is valid. Otherwise, the current page is set to 1 - */ - function checkCurrentPage(){ - $total=get_total_image_number(ADMIN_PANEL, $this->getVariable('course_id'), $this->getVariable('mode')); - $last_page=get_last_page(ADMIN_NUMBER_OF_IMAGE, $total); - $this->setVariable('total', $total); - $this->setVariable('last_page', $last_page); - if (!isset($_GET['current_page'])){ - $this->setVariable('current_page', FIRST_PAGE); - } else { - $current_page=to_pos_int($_GET['current_page']); - if ($current_page > $last_page){ - $this->setVariable('current_page',$last_page); - } else { - $this->setVariable('current_page', $current_page); - } - } - } - - /** - * @desc This function sets the image array - */ - function setImages(){ - $temp=get_image_array(ADMIN_PANEL, parent::getVariable('course_id'), $this->getVariable('mode'), $this->getVariable('current_page'), ADMIN_NUMBER_OF_IMAGE); - $this->image_array=&$temp; - } - - /** - * @desc This function sets the given string value for the class object - * @param String $string string name to be set - * @param mixed $value string value - */ - function setVariable($string, $value){ - switch ($string){ - case 'mode': - if ($value==APPROVED || $value==DISAPPROVED || $value==POSTED_NEW){ - $this->{$string}=$value; - } - break; - case 'current_page': - case 'last_page': - case 'total': - if (is_int($value)){ - $this->{$string}=$value; - } else { - parent::storeError("value ".$string." is not integer"); - } - break; - case 'show_page_left_buttons': - case 'show_page_right_buttons': - if (is_bool($value)){ - $this->{$string}=$value; - } else { - parent::storeError("value ".$string." is not boolean"); - } - break; - } - } -} \ No newline at end of file diff --git a/mods/photo_album/classes/pa_index.class.php b/mods/photo_album/classes/pa_index.class.php deleted file mode 100644 index d16989ddf..000000000 --- a/mods/photo_album/classes/pa_index.class.php +++ /dev/null @@ -1,118 +0,0 @@ -checkCurrentPage(); - $this->setImages(); - $this->setPages(); - } - - /** - * @desc this function sets the image array to display the index page - */ - function setImages(){ - $temp=get_image_array(STUDENT, $this->getVariable('course_id'), APPROVED, $this->getVariable('current_page'), THUMB_NUMBER_OF_IMAGE); - $this->image_array=&$temp; - } - - /** - * @desc This function decides whether the left arrow and right arrow button should be displayed in the page table - */ - function setPages(){ - $temp=get_page_array(THUMB_NUMBER_OF_IMAGE, THUMB_NUMBER_OF_IMAGE_PAGE, $this->getVariable('current_page'), $this->getVariable('last_page')); - if ($temp['current'] >1 ){ - $this->setVariable('show_page_left_buttons', true); - } - if ($temp['current'] < $temp['last_page']){ - $this->setVariable('show_page_right_buttons', true); - } - $this->page_array=&$temp; - } - - /** - * @desc This function sets the given string value - * @param String $string string name to be set up - * @param mixed $value string value - */ - function setVariable($string, $value){ - switch ($string){ - case 'current_page': - case 'total': - case 'last_page': - if (is_int($value)){ - $this->{$string}=$value; - } else { - parent::storeError("variable ".$string." is not an positive int"); - } - break; - case 'show_page_left_buttons': - case 'show_page_right_buttons': - if (is_bool($value)){ - $this->{$string}=$value; - } else { - parent::storeError("variable ".$string." is not boolean"); - } - break; - } - } - - /** - * @desc This function checks whether the current page value is valid. Otherwise it sets 1 for the current page value - */ - function checkCurrentPage(){ - $total=get_total_image_number(STUDENT, $this->getVariable('course_id'), APPROVED); - $last_page=get_last_page(THUMB_NUMBER_OF_IMAGE, $total); - $this->setVariable('total', $total); - $this->setVariable('last_page', $last_page); - - if (!isset($_GET['current_page'])){ - $this->setVariable('current_page', FIRST_PAGE); - } else { - $current_page=to_pos_int($_GET['current_page']); - if ($current_page > $last_page){ - $this->setVariable('current_page',$last_page); - } else { - $this->setVariable('current_page', $current_page); - } - } - } -} \ No newline at end of file diff --git a/mods/photo_album/classes/pa_mycomment.class.php b/mods/photo_album/classes/pa_mycomment.class.php deleted file mode 100644 index 84ec777e5..000000000 --- a/mods/photo_album/classes/pa_mycomment.class.php +++ /dev/null @@ -1,141 +0,0 @@ -setMode(); - $this->checkCurrentPage(); - $this->setComments(); - $this->setPages(); - - } - - /** - * @desc This function decides whether to display left arrow and right arrow buttons in the page table - */ - function setPages(){ - $temp=get_page_array(MYCOMMENT_NUMBER_OF_COMMENT, MYCOMMENT_NUMBER_OF_COMMENT_PAGE, $this->getVariable('current_page'), $this->getVariable('last_page')); - $current=$this->getVariable('current_page'); - if ($current > 1){ - $this->setVariable('show_page_left_buttons', true); - } - if ($current < $temp['last_page']){ - $this->setVariable('show_page_right_buttons', true); - } - $this->page_array=&$temp; - - } - - /** - * @desc This function sets the mode value for the comments displayed. The mode value can be one of POSTED_NEW, APPROVED, DISAPPROVED - */ - function setMode(){ - if (isset($_GET['mode'])){ - $this->setVariable('mode', intval($_GET['mode'])); - } - } - - /** - * @desc This function checks the current page is valid. Otherwise, the current page is 1 - */ - function checkCurrentPage(){ - $total=get_total_comment_number(MY_COMMENT, $this->getVariable('course_id'), $this->getVariable('mode')); - $last_page=get_last_page(MYCOMMENT_NUMBER_OF_COMMENT, $total); - $this->setVariable('total', $total); - $this->setVariable('last_page', $last_page); - - if (!isset($_GET['current_page'])){ - $this->setVariable('current_page', FIRST_PAGE); - } else { - $current_page=to_pos_int($_GET['current_page']); - if ($current_page > $last_page){ - $this->setVariable('current_page',$last_page); - } else { - $this->setVariable('current_page', $current_page); - } - } - } - - /** - * @desc This function sets the comment array - */ - function setComments(){ - $array=get_comment_array(MY_COMMENT, parent::getVariable('course_id'), $this->getVariable('mode'), NOT_SET, MYCOMMENT_NUMBER_OF_COMMENT, $this->getVariable('current_page')); - $this->comment_array=&$array; - } - - /** - * @desc This function sets the given string value for the class object - * @param String $string string name to set - * @param mixed $value string value - */ - function setVariable($string, $value){ - switch ($string){ - case 'mode': - if ($value==APPROVED || $value==DISAPPROVED || $value==POSTED_NEW){ - $this->{$string}=$value; - } - break; - case 'current_page': - case 'last_page': - case 'total': - if (is_int($value)){ - $this->{$string}=$value; - } else { - parent::storeError("value ".$string." is not integer"); - } - break; - case 'show_page_left_buttons': - case 'show_page_right_buttons': - if (is_bool($value)){ - $this->{$string}=$value; - } else { - parent::storeError("value ".$string." is not boolean"); - } - break; - } - } -} \ No newline at end of file diff --git a/mods/photo_album/classes/pa_mypic.class.php b/mods/photo_album/classes/pa_mypic.class.php deleted file mode 100644 index 0ebe3c50c..000000000 --- a/mods/photo_album/classes/pa_mypic.class.php +++ /dev/null @@ -1,140 +0,0 @@ -setMode(); - $this->checkCurrentPage(); - $this->setImages(); - $this->setPages(); - - } - - /** - * @desc This function decides whether to display left arrow and right arrow buttons for the page table - */ - function setPages(){ - $temp=get_page_array(MYPIC_NUMBER_OF_IMAGE, MYPIC_NUMBER_OF_IMAGE_PAGE, $this->getVariable('current_page'), $this->getVariable('last_page')); - $current=$this->getVariable('current_page'); - if ($current > 1){ - $this->setVariable('show_page_left_buttons', true); - } - if ($current < $temp['last_page']){ - $this->setVariable('show_page_right_buttons', true); - } - $this->page_array=&$temp; - - } - - /** - * @desc This function sets the mode value for the image display. The mode value can be one of POSTED_NEW, APPROVED, DISAPPROVED - */ - function setMode(){ - if (isset($_GET['mode'])){ - $this->setVariable('mode', intval($_GET['mode'])); - } - } - - /** - * @desc This function checks the current page is valid. Otherwise, the current page is set to 1 - */ - function checkCurrentPage(){ - $total=get_total_image_number(MY_PIC, $this->getVariable('course_id'), $this->getVariable('mode')); - $last_page=get_last_page(MYPIC_NUMBER_OF_IMAGE, $total); - $this->setVariable('total', $total); - $this->setVariable('last_page', $last_page); - - if (!isset($_GET['current_page'])){ - $this->setVariable('current_page', FIRST_PAGE); - } else { - $current_page=to_pos_int($_GET['current_page']); - if ($current_page > $last_page){ - $this->setVariable('current_page',$last_page); - } else { - $this->setVariable('current_page', $current_page); - } - } - } - - /** - * @desc This function sets the image array - */ - function setImages(){ - $array=get_image_array(MY_PIC, parent::getVariable('course_id'), $this->getVariable('mode'), $this->getVariable('current_page'), MYPIC_NUMBER_OF_IMAGE, $_SESSION['login']); - $this->image_array=&$array; - } - - /** - * @desc This function sets the given string to a value for the class object - * @param String $string string name to set up - * @param mixed $value string value - */ - function setVariable($string, $value){ - switch ($string){ - case 'mode': - if ($value==APPROVED || $value==DISAPPROVED || $value==POSTED_NEW){ - $this->{$string}=$value; - } - break; - case 'current_page': - case 'last_page': - case 'total': - if (is_int($value)){ - $this->{$string}=$value; - } else { - parent::storeError("value ".$string." is not integer"); - } - break; - case 'show_page_left_buttons': - case 'show_page_right_buttons': - if (is_bool($value)){ - $this->{$string}=$value; - } else { - parent::storeError("value ".$string." is not boolean"); - } - break; - } - } -} \ No newline at end of file diff --git a/mods/photo_album/classes/pa_view.class.php b/mods/photo_album/classes/pa_view.class.php deleted file mode 100644 index 2c76d48f0..000000000 --- a/mods/photo_album/classes/pa_view.class.php +++ /dev/null @@ -1,111 +0,0 @@ -checkImageId(); - $this->checkAuthority(); - $this->setImage(); - $this->setComments(); - } - - /** - * @desc This function checks if the image has approved status. If the image is not set to approved and user is neither admin nor instructor, it redirects user to the index page - */ - function checkAuthority(){ - $image_array=get_single_data(IMAGE, $this->getVariable('image_id'), parent::getVariable('course_id')); - if (!(($_SESSION['is_admin']==true) || ($_SESSION['privileges'] > 0))){ - if ($image_array['status']!=APPROVED){ - global $msg; - $msg->addError('pa_var_unauthorized'); - redirect('index.php'); - } - } - } - - /** - * @desc This function checks whether the given image_id exists in the database - */ - function checkImageId(){ - global $msg; - if (isset($_GET['image_id'])){ - if (image_exist(intval($_GET['image_id']), parent::getVariable('course_id'))){ - $this->setVariable('image_id', intval($_GET['image_id'])); - } else { - $msg->addError('pa_var_unauthorized'); - redirect('index.php'); - } - } else { - $msg->addError('pa_var_unauthorized'); - redirect ('index.php'); - } - } - - /** - * @desc This function sets the string to a value - * @param String $string string name to set up - * @param mixed $value string value - */ - function setVariable($string, $value){ - switch ($string){ - case 'image_id': - if (is_int($value) && ($value > 0)){ - $this->{$string}=$value; - } else { - parent::storeError("string ".$string." is not integer"); - } - break; - } - } - - /** - * @desc This function sets the image array - */ - function setImage(){ - $this->image_array=&get_single_data(IMAGE, $this->getVariable('image_id'), parent::getVariable('course_id')); - } - - /** - * @desc This function sets the comment array - */ - function setComments(){ - $this->comment_array=&get_comment_array(ADMIN_VIEW, $this->getVariable('course_id'), NOT_SET, $this->getVariable('image_id')); - } -} \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/cache/index.php b/mods/photo_album/classes/phpThumb_1.7.2/cache/index.php deleted file mode 100644 index cee9927f2..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/cache/index.php +++ /dev/null @@ -1,4 +0,0 @@ - \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/cache/source/index.php b/mods/photo_album/classes/phpThumb_1.7.2/cache/source/index.php deleted file mode 100644 index cee9927f2..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/cache/source/index.php +++ /dev/null @@ -1,4 +0,0 @@ - \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.changelog.txt b/mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.changelog.txt deleted file mode 100644 index 99bb24e59..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.changelog.txt +++ /dev/null @@ -1,1137 +0,0 @@ -////////////////////////////////////////////////////////////// -/// phpThumb() by James Heinrich // -// available at http://phpthumb.sourceforge.net /// -////////////////////////////////////////////////////////////// - -¤ = structure change or important new feature -* = less important new feature or change - -v1.7.2 - June 22, 2006 - ¤ [#1256693] Added $this->exif_raw_data which is returned - data from exif_read_data() on source image. - Requires PHP v4.2.0+ (thanks tebiØusers*sourceforge*net) - ¤ Added $this->outputImageData and RenderOutput() to allow - easy outputting of thumbnail data to a database or such. - Call RenderOutput() instead of RenderToFile() and then - access raw data in $this->outputImageData - (thanks r*cremerØswitch*nl) - ¤ Added 'crop' filter, which is applied after resizing (as - opposed to sx,sy,sw,sh which are before resizing) - (thanks scottØscottjehl*com) - * Enable creating new images with PATH_INFO style call - (thanks edenØinstyleit*com*au) - * Added warning message to encourage users not to use - full HTTP paths for "src" parameter - * Added fallback 'preg_quote' to phpthumb.functions.php in - case your PHP installation does not have preg_* functions - (thanks mortenØemeskay*dk) - * Added fallback 'imagesavealpha' if GD < v2.0.1 - (thanks oliver*heegerØweb*de) - * Added fallback 'imagealphablending' if GD < v2.0.1 - (thanks oliver*heegerØweb*de) - * Added 'nocache' parameter that suppresses writing to cache - file, but only if high_security_enabled is set - (thanks federicoØdonelleschi*com) - * Attempt to detect supported ImageMagick features - (thanks simonØjapancentre*com) - * Added temp dir detection to phpThumb.demo.check.php - * Added ImageMagick dir to phpThumb.demo.check.php - * Added ImageMagick features to phpThumb.demo.check.php - * Default (config_allow_src_above_docroot = true) when PHP - running in "cli" mode (thanks flobeeØgmail*com) - * Bugfix: [#1470791] 'iar' not working properly with - ImageMagick (thanks w1xØusers*sourceforge*net) - * Bugfix: [#1498564] illegal characters in cache filenames - (thanks carl-evertØusers*sourceforge*net) - * Bugfix: 'sx','sy','sw','sh','zc' cache parameters broken - (thanks federicoØdonelleschi*com) - * Bugfix: 'config_max_source_pixels' incorrectly handled - (thanks oliver*heegerØweb*de) - * Bugfix: 'aoe' not working properly - (thanks w1xØusers*sourceforge*net) - * Bugfix: setParameter() was broken for arrays - * Bugfix: setSourceFilename() wasn't setting 'src' - * Bugfix: suppress stat()-related file permission - notices (thanks lanceØmainecoastdesign*com) - * Bugfix: image format now initialized during ErrorImage() - * Bugfix: domain matching now case-insensitive - * Bugfix: some versions of ImageMagick not detected - (thanks arvidØfys*ku*dk) - * Bugfix: sometimes no image returned in safe_mode - (thanks bkainersØgmail*com) - * Bugfix: 'far' not always handled correctly - (thanks matthew*newtonØrealworldweb*com) - * Bugfix: PATH_INFO method not working if no filters specified - (thanks jjimenezØpracticaldata*com) - * Bugfix: first (internal) call to ImageMagickVersion() failed - under Windows - * Bugfix: Images source-cropped AND resized with ImageMagick were - wrong size (cropped size, not resized size) - (thanks joao*saleiroØwebfuel*pt) - * Bugfix: stat() warnings in CleanUpCacheDirectory() - (thanks christianØhss-haage*de) - * Bugfix: $PHPTHUMB_DEFAULTS not working when no other processing - parameters specified (thanks tbittnersØcox*net) - - -v1.7.1 - March 16, 2006 - * /demo/phpThumb.demo.check.php now checks: - - server software - - local and master config values (with ini_get and - get_cfg_var respectively) (thanks nEUTRonØgmx*tm) - - existance of assorted PHP functions and explains their - importance - * Bugfix: config_error_die_on_error now defaults to FALSE to - prevent object-mode errors dying in an error image - (thanks moshØtobt*de; riteshgupta1974Øgmail*com) - * Bugfix: setParameter() now handles array parameters (such - as 'fltr') by appending $value to $parameter - * Bugfix: /demo/phpThumb.demo.check.php incorrect CURL value - under PHP5 (thanks nEUTRonØgmx*tm) - * Bugfix: [#1439110] Limit fread() calls to 8kB - (see http://bugs.php.net/bug.php?id=35859) - (thanks andig2Øusers*sourceforge*net) - * Bugfix: Prevent RenderToFilename() from trying to render - to URLs (thanks Tim*MasseyØitrm*co*uk) - * Bugfix: [#1438657] missing path in phpThumbURL() - (thanks terracesØusers*sourceforge*net) - * Bugfix: zoomcrop was broken for non-square output - (thanks alisonØsemidivine*com, federicoØdonelleschi*com) - * Bugfix: suppress error messages when stat access to temp - dir is disabled (thanks rfineØvnuinc*com) - * Bugfix: ImageMagick processing was broken for source - images of types not supported by GetImageSize - (thanks rfineØvnuinc*com) - -v1.7.0 - February 15, 2006 - ¤ ImageMagick output is used directly far more frequently - for much improved speed and minor quality improvement. - ¤ ImageMagick now processes most of the image filters if - possible (will fall back to GD methods if unavailable) - ¤ GD support is now optional if ImageMagick is installed. - Known limitations include: - - no support for HTTP source images - - ICO output is buggy (in some ImageMagick versions) - - most &fltr[] filters don't work at all - - 'ar', 'ra', 'far' don't work - ¤ Added output support for ICO (icon) format (&f=ico). - Currently only supports single-image icons, but multi- - resolution support may be added in future versions - New file: phpthumb.ico.php - ¤ Added output support for BMP (bitmap) format (&f=bmp). - Currently only supports 24-bit RGB format (for simplicity) - ¤ Added new configuration & compatability checker - New file: demo/phpThumb.demo.check.php - * ImageMagick-generated thumbnails now have extra hidden - contents (EXIF data, etc) stripped (by using -thumbnail - instead of -resize) resulting in smaller filesizes - * Added background fill color, opacity and extent options to - 'wmt' filter (thanks craigØpc-fanatics*com) - * Added metacharacter (^*) support for 'wmt', currently: - source filesize in bytes (^Fb), kB (^Fk), MB (^Fm), - source image width (^X), source image height (^Y), - thumbnail width (^x), thumbnail height (^y) and caret (^^) - (Feature Request #1357815) - (thanks ticklemeozmoØusers*sourceforge*net) - * Moved ImageDestroy call from OutputThumbnail to end of - phpThumb.php to allow multiple calls to OutputThumbnail - * Added config_http_user_agent for site with browsersniffers - (thanks redrobØgmail*com) - * Added $PHPTHUMB_CONFIG['disable_pathinfo_parsing'] (default - false) which disables parsing $_SERVER[PATH_INFO] for - parameters. If you want to parse PATH_INFO, set to false - * Added $PHPTHUMB_CONFIG['disable_imagecopyresampled'] (default - false) which replaces ImageCopyResampled with - ImageCopyResampleBicubic for buggy PHP-GD versions - (thanks g*pelagattiØnetface*it) - * Added $PHPTHUMB_CONFIG['cache_prefix'] to allow sharing of - cache files across virtual servers (Feature Request #1395332) - (thanks doggyfrØusers*sourceforge*net) - * Added $PHPTHUMB_CONFIG['disable_onlycreateable_passthru'] with - default=true (increased speed) to allow direct passthru of - images that don't have GD support. (Feature Request #1396446) - (thanks zedboyØusers*sourceforge*net) - * Removed $PHPTHUMB_CONFIG['cache_differentiate_offsite'] because - it is now automatically tied in with nooffsitelink_enabled - (thanks doggysworldØlibertysurf*fr) - * Removed phpThumb.demo.cacheconvert2.php - * Debug messages are now passed back from filters - * $PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] now - defaults to true for much-improved cached performance - (thanks redrobØgmail*com) - * $PHPTHUMB_CONFIG['cache_differentiate_offsite'] now defaults - to false - * Added $PHPTHUMB_DEFAULTS['ar']='x' to phpThumb.config.php.default - * Added ImageDestroy($this->gdimg_source) to GenerateThumbnail() - to save memory before applying image filters - * gd_info() no longer member of phpthumb_functions - * cache files now default to using SERVER_NAME without 'www.' - * phpUnsharpMask::applyUnsharpMask() should be faster under PHP5 by - using ImageFilter(IMG_FILTER_GAUSSIAN_BLUR) when radius==1 - * Added alternate CURL method for HTTP source images if - allow_url_fopen is disabled (thanks webweberØmotiondraw*com) - * Replaced $this->osslash with DIRECTORY_SEPARATOR constant - * Bugfix: [#1398327] 'new' got broken (1x1 images) - * Bugfix: [#1412552] HTTP source images with special characters were - not getting urlencoded - * Bugfix: ImageSaveAlpha errors on GD v2.0.0 - * Bugfix: phpThumbDebug now entirely disabled if high_security=true - * Bugfix: source images with transparency lost transparency when - rotated (thanks roalklØyahoo*com) - * Bugfix: square source images were not resized when only (w|h)(p|l) - parameters passed - * Bugfix: source images are passed through unmodified in more cases - * Bugfix: ImageMagick not used on systems where it exists outside - defined open_basedir - * Bugfix: ImageMagickVersion() now returns correct versionstring - * Bugfix: ImageMagick warnings no longer cause ImageMagick to fail - * Bugfix: ErrorImage no longer fatal to phpThumbDebug - * Bugfix: "Array to string conversion" in foreach($a as $v) loops - (thanks zeeshanØtargetedmedia*co*uk) - * Bugfix: safe mode warnings in ImageCreateFromStringReplacement - (thanks adminØalex-home*net) - * Bugfix: nooffsitelink broken if !nooffsitelink_require_refer - (thanks depronØgmx*net) - * Bugfix: phpThumb failed when magic_quotes_runtime=true - (thanks stansawyerØyahoo*com) - * Bugfix: several issues with HTTP image sources - (thanks redrobØgmail*com) - * Bugfix: phpThumb_tempnam() would return incomplete temp filenames - under Windows, which may result in orphaned zero-byte temp files - in C:\ if multiple drives exist - -v1.6.2 - November 24, 2005 - ¤ Animated GIF output is now possible if ImageMagick is - available and no filters (other than resize) are applied - (thanks brandenbassØgmail*com for idea) - * Added $PHPTHUMB_CONFIG['cache_force_passthru'] to work - around cached-image-only-works-second-time issue - (thanks yakoØ11y11*com) - * Bugfix: black borders on some image edges - (thanks atelierØdelirius*ch && chuckØcatalyststudio*com) - * Bugfix: uncaught PHP warning in RenderToFile DebugMessage - * Bugfix: allow phpThumbDebug in noGD PHP installations - * Bugfix: 'hash' warning in high_security mode - (thanks bernhardØwtf*at) - * Bugfix: non-TTF rotated text watermarks now work (unrotated) - with no warnings if ImageRotate is unavailable - (thanks aparviaiØusers*sourceforge*net) - -v1.6.1 - August 26, 2005 - ¤ Filters now use GD functions where available (using - ImageFilter, only available in PHP v5.0.0+ with bundled - version of GD). Enabled for: colorize, negative, - grayscale, brightness, contrast, gaussian blur, selective - blur, mean removal (thanks donlaurØmac*com) - ¤ Added config_prefer_imagemagick (defaults=true) - ¤ Added phpthumb_filters::Grayscale() 'gray' - ¤ Added phpthumb_filters::ReduceColorDepth() 'rcd' - ¤ Added phpthumb_filters::Brightness() 'brit' - ¤ Added phpthumb_filters::Contrast() 'cont' - ¤ Added phpthumb_filters::Saturation() 'sat' - ¤ Added phpthumb_filters::EdgeDetect() 'edge' [PHP5 only] - ¤ Added phpthumb_filters::BlurGaussian() 'gblr' [PHP5 only] - ¤ Added phpthumb_filters::BlurSelective() 'gblr' [PHP5 only] - ¤ Added phpthumb_filters::MeanRemoval() 'mean' [PHP5 only] - ¤ Added phpthumb_filters::Smooth() 'smth' [PHP5 only] - * New timing debug info in phpThumbDebug - * Added config_cache_differentiate_offsite - * config_die_on_error now defaults to false - * ResolveSource works better - * cache filenames with 'fltr' parameters have changed - * Filters now skip processing if amount=0 or similar - * [#1263051] 'far' now accepts L,R,T,B,C as values giving - alignment of left/right/top/bottom/center respectively. - Old value of '1' defaults to centered - (thanks webgrappaØusers*sourceforge*net) - * Bugfix: RenderToFile() now fails properly when output format - is unknown - * Bugfix: PNG transparency wasn't working with 'far' - * Bugfix: source images with EXIF thumbnails that differ in - aspect ratio no longer use EXIF thumbnails as source unless - no other options exist - * Bugfix: setting 'src' with setParameter now invokes - setSourceFilename to properly set $this->sourceFilename - (thanks Gazou) - * Bugfix: 'zc' had poor quality when used with ImageMagick - * Bugfix: 'aoe' parameter broken when not using ImageMagick - (thanks frankieali4Øhotmail*com) - * Bugfix: fixed issue with symbolic links - (thanks hornet136Øgmail*com) - * Bugfix: config_max_source_pixels now defaults to same - calculation as used in phpThumb.config.php - (thanks vukshaØhotmail*com) - * Bugfix: Offsite cached thumbnails no longer use unique - referer (now either nothing or "_offsite") - (thanks swaayeØyahoo*com) - * Bugfix: "Unknown image type identified by “] - where is the target hex color to white balance - on, this color is what "should be" white, or light - gray. The filter attempts to maintain brightness so - any gray color can theoretically be used. If is - omitted the filter guesses based on brightest pixels - in each of RGB - ¤ Cached files are used by a Location header instead of - being passed through phpThumb.php using readfile - (thanks newtnØthrillnerds*com) - * Added 'cache_source_filemtime_ignore_local' and - 'cache_source_filemtime_ignore_remote' configurations - to ignore source modification and/or removal - (thanks raynerapeØgmail*com) - * Added 'md5s' parameter, which is the MD5 hash of the - source image -- if this parameter is passed with the - hash of the source image then the source image is not - checked for existance or modification and the cached - file is used (if available). If 'md5s' is passed an - empty string then phpThumb.php dies and outputs the - correct MD5 hash value. This parameter is the single- - file equivalent of 'cache_source_filemtime_ignore_*' - configuration paramters (thanks raynerapeØgmail*com) - * Added /demo/phpThumb.demo.object.php - * Unused parameter 'bgt' removed - * Added empty /cache/source/ directory to distribution - * Added /demo/ and /docs/ and /fonts/ directories - * Set default config_use_exif_thumbnail_for_speed = false - * Bugfix: Wrapped output buffering around all - include_once calls to prevent headers getting sent - accidentally - * Bugfix: md5_file and imagecolorallocatealpha calls - were undefined under PHP v4.1.x (thanks tomØemile*com) - * Bugfix: default 'f' parameter ('jpeg') overrode - config_output_format in object mode - (thanks mailØmmjaeger*com) - * Bugfix: suppressed error message for IIS shell_exec - errors (thanks tomØemile*com) - * Bugfix: Added PHP version check for stream_set_timeout - for HTTP sources (thanks raynerapeØgmail*com) - * Bugfix: overlay margins of 0.5-1.0 cause invalid image - dimensions error (thanks mailØmmjaeger*com) - * Bugfix: underlay margins were not working - (thanks mailØmmjaeger*com) - * Bugfix: [#1187735] EXIF thumbnails were incorrectly - output to the browser directly if requested thumbnail - exactly matched EXIF dimensions - (thanks rebootØusers*sourceforge*net) - -v1.5.2 - April 20, 2005 - ¤ phpThumb.config.php is renamed to - phpThumb.config.php.default to prevent accidental - overwriting. Please migrate your old settings to the new - file, delete your old config and rename the default to - phpThumb.config.php - ¤ Added new filters: - - 'blur' (Blur) [ex: &fltr[]=blur|] - where (0 < < 25) (default = 1) - (thanks thoensiØnetcom*no for code) - - 'hist' (Histogram) - [ex: &fltr[]=hist|||||||] - Where is the color band(s) to display, from back - to front (one or more of "rgba*" for Red Green Blue - Alpha and Grayscale respectively); - is a semicolon-seperated list of hex colors to - use for each graph band (defaults to FF0000, 00FF00, - 0000FF, 999999, FFFFFF respectively); - and are the width and height of the overlaid - histogram in pixels, or if <= 1 then percentage of - source image width/height; - is the alignment (same as for "wmi" and "wmt"); - is opacity from 0 to 100; - is the edge (and inter-tile) margin in percent - - 'over' (OVERlay/underlay image) overlays an image on - the thumbnail, or overlays the thumbnail on another - image (to create a picture frame for example) - [ex: &fltr[]=over||||] - where is the image filename; is "0" (default) - for overlay the image on top of the thumbnail or "1" - for overlay the thumbnail on top of the image; is - the margin - can be absolute pixels, or if < 1 is a - percentage of the thumbnail size [must be < 0.5] - (default is 0 for overlay and 10% for underlay); - is opacity (0 = transparent, 100 = opaque) - (thanks raynerapeØgmail*com, shabazz3Ømsu*edu) - - 'gray' (GRAYscale) [ex: &fltr[]=gray] - is an alias to 100% desaturation - * New configuration 'cache_source_directory' allows the - unprocessed source image to be cached when source is - HTTP or from a database (thanks raynerapeØgmail*com) - * Added 'cache' subdirectory to phpThumb distribution - since this is the default location for the cache - folder. - * Default value for config_error_die_on_source_failure - changed to true (thanks shabazz3Ømsu*edu) - * Added checks to make sure $this->gdimg_output is a - resource before allowing calls to RenderToFile or - OutputThumbnail - * Better error messages when phpThumb.config.php missing - * Bugfix: watermark overlay margins were wrong - * Bugfix: 'lvl' filter no longer processes if not needed - * Bugfix: off-server thumbnail error message was wrong - * Bugfix: several PHP safe mode fixes - (thanks virginiaØalertbutnotalarmed*com) - * Bugfix: cache filenames broken for filter parameters - with paths (thanks srcericØusers.sourceforge.net) - -v1.5.1 - April 06, 2005 - * Added some security upgrades: - - 'config_*' parameters cannot be passed by GETstring - - 'config_nooffsitelink_require_refer' is a new option - (disabled by default) that only allows calls to - phpThumb() from a refering domain listed in - 'config_nooffsitelink_valid_domains' - - disallowed paramters now generate an error image if - present in the GETstring - - 'high_security_enabled' if set to true enabled new - mode of verification, and requires a small function - to generate a hash for calls to phpThumb: - echo ''; - This function is supplied at the bottom of - phpThumb.config.php (thanks paulØstonie*co*uk) - ¤ Added new parameter "new" (phpThumb.php only) which can - create a new image without using "src" parameter. Set - "&new=|" where is the background hex color, - is (optional) opacity (0=transparent, 100=opaque). - (thanks mailØmmjaeger*com) - ¤ Added new filters: - - 'sep' (Sepia) [ex: &fltr[]=sep||] - where is a number between 0 and 100 for the - amount of colorization (default=50), and is - the hex color to colorize to (default=A28065). - (thanks mailØmmjaeger*com) - - 'lvl' (Levels) [ex: &fltr[]=lvl||| - where can be one of 'r', 'g', 'b', 'a' (for - Red, Green, Blue, Alpha respectively), or '*' for all - channels based on average grayscale value (default). - and are the clip points for the levels - (range = 0-255) and are set to clip 0.1% of each end - by default. Use -1 for min and/or max to invoke auto- - detect mode. Using default parameters (&fltr[]=lvl) - is similar to Auto Contrast in Adobe Photoshop. - * Bugfix: Image MIME header was incorrect for cached - images. - * Bugfix: Cache was broken for images pulled from a - database in phpThumb.php - (thanks dragutin*cvetkovicØdragontech-ltd*com) - * Bugfix: Hotlink/Offsite prevention was broken when - image was already cached. - * Bugfix: ImageMagick path was incorrect in some cases - (thanks joshgØtwcny*rr*com) - * Bugfix: ProportionalResize() in phpthumb.functions.php - had a broken check for default values - (thanks Bert*ClaeysØarinso*com) - * Bugfix: transparency now preserved for GIF & PNG input - (thanks tristanØcyrax*ch) - * Bugfix: transparency now supported for GIF output - (thanks j_ivanovØabv*bg) - * Bugfix: alpha transparency could be lost in ApplyMask() - (thanks analyzerxØgmail*com) - * Bugfix: errors on 16/32-bit BMPs - (thanks mattØhellstrominc*com) - * Bugfix: Added datestamp to cached filenames for remote - (HTTP) files, and better warning for caching - (thanks a*gambinoØabramo*it) - * Faster BMP parsing (thanks sgeppertØmail*utexas*edu) - * Added 'error_die_on_source_failure' configuration to - allow invalid source images to show an error rather - than output unmodified source image. - (thanks mindpixelØgmail*com) - * Added $phpThumb->fatalerror which will contain the - text of the fatal error if 'error_die_on_error' is - false. (thanks mindpixelØgmail*com) - -v1.5.0 - February 4, 2005 - * Added new filter parameter 'fltr' that is an array and - can apply multiple effects in sequence. Current filters - that can be called are: - - 'gam' (Gamma Correction) [ex: &fltr[]=gam|] - where can be a number >0 to 10+ (default 1.0) - - 'ds' (DeSaturate) [ex: &fltr[]=ds|] - where is a number between zero (no change) - and 100 (complete desaturation -- grayscale), or it - can be a negative number for saturation boost. - (thanks mailØmmjaeger*com) - - 'clr' (Colorize) [ex: &fltr[]=clr||] - where is a number between 0 and 100 for the - amount of colorization, and is the hex color - to colorize to. (thanks mailØmmjaeger*com) - - 'neg' (Negative) [ex: &fltr[]=neg] - inverts the color - - 'th' (ThresHold) [ex: &fltr[]=th|] (range 0-255) - every grayscale pixel brighter than is set to - white, every darker pixel is set to black - (thanks mailØmmjaeger*com) - - 'usm' (UnSharpMask) [ex: &fltr[]=usm|||] - where is the amount (default = 80), is the - radius (default = 0.5), is the threshold - (default = 3). - - 'wmi' (WaterMarkImage) - [ex: &fltr[]=wmi||||] where is the - filename of the image to overlay, is the - alignment (one of BR, BL, TR, TL, C, R, L, T, B, * - where B=bottom, T=top, L=left, R=right, C=centre, - *=tile), is opacity from 0 to 100, is the - edge (and inter-tile) margin in percent - - 'wmt' (WaterMarkText) - [ex: &fltr[]=wmt||||||||] - where: - is the text to use as a watermark, - is the font size (1-5 for built-in font, or point - size for TrueType fonts), - is the alignment (one of BR, BL, TR, TL, C, R, L, - T, B, * where B=bottom, T=top, L=left, R=right, - C=centre, *=tile), - is the hex color of the text - is the filename of the TTF file (optional, if - omitted a built-in font will be used) - is opacity from 0 to 100, - is the edge (and inter-tile) margin in percent - is the angle - (thanks mailØmmjaeger*com) - - 'flip' [ex: &fltr[]=flip|x or &fltr[]=flip|y] - flip image on X or Y axis - (thanks mailØmmjaeger*com) - - 'elip' [ex: &fltr[]=elip] - similar to rounded corners but more extreme - (thanks mailØmmjaeger*com) - - 'mask' [ex: &fltr[]=mask|filename.png] - greyscale values of mask are applied as the alpha - channel to the main image. White is opaque, black - is transparent. - - 'bvl' (BeVeL) [ex: &fltr[]=bvl|||] - where is the bevel width, is the hex color - for the top and left shading, is the hex color - for the bottom and right shading - (thanks mailØmmjaeger*com) - - 'fram' (FRAMe) draws a frame, similar to border but - more configurable (thanks mailØmmjaeger*com) - [ex: &fltr[]=fram|||||] - where is the width of the main border, is - the width of each side of the bevel part, is the - hex color of the main border, is the highlight - bevel color, is the shadow bevel color - - 'drop' (DROP shadow) - [ex: &fltr[]=drop||||] - where is distance from image to shadow, is - width of shadow fade (not yet implemented), is - the hex color of the shadow, and is the angle of - the shadow (default=225) - - 'ric' (Rounded Image Corners) - [ex: &fltr[]=ric||] - where is the horizontal corner radius, - is the vertical corner radius - * Split out filter functions into phpthumb.filters.php - * 'usa','usr','ust' parameters have been removed and - replaced with the 'fltr' call (see above) - * 'wmf','wma','wmp','wmm' parameters have been removed - and replaced with the 'fltr' call (see above) - * 'brx','bry','bw' parameters have been removed - and replaced with the 'fltr' call (see above) - * 'bw=0' to force aspect ratio has been replaced by - 'far=1' (force aspect ratio) - * Filters that produce transparent sections (such as - Rounded Corners, Ellipse, Mask, Rotate) are now output - as 32-bit/alpha PNG, or flattened with "bg" background - color for JPEG/GIF output (thanks mailØmmjaeger*com) - * Added 'zc' (Zoom Crop) parameter - (thanks arcookeØgmail*com, mailØmmjaeger*com, - pl16056Ømacnews*de, kezzasmØusers*sourceforge*net, etc) - * AutoRotate now can use EXIF orientation tag ('ar=x') - * Added 'ttf_directory' configuration parameter for - TrueType watermarks (thanks mailØmmjaeger*com) - * Added "Last-Modified" header to cache portion of - phpThumb.php which should allow better user-side - caching of thumbnails. (thanks derekØnetsimple*net) - * Added 'cache_disable_warning' configuration which will - cause an error image to be displayed if the cache - directory isn't configured, unless explicitly disabled - * Added 'nooffsitelink_enabled' configuration which - prevents linking to thumbnails on your server from - another domain. Defaults to watermaking linked images - with text warning message. - (thanks anteØabstraktmedia*com) - * Added 'error_image_width' & 'error_image_height' - config variables (thanks mailØmmjaeger*com) - * Rounded image corners now requires GD v2.0.1 and PHP - v4.3.2. Corners are transparent (for PNG output) and - antialiased. - * Rotate by arbitary angle ('ra') now has a transparent - background for PNG output - * Cached filenames now have an additional component for - applied filters - * Cached filenames now have an additional component for - HTTP referer, but only if the refering domain does not - match the domain of the server (designed to prevent - imaged linked from offsite with error message being - cached the same as the local cached version) - * Added setSourceImageResource() to allow use of an - existing GD image resource for thumbnailing - (thanks danØgonmad*co*uk) - * Now including phpThumb.demo.demo1.php (main demo page) - and phpThumb.demo.demo2.php (configurable demo page) - in the phpThumb() distribution - (thanks mailØmmjaeger*com) - * Added many more debugging/tracing message points - * Added set_time_limit(30) to phpThumb.php - * Bugfix: ImageMagick not used if `which convert` points - to a link and not a file (thanks bkainersØgmail*com) - * Bugfix: 'bgt' parameter was sometimes misspelled 'bct' - * Bugfix: 'wmm' couldn't be set to zero - * Bugfix: 'wmm' parameter was only applied to top/left of - image - * Bugfix: auto-detection of document_root failed on - Windows (thanks xbartvØhotmail*com) - * Bugfix: phpThumbDebug could be bypassed if EXIF - thumbnail present (thanks olgradinØcheckfree*com) - * Bugfix: cache file wasn't being written if EXIF data - was used directly (thanks olgradinØcheckfree*com) - * Bugfix: phpThumb.demo.showpic.php was broken by popup - blockers for images larger than the screen. - (thanks mailØmmjaeger*com) - -v1.4.11 - October 11, 2004 - * Changed sx/sy/sw/sh parameters to allow decimal values - (>0 but <1) to represent percent of source image - (thanks mordorØdefault*co*yu) - * Added config_error_silent_die_on_error for no-output - die on fatal errors (thanks johannesØformformat*se) - * Added auto-detection of probable 'document_root' if - that key is not available in $_SERVER - * Bugfix: Check `which convert` failing with error - message (thanks chadØchadshome*com) - * Bugfix: Image cropping to invalid areas outside source - image caused text output (thanks mordorØdefault*co*yu) - -v1.4.10 - August 22, 2004 - * Bugfix: cached files not written in most cases - (thanks kizerØcourtkizer*com, snuffØinbox*ru) - * Bugfix: ApacheLookupURIarray() crashes in CGI mode - (thanks hanskrentelØyahoo*de) - * Bugfix: phpthumb_bmpfile2gd() was broken - (thanks iØmindlace*net) - -v1.4.9 - August 9, 2004 - * Bugfix: changed destination filename in RenderToFile() - (thanks alextkØwalla*com) - * Bugfix: problems with HTTP image source when called as - an object (thanks alextkØwalla*com) - -v1.4.8 - August 4, 2004 - * $this->error has changed to $this->errors and is now - an array of strings (instead of a single string) - * A lot more error conditions (invalid cache directory, - etc) are now reported in $this->errors - (thanks aidan*slingsbyØlineone*net) - * Removed all define(CONSTANT) in the phpThumb() - constructor - you can now access: - - PHPTHUMB_VERSION == $this->phpthumb_version; - - PHPTHUMB_OSSLASH == $this->osslash; - - PHPTHUMB_ISWINDOWS == $this->iswindows; - * Bugfix: Error message from apache_lookup_uri() failing - under Apache2 now reported cleanly - (thanks derbaffØyahoo*com) - * Bugfix: missing phpthumb_functions:: class name for - ImageTypeToMIMEtype() call in ExtractEXIFgetImageSize() - (thanks aidan*slingsbyØlineone*net) - * Bugfix: ImageTypeToMIMEtype() was broken for PHP older - than v4.3.0 (thanks georg*schreiberØbatch-pc*es) - * Bugfix: RenderToFile() now returns false if it fails - (thanks phpthumbØsendthemtomir*com) - * Bugfix: Corrupt JPEG/PNG/GIF files that failed - ImageCreateFrom*() were not being passed to ImageMagick - for fallback, nor passed through unmodified if IM was - unavailable or failed (thanks r*chongØmogenic*net) - * Bugfix: Improved backtick safe-mode limit detection - (thanks 1Øadamcarrington*com) - * Bugfix: EXIF thumbnails were being used as source when - they should not be (thanks aidan*slingsbyØlineone*net) - * Bugfix: Cached files were not being created or used - properly (thanks aidan*slingsbyØlineone*net) - * Bugfix: max_source_pixels not set correct on some PHP - versions (thanks derbaffØyahoo*com) - * Bugfix: 'down' parameter ignored for unprocessed and - cached files (thanks aidan*slingsbyØlineone*net) - -v1.4.7 - July 27, 2004 - * Included a modified version of "module.graphic.bmp.php" - from getID3() [http://getid3.sourceforge.net] as - "phpthumb.bmp.php" for BMP reading support without - ImageMagick. It works, but it's *very* slow, especially - for large images (as in 640x480 or larger). - * Added check to prevent error messages when shell_exec - is disabled (thanks webmasterØneester*com) - -v1.4.6 - July 22, 2004 - * Added new section to phpthumb.config.php where you can - easily specify defaults for any parameter you can set - in the URL. Normally URL parameters override these - default values, unless you set - $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE to false - * Renamed phpthumb.config.php to phpThumb.config.php - since it's part of phpThumb.php, not part of - phpthumb.class.php (change of case only, will not - affect Windows servers, but will affect *nix) - * Changed cached filename of rawImageData-source images - from urlencode('') to md5(rawImageData). This should - make caching thumbnails from non-file sources more - reliable. - * Added ImageMagick debugging information - * Removed unneccesary default values from cached - filenames. This may invalidate some previously cached - files. phpthumb.demo.cacheconvert.php has been updated - to handle v1.4.1-1.4.5 => v1.4.6+ cache filenames. - * Bugfix: Cached filename did not have file-modified - datestamp when used as implmented in phpThumb.php - * Bugfix: RenderToFile() now accepts relative filenames - (thanks aidan*slingsbyØlineone*net) - * Bugfix: AllowOutputEnlargment setting was ignored when - falling back to ImageMagick - * Bugfix: IgnoreAspectRatio setting was ignored when - falling back to ImageMagick - * Bugfix: config_temp_directory was ignored in gd_info() - in PHP < v4.3.0 when phpinfo() returns no GD - information (due to safe mode restrictions) - (thanks mimyrtekØmyrtek*com) - -v1.4.5 - June 28, 2004 - * Added new parameter 'down' where you can specify a - filename and OutputThumbnail() will cause the file - to be downloaded rather than displayed in the browser. - Demo images on silisoftware.com/scripts/phpThumb/demo/ - can all be downloaded to show off this feature. - (thanks stuartscrumpØyahoo*co*uk) - * Added ability to remove old files from cache directory - based on last-access time and/or number of cached files - and/or total size of cached files - (thanks jrmhaigØyahoo*co*uk) - * Added public CleanUpCacheDirectory() for cache cleaning - (see above) if you need to call it manually - * Included new file phpThumb.demo.cacheconvert.php to - convert old-style cache names to the current (and - hopefully last!) standard naming convention. - (thanks joshgØtwcny*rr*com) - * Added configuration value 'document_root' for rare case - when $_SERVER['DOCUMENT_ROOT'] return incorrect value - (thanks joshgØtwcny*rr*com) - * Now tries to create thumbnail with ImageMagick if - ImageCreateFromJPEG etc fails, before falling back to - outputting unmodified source data. - * Bugfix: HTTP image sources were broken - (thanks fritz*weisshartØt-online*de) - * Bugfix: ImageMagick callout wasn't being used if EXIF - thumbnail was available - (thanks joshgØtwcny*rr*com) - * Bugfix: HTTP src with space in filename was broken - (thanks drØrhodes360*com) - * Bugfix: version_compare_replacement() was broken for - PHP v4.1.0+ - -v1.4.4 - June 8, 2004 - * Bugfix: network-share (Windows) source filenames were - not possible. Now works, but you must use the network - name and not a mapped drive name, for example: - \\othercomputer\file.jpg - good - \\192.168.2.1\file.jpg - good - z:\file.jpg - won't work - This is a PHP limitation (see www.php.net/file-exists) - Note: you may want to use "/" slashes instead of "\" if - you have magic_quotes_gpc enabled to avoid stripslashes - problems. - (thanks drØrhodes360*com) - * Bugfix: missing "phpthumb_functions::" in - ImageCreateFromStringReplacement() - (thanks zapletalØsoftwaremedia*cz) - -v1.4.3 - May 25, 2004 - * Added new configuration variable 'config_temp_directory' - to allow you to specify a writable directory name for - temp files if you do not have access to the system temp - directory on your server (Safe Mode restrictions etc) - (thanks nickØregenmag*com) - * Added new configuration variable - 'config_error_die_on_error' which can be set to false if - you want to retrieve the error message without having it - dumped as an image - the error message is now available - in $phpThumb->error - * Images are passed through directly with no processing - and no caching if no parameters are passed to alter the - image (resize, crop, sharpening, etc) - (thanks nchmuraØusers*sourceforge*net) - * Added new configuration variable 'config_disable_debug' - which disabled phpThumbDebug from working if you have - security concerns about the displayed information - * Bugfix: Added detection at the top of phpThumb.php for - no-GD errors to avoid parse errors later in the code - (thanks nickØregenmag*com) - * Bugfix: RoundedImageCorners() had some off-by-1 errors - (thanks ola*thunbergØhome*se) - -v1.4.2 - May 10, 2004 - * Added IE-compatability mode for transparent corners - (set 'bct=256') - * Bugfix: version_compare_replacement() was broken in PHP - older than 4.1.0 - (thanks nickØregenmag*com) - -v1.4.1.1 - May 9, 2004 - * Bugfix: Removed ImageTrueColorToPalette hack. - See http://bugs.php.net/bug.php?id=28341 - * Bugfix: 'maxb' option for PNG/GIF output incorrect - bit depth under some circumstances - -v1.4.1 - May 9, 2004 - * Added 'maxb' (MAXimum Bytes) option to auto-set the - output image quality (JPEG) or bit depth (PNG/GIF) so - that the output thumbnail is less than 'maxb' bytes - (thanks e_belleØhotmail*com) - * Added 'bgt' parameter to make rounded corners from - 'brx'/'bry' option transparent when used with PNG - output. Note: PHP/GD appears buggy at this time, so this - option must force output to 256-color mode for this - to work. The feature will be updated when a non-broken - version of PHP/GD is released. - (thanks javierØircorion*net) - * Bugfix: Caching was broken - (thanks mikeØgdaymate*nl, jurewiczØgo3*pl) - -v1.4.0 - April 30, 2004 - * Rewritten as a PHP class. Split into several files: - - phpthumb.class.php = most processing code - - phpthumb.functions.php = support functions - - phpthumb.readme.txt = usage instructions - - phpthumb.changelog.txt = this file - - phpthumb.config.php = configuration file - - phpthumb.gif.php = Non-GD GIF reading support - - phpthumb.unsharp.php = Unsharp Masking support - - phpThumb.php = demo script that works - exactly as previous versions; this is a drop-in - replacement for existing phpThumb() installations - - phpThumb.demo.showpic.php = demo script that auto- - resizes a popup window to the size of the image - shown. Useful if you want popup images but do not - know the large image size beforehand - * Added optional call-out to ImageMagick (if avaible) if - source image is larger than PHP memory restrictions - allow. ImageMagick installation should be auto-detected - under *nix, but you should configure 'imagemagick_path' - for use under Windows. - * 'max_source_pixels' is now auto-calculated from PHP - configuration settings. Due to various server-level - restrictions that may override PHP settings this - calculated value may not always be correct, and you may - have to specify the value manually. - * Added rounded-corner border option. You must specify - both 'brx' (horizontal radius) and 'bry' (vertical - radius) as well as 'bw' (border width). If 'bw' is - greater than zero, the image will be shrunk to fit - inside the border with a margin of background color. - If 'bw' is zero, the corners of the image will be - cut off and filled with background color. - (thanks javierØircorion*net) - * Minor speed improvement for unsharp masking - -v1.3.7 - March 28, 2004 - * Bugfix: GD version detection was broken on PHP <4.3.0 - on servers where phpinfo() was disabled - (thanks javierØircorion*net) - * Bugfix: Non-GD GIF support was broken on restricted - PHP configurations - (thanks javierØircorion*net) - * Bugfix: phpThumb.gif.php output error messages if PHP - was running in Safe Mode - * Added 'iar' parameter (Ignore Aspect Ratio) to allow - non-proportional resizing (stretch image to fit). - You must specify 'h' and 'w' to use this option. - (thanks javierØircorion*net) - -v1.3.6 - March 14, 2004 - * Bugfix: was broken when register_globals turned on - (thanks joshgØtwcny*rr*com) - * Bugfix: Images with transparent backgrounds now have - the background color filled with the color specified - by the 'bg' parameter - * Bugfix: ImageCreateFromString() is broken in the - non-bundled GD. Added workaround, but please use - the bundled version of GD if possible - (thanks dnØxbe*ch) - * Bugfix: EXIF thumbnail caching was broken - * Bugfix: EXIF thumbnail handling was broken for PHP - v4.2.x - (thanks smithk1Øshaw*ca) - * Bugfix: Image borders with GD2 were misaligned - * Bugfix: virtual paths/filenames like /~user/foo.jpg - should now work properly, if PHP is installed as an - Apache module (see www.php.net/apache-lookup-uri) - * Bugfix: contents of any non-image file could be - displayed (including PHP & HTML files) - (thanks arsyanØarsyan*com) - * Added rotation parameters 'ra' and 'ar' - (thanks drØrhodes360*com) - * Added $CONFIG['output_allow_enlarging'], defaulted - to false, to prevent smaller-than-max-size images - from being enlarged beyond their original size. If - you want to be able to enlarge images, set this to - false. Can be overridden with the 'aoe' parameter - (thanks dnØxbe*ch) - * Changed all configuration variables to be under one - array named $CONFIG - * Moved color and font options for ErrorImage() to - $CONFIG variables - * Changed cached filename structure (again) to a more - flexible format that can handle future expansion - (old cached files are invalid and will be recreated) - * Added more debugging code to phpThumbDebug - -v1.3.5 - February 29, 2004 - * Added capability to use EXIF thumbnail that may be - embedded in source image (often is in digital camera - JPEGs) and source image dimensions are larger than - $config_max_source_pixels. This will overcome the - limitation where PHP runs out of memory processing - large images (usually >1600x1200). EXIF thumbnail - extraction requires PHP v4.2.0 or higher and EXIF - support compiled into PHP (or php_exif extension) - * Eliminated intermediate read-file-to-memory stage if - image is created from local file. Should allow - larger images to be processed without running out of - memory. - * Added optional 'goto' parameter to be used with the - 'file' parameter, where 'goto' is a URL that is - redirected to after image is rendered to file - (thanks wimbleØwebdonors*com) - * Added optional 'xto' parameter that will bypass all - processing and just return the embedded EXIF - thumbnail, if available. - * Added error-handling if ImageTypes() is unavailable - -v1.3.4 - February 15, 2004 - * Custom error image option (&err=img.jpg) which can - also be set as $config_error_message_image_default - (thanks carlØ4thstar*net) - * &f=text will now output plain-text error messages - * ErrorImage() now used for anti-hotlink messages (if - $config_nohotlink_erase_image is true) - -v1.3.3 - February 5, 2004 - * Bugfix: Added stripslashes() to filenames if - magic_quotes_gpc is enabled - (thanks arsyanØarsyan*com) - * Output can now be rendered to a file only (not to - browser) specified by the 'file' parameter - (thanks arsyanØarsyan*com) - * JPEG quality now has a maximum of 95%, as specified - in the GD documentation - -v1.3.2.1 - February 3, 2004 - * Bugfix: gd_version() was broken for GD v2.0+ - * Bugfix: removed debugging code - -v1.3.2 - February 3, 2004 - * Bugfix: when borders are enabled, portait images - with no width constraint, or landscape images with - no height constraint were smaller than neccesary by - double the border width - (thanks jjjØxs4all*nl) - * Added unsharp mask option thanks to Torstein Hønsi: - http://www.vikjavev.com/hovudsida/umtestside.php - Note: requires GD v2.x to function - (thanks jjjØxs4all*nl) - * Updated cache filenames to reflect new parameters, - this means old cached files will need to be deleted - (or not, they just will never get called again) and - new cached versions will be created. - * Added caching to gd_info() calls for minor speedup - -v1.3.1 - February 2, 2004 - * Added optional border (width and color configurable) - (thanks arsyanØarsyan*com) - * Added option to create fixed-dimension thumbnails - regardless of source aspect ration. Set the 'bw' - (BorderWidth) parameter (even to 0) and this will be - enabled. Outside the actual image will be filled - with 'bg' color (default FFFFFF) - (thanks arsyanØarsyan*com) - -v1.3.0 - January 27, 2004 - * Added watermarking option to overlay thumbnails with - a semi-transparent watermark image (copied from a - seperate source watermark image) - (thanks arsyanØarsyan*com) - * Added option for absolute filenames (on both Windows - and *nix) outside the DOCUMENT_ROOT directory - * Added debug output dump for diagnosing problems) - -v1.2.8 - January 19, 2004 - * added ability to specify relative pathnames as well - as absolute pathnames (pathname is relative to the - location of phpThumb.php if the passed source does - not begin with "/" - -v1.2.7 - January 7, 2004 - * Added patch to allow use of PHP older than 4.1.0 - (or GD without PNG support) for non-GD GIF support - (thanks hostwebserverØhotmail*com) - -v1.2.6 - January 4, 2004 - * Added patch to allow use of PHP older than 4.1.0 - (without the superglobals arrays) - -v1.2.5 - December 26, 2003 - * Added configuration options for default output image - format and max width/height - -v1.2.4 - December 20, 2003 - * Bugfix: temp directory for non-native GD support not - always returning valid directory - * Caching feature reintroduced (see configuration) - -v1.2.3 - December 19, 2003 - * Added anti-hotlink code so the thumbnail script on - one domain cannot be used by another domain. The - list of allowed domains defaults to the current - domain but is configurable below as - $config_nohotlink_valid_domains. The message, text - size, colors and whether to blank the image or not - are also configurable - * Bugfix: URL image sources were not able to use the - non-GD GIF-reading functions - -v1.2.2 - December 17, 2003 - * Added option to use http:// URL as image source - -v1.2.1 - December 11, 2003 - * Added option to get source data from a database - rather than a physical file - * Bugfix: resize not proportional when wide image - limited more by max height than max width - Thanks mathias_strasserØgmx*net - * Removed caching code - -v1.2.0 - December 10, 2003 - * Added GIF support for versions of GD that do not - have built-in GIF support (v1.6.x) via the "GIF - Util" class by Fabien Ezber (www.yamasoft.com) - GD's built-in GIF-reading functions are faster, and - are present in PHP v4.3.0 or newer, but all versions - of GD can display resized GIF thumbnails now. - -v1.1.2 - October 26, 2003 - * check for source image existance to prevent text - error messages - * if GD not available, a GIF saying "no GD" is shown - instead of showing the original image - * Cache feature introduced - -v1.1.1 - September 28, 2003 - * better resize code by sfisher10Øcox*net - -v1.1.0 - September 1, 2003 - * initial public release - * thumbnails can now be larger than source image - * graphical error messages - -v1.0.0 - January 7, 2002 - * initial private release diff --git a/mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.faq.txt b/mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.faq.txt deleted file mode 100644 index c482dfd33..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.faq.txt +++ /dev/null @@ -1,280 +0,0 @@ -////////////////////////////////////////////////////////////// -/// phpThumb() by James Heinrich // -// available at http://phpthumb.sourceforge.net /// -////////////////////////////////////////////////////////////// -/// // -// Frequently Asked Questions (FAQ) about phpThumb() // -// /// -////////////////////////////////////////////////////////////// - - -Q: My question isn't answered here and I can't find any - forums, how do I get support? -A: Please email me directly at info@silisoftware.com with - any questions, suggestions, donations, etc. - - -Q: I think I found a bug, what's the first thing I should do? -A: Please make sure you're using the latest version. There's - a good chance I may have already fixed the bug, so please - make sure you can reproduce it with the latest version - before reporting the bug. - - -Q: phpThumb doesn't work as expected, and it may be a server - configuration issue -- how do I check? -A: Please run /demo/demo.check.php to find out how your server - matches up with the recommended configuration and for - suggestions on what to change for improved performance. - - -Q: What is the GPL? Can I use this for commercial sites? -A: See the GPL FAQ: http://www.gnu.org/licenses/gpl-faq.html - In general, if you just want to call phpThumb.php in the - standard manner - then there is no problem, you're free to do this no matter - if you site is commercial or not, or what license your code - is released under. - If you're calling phpThumb() as an object then you will - probably run into license issues, so consult the above FAQ - and the GPL itself. - No matter if you use phpThumb() commercially or not, no - payment is required. However, donations are always welcome - and can be made at http://phpthumb.sourceforge.net - - -Q: Some images generate thumbnails, but some fail (the original - non-resized image is output instead). -A: Your PHP installation does not have a high enough memory_limit - and ImageMagick is not installed on the server. The PHP memory - required is 5 times the number of pixels in the image. - For example: - 640x480x5 = 1.5MB - 1600x1200x5 = 9.2MB - You can adjust the PHP memory limit in php.ini (if you have - permission on your server to do so), or (better yet) install - ImageMagick on the server and that will bypass the memory limit - issue. If you can't do either of the above, you can resize the - images manually (with your favourite image editor) to a size - that your memory_limit setting can handle, and/or you can - re-save the images with an image editor that can embed an EXIF - thumbnail (Photoshop for example) which phpThumb can use as an - image source (lower image quality, but perhaps better than - nothing). - - -Q: I'm getting is this error message: - Failed: RenderToFile() failed because - !is_resource($this->gdimg_output) -A: You missed the call to GenerateThumbnail() before - RenderToFile() or OutputThumbnail. - See /demo/phpThumb.demo.object.php for an example. - - -Q: I'm trying to save a phpThumb-generated image in Internet - Explorer and it saves in BMP format, why? -A: This is not phpThumb's fault, it is an IE issue: - http://support.microsoft.com/default.aspx?scid=kb;en-us;810978 - http://support.microsoft.com/default.aspx?scid=kb;en-us;260650 - - -Q: PNG images with transparent areas show up with gray background - in the areas that are supposed to be transparent. -A: Internet Explorer has had a broken PNG alpha-channel display - implementation for a decade, so it may never get fixed. Other - major browsers generally handle alpha-transparent PNGs fine. - See http://www.silisoftware.com/png_transparency/ - For an alpha-channel PNG display in IE hack, see this page: - http://www.koivi.com/ie-png-transparency/ - - -Q: I'm getting " does not exist" when I know the - file does exist -A: Check that these two values are present and properly - configured in phpThumb.config.php (introduced in v1.6.0): - $PHPTHUMB_CONFIG['allow_src_above_docroot'] (default=false) - $PHPTHUMB_CONFIG['allow_src_above_phpthumb'] (default=true) - If your images are outside DOCUMENT_ROOT then you will have - to configure 'allow_src_above_docroot' to true. - Make sure whatever user the webserver is running as has read - permission to the file/directory you're reading from - - -Q: Should I use phpThumb.php, or use phpThumb() as an object? -A: phpThumb.php is easier to use (less coding) for basic uses. - phpThumb.php handles all caching; your own object will need - to have its own caching code. If you just want to display a - thumbnailed version of an existing image, use phpThumb.php - If you want to render one (or more) thumbnails to static - files (during upload, for example), that's an appropriate - use for the object mode. Also, phpThumb.config.php is only - used by phpThumb.php, so if you instantiate your own object - you need to manually set all configuration options because - phpThumb.config.php has NO effect. So, to repeat: - **always use phpThumb.php unless you NEED to have an object** - - -Q: The first time I go to a page which contains thumbnails I - don't actually see the thumbnail, I just get a browser image - placeholder (or no image). As soon as I hit refresh, all the - thumbnail images pop into place really fast. -A: You can try and see if it works better with - $PHPTHUMB_CONFIG['cache_force_passthru'] = false; - but typically the default setting works better. - This is something of an unresolved issue on some servers, - where for whatever reason I haven't (yet?) been able to - figure out a setting that always works the first time. If the - above config setting doesn't help, you might be stuck with - having to manually or automagically pre-cache thumbnails as - they're created. Please email info@silisoftware.com if you - have a better solution... - - -Q: Are there any front-end GUI interfaces to phpThumb()? -A: See /demo/readme.demo.txt - - -Q: Are there / have there been any security issues in phpThumb? -A: http://secunia.com/product/5199/ - - -Q: Why can't Flash work with images output from phpThumb()? -A: Flash doesn't like progressive JPEG. Set: - $PHPTHUMB_CONFIG['output_interlace'] = false; - - -Q: Image quality is not very good - why? -A: If you're using GD v1.x, no way around it. Upgrade to GD v2.x - - -Q: Image quality is very bad, very pixelated -- why? -A: You may be trying to resize images larger than the available - PHP memory, so phpThumb is simply extracting and using the - EXIF thumbnail as the image source, which is usually about - 160x120 (so if you resize it to 640x480 it will look very bad). - To calculate the required size for memory_limit in php.ini, - calculate the number of pixels in the image and multiply by 5: - For example, 1600x1200 = 1600 * 1200 * 5 = 9600000 = 10M - Easy solution: install ImageMagick - - -Q: Can I save the generated thumbnail to a file? -A: Yes, there are several ways to do so; the best way is to call - phpThumb as an object and call RenderToFile() to save the - thumbnail to whatever filename you want. - See /demo/phpThumb.demo.object.php for an example. - The other way is to use the 'file' parameter (see - /docs/phpthumb.readme.txt) but this parameter is deprecated - and may not exist in future versions of phpThumb(). - - -Q: "Off-server thumbnailing is not allowed" -- how do I enable it? -A: By default, phpThumb() only makes thumbnails for the same - domain that it is running on. To allow it to make thumbnails - for a limited number of other domains, add them - (in phpThumb.config.php) like this: - $PHPTHUMB_CONFIG['nohotlink_valid_domains'] = array( - @$_SERVER['HTTP_HOST'], 'example.com', 'www.example.com', - 'subdomain.example.net', 'example.org'); - To disable off-server thumbnail blocking, just set: - $PHPTHUMB_CONFIG['nohotlink_enabled'] = false; - - -Q: Is it possible to set the parameters (like w/h/fltr[]) in - the config, so that they can't be changed over the URL? -A: Take a look at $PHPTHUMB_DEFAULTS at the bottom of - phpThumb.config.php You'll want to set - $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE = false - possibly also - $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = true - You may also want to investigate - $PHPTHUMB_CONFIG['high_security_enabled'] = true - (see the example at the bottom of phpThumb.config.php - for how to call images in HighSecurity mode) - - -Q: Is there a way to use phpThumb() object to create thumbnails - without the parameters in the URL showing the location of - the image etc? -A: There is a demo in /demo/phpThumb.demo.object.php. You could - modify this into your own file, but there still remains the - problem of passing parameters to the file, whether it's - phpThumb.php or your own instantiation of a phpThumb() object. - I would suggest is putting as many of the common parameters - into phpThumb.config.php as possible under $PHPTHUMB_DEFAULTS, - so you then don't have to pass them for each image. If you - don't want people modifying the parameters, turn on - $PHPTHUMB_CONFIG['high_security_enabled'] and set a password - (you'll need to generate the tags with phpThumbURL() - provided at the bottom of phpThumb.config.php). If you don't - want people accessing your source images at all, you can - place them outside DOCUMENT_ROOT on your server (as long as - phpThumb/PHP has read access to the directory). The other - option is to put your source images in a MySQL database - and set $PHPTHUMB_CONFIG['mysql_query'] and related - parameters in phpThumb.config.php to pull your source images - from the database. That way it's impossible to retrieve the - images except through phpThumb.php, and if high_security is - enabled, then nobody can modify the parameters to view - anything except what you want to show. So, yes, it's possible - to use your own object, but it's probably better to use - phpThumb.php if possible -- one notable issue is that - phpThumb.php handles all the caching, so you're on your own - to deal with that if you create your own object. - - -Q: How do I write the output thumbnail back to a database instead - of outputting to the browser or a file? -A: See /demo/phpThumb.demo.object.php Basically you need to call - $this->GenerateThumbnail() then $this->RenderOutput() and then - the output raw image data is found in $this->outputImageData - - -Q: phpThumb runs slowly, as if the images aren't cached, when I use HTTP source - images (not on my server). How can I make it go faster? -A: $PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] = true; - // if true, remote source images will not be checked for modification date and - // cached image will be used if available, even if source image is changed or removed - - -Q: What does the "cache_default_only_suffix" configuration option do? -A: Cache files are normally created with big ugly names like - "phpThumb_cache_www.example.com_src1a482c2c760463795ff18faf073b389f_par3e099041c2f4a73041a7f5d7e7fc481a_dat1119952152.jpeg" - but if cache_default_only_suffix is enabled, cache filenames are simplified to - "pic_thumb.jpg" (for example). The problem is that only one version of that - thumbnail is possible, and you can never call it again with a different size, - or different filters, etc. Generally you don't want that enabled, but it's - there because some people asked for it. - - -Q: Why is the visual size of rotated images smaller than the unrotated images? -A: phpThumb fits the rotated image into the 'w' and 'h' dimensions. - Try not specifying a 'w' parameter: phpThumb.php?src=file.png&ra=15 - That should leave the image the apparent same size as the unrotated image - (in actual fact the canvas size is enlarged to fit the rotated image in it). - - -Q: How can I purge cached files when I delete the source image? -A: You can either let phpThumb's built-in cache purging features (see phpThumb.config.php) - take effect, or you can manually walk through your source images to delete and find - the matching cache files and delete them: - if ($dh = opendir($sourcedir)) { - while ($file = readddir($dh)) { - if ($file == $WhatIwantToDelete) { - $md5 = md5_file($sourcedir.'/'.$file); - unlink($phpthumb_cache_dir.'/phpThumb_cache_www.example.com_src'.$md5.'*.*'); - } - } - closedir($dh); - } - - -Q: What is the proper name for this script/program/library? -A: The official name is "phpThumb()" but it may be written - as simply "phpThumb" in short form (or where parentheses - are not permitted), or "phpthumb" in case-insensitive - environments. The following is a non-exhaustive sample of - unacceptable forms: PHPthumb; phpThumbs; phpthump; - phpthumbnailer; phpThumbnail; PHP Thumb; Phpthumb; etc. - - diff --git a/mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.license.txt b/mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.license.txt deleted file mode 100644 index 9fec80829..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.license.txt +++ /dev/null @@ -1,340 +0,0 @@ - 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 - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; 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 - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.readme.txt b/mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.readme.txt deleted file mode 100644 index 22e00c969..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/docs/phpthumb.readme.txt +++ /dev/null @@ -1,549 +0,0 @@ -////////////////////////////////////////////////////////////// -/// phpThumb() by James Heinrich // -// available at http://phpthumb.sourceforge.net /// -////////////////////////////////////////////////////////////// -/// // -// This code is released under the GNU GPL: // -// http://www.gnu.org/copyleft/gpl.html // -// // -// +-----------------------------------------------+ // -// | phpThumb() is free to use according to the | // -// | terms of the GPL. Donations also gratefully | // -// | GPL FAQ: http://gnu.org/licenses/gpl-faq.html | // -// | | // -// | Donations are gratefully accepted from happy | // -// | users :) See http://phpthumb.sourceforge.net | // -// | | // -// | If you like phpThumb(), please consider | // -// | writing a review at HotScripts.com: | // -// | http://www.hotscripts.com/Detailed/25654.html | // -// | | // -// | If you do use this code somewhere, send me | // -// | an email and tell me how/where you used it. | // -// +-----------------------------------------------+ // -// /// -////////////////////////////////////////////////////////////// - -============ -Description: -============ - -phpThumb() uses the GD library to create thumbnails from -images (GIF, PNG or JPEG) on the fly. The output size is -configurable (can be larger or smaller than the source), -and the source may be the entire image or only a portion -of the original image. True color and resampling is used -if GD v2.0+ is available, otherwise low-color and simple -resizing is used. Source image can be a physical file on -the server or can be retrieved from a database. GIFs are -supported on all versions of GD even if GD does not have -native GIF support thanks to the GIFutil class by Fabien -Ezber. AntiHotlinking feature prevents other people from -using your server to resize their thumbnails, or link to -your images from another server. The cache feature -reduces server load. - - -======== -Support: -======== - -First, read this file. -Then read phpthumb.faq.txt -Then run /demo/phpThumb.demo.check.php -If you still think it's a bug, email info@silisoftware.com - - -====== -Usage: -====== - -Call phpThumb() just like you would a normal image. -Examples: - - -See the "demo" link on http://phpthumb.sourceforge.net -for more usage examples). Parameters that can be passed -are listed below under "URL Parameters". - -NOTE: It's recommended you use the local image filename -wherever possible (rather than http://) because performance -is much better, less (or no) use of temp files, and the -last-modified check for cached files doesn't work for -remote files. - -To access files over a LAN with Windows share names you -must use the network name (or IP) and not a mapped drive -name, for example: - //othercomputer/file.jpg - good - //192.168.2.1/file.jpg - good - z:/file.jpg - won't work -This is a PHP limitation (see www.php.net/file-exists) -Note: you may want to use "/" slashes instead of "\" if -you have magic_quotes_gpc enabled to avoid stripslashes -problems, although either slash should work if -magic_quotes_gpc is disabled - - -================================ -Alternate PATH_INFO-style Usage: -================================ - -phpThumb.php can also be called by passing parameters not -after the usual "?" but like this: - phpThumb.php/=;x; -For example: - phpThumb.php/100;pic.jpg - phpThumb.php/100;images/pic.jpg - phpThumb.php/100;/images/pic.jpg - phpThumb.php/100x200;pic.jpg - phpThumb.php/x200;pic.jpg - phpThumb.php/f=jpeg;q=50;100x200;pic.jpg - phpThumb.php/fltr[]=usm;100;pic.jpg - - must be the last item. Dimensions must be the second- -last item. As many key/value pairs for parameters can be -passed before those last two items, with each pair joined by -equals ("=") and seperated by semicolon (";") - - -============================================== -Calling as an object (not using phpThumb.php): -============================================== - -NOTE: most people don't need to and should not do this. -If you just want to display resized images, please just -use phpThumb.php, not the object mode. To render output -to one (or more) files instead of the browser, you should -skip phpThumb.php and instantiate your own object. Please -take a look at /demo/phpThumb.demo.object.php for details. - -Note: phpThumb.php is where the caching code is located, if - you instantiate your own phpThumb() object that code is - bypassed and it's up to you to handle the reading and - writing of cached files. - - -============== -Configuration: -============== - -There are some configuration options you may (but are -not required to) change. Most configuration options can -be set when you call phpThumb() - see list below), but -default configuration options (such as cache directory) -are in phpThumb.config.php - this is the only file you -should ever modify. - -The configuration file is distributed as -phpThumb.config.php.default to prevent accidental -overwriting of old configuration settings. Please -migrate your old settings to the new file (if upgrading), -or delete your old config and rename the default to -phpThumb.config.php - - -The amount of memory required for phpThumb depends on -several factors: the dimensions of the source image, -the dimensions of the output image, whether unsharp -masking is applied, whether watermarks are applied, etc. -The auto-detection of memory limits works as a general -"safe" value. You may be able to exceed the auto value -by a small or large amount, depending on whether you -apply watermarks and/or sharpening, and the output size -of your thumbnails. I do not currently have a reliable -formula for calculating such things, but I will attempt -to craft one for future versions of phpThumb(). Until -then, set "max_source_pixels" in phpThumb.config.php to a -value that works well for you (or leave it alone if the -defaults give you no problems). - -The configuration options you should maybe modify are: -* cache_directory - thumbnailing is slow and processor- - intensive. Enabling caching will dramatically speed - up future thumbnail serving -* max_source_pixels - This should be auto-detected, but - if auto-detection fails and you get an invalid image - from large source images, set this to about 20% of - your available PHP memory limit. -* imagemagick_path - If the source image is larger than - max_source_pixels allows, but ImageMagick is available - phpThumb() will use it to generate the thumbnail. - - -/////////////////////////////////////////////////////////// -Note: High-Security mode is recommended enabled if possible. - Set $PHPTHUMB_CONFIG['high_security_enabled'] in - phpThumb.config.php to enable it. Each call to phpThumb - needs to be made through the function supplied at the - bottom of phpThumb.config.php which create the hash: - require_once('phpThumb.config.php'); - echo ''; -/////////////////////////////////////////////////////////// - - -=============== -URL Parameters: -=============== - - src = filename of source image - new = create new image, not thumbnail of existing image. - Requires "w" and "h" parameters set. - [ex: &new=FF0000|75] - red background, 75% opacity - Set to hex color string of background. Opacity is - optional (defaults to 100% opaque). - w = max width of output thumbnail in pixels - h = max height of output thumbnail in pixels - wp = max width for portrait images - hp = max height for portrait images - wl = max width for landscape images - hl = max height for landscape images - ws = max width for square images - hs = max height for square images - f = output image format ("jpeg", "png", or "gif") - q = JPEG compression (1=worst, 95=best, 75=default) - sx = left side of source rectangle (default = 0) - (values 0 < sx < 1 represent percentage) - sy = top side of source rectangle (default = 0) - (values 0 < sy < 1 represent percentage) - sw = width of source rectangle (default = fullwidth) - (values 0 < sw < 1 represent percentage) - sh = height of source rectangle (default = fullheight) - (values 0 < sh < 1 represent percentage) - zc = zoom-crop. Will auto-crop off the larger dimension - so that the image will fill the smaller dimension - (requires both "w" and "h"). Set "zc=1" to enable. - (overrides both "iar" and "far") - bg = background hex color (default = FFFFFF) - bc = border hex color (default = 000000) -fltr = filter system. Call as an array as follows: - - "brit" (Brightness) [ex: &fltr[]=brit|] - where is the amount +/- to adjust brightness - (range -255 to 255) - Availble in PHP5 with bundled GD only. - - "cont" (Constrast) [ex: &fltr[]=cont|] - where is the amount +/- to adjust contrast - (range -255 to 255) - Availble in PHP5 with bundled GD only. - - "gam" (Gamma Correction) [ex: &fltr[]=gam|] - where can be a number >0 to 10+ (default 1.0) - Must be >0 (zero gives no effect). There is no max, - although beyond 10 is pretty useless. Negative - numbers actually do something, maybe not quite the - desired effect, but interesting nonetheless. - - "sat" (SATuration) [ex: &fltr[]=sat|] - where is a number between zero (no change) - and -100 (complete desaturation = grayscale), or it - can be any positive number for increased saturation. - - "ds" (DeSaturate) [ex: &fltr[]=ds|] - is an alias for "sat" except values are inverted - (positive values remove color, negative values boost - saturation) - - "gray" (Grayscale) [ex: &fltr[]=gray] - remove all color from image, make it grayscale - - "th" (Threshold) [ex: &fltr[]=th|] - makes image greyscale, then sets all pixels brighter - than (range 0-255) to white, and all pixels - darker than to black - - "rcd" (Reduce Color Depth) [ex: &fltr[]=rcd||] - where is the number of colors (2-256) you want - in the output image, and is "1" for dithering - (deault) or "0" for no dithering - - "clr" (Colorize) [ex: &fltr[]=clr||] - where is a number between 0 and 100 for the - amount of colorization, and is the hex color - to colorize to. - - "sep" (Sepia) [ex: &fltr[]=sep||] - where is a number between 0 and 100 for the - amount of colorization (default=50), and is - the hex color to colorize to (default=A28065). - Note: this behaves differently when applied by - ImageMagick, in which case 80 is default, and lower - values give brighter/yellower images and higher - values give darker/bluer images - - "usm" (UnSharpMask) [ex: &fltr[]=usm|||] - where is the amount (default = 80), is the - radius (default = 0.5), is the threshold - (default = 3). - - "blur" (Blur) [ex: &fltr[]=blur|] - where (0 < < 25) (default = 1) - - "gblr" (Gaussian Blur) [ex: &fltr[]=gblr] - Availble in PHP5 with bundled GD only. - - "sblr" (Selective Blur) [ex: &fltr[]=gblr] - Availble in PHP5 with bundled GD only. - - "smth" (Smooth) [ex: &fltr[]=smth|] - where is the weighting value for the matrix - (range -10 to 10, default 6) - Availble in PHP5 with bundled GD only. - - "lvl" (Levels) [ex: &fltr[]=lvl||| - where can be one of 'r', 'g', 'b', 'a' (for - Red, Green, Blue, Alpha respectively), or '*' for all - channels based on average grayscale value (default). - and are the clip points for the levels - and are set to clip 0.1% of each end by default. - (range = 0-255) and are set to clip 0.1% of each end - by default. Use -1 for min and/or max to invoke auto- - detect mode. Using default parameters (&fltr[]=lvl) - is similar to Auto Contrast in Adobe Photoshop. - - "wb" (White Balance) [ex: &fltr[]=wb|] - where is the target hex color to white balance - on, this color is what "should be" white, or light - gray. The filter attempts to maintain brightness so - any gray color can theoretically be used. If is - omitted the filter guesses based on brightest pixels - in each of RGB - - "hist" (Histogram) - [ex: &fltr[]=hist|||||||] - Where is the color band(s) to display, from back - to front (one or more of "rgba*" for Red Green Blue - Alpha and Grayscale respectively); - is a semicolon-seperated list of hex colors to - use for each graph band (defaults to FF0000, 00FF00, - 0000FF, 999999, FFFFFF respectively); - and are the width and height of the overlaid - histogram in pixels, or if <= 1 then percentage of - source image width/height; - is the alignment (same as for "wmi" and "wmt"); - is opacity from 0 (transparent) to 100 (opaque) - (requires PHP v4.3.2, otherwise 100% opaque); - is the edge (and inter-tile) margin in percent - - "over" (OVERlay/underlay image) overlays an image on - the thumbnail, or overlays the thumbnail on another - image (to create a picture frame for example) - [ex: &fltr[]=over||||] - where is the image filename; is "0" (default) - for overlay the image on top of the thumbnail or "1" - for overlay the thumbnail on top of the image; is - the margin - can be absolute pixels, or if < 1 is a - percentage of the thumbnail size [must be < 0.5] - (default is 0 for overlay and 10% for underlay); - is opacity (0 = transparent, 100 = opaque) - (requires PHP v4.3.2, otherwise 100% opaque); - (thanks raynerapeØgmail*com, shabazz3Ømsu*edu) - - "wmi" (WaterMarkImage) - [ex: &fltr[]=wmi||||] where - is the filename of the image to overlay; - is the alignment (one of BR, BL, TR, TL, C, - R, L, T, B, *) where B=bottom, T=top, L=left, - R=right, C=centre, *=tile); - is opacity from 0 (transparent) to 100 (opaque) - (requires PHP v4.3.2, otherwise 100% opaque); - is the edge (and inter-tile) margin in percent - - "wmt" (WaterMarkText) - [ex: &fltr[]=wmt|||||||||||] - where: - is the text to use as a watermark; - URLencoded Unicode HTMLentities must be used for - characters beyond chr(127). For example, the - "eighth note" character (U+266A) is represented - as "♪" and then urlencoded to "%26%239834%3B" - Any instance of metacharacters will be replaced - with their calculated value. Currently supported: - ^Fb = source image filesize in bytes - ^Fk = source image filesize in kilobytes - ^Fm = source image filesize in megabytes - ^X = source image width in pixels - ^Y = source image height in pixels - ^x = thumbnail width in pixels - ^y = thumbnail height in pixels - ^^ = the character ^ - is the font size (1-5 for built-in font, or point - size for TrueType fonts); - is the alignment (one of BR, BL, TR, TL, C, R, L, - T, B, * where B=bottom, T=top, L=left, R=right, - C=centre, *=tile); - is the hex color of the text; - is the filename of the TTF file (optional, if - omitted a built-in font will be used); - is opacity from 0 (transparent) to 100 (opaque) - (requires PHP v4.3.2, otherwise 100% opaque); - is the edge (and inter-tile) margin in percent; - is the angle - is the hex color of the background; - is background opacity from 0 (transparent) to - 100 (opaque) - (requires PHP v4.3.2, otherwise 100% opaque); - is the direction(s) in which the background is - extended (either 'x' or 'y' (or both, but both - will obscure entire image)) - Note: works with TTF fonts only, not built-in - - "flip" [ex: &fltr[]=flip|x or &fltr[]=flip|y] - flip image on X or Y axis - - "ric" [ex: &fltr[]=ric||] - rounds off the corners of the image (to transparent - for PNG output), where is the horizontal radius - of the curve and is the vertical radius - - "elip" [ex: &fltr[]=elip] - similar to rounded corners but more extreme - - "mask" [ex: &fltr[]=mask|filename.png] - greyscale values of mask are applied as the alpha - channel to the main image. White is opaque, black - is transparent. - - "bvl" (BeVeL) [ex: &fltr[]=bvl|||] - where is the bevel width, is the hex color - for the top and left shading, is the hex color - for the bottom and right shading - - "bord" (BORDer) [ex: &fltr[]=bord|||| - where is the width in pixels, and are - horizontal and vertical radii for rounded corners, - and is the hex color of the border - - "fram" (FRAMe) draws a frame, similar to "bord" but - more configurable - [ex: &fltr[]=fram|||||] - where is the width of the main border, is - the width of each side of the bevel part, is the - hex color of the main border, is the highlight - bevel color, is the shadow bevel color - - "drop" (DROP shadow) - [ex: &fltr[]=drop||||] - where is distance from image to shadow, is - width of shadow fade (not yet implemented), is - the hex color of the shadow, and is the angle of - the shadow (default=225) - - "crop" (CROP image) - [ex: &fltr[]=crop||||] - where is the number of pixels to crop from the left - side of the resized image; , , are for right, - top and bottom respectively. Where (0 < x < 1) the - value will be used as a percentage of width/height. - Left and top crops take precedence over right and - bottom values. Cropping will be limited such that at - least 1 pixel of width and height always remains. -file = if set then thumbnail will be rendered to this - filename, not output and not cached. - (Deprecated. Disabled by default since v1.6.0. - You should instantiate your own object instead) -goto = URL to redirect to after rendering image to file - * Must begin with "http://" - * Requires file parameter set - (Deprecated. Disabled by default since v1.6.0. - You should instantiate your own object instead) - err = custom error image filename instead of showing - error messages (for use on production sites) -md5s = MD5 hash of the source image -- if this parameter is - passed with the hash of the source image then the - source image is not checked for existance or - modification and the cached file is used (if - available). If 'md5s' is passed an empty string then - phpThumb.php dies and outputs the correct MD5 hash - value. This parameter is the single-file equivalent - of 'cache_source_filemtime_ignore_*' configuration - paramters - xto = EXIF Thumbnail Only - set to only extract EXIF - thumbnail and not do any additional processing - ra = Rotate by Angle: angle of rotation in degrees - positive = counterclockwise, negative = clockwise - ar = Auto Rotate: set to "x" to use EXIF orientation - stored by camera. Can also be set to "l" or "L" - for landscape, or "p" or "P" for portrait. "l" - and "P" rotate the image clockwise, "L" and "p" - rotate the image counter-clockwise. - aoe = Output Allow Enlarging - override the setting for - $CONFIG['output_allow_enlarging'] (1=on, 0=off) - ("far" and "iar" both override this and allow output - larger than input) - iar = Ignore Aspect Ratio - disable proportional resizing - and stretch image to fit "h" & "w" (which must both - be set). (1=on, 0=off) (overrides "far") - far = Force Aspect Ratio - image will be created at size - specified by "w" and "h" (which must both be set). - Alignment: L=left,R=right,T=top,B=bottom,C=center - BL,BR,TL,TR use the appropriate direction if the - image is landscape or portrait. -maxb = MAXimum Byte size - output quality is auto-set to - fit thumbnail into "maxb" bytes (compression - quality is adjusted for JPEG, bit depth is adjusted - for PNG and GIF) -down = filename to save image to. If this is set the - browser will prompt to save to this filename rather - than display the image - - - -============== -General Notes: -============== - -* Always use the local image filename wherever possible - rather than a full http:// URL because performance is - much better, less (or no) use of temp files, and the - last-modified check for cached files doesn't work for - remote files. For example: - good: phpThumb.php?src=/images/nicepic.jpg - bad: phpThumb.php?src=/home/httpd/example/images/nicepic.jpg - worse: phpThumb.php?src=http://example.com/images/nicepic.jpg - -* Thumbnails will be scaled proportionately to fit in a - box of at most (width * height) pixels - (unless "iar" is set) - -* Thumbnail caching for URL or database sources requires - an absolute directory name for $config_cache_directory - Physical file cached thumbnails will be recreated if - the source file changes, but remote/database files - cannot (modification time isn't readily available) - -* If you need a GUI interface to phpThumb(), or for a user - to specify crop settings, or something like that please - see the list of known programs in /demo/readme.demos.txt - -* Cropping images can be specified with either exact pixel - values for sx/sy/sw/sh parameters, or if those are set - to a value >0 and <1 then these are interpreted as a - percentage of the source image width/height. For example, - to crop 25% off all sides, you would specify parameters: - phpThumb.php?src=pic.jpg&sx=.25&sy=.25&sw=.5&sh=.5 - -* phpThumb() may have tempfile access issues on servers - where Safe Mode is enabled, specificly when accessing - a file over HTTP, or when a non-bundled version of GD - is in use. Specifying "config_temp_directory" may help - -* Properly resolving /~user/ style filenames requires - apache_lookup_uri(), which is missing or broken in - Apache2, or if PHP is not installed as an Apache module. - phpThumb() does try and work around this if it is - unavailble, but you may have to specify a full filename - for "src" if you encounter problems. - -* phpThumb() should work with PHP v4.0.6+, but seems to - have a few quirks before v4.1.0 - EXIF thumbnail extraction requires PHP v4.2.0+ - Image rotation requires PHP v4.3.0+. There have been - reports of problems with PHP older than v4.3.3 - Some image filters require PHP v5.0.0+ - Run /demo/phpThumb.demo.check.php to examine your server - -* phpThumb() works better and faster when ImageMagick is - available. Most functions will work with only GD2, but - speed is much faster with ImageMagick, and much larger - images can be processed with ImageMagick than GD. - -* phpThumb() works with GD v1.x, but works better with - GD v2.0+ because of the true-color image support - and ImageCopyResampled(). Also, there appears to be a - bug in ImageCopyResized() which is used with GD v1.x - where the bottom and/or right line of pixels is set - to the background color (due to a rounding error?) - NOTE: Please use the bundled version of GD if at all - possible (with PHP v4.3.0+) because the non-bundled - version has bugs which may cause PHP to crash: - * http://bugs.php.net/bug.php?id=21518 - * http://bugs.php.net/bug.php?id=24174 - phpThumb() has a workaround for the above bug but - there may be other bugs, and the workaround is slow. - Alpha transparent output requires GD >= 2.0.1 and - PHP >= 4.3.2 - Most (if not all) filters require GD v2.x to function - at all. But many filters can be handled by ImageMagick - instead of GD. - -* Filters handled by ImageMagick or GD: - - brit;cont;ds;sat;gray;clr;sep;gam;neg;th;rcd;flip;edge; - emb;lvl;blur;gblr;usm; -* Filters handled only by ImageMagick: - - none yet -* Filters handled only by GD + PHP5: - - sblr;mean;smth; -* Filters handled only by GD2: - - bvl;wmi;wmt;over;wb;hist;fram;drop;mask;elip;ric;bord; diff --git a/mods/photo_album/classes/phpThumb_1.7.2/fonts/readme.txt b/mods/photo_album/classes/phpThumb_1.7.2/fonts/readme.txt deleted file mode 100644 index 04935c200..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/fonts/readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -This is the default location for TTF fonts. - -You can safely delete or ignore this directory if you're not using -TTF fonts for text watermarks. You can also specify an alternate -directory in phpThumb.config.php \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/images/readme.txt b/mods/photo_album/classes/phpThumb_1.7.2/images/readme.txt deleted file mode 100644 index c1c10ff5f..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/images/readme.txt +++ /dev/null @@ -1,4 +0,0 @@ -If you're looking for the demo images, they can be downloaded from -the bottom of the phpThumb demo page on SourceForge: - -http://phpthumb.sourceforge.net/demo/demo/phpThumb.demo.demo.php \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/index.php b/mods/photo_album/classes/phpThumb_1.7.2/index.php deleted file mode 100644 index a72286161..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/index.php +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/phpThumb.config.php.default b/mods/photo_album/classes/phpThumb_1.7.2/phpThumb.config.php.default deleted file mode 100644 index 9950e1925..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/phpThumb.config.php.default +++ /dev/null @@ -1,242 +0,0 @@ - // -// available at http://phpthumb.sourceforge.net /// -////////////////////////////////////////////////////////////// -/// // -// See: phpthumb.readme.txt for usage instructions // -// /// -////////////////////////////////////////////////////////////// - -ob_start(); -if (!file_exists(dirname(__FILE__).'/phpthumb.functions.php') || !include_once(dirname(__FILE__).'/phpthumb.functions.php')) { - ob_end_flush(); - die('failed to include_once(phpthumb.functions.php) - realpath="'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'"'); -} -ob_end_clean(); - -// START USER CONFIGURATION SECTION: - -// * DocumentRoot configuration -// phpThumb() depends on $_SERVER['DOCUMENT_ROOT'] to resolve path/filenames. This value is usually correct, -// but has been known to be broken on some servers. This value allows you to override the default value. -// Do not modify from the auto-detect default value unless you are having problems. -//$PHPTHUMB_CONFIG['document_root'] = '/home/httpd/httpdocs'; -//$PHPTHUMB_CONFIG['document_root'] = 'c:\\webroot\\example.com\\www'; -//$PHPTHUMB_CONFIG['document_root'] = $_SERVER['DOCUMENT_ROOT']; -//$PHPTHUMB_CONFIG['document_root'] = realpath((@$_SERVER['DOCUMENT_ROOT'] && file_exists(@$_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF'])) ? $_SERVER['DOCUMENT_ROOT'] : str_replace(dirname(@$_SERVER['PHP_SELF']), '', str_replace(DIRECTORY_SEPARATOR, '/', realpath('.')))); -$PHPTHUMB_CONFIG['document_root'] = realpath((getenv('DOCUMENT_ROOT') && ereg('^'.preg_quote(realpath(getenv('DOCUMENT_ROOT'))), realpath(__FILE__))) ? getenv('DOCUMENT_ROOT') : str_replace(dirname(@$_SERVER['PHP_SELF']), '', str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__)))); - -// * Cache directory configuration (choose only one of these - leave the other lines commented-out): -// Note: this directory must be writable (usually chmod 777 is neccesary) for caching to work. -// If the directory is not writable no error will be generated but caching will be disabled. -$PHPTHUMB_CONFIG['cache_directory'] = dirname(__FILE__).'/cache/'; // set the cache directory relative to the phpThumb() installation -//$PHPTHUMB_CONFIG['cache_directory'] = $PHPTHUMB_CONFIG['document_root'].'/phpthumb/cache/'; // set the cache directory to an absolute directory for all source images -//$PHPTHUMB_CONFIG['cache_directory'] = './cache/'; // set the cache directory relative to the source image - must start with '.' (will not work to cache URL- or database-sourced images, please use an absolute directory name) -//$PHPTHUMB_CONFIG['cache_directory'] = null; // disable thumbnail caching (not recommended) - -$PHPTHUMB_CONFIG['cache_disable_warning'] = false; // If [cache_directory] is non-existant or not writable, and [cache_disable_warning] is false, an error image will be generated warning to either set the cache directory or disable the warning (to avoid people not knowing about the cache) - - -// * Cache culling: phpThumb can automatically limit the contents of the cache directory -// based on last-access date and/or number of files and/or total filesize. - -//$PHPTHUMB_CONFIG['cache_maxage'] = null; // never delete cached thumbnails based on last-access time -$PHPTHUMB_CONFIG['cache_maxage'] = 86400 * 90; // delete cached thumbnails that haven't been accessed in more than [90 days] (value is maximum time since last access in seconds to avoid deletion) - -//$PHPTHUMB_CONFIG['cache_maxsize'] = null; // never delete cached thumbnails based on byte size of cache directory -$PHPTHUMB_CONFIG['cache_maxsize'] = 10 * 1024 * 1024; // delete least-recently-accessed cached thumbnails when more than [10MB] of cached files are present (value is maximum bytesize of all cached files) - -//$PHPTHUMB_CONFIG['cache_maxfiles'] = null; // never delete cached thumbnails based on number of cached files -$PHPTHUMB_CONFIG['cache_maxfiles'] = 500; // delete least-recently-accessed cached thumbnails when more than [500] cached files are present (value is maximum number of cached files to keep) - - -// * Source image cache configuration -$PHPTHUMB_CONFIG['cache_source_enabled'] = false; // if true, source images obtained via HTTP are cached to $PHPTHUMB_CONFIG['cache_source_directory'] -$PHPTHUMB_CONFIG['cache_source_directory'] = dirname(__FILE__).'/cache/source/'; // set the cache directory for unprocessed source images - -// * cache source modification date configuration -$PHPTHUMB_CONFIG['cache_source_filemtime_ignore_local'] = false; // if true, local source images will not be checked for modification date and cached image will be used if available, even if source image is changed or removed -$PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] = true; // if true, remote source images will not be checked for modification date and cached image will be used if available, even if source image is changed or removed. WARNING: cached performance MUCH slower if this is set to false. - - -// * Simplified cache filename configuration -// Instead of creating unique cache filenames for all parameter combinations, create "simple" cache files (eg: "pic_thumb.jpg") -// If cache_default_only_suffix is non-empty, GETstring parameters (except 'src') are ignored and only $PHPTHUMB_DEFAULTS -// parameters (set at the bottom of phpThumb.config.php) are used for processing. -// The '*' character MUST be used to represent the source image name -$PHPTHUMB_CONFIG['cache_default_only_suffix'] = ''; // cached in normal phpThumb manner -//$PHPTHUMB_CONFIG['cache_default_only_suffix'] = '*_thumb'; // cache 'pic.jpg' becomes 'pic_thumb.jpg' (or 'pic_thumb.png' if PNG output is selected, etc) -//$PHPTHUMB_CONFIG['cache_default_only_suffix'] = 'small-*'; // cache 'pic.jpg' becomes 'small-pic.jpg' (or 'small-pic.png' if PNG output is selected, etc) - -$PHPTHUMB_CONFIG['cache_prefix'] = 'phpThumb_cache_'.str_replace('www.', '', @$_SERVER['SERVER_NAME']); -//$PHPTHUMB_CONFIG['cache_prefix'] = 'phpThumb_cache'; // allow phpThumb to share 1 set of cached files even if accessed under different servername/domains on same server - -$PHPTHUMB_CONFIG['cache_force_passthru'] = true; // if true, cached image data will always be passed to browser; if false, HTTP redirect will be used instead - - - -// * Temp directory configuration -// phpThumb() may need to create temp files. Usually the system temp dir is writable and can be used. -// Leave this value as NULL in most cases. If you get errors about "failed to open for writing" -// you should change this to a full pathname to a directory you do have write access to. -//$PHPTHUMB_CONFIG['temp_directory'] = '/tmp/'; -$PHPTHUMB_CONFIG['temp_directory'] = null; - - -// maximum number of pixels in source image to attempt to process entire image. -// If this is zero then no limit on source image dimensions. -// If this is nonzero then this is the maximum number of pixels the source image -// can have to be processed normally, otherwise the embedded EXIF thumbnail will -// be used (if available) or an "image too large" notice will be displayed. -// This is to be used for large source images (> 1600x1200) and low PHP memory -// limits. If PHP runs out of memory the script will usually just die with no output. -// To calculate this number, multiply the dimensions of the largest image -// you can process with your memory limitation (e.g. 1600 * 1200 = 1920000) -// As a general guideline, this number will be about 20% of your PHP memory -// configuration, so 8M = 1,677,722; 16M = 3,355,443; 32M = 6,710,886; etc. -if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=') && !defined('memory_get_usage') && !@ini_get('memory_limit')) { - // memory_get_usage() will only be defined if your PHP is compiled with the --enable-memory-limit configuration option. - $PHPTHUMB_CONFIG['max_source_pixels'] = 0; // no memory limit -} else { - // calculate default max_source_pixels as 20% of memory limit configuration - $PHPTHUMB_CONFIG['max_source_pixels'] = round(max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576 * 0.20); - //$PHPTHUMB_CONFIG['max_source_pixels'] = 0; // no memory limit - //$PHPTHUMB_CONFIG['max_source_pixels'] = 1920000; // allow 1600x1200 images (2Mpx), no larger (about 10MB memory required) - //$PHPTHUMB_CONFIG['max_source_pixels'] = 3355443; // 16MB memory limit - //$PHPTHUMB_CONFIG['max_source_pixels'] = 3871488; // allow 2272x1704 images (4Mpx), no larger (about 16MB memory required) -} - - -// ImageMagick configuration -// If source image is larger than available memory limits as defined above in -// 'max_source_pixels' AND ImageMagick's "convert" program is available, phpThumb() -// will call ImageMagick to perform the thumbnailing of the source image to bypass -// the memory limitation. Leaving the value as NULL will cause phpThumb() to -// attempt to detect ImageMagick's presence with `which` -if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { - // Windows: set absolute pathname - $PHPTHUMB_CONFIG['imagemagick_path'] = 'C:/Program Files/ImageMagick-6.2.5-Q16/convert.exe'; -} else { - // *nix: set absolute pathname to "convert", or leave as null if "convert" is in the path - //$PHPTHUMB_CONFIG['imagemagick_path'] = '/usr/local/bin/convert'; - $PHPTHUMB_CONFIG['imagemagick_path'] = null; -} - - -// * Default output configuration: -$PHPTHUMB_CONFIG['output_format'] = 'jpeg'; // default output format ('jpeg', 'png' or 'gif') - thumbnail will be output in this format (if available in your version of GD). This is always overridden by ?f=___ GETstring parameter -$PHPTHUMB_CONFIG['output_maxwidth'] = 0; // default maximum thumbnail width. If this is zero then default width is the width of the source image. This is always overridden by ?w=___ GETstring parameter -$PHPTHUMB_CONFIG['output_maxheight'] = 0; // default maximum thumbnail height. If this is zero then default height is the height of the source image. This is always overridden by ?h=___ GETstring parameter -$PHPTHUMB_CONFIG['output_interlace'] = true; // if true: interlaced output for GIF/PNG, progressive output for JPEG; if false: non-interlaced for GIF/PNG, baseline for JPEG. - -// * Error message configuration -$PHPTHUMB_CONFIG['error_image_width'] = 400; // default width for error images -$PHPTHUMB_CONFIG['error_image_height'] = 100; // default height for error images -$PHPTHUMB_CONFIG['error_message_image_default'] = ''; // Set this to the name of a generic error image (e.g. '/images/error.png') that you want displayed in place of any error message that may occur. This setting is overridden by the 'err' parameter, which does the same thing. -$PHPTHUMB_CONFIG['error_bgcolor'] = 'CCCCFF'; // background color of error message images -$PHPTHUMB_CONFIG['error_textcolor'] = 'FF0000'; // color of text in error messages -$PHPTHUMB_CONFIG['error_fontsize'] = 1; // size of text in error messages, from 1 (smallest) to 5 (largest) -$PHPTHUMB_CONFIG['error_die_on_error'] = true; // die with error message on any fatal error (recommended with standalone phpThumb.php) -$PHPTHUMB_CONFIG['error_silent_die_on_error'] = false; // simply die with no output of any kind on fatal errors (not recommended) -$PHPTHUMB_CONFIG['error_die_on_source_failure'] = true; // die with error message if source image cannot be processed by phpThumb() (usually because source image is corrupt in some way). If false the source image will be passed through unprocessed, if true (default) an error message will be displayed. - -// * Off-server Thumbnailing Configuration: -$PHPTHUMB_CONFIG['nohotlink_enabled'] = true; // If false will allow thumbnailing from any source domain -$PHPTHUMB_CONFIG['nohotlink_valid_domains'] = array(@$_SERVER['HTTP_HOST']); // This is the list of domains for which thumbnails are allowed to be created. The default value of the current domain should be fine in most cases, but if neccesary you can add more domains in here, in the format 'www.example.com' -$PHPTHUMB_CONFIG['nohotlink_erase_image'] = true; // if true thumbnail is covered up with $PHPTHUMB_CONFIG['nohotlink_fill_color'] before text is applied, if false text is written over top of thumbnail -$PHPTHUMB_CONFIG['nohotlink_text_message'] = 'Off-server thumbnailing is not allowed'; // text of error message - -// * Off-server Linking Configuration: -$PHPTHUMB_CONFIG['nooffsitelink_enabled'] = true; // If false will allow thumbnails to be linked to from any domain, if true only domains listed below in 'nooffsitelink_valid_domains' will be allowed. -$PHPTHUMB_CONFIG['nooffsitelink_valid_domains'] = array(@$_SERVER['HTTP_HOST']); // This is the list of domains for which thumbnails are allowed to be created. The default value of the current domain should be fine in most cases, but if neccesary you can add more domains in here, in the format 'www.example.com' -$PHPTHUMB_CONFIG['nooffsitelink_require_refer'] = false; // If false will allow standalone calls to phpThumb(). If true then only requests with a $_SERVER['HTTP_REFERER'] value in 'nooffsitelink_valid_domains' are allowed. -$PHPTHUMB_CONFIG['nooffsitelink_erase_image'] = true; // if true thumbnail is covered up with $PHPTHUMB_CONFIG['nohotlink_fill_color'] before text is applied, if false text is written over top of thumbnail -$PHPTHUMB_CONFIG['nooffsitelink_text_message'] = 'Image taken from '.@$_SERVER['HTTP_HOST']; // text of error message - - -// * Border & Background default colors -$PHPTHUMB_CONFIG['border_hexcolor'] = '000000'; // Default border color - usual HTML-style hex color notation (overidden with 'bc' parameter) -$PHPTHUMB_CONFIG['background_hexcolor'] = 'FFFFFF'; // Default background color when thumbnail aspect ratio does not match fixed-dimension box - usual HTML-style hex color notation (overridden with 'bg' parameter) - -// * Watermark configuration -$PHPTHUMB_CONFIG['ttf_directory'] = dirname(__FILE__).'/fonts'; // Base directory for TTF font files -//$PHPTHUMB_CONFIG['ttf_directory'] = 'c:/windows/fonts'; - - -// * MySQL configuration -// You may want to pull data from a database rather than a physical file -// If so, modify the $PHPTHUMB_CONFIG['mysql_query'] line to suit your database structure -// Note: the data retrieved must be the actual binary data of the image, not a URL or filename -// see http://www.billy-corgan.com/blog/archive/000143.php for a brief tutorial on this section - -$PHPTHUMB_CONFIG['mysql_query'] = ''; -//$PHPTHUMB_CONFIG['mysql_query'] = 'SELECT `picture` FROM `products` WHERE (`id` = \''.mysql_escape_string(@$_GET['id']).'\')'; - -// These 4 values must be modified if $PHPTHUMB_CONFIG['mysql_query'] is not empty, but may be ignored if $PHPTHUMB_CONFIG['mysql_query'] is blank. -$PHPTHUMB_CONFIG['mysql_hostname'] = 'localhost'; -$PHPTHUMB_CONFIG['mysql_username'] = ''; -$PHPTHUMB_CONFIG['mysql_password'] = ''; -$PHPTHUMB_CONFIG['mysql_database'] = ''; - - -// * Security configuration -$PHPTHUMB_CONFIG['high_security_enabled'] = false; // if enabled, requires 'high_security_password' set to at least 5 characters, and requires the use of phpThumbURL() function (at the bottom of phpThumb.config.php) to generate hashed URLs -$PHPTHUMB_CONFIG['high_security_password'] = ''; // required if 'high_security_enabled' is true, must be at least 5 characters long -$PHPTHUMB_CONFIG['disable_debug'] = false; // prevent phpThumb from displaying any information about your system. If true, phpThumbDebug and error messages will be disabled -$PHPTHUMB_CONFIG['allow_src_above_docroot'] = false; // if true, allow src to be anywhere in filesystem; if false (default) only allow src within document_root -$PHPTHUMB_CONFIG['allow_src_above_phpthumb'] = true; // if true (default), allow src to be anywhere in filesystem; if false only allow src within sub-directory of phpThumb installation -$PHPTHUMB_CONFIG['allow_parameter_file'] = false; // if true, allow use of 'file' parameter; if false (default) the 'file' parameter is disabled/ignored -$PHPTHUMB_CONFIG['allow_parameter_goto'] = false; // if true, allow use of 'goto' parameter; if false (default) the 'goto' parameter is disabled/ignored - - -// * HTTP UserAgent configuration -//$PHPTHUMB_CONFIG['http_user_agent'] = ''; // PHP default: none -//$PHPTHUMB_CONFIG['http_user_agent'] = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'; // Windows XP, Internet Explorer -$PHPTHUMB_CONFIG['http_user_agent'] = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7'; // Windows XP, Firefox - - -// * Compatability settings -$PHPTHUMB_CONFIG['disable_pathinfo_parsing'] = false; // if true, $_SERVER[PATH_INFO] is not parsed. May be needed on some server configurations to allow normal behavior. -$PHPTHUMB_CONFIG['disable_imagecopyresampled'] = false; // if true, ImageCopyResampled is replaced with ImageCopyResampleBicubic. May be needed for buggy versions of PHP-GD. -$PHPTHUMB_CONFIG['disable_onlycreateable_passthru'] = true; // if true, any image that can be parsed by GetImageSize() can be passed through; if false, only images that can be converted to GD by ImageCreateFrom(JPEG|GIF|PNG) functions are allowed - - -// * Speed optimizations configuration -$PHPTHUMB_CONFIG['prefer_imagemagick'] = true; // If true, use ImageMagick to resize thumbnails if possible, since it is usually faster than GD functions; if false only use ImageMagick if PHP memory limit is too low. -$PHPTHUMB_CONFIG['use_exif_thumbnail_for_speed'] = false; // If true, and EXIF thumbnail is available, and is larger or equal to output image dimensions, use EXIF thumbnail rather than actual source image for generating thumbnail. Benefit is only speed, avoiding resizing large image. -$PHPTHUMB_CONFIG['allow_local_http_src'] = false; // If true, 'src' parameter can be "http:///path/image.ext" instead of just "/path/image.ext"; if false then display warning message to encourage more efficient local-filename calling. - -// END USER CONFIGURATION SECTION - -/////////////////////////////////////////////////////////////////////////////// - -// START DEFAULT PARAMETERS SECTION -// If any parameters are constant across ALL images, you can set them here - -$PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE = true; // if true, any parameters in the URL will override the defaults set here; if false, any parameters set here cannot be overridden in the URL -$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = false; // if true, GETstring parameters will be ignored (except for 'src') and only below default parameters will be used; if false, both default and GETstring parameters will be used (depending on $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE). Will be auto-set true if !empty($PHPTHUMB_CONFIG['cache_default_only_suffix']) - -//$PHPTHUMB_DEFAULTS['w'] = 100; -//$PHPTHUMB_DEFAULTS['fltr'] = array('blur|10'); -//$PHPTHUMB_DEFAULTS['q'] = 90; - - -// END DEFAULT PARAMETERS SECTION - - - -/////////////////////////////////////////////////////////////////////////////// -// Function for generating hashed calls to phpThumb if 'high_security_enabled' -// example: -// require_once('phpThumb.config.php'); -// echo ''; - -function phpThumbURL($ParameterString) { - global $PHPTHUMB_CONFIG; - return str_replace(@$PHPTHUMB_CONFIG['document_root'], '', dirname(__FILE__)).DIRECTORY_SEPARATOR.'phpThumb.php?'.$ParameterString.'&hash='.md5($ParameterString.@$PHPTHUMB_CONFIG['high_security_password']); -} - -/////////////////////////////////////////////////////////////////////////////// - -?> \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/phpThumb.php b/mods/photo_album/classes/phpThumb_1.7.2/phpThumb.php deleted file mode 100644 index 56d5b521d..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/phpThumb.php +++ /dev/null @@ -1,601 +0,0 @@ - // -// available at http://phpthumb.sourceforge.net /// -////////////////////////////////////////////////////////////// -/// // -// See: phpthumb.changelog.txt for recent changes // -// See: phpthumb.readme.txt for usage instructions // -// /// -////////////////////////////////////////////////////////////// - -error_reporting(E_ALL); -ini_set('display_errors', '1'); -if (!@ini_get('safe_mode')) { - set_time_limit(60); // shouldn't take nearly this long in most cases, but with many filter and/or a slow server... -} -ini_set('magic_quotes_runtime', '0'); -if (@ini_get('magic_quotes_runtime')) { - die('"magic_quotes_runtime" is set in php.ini, cannot run phpThumb with this enabled'); -} -$starttime = array_sum(explode(' ', microtime())); - -// this script relies on the superglobal arrays, fake it here for old PHP versions -if (phpversion() < '4.1.0') { - $_SERVER = $HTTP_SERVER_VARS; - $_GET = $HTTP_GET_VARS; -} - -// instantiate a new phpThumb() object -ob_start(); -if (!include_once(dirname(__FILE__).'/phpthumb.class.php')) { - ob_end_flush(); - die('failed to include_once("'.realpath(dirname(__FILE__).'/phpthumb.class.php').'")'); -} -ob_end_clean(); -$phpThumb = new phpThumb(); -$phpThumb->DebugTimingMessage('phpThumb.php start', __FILE__, __LINE__, $starttime); - -// phpThumbDebug[0] used to be here, but may reveal too much -// info when high_security_mode should be enabled (not set yet) - -if (file_exists(dirname(__FILE__).'/phpThumb.config.php')) { - ob_start(); - if (include_once(dirname(__FILE__).'/phpThumb.config.php')) { - // great - } else { - ob_end_flush(); - $phpThumb->ErrorImage('failed to include_once('.dirname(__FILE__).'/phpThumb.config.php) - realpath="'.realpath(dirname(__FILE__).'/phpThumb.config.php').'"'); - } - ob_end_clean(); -} elseif (file_exists(dirname(__FILE__).'/phpThumb.config.php.default')) { - $phpThumb->ErrorImage('Please rename "phpThumb.config.php.default" to "phpThumb.config.php"'); -} else { - $phpThumb->ErrorImage('failed to include_once('.dirname(__FILE__).'/phpThumb.config.php) - realpath="'.realpath(dirname(__FILE__).'/phpThumb.config.php').'"'); -} - -if (!@$PHPTHUMB_CONFIG['disable_pathinfo_parsing'] && (empty($_GET) || isset($_GET['phpThumbDebug'])) && !empty($_SERVER['PATH_INFO'])) { - $_SERVER['PHP_SELF'] = str_replace($_SERVER['PATH_INFO'], '', @$_SERVER['PHP_SELF']); - - $args = explode(';', substr($_SERVER['PATH_INFO'], 1)); - $phpThumb->DebugMessage('PATH_INFO.$args set to ('.implode(')(', $args).')', __FILE__, __LINE__); - if (!empty($args)) { - $_GET['src'] = @$args[count($args) - 1]; - if (eregi('^new\=([a-z0-9]+)', $_GET['src'], $matches)) { - unset($_GET['src']); - $_GET['new'] = $matches[1]; - } - } - if (eregi('^([0-9]*)x?([0-9]*)$', @$args[count($args) - 2], $matches)) { - $_GET['w'] = $matches[1]; - $_GET['h'] = $matches[2]; - $phpThumb->DebugMessage('PATH_INFO."w"x"h" set to "'.$_GET['w'].'"x"'.$_GET['h'].'"', __FILE__, __LINE__); - } - for ($i = 0; $i < count($args) - 2; $i++) { - @list($key, $value) = explode('=', @$args[$i]); - if (substr($key, -2) == '[]') { - $array_key_name = substr($key, 0, -2); - $_GET[$array_key_name][] = $value; - $phpThumb->DebugMessage('PATH_INFO."'.$array_key_name.'[]" = "'.$value.'"', __FILE__, __LINE__); - } else { - $_GET[$key] = $value; - $phpThumb->DebugMessage('PATH_INFO."'.$key.'" = "'.$value.'"', __FILE__, __LINE__); - } - } -} - -if (@$PHPTHUMB_CONFIG['high_security_enabled']) { - if (!@$_GET['hash']) { - $phpThumb->ErrorImage('ERROR: missing hash'); - } elseif (strlen($PHPTHUMB_CONFIG['high_security_password']) < 5) { - $phpThumb->ErrorImage('ERROR: strlen($PHPTHUMB_CONFIG[high_security_password]) < 5'); - } elseif ($_GET['hash'] != md5(str_replace('&hash='.$_GET['hash'], '', $_SERVER['QUERY_STRING']).$PHPTHUMB_CONFIG['high_security_password'])) { - $phpThumb->ErrorImage('ERROR: invalid hash'); - } -} - -//////////////////////////////////////////////////////////////// -// Debug output, to try and help me diagnose problems -$phpThumb->DebugTimingMessage('phpThumbDebug[0]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '0') { - $phpThumb->phpThumbDebug(); -} -//////////////////////////////////////////////////////////////// - -// returned the fixed string if the evil "magic_quotes_gpc" setting is on -if (get_magic_quotes_gpc()) { - $RequestVarsToStripSlashes = array('src', 'wmf', 'file', 'err', 'goto', 'down'); - foreach ($RequestVarsToStripSlashes as $dummy => $key) { - if (isset($_GET[$key])) { - $_GET[$key] = stripslashes($_GET[$key]); - } - } -} - -if (!@$_SERVER['PATH_INFO'] && !@$_SERVER['QUERY_STRING']) { - echo 'phpThumb() v'.$phpThumb->phpthumb_version.'
    http://phpthumb.sourceforge.net

    ERROR: no parameters specified'; - unset($phpThumb); - exit; -} - -if (@$_GET['src'] && isset($_GET['md5s']) && empty($_GET['md5s'])) { - if (eregi('^(f|ht)tps?://', $_GET['src'])) { - if ($rawImageData = phpthumb_functions::SafeURLread($_GET['src'], $error)) { - $md5s = md5($rawImageData); - } - } else { - $SourceFilename = $phpThumb->ResolveFilenameToAbsolute($_GET['src']); - if (is_readable($SourceFilename)) { - $md5s = phpthumb_functions::md5_file_safe($SourceFilename); - } else { - $phpThumb->ErrorImage('ERROR: "'.$SourceFilename.'" cannot be read'); - } - } - if (@$_SERVER['HTTP_REFERER']) { - $phpThumb->ErrorImage('&md5s='.$md5s); - } else { - die('&md5s='.$md5s); - } -} - -if (!empty($PHPTHUMB_CONFIG)) { - foreach ($PHPTHUMB_CONFIG as $key => $value) { - $keyname = 'config_'.$key; - $phpThumb->setParameter($keyname, $value); - if (!eregi('password', $key)) { - $phpThumb->DebugMessage('setParameter('.$keyname.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); - } - } -} else { - $phpThumb->DebugMessage('$PHPTHUMB_CONFIG is empty', __FILE__, __LINE__); -} - -if (@$_GET['src'] && !@$PHPTHUMB_CONFIG['allow_local_http_src'] && eregi('^http://'.@$_SERVER['HTTP_HOST'].'(.+)', @$_GET['src'], $matches)) { - $phpThumb->ErrorImage('It is MUCH better to specify the "src" parameter as "'.$matches[1].'" instead of "'.$matches[0].'".'."\n\n".'If you really must do it this way, enable "allow_local_http_src" in phpThumb.config.php'); -} - -//////////////////////////////////////////////////////////////// -// Debug output, to try and help me diagnose problems -$phpThumb->DebugTimingMessage('phpThumbDebug[1]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '1') { - $phpThumb->phpThumbDebug(); -} -//////////////////////////////////////////////////////////////// - -$parsed_url_referer = parse_url(@$_SERVER['HTTP_REFERER']); -if ($phpThumb->config_nooffsitelink_require_refer && !in_array(@$parsed_url_referer['host'], $phpThumb->config_nohotlink_valid_domains)) { - $phpThumb->ErrorImage('config_nooffsitelink_require_refer enabled and '.(@$parsed_url_referer['host'] ? '"'.$parsed_url_referer['host'].'" is not an allowed referer' : 'no HTTP_REFERER exists')); -} -$parsed_url_src = parse_url(@$_GET['src']); -if ($phpThumb->config_nohotlink_enabled && $phpThumb->config_nohotlink_erase_image && eregi('^(f|ht)tps?://', @$_GET['src']) && !in_array(@$parsed_url_src['host'], $phpThumb->config_nohotlink_valid_domains)) { - $phpThumb->ErrorImage($phpThumb->config_nohotlink_text_message); -} - -if ($phpThumb->config_mysql_query) { - if ($cid = @mysql_connect($phpThumb->config_mysql_hostname, $phpThumb->config_mysql_username, $phpThumb->config_mysql_password)) { - if (@mysql_select_db($phpThumb->config_mysql_database, $cid)) { - if ($result = @mysql_query($phpThumb->config_mysql_query, $cid)) { - if ($row = @mysql_fetch_array($result)) { - - mysql_free_result($result); - mysql_close($cid); - $phpThumb->setSourceData($row[0]); - unset($row); - - } else { - mysql_free_result($result); - mysql_close($cid); - $phpThumb->ErrorImage('no matching data in database.'); - } - } else { - mysql_close($cid); - $phpThumb->ErrorImage('Error in MySQL query: "'.mysql_error($cid).'"'); - } - } else { - mysql_close($cid); - $phpThumb->ErrorImage('cannot select MySQL database: "'.mysql_error($cid).'"'); - } - } else { - $phpThumb->ErrorImage('cannot connect to MySQL server'); - } - unset($_GET['id']); -} - -//////////////////////////////////////////////////////////////// -// Debug output, to try and help me diagnose problems -$phpThumb->DebugTimingMessage('phpThumbDebug[2]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '2') { - $phpThumb->phpThumbDebug(); -} -//////////////////////////////////////////////////////////////// - -if (@$PHPTHUMB_CONFIG['cache_default_only_suffix'] && (strpos($PHPTHUMB_CONFIG['cache_default_only_suffix'], '*') !== false)) { - $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = true; -} -$allowedGETparameters = array('src', 'new', 'w', 'h', 'wp', 'hp', 'wl', 'hl', 'ws', 'hs', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'zc', 'bc', 'bg', 'bgt', 'fltr', 'file', 'goto', 'err', 'xto', 'ra', 'ar', 'aoe', 'far', 'iar', 'maxb', 'down', 'phpThumbDebug', 'hash', 'md5s'); -if (!empty($PHPTHUMB_DEFAULTS) && is_array($PHPTHUMB_DEFAULTS)) { - $phpThumb->DebugMessage('setting $PHPTHUMB_DEFAULTS['.implode(';', array_keys($PHPTHUMB_DEFAULTS)).']', __FILE__, __LINE__); - foreach ($PHPTHUMB_DEFAULTS as $key => $value) { - if ($PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE || !isset($_GET[$key])) { - $_GET[$key] = $value; - $phpThumb->DebugMessage('PHPTHUMB_DEFAULTS assigning ('.$value.') to $_GET['.$key.']', __FILE__, __LINE__); - //$phpThumb->DebugMessage('PHPTHUMB_DEFAULTS.setParameter('.$key.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); - //$phpThumb->setParameter($key, $value); - } - } -} -foreach ($_GET as $key => $value) { - if (@$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS && ($key != 'src')) { - // disabled, do not set parameter - $phpThumb->DebugMessage('ignoring $_GET['.$key.'] because of $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS', __FILE__, __LINE__); - } elseif (in_array($key, $allowedGETparameters)) { - $phpThumb->DebugMessage('setParameter('.$key.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); - $phpThumb->setParameter($key, $value); - } else { - $phpThumb->ErrorImage('Forbidden parameter: '.$key); - } -} - -//////////////////////////////////////////////////////////////// -// Debug output, to try and help me diagnose problems -$phpThumb->DebugTimingMessage('phpThumbDebug[3]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '3') { - $phpThumb->phpThumbDebug(); -} -//////////////////////////////////////////////////////////////// - -//if (!@$_GET['phpThumbDebug'] && !$phpThumb->sourceFilename && !function_exists('ImageJPEG') && !function_exists('ImagePNG') && !function_exists('ImageGIF')) { -if (!@$_GET['phpThumbDebug'] && !is_file($phpThumb->sourceFilename) && !phpthumb_functions::gd_version()) { - if (!headers_sent()) { - // base64-encoded error image in GIF format - $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7'; - header('Content-Type: image/gif'); - echo base64_decode($ERROR_NOGD); - } else { - echo '*** ERROR: No PHP-GD support available ***'; - } - exit; -} - -// check to see if file can be output from source with no processing or caching -$CanPassThroughDirectly = true; -if ($phpThumb->rawImageData) { - // data from SQL, should be fine -} elseif (eregi('^(f|ht)tp\://', $phpThumb->src)) { - $phpThumb->DebugMessage('$CanPassThroughDirectly=false because eregi("^(f|ht)tp\://", '.$phpThumb->src.')', __FILE__, __LINE__); - $CanPassThroughDirectly = false; -} elseif (!@is_file($phpThumb->sourceFilename)) { - $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_file('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); - $CanPassThroughDirectly = false; -} elseif (!@is_readable($phpThumb->sourceFilename)) { - $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_readable('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); - $CanPassThroughDirectly = false; -} -foreach ($_GET as $key => $value) { - switch ($key) { - case 'src': - // allowed - break; - - case 'w': - case 'h': - // might be OK if exactly matches original - break; - - case 'phpThumbDebug': - // handled in direct-passthru code - break; - - default: - // all other parameters will cause some processing, - // therefore cannot pass through original image unmodified - $CanPassThroughDirectly = false; - $UnAllowedGET[] = $key; - break; - } -} -if (!empty($UnAllowedGET)) { - $phpThumb->DebugMessage('$CanPassThroughDirectly=false because $_GET['.implode(';', array_unique($UnAllowedGET)).'] are set', __FILE__, __LINE__); -} - -//////////////////////////////////////////////////////////////// -// Debug output, to try and help me diagnose problems -$phpThumb->DebugTimingMessage('phpThumbDebug[4]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '4') { - $phpThumb->phpThumbDebug(); -} -//////////////////////////////////////////////////////////////// - -function SendSaveAsFileHeaderIfNeeded() { - if (headers_sent()) { - return false; - } - global $phpThumb; - if (@$_GET['down']) { - $downloadfilename = ereg_replace('[/\\:\*\?"<>|]', '_', $_GET['down']); - if (phpthumb_functions::version_compare_replacement(phpversion(), '4.1.0', '>=')) { - $downloadfilename = trim($downloadfilename, '.'); - } - if (@$downloadfilename) { - $phpThumb->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: attachment; filename="'.$downloadfilename.'"', __FILE__, __LINE__); - header('Content-Disposition: attachment; filename="'.$downloadfilename.'"'); - return true; - } - } - $phpThumb->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: inline', __FILE__, __LINE__); - header('Content-Disposition: inline'); - return true; -} - -$phpThumb->DebugMessage('$CanPassThroughDirectly="'.intval($CanPassThroughDirectly).'" && $phpThumb->src="'.$phpThumb->src.'"', __FILE__, __LINE__); -while ($CanPassThroughDirectly && $phpThumb->src) { - // no parameters set, passthru - $SourceFilename = $phpThumb->ResolveFilenameToAbsolute($phpThumb->src); - - // security and size checks - if ($phpThumb->getimagesizeinfo = @GetImageSize($SourceFilename)) { - $phpThumb->DebugMessage('Direct passthru GetImageSize() returned [w='.$phpThumb->getimagesizeinfo[0].';h='.$phpThumb->getimagesizeinfo[1].';t='.$phpThumb->getimagesizeinfo[2].']', __FILE__, __LINE__); - - if (!@$_GET['w'] && !@$_GET['wp'] && !@$_GET['wl'] && !@$_GET['ws'] && !@$_GET['h'] && !@$_GET['hp'] && !@$_GET['hl'] && !@$_GET['hs']) { - // no resizing needed - $phpThumb->DebugMessage('Passing "'.$SourceFilename.'" through directly, no resizing required ("'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'")', __FILE__, __LINE__); - } elseif (($phpThumb->getimagesizeinfo[0] <= @$_GET['w']) && ($phpThumb->getimagesizeinfo[1] <= @$_GET['h']) && ((@$_GET['w'] == $phpThumb->getimagesizeinfo[0]) || (@$_GET['h'] == $phpThumb->getimagesizeinfo[1]))) { - // image fits into 'w'x'h' box, and at least one dimension matches exactly, therefore no resizing needed - $phpThumb->DebugMessage('Passing "'.$SourceFilename.'" through directly, no resizing required ("'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'" fits inside "'.@$_GET['w'].'"x"'.@$_GET['h'].'")', __FILE__, __LINE__); - } else { - $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because resizing required (from "'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'" to "'.@$_GET['w'].'"x"'.@$_GET['h'].'")', __FILE__, __LINE__); - break; - } - switch ($phpThumb->getimagesizeinfo[2]) { - case 1: // GIF - case 2: // JPG - case 3: // PNG - // great, let it through - break; - default: - // browser probably can't handle format, remangle it to JPEG/PNG/GIF - $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because $phpThumb->getimagesizeinfo[2] = "'.$phpThumb->getimagesizeinfo[2].'"', __FILE__, __LINE__); - break 2; - } - - $ImageCreateFunctions = array(1=>'ImageCreateFromGIF', 2=>'ImageCreateFromJPEG', 3=>'ImageCreateFromPNG'); - $theImageCreateFunction = @$ImageCreateFunctions[$phpThumb->getimagesizeinfo[2]]; - if ($phpThumb->config_disable_onlycreateable_passthru || (function_exists($theImageCreateFunction) && ($dummyImage = @$theImageCreateFunction($SourceFilename)))) { - - // great - if (@is_resource($dummyImage)) { - unset($dummyImage); - } - - if (headers_sent()) { - $phpThumb->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')'); - exit; - } - if (@$_GET['phpThumbDebug']) { - $phpThumb->DebugTimingMessage('skipped direct $SourceFilename passthru', __FILE__, __LINE__); - $phpThumb->DebugMessage('Would have passed "'.$SourceFilename.'" through directly, but skipping due to phpThumbDebug', __FILE__, __LINE__); - break; - } - - SendSaveAsFileHeaderIfNeeded(); - header('Last-Modified: '.gmdate('D, d M Y H:i:s', @filemtime($SourceFilename)).' GMT'); - if ($contentType = phpthumb_functions::ImageTypeToMIMEtype(@$phpThumb->getimagesizeinfo[2])) { - header('Content-Type: '.$contentType); - } - @readfile($SourceFilename); - exit; - - } else { - $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because ($phpThumb->config_disable_onlycreateable_passthru = "'.$phpThumb->config_disable_onlycreateable_passthru.'") and '.$theImageCreateFunction.'() failed', __FILE__, __LINE__); - break; - } - - } else { - $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because GetImageSize() failed', __FILE__, __LINE__); - break; - } - break; -} - -//////////////////////////////////////////////////////////////// -// Debug output, to try and help me diagnose problems -$phpThumb->DebugTimingMessage('phpThumbDebug[5]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '5') { - $phpThumb->phpThumbDebug(); -} -//////////////////////////////////////////////////////////////// - -function RedirectToCachedFile() { - global $phpThumb, $PHPTHUMB_CONFIG; - - $nice_cachefile = str_replace(DIRECTORY_SEPARATOR, '/', $phpThumb->cache_filename); - $nice_docroot = str_replace(DIRECTORY_SEPARATOR, '/', rtrim($PHPTHUMB_CONFIG['document_root'], '/\\')); - - $parsed_url = @parse_url(@$_SERVER['HTTP_REFERER']); - - $nModified = filemtime($phpThumb->cache_filename); - - if ($phpThumb->config_nooffsitelink_enabled && @$_SERVER['HTTP_REFERER'] && !in_array(@$parsed_url['host'], $phpThumb->config_nooffsitelink_valid_domains)) { - - $phpThumb->DebugMessage('Would have used cached (image/'.$phpThumb->thumbnailFormat.') file "'.$phpThumb->cache_filename.'" (Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT), but skipping because $_SERVER[HTTP_REFERER] ('.@$_SERVER['HTTP_REFERER'].') is not in $phpThumb->config_nooffsitelink_valid_domains ('.implode(';', $phpThumb->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); - - } elseif ($phpThumb->phpThumbDebug) { - - $phpThumb->DebugTimingMessage('skipped using cached image', __FILE__, __LINE__); - $phpThumb->DebugMessage('Would have used cached file, but skipping due to phpThumbDebug', __FILE__, __LINE__); - $phpThumb->DebugMessage('* Would have sent headers (1): Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT', __FILE__, __LINE__); - if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { - $phpThumb->DebugMessage('* Would have sent headers (2): Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2]), __FILE__, __LINE__); - } - if (ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) { - $phpThumb->DebugMessage('* Would have sent headers (3): Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1])), __FILE__, __LINE__); - } else { - $phpThumb->DebugMessage('* Would have sent data: readfile('.$phpThumb->cache_filename.')', __FILE__, __LINE__); - } - - } else { - - if (headers_sent()) { - $phpThumb->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')'); - exit; - } - SendSaveAsFileHeaderIfNeeded(); - - header('Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT'); - if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] && ($nModified == strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) && @$_SERVER['SERVER_PROTOCOL']) { - header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); - exit; - } - - if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { - header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2])); - } elseif (eregi('\.ico$', $phpThumb->cache_filename)) { - header('Content-Type: image/x-icon'); - } - if (!@$PHPTHUMB_CONFIG['cache_force_passthru'] && ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) { - header('Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1]))); - } else { - @readfile($phpThumb->cache_filename); - } - exit; - - } - return true; -} - -// check to see if file already exists in cache, and output it with no processing if it does -$phpThumb->SetCacheFilename(); -if (@is_file($phpThumb->cache_filename)) { - RedirectToCachedFile(); -} else { - $phpThumb->DebugMessage('Cached file "'.$phpThumb->cache_filename.'" does not exist, processing as normal', __FILE__, __LINE__); -} - -//////////////////////////////////////////////////////////////// -// Debug output, to try and help me diagnose problems -$phpThumb->DebugTimingMessage('phpThumbDebug[6]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '6') { - $phpThumb->phpThumbDebug(); -} -//////////////////////////////////////////////////////////////// - -if ($phpThumb->rawImageData) { - - // great - -} elseif (@$_GET['new']) { - - // generate a blank image resource of the specified size/background color/opacity - if (($phpThumb->w <= 0) || ($phpThumb->h <= 0)) { - $phpThumb->ErrorImage('"w" and "h" parameters required for "new"'); - } - @list($bghexcolor, $opacity) = explode('|', $_GET['new']); - if (!phpthumb_functions::IsHexColor($bghexcolor)) { - $phpThumb->ErrorImage('BGcolor parameter for "new" is not valid'); - } - $opacity = (strlen($opacity) ? $opacity : 100); - if ($phpThumb->gdimg_source = phpthumb_functions::ImageCreateFunction($phpThumb->w, $phpThumb->h)) { - $alpha = (100 - min(100, max(0, $opacity))) * 1.27; - if ($alpha) { - $phpThumb->setParameter('is_alpha', true); - ImageAlphaBlending($phpThumb->gdimg_source, false); - ImageSaveAlpha($phpThumb->gdimg_source, true); - } - $new_background_color = phpthumb_functions::ImageHexColorAllocate($phpThumb->gdimg_source, $bghexcolor, false, $alpha); - ImageFilledRectangle($phpThumb->gdimg_source, 0, 0, $phpThumb->w, $phpThumb->h, $new_background_color); - } else { - $phpThumb->ErrorImage('failed to create "new" image ('.$phpThumb->w.'x'.$phpThumb->h.')'); - } - -} elseif (!$phpThumb->src) { - - $phpThumb->ErrorImage('Usage: '.$_SERVER['PHP_SELF'].'?src=/path/and/filename.jpg'."\n".'read Usage comments for details'); - -} elseif (eregi('^(f|ht)tp\://', $phpThumb->src)) { - - if ($phpThumb->config_http_user_agent) { - ini_set('user_agent', $phpThumb->config_http_user_agent); - } - $basename = preg_quote(basename($phpThumb->src)); - $encoded = rawurlencode(basename($phpThumb->src)); - $HTTPurl = ereg_replace('(.*)'.$basename.'$', '\\1'.$encoded, $phpThumb->src); - if ($rawImageData = phpthumb_functions::SafeURLread($HTTPurl, $error)) { - $phpThumb->setSourceData($rawImageData, urlencode($phpThumb->src)); - } else { - $phpThumb->ErrorImage($error); - } - -} - -//////////////////////////////////////////////////////////////// -// Debug output, to try and help me diagnose problems -$phpThumb->DebugTimingMessage('phpThumbDebug[7]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '7') { - $phpThumb->phpThumbDebug(); -} -//////////////////////////////////////////////////////////////// - -$phpThumb->GenerateThumbnail(); - -//////////////////////////////////////////////////////////////// -// Debug output, to try and help me diagnose problems -$phpThumb->DebugTimingMessage('phpThumbDebug[8]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '8') { - $phpThumb->phpThumbDebug(); -} -//////////////////////////////////////////////////////////////// - -if ($phpThumb->config_allow_parameter_file && $phpThumb->file) { - - $phpThumb->RenderToFile($phpThumb->ResolveFilenameToAbsolute($phpThumb->file)); - if ($phpThumb->config_allow_parameter_goto && $phpThumb->goto && eregi('^(f|ht)tps?://', $phpThumb->goto)) { - // redirect to another URL after image has been rendered to file - header('Location: '.$phpThumb->goto); - exit; - } - -} elseif (@$PHPTHUMB_CONFIG['high_security_enabled'] && @$_GET['nocache']) { - - // cache disabled, don't write cachefile - -} else { - - if ((file_exists($phpThumb->cache_filename) && is_writable($phpThumb->cache_filename)) || is_writable(dirname($phpThumb->cache_filename))) { - - $phpThumb->CleanUpCacheDirectory(); - if ($phpThumb->RenderToFile($phpThumb->cache_filename) && is_readable($phpThumb->cache_filename)) { - chmod($phpThumb->cache_filename, 0644); - RedirectToCachedFile(); - } else { - $phpThumb->DebugMessage('Failed: RenderToFile('.$phpThumb->cache_filename.')', __FILE__, __LINE__); - } - - } else { - - $phpThumb->DebugMessage('Cannot write to $phpThumb->cache_filename ('.$phpThumb->cache_filename.') because that directory ('.dirname($phpThumb->cache_filename).') is not writable', __FILE__, __LINE__); - - } - -} - -//////////////////////////////////////////////////////////////// -// Debug output, to try and help me diagnose problems -$phpThumb->DebugTimingMessage('phpThumbDebug[9]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '9') { - $phpThumb->phpThumbDebug(); -} -//////////////////////////////////////////////////////////////// - -if (!$phpThumb->OutputThumbnail()) { - $phpThumb->ErrorImage('Error in OutputThumbnail():'."\n".$phpThumb->debugmessages[(count($phpThumb->debugmessages) - 1)]); -} - -//////////////////////////////////////////////////////////////// -// Debug output, to try and help me diagnose problems -$phpThumb->DebugTimingMessage('phpThumbDebug[10]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '10') { - $phpThumb->phpThumbDebug(); -} -//////////////////////////////////////////////////////////////// - -?> \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.bmp.php b/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.bmp.php deleted file mode 100644 index 1fe30c6b9..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.bmp.php +++ /dev/null @@ -1,874 +0,0 @@ - // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // -///////////////////////////////////////////////////////////////// -// // -// module.graphic.bmp.php // -// module for analyzing BMP Image files // -// dependencies: NONE // -// /// -///////////////////////////////////////////////////////////////// -// // -// Modified for use in phpThumb() - James Heinrich 2004.07.27 // -// // -///////////////////////////////////////////////////////////////// - - -class phpthumb_bmp { - - function phpthumb_bmp() { - return true; - } - - function phpthumb_bmp2gd(&$BMPdata, $truecolor=true) { - $ThisFileInfo = array(); - if ($this->getid3_bmp($BMPdata, $ThisFileInfo, true, true)) { - $gd = $this->PlotPixelsGD($ThisFileInfo['bmp'], $truecolor); - return $gd; - } - return false; - } - - function phpthumb_bmpfile2gd($filename, $truecolor=true) { - if ($fp = @fopen($filename, 'rb')) { - $BMPdata = fread($fp, filesize($filename)); - fclose($fp); - return $this->phpthumb_bmp2gd($BMPdata, $truecolor); - } - return false; - } - - function GD2BMPstring(&$gd_image) { - $imageX = ImageSX($gd_image); - $imageY = ImageSY($gd_image); - - $BMP = ''; - for ($y = ($imageY - 1); $y >= 0; $y--) { - $thisline = ''; - for ($x = 0; $x < $imageX; $x++) { - $argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y); - $thisline .= chr($argb['blue']).chr($argb['green']).chr($argb['red']); - } - while (strlen($thisline) % 4) { - $thisline .= "\x00"; - } - $BMP .= $thisline; - } - - $bmpSize = strlen($BMP) + 14 + 40; - // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp - $BITMAPFILEHEADER = 'BM'; // WORD bfType; - $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String($bmpSize, 4); // DWORD bfSize; - $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 0, 2); // WORD bfReserved1; - $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 0, 2); // WORD bfReserved2; - $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 54, 4); // DWORD bfOffBits; - - // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp - $BITMAPINFOHEADER = phpthumb_functions::LittleEndian2String( 40, 4); // DWORD biSize; - $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageX, 4); // LONG biWidth; - $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageY, 4); // LONG biHeight; - $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 1, 2); // WORD biPlanes; - $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 24, 2); // WORD biBitCount; - $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biCompression; - $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biSizeImage; - $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 2835, 4); // LONG biXPelsPerMeter; - $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 2835, 4); // LONG biYPelsPerMeter; - $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biClrUsed; - $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biClrImportant; - - return $BITMAPFILEHEADER.$BITMAPINFOHEADER.$BMP; - } - - function getid3_bmp(&$BMPdata, &$ThisFileInfo, $ExtractPalette=false, $ExtractData=false) { - - // shortcuts - $ThisFileInfo['bmp']['header']['raw'] = array(); - $thisfile_bmp = &$ThisFileInfo['bmp']; - $thisfile_bmp_header = &$thisfile_bmp['header']; - $thisfile_bmp_header_raw = &$thisfile_bmp_header['raw']; - - // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp - // all versions - // WORD bfType; - // DWORD bfSize; - // WORD bfReserved1; - // WORD bfReserved2; - // DWORD bfOffBits; - - $offset = 0; - $overalloffset = 0; - $BMPheader = substr($BMPdata, $overalloffset, 14 + 40); - $overalloffset += (14 + 40); - - $thisfile_bmp_header_raw['identifier'] = substr($BMPheader, $offset, 2); - $offset += 2; - - if ($thisfile_bmp_header_raw['identifier'] != 'BM') { - $ThisFileInfo['error'][] = 'Expecting "BM" at offset '.intval(@$ThisFileInfo['avdataoffset']).', found "'.$thisfile_bmp_header_raw['identifier'].'"'; - unset($ThisFileInfo['fileformat']); - unset($ThisFileInfo['bmp']); - return false; - } - - $thisfile_bmp_header_raw['filesize'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['reserved1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); - $offset += 2; - $thisfile_bmp_header_raw['reserved2'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); - $offset += 2; - $thisfile_bmp_header_raw['data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['header_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - - - // check if the hardcoded-to-1 "planes" is at offset 22 or 26 - $planes22 = $this->LittleEndian2Int(substr($BMPheader, 22, 2)); - $planes26 = $this->LittleEndian2Int(substr($BMPheader, 26, 2)); - if (($planes22 == 1) && ($planes26 != 1)) { - $thisfile_bmp['type_os'] = 'OS/2'; - $thisfile_bmp['type_version'] = 1; - } elseif (($planes26 == 1) && ($planes22 != 1)) { - $thisfile_bmp['type_os'] = 'Windows'; - $thisfile_bmp['type_version'] = 1; - } elseif ($thisfile_bmp_header_raw['header_size'] == 12) { - $thisfile_bmp['type_os'] = 'OS/2'; - $thisfile_bmp['type_version'] = 1; - } elseif ($thisfile_bmp_header_raw['header_size'] == 40) { - $thisfile_bmp['type_os'] = 'Windows'; - $thisfile_bmp['type_version'] = 1; - } elseif ($thisfile_bmp_header_raw['header_size'] == 84) { - $thisfile_bmp['type_os'] = 'Windows'; - $thisfile_bmp['type_version'] = 4; - } elseif ($thisfile_bmp_header_raw['header_size'] == 100) { - $thisfile_bmp['type_os'] = 'Windows'; - $thisfile_bmp['type_version'] = 5; - } else { - $ThisFileInfo['error'][] = 'Unknown BMP subtype (or not a BMP file)'; - unset($ThisFileInfo['fileformat']); - unset($ThisFileInfo['bmp']); - return false; - } - - $ThisFileInfo['fileformat'] = 'bmp'; - $ThisFileInfo['video']['dataformat'] = 'bmp'; - $ThisFileInfo['video']['lossless'] = true; - $ThisFileInfo['video']['pixel_aspect_ratio'] = (float) 1; - - if ($thisfile_bmp['type_os'] == 'OS/2') { - - // OS/2-format BMP - // http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm - - // DWORD Size; /* Size of this structure in bytes */ - // DWORD Width; /* Bitmap width in pixels */ - // DWORD Height; /* Bitmap height in pixel */ - // WORD NumPlanes; /* Number of bit planes (color depth) */ - // WORD BitsPerPixel; /* Number of bits per pixel per plane */ - - $thisfile_bmp_header_raw['width'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); - $offset += 2; - $thisfile_bmp_header_raw['height'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); - $offset += 2; - $thisfile_bmp_header_raw['planes'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); - $offset += 2; - $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); - $offset += 2; - - $ThisFileInfo['video']['resolution_x'] = $thisfile_bmp_header_raw['width']; - $ThisFileInfo['video']['resolution_y'] = $thisfile_bmp_header_raw['height']; - $ThisFileInfo['video']['codec'] = 'BI_RGB '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; - $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel']; - - if ($thisfile_bmp['type_version'] >= 2) { - // DWORD Compression; /* Bitmap compression scheme */ - // DWORD ImageDataSize; /* Size of bitmap data in bytes */ - // DWORD XResolution; /* X resolution of display device */ - // DWORD YResolution; /* Y resolution of display device */ - // DWORD ColorsUsed; /* Number of color table indices used */ - // DWORD ColorsImportant; /* Number of important color indices */ - // WORD Units; /* Type of units used to measure resolution */ - // WORD Reserved; /* Pad structure to 4-byte boundary */ - // WORD Recording; /* Recording algorithm */ - // WORD Rendering; /* Halftoning algorithm used */ - // DWORD Size1; /* Reserved for halftoning algorithm use */ - // DWORD Size2; /* Reserved for halftoning algorithm use */ - // DWORD ColorEncoding; /* Color model used in bitmap */ - // DWORD Identifier; /* Reserved for application use */ - - $thisfile_bmp_header_raw['compression'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['bmp_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['resolution_h'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['resolution_v'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['colors_used'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['resolution_units'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); - $offset += 2; - $thisfile_bmp_header_raw['reserved1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); - $offset += 2; - $thisfile_bmp_header_raw['recording'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); - $offset += 2; - $thisfile_bmp_header_raw['rendering'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); - $offset += 2; - $thisfile_bmp_header_raw['size1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['size2'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['color_encoding'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['identifier'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - - $thisfile_bmp_header['compression'] = $this->BMPcompressionOS2Lookup($thisfile_bmp_header_raw['compression']); - - $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; - } - - } elseif ($thisfile_bmp['type_os'] == 'Windows') { - - // Windows-format BMP - - // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp - // all versions - // DWORD biSize; - // LONG biWidth; - // LONG biHeight; - // WORD biPlanes; - // WORD biBitCount; - // DWORD biCompression; - // DWORD biSizeImage; - // LONG biXPelsPerMeter; - // LONG biYPelsPerMeter; - // DWORD biClrUsed; - // DWORD biClrImportant; - - $thisfile_bmp_header_raw['width'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); - $offset += 4; - $thisfile_bmp_header_raw['height'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); - $offset += 4; - $thisfile_bmp_header_raw['planes'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); - $offset += 2; - $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); - $offset += 2; - $thisfile_bmp_header_raw['compression'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['bmp_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['resolution_h'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); - $offset += 4; - $thisfile_bmp_header_raw['resolution_v'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); - $offset += 4; - $thisfile_bmp_header_raw['colors_used'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - - $thisfile_bmp_header['compression'] = $this->BMPcompressionWindowsLookup($thisfile_bmp_header_raw['compression']); - $ThisFileInfo['video']['resolution_x'] = $thisfile_bmp_header_raw['width']; - $ThisFileInfo['video']['resolution_y'] = $thisfile_bmp_header_raw['height']; - $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; - $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel']; - - if (($thisfile_bmp['type_version'] >= 4) || ($thisfile_bmp_header_raw['compression'] == 3)) { - // should only be v4+, but BMPs with type_version==1 and BI_BITFIELDS compression have been seen - $BMPheader .= substr($BMPdata, $overalloffset, 44); - $overalloffset += 44; - - // BITMAPV4HEADER - [44 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_2k1e.asp - // Win95+, WinNT4.0+ - // DWORD bV4RedMask; - // DWORD bV4GreenMask; - // DWORD bV4BlueMask; - // DWORD bV4AlphaMask; - // DWORD bV4CSType; - // CIEXYZTRIPLE bV4Endpoints; - // DWORD bV4GammaRed; - // DWORD bV4GammaGreen; - // DWORD bV4GammaBlue; - $thisfile_bmp_header_raw['red_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['green_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['blue_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['alpha_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['cs_type'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['ciexyz_red'] = substr($BMPheader, $offset, 4); - $offset += 4; - $thisfile_bmp_header_raw['ciexyz_green'] = substr($BMPheader, $offset, 4); - $offset += 4; - $thisfile_bmp_header_raw['ciexyz_blue'] = substr($BMPheader, $offset, 4); - $offset += 4; - $thisfile_bmp_header_raw['gamma_red'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['gamma_green'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['gamma_blue'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - - $thisfile_bmp_header['ciexyz_red'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_red'])); - $thisfile_bmp_header['ciexyz_green'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_green'])); - $thisfile_bmp_header['ciexyz_blue'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_blue'])); - } - - if ($thisfile_bmp['type_version'] >= 5) { - $BMPheader .= substr($BMPdata, $overalloffset, 16); - $overalloffset += 16; - - // BITMAPV5HEADER - [16 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_7c36.asp - // Win98+, Win2000+ - // DWORD bV5Intent; - // DWORD bV5ProfileData; - // DWORD bV5ProfileSize; - // DWORD bV5Reserved; - $thisfile_bmp_header_raw['intent'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['profile_data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['profile_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - $thisfile_bmp_header_raw['reserved3'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); - $offset += 4; - } - - } else { - - $ThisFileInfo['error'][] = 'Unknown BMP format in header.'; - return false; - - } - - if ($ExtractPalette || $ExtractData) { - $PaletteEntries = 0; - if ($thisfile_bmp_header_raw['bits_per_pixel'] < 16) { - $PaletteEntries = pow(2, $thisfile_bmp_header_raw['bits_per_pixel']); - } elseif (isset($thisfile_bmp_header_raw['colors_used']) && ($thisfile_bmp_header_raw['colors_used'] > 0) && ($thisfile_bmp_header_raw['colors_used'] <= 256)) { - $PaletteEntries = $thisfile_bmp_header_raw['colors_used']; - } - if ($PaletteEntries > 0) { - $BMPpalette = substr($BMPdata, $overalloffset, 4 * $PaletteEntries); - $overalloffset += 4 * $PaletteEntries; - - $paletteoffset = 0; - for ($i = 0; $i < $PaletteEntries; $i++) { - // RGBQUAD - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_5f8y.asp - // BYTE rgbBlue; - // BYTE rgbGreen; - // BYTE rgbRed; - // BYTE rgbReserved; - $blue = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); - $green = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); - $red = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); - if (($thisfile_bmp['type_os'] == 'OS/2') && ($thisfile_bmp['type_version'] == 1)) { - // no padding byte - } else { - $paletteoffset++; // padding byte - } - $thisfile_bmp['palette'][$i] = (($red << 16) | ($green << 8) | ($blue)); - } - } - } - - if ($ExtractData) { - $RowByteLength = ceil(($thisfile_bmp_header_raw['width'] * ($thisfile_bmp_header_raw['bits_per_pixel'] / 8)) / 4) * 4; // round up to nearest DWORD boundry - - $BMPpixelData = substr($BMPdata, $thisfile_bmp_header_raw['data_offset'], $thisfile_bmp_header_raw['height'] * $RowByteLength); - $overalloffset = $thisfile_bmp_header_raw['data_offset'] + ($thisfile_bmp_header_raw['height'] * $RowByteLength); - - $pixeldataoffset = 0; - switch (@$thisfile_bmp_header_raw['compression']) { - - case 0: // BI_RGB - switch ($thisfile_bmp_header_raw['bits_per_pixel']) { - case 1: - for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { - for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) { - $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++}); - for ($i = 7; $i >= 0; $i--) { - $paletteindex = ($paletteindexbyte & (0x01 << $i)) >> $i; - $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; - $col++; - } - } - while (($pixeldataoffset % 4) != 0) { - // lines are padded to nearest DWORD - $pixeldataoffset++; - } - } - break; - - case 4: - for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { - for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) { - $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++}); - for ($i = 1; $i >= 0; $i--) { - $paletteindex = ($paletteindexbyte & (0x0F << (4 * $i))) >> (4 * $i); - $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; - $col++; - } - } - while (($pixeldataoffset % 4) != 0) { - // lines are padded to nearest DWORD - $pixeldataoffset++; - } - } - break; - - case 8: - for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { - for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { - $paletteindex = ord($BMPpixelData{$pixeldataoffset++}); - $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; - } - while (($pixeldataoffset % 4) != 0) { - // lines are padded to nearest DWORD - $pixeldataoffset++; - } - } - break; - - case 24: - for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { - for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { - $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset}); - $pixeldataoffset += 3; - } - while (($pixeldataoffset % 4) != 0) { - // lines are padded to nearest DWORD - $pixeldataoffset++; - } - } - break; - - case 32: - for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { - for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { - $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+3}) << 24) | (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset}); - $pixeldataoffset += 4; - } - while (($pixeldataoffset % 4) != 0) { - // lines are padded to nearest DWORD - $pixeldataoffset++; - } - } - break; - - case 16: - // ? - break; - - default: - $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; - break; - } - break; - - - case 1: // BI_RLE8 - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_6x0u.asp - switch ($thisfile_bmp_header_raw['bits_per_pixel']) { - case 8: - $pixelcounter = 0; - while ($pixeldataoffset < strlen($BMPpixelData)) { - $firstbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); - $secondbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); - if ($firstbyte == 0) { - - // escaped/absolute mode - the first byte of the pair can be set to zero to - // indicate an escape character that denotes the end of a line, the end of - // a bitmap, or a delta, depending on the value of the second byte. - switch ($secondbyte) { - case 0: - // end of line - // no need for special processing, just ignore - break; - - case 1: - // end of bitmap - $pixeldataoffset = strlen($BMPpixelData); // force to exit loop just in case - break; - - case 2: - // delta - The 2 bytes following the escape contain unsigned values - // indicating the horizontal and vertical offsets of the next pixel - // from the current position. - $colincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); - $rowincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); - $col = ($pixelcounter % $thisfile_bmp_header_raw['width']) + $colincrement; - $row = ($thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width'])) - $rowincrement; - $pixelcounter = ($row * $thisfile_bmp_header_raw['width']) + $col; - break; - - default: - // In absolute mode, the first byte is zero and the second byte is a - // value in the range 03H through FFH. The second byte represents the - // number of bytes that follow, each of which contains the color index - // of a single pixel. Each run must be aligned on a word boundary. - for ($i = 0; $i < $secondbyte; $i++) { - $paletteindex = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); - $col = $pixelcounter % $thisfile_bmp_header_raw['width']; - $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); - $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; - $pixelcounter++; - } - while (($pixeldataoffset % 2) != 0) { - // Each run must be aligned on a word boundary. - $pixeldataoffset++; - } - break; - } - - } else { - - // encoded mode - the first byte specifies the number of consecutive pixels - // to be drawn using the color index contained in the second byte. - for ($i = 0; $i < $firstbyte; $i++) { - $col = $pixelcounter % $thisfile_bmp_header_raw['width']; - $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); - $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$secondbyte]; - $pixelcounter++; - } - - } - } - break; - - default: - $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; - break; - } - break; - - - - case 2: // BI_RLE4 - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_6x0u.asp - switch ($thisfile_bmp_header_raw['bits_per_pixel']) { - case 4: - $pixelcounter = 0; - while ($pixeldataoffset < strlen($BMPpixelData)) { - $firstbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); - $secondbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); - if ($firstbyte == 0) { - - // escaped/absolute mode - the first byte of the pair can be set to zero to - // indicate an escape character that denotes the end of a line, the end of - // a bitmap, or a delta, depending on the value of the second byte. - switch ($secondbyte) { - case 0: - // end of line - // no need for special processing, just ignore - break; - - case 1: - // end of bitmap - $pixeldataoffset = strlen($BMPpixelData); // force to exit loop just in case - break; - - case 2: - // delta - The 2 bytes following the escape contain unsigned values - // indicating the horizontal and vertical offsets of the next pixel - // from the current position. - $colincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); - $rowincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); - $col = ($pixelcounter % $thisfile_bmp_header_raw['width']) + $colincrement; - $row = ($thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width'])) - $rowincrement; - $pixelcounter = ($row * $thisfile_bmp_header_raw['width']) + $col; - break; - - default: - // In absolute mode, the first byte is zero. The second byte contains the number - // of color indexes that follow. Subsequent bytes contain color indexes in their - // high- and low-order 4 bits, one color index for each pixel. In absolute mode, - // each run must be aligned on a word boundary. - unset($paletteindexes); - for ($i = 0; $i < ceil($secondbyte / 2); $i++) { - $paletteindexbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); - $paletteindexes[] = ($paletteindexbyte & 0xF0) >> 4; - $paletteindexes[] = ($paletteindexbyte & 0x0F); - } - while (($pixeldataoffset % 2) != 0) { - // Each run must be aligned on a word boundary. - $pixeldataoffset++; - } - - foreach ($paletteindexes as $dummy => $paletteindex) { - $col = $pixelcounter % $thisfile_bmp_header_raw['width']; - $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); - $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; - $pixelcounter++; - } - break; - } - - } else { - - // encoded mode - the first byte of the pair contains the number of pixels to be - // drawn using the color indexes in the second byte. The second byte contains two - // color indexes, one in its high-order 4 bits and one in its low-order 4 bits. - // The first of the pixels is drawn using the color specified by the high-order - // 4 bits, the second is drawn using the color in the low-order 4 bits, the third - // is drawn using the color in the high-order 4 bits, and so on, until all the - // pixels specified by the first byte have been drawn. - $paletteindexes[0] = ($secondbyte & 0xF0) >> 4; - $paletteindexes[1] = ($secondbyte & 0x0F); - for ($i = 0; $i < $firstbyte; $i++) { - $col = $pixelcounter % $thisfile_bmp_header_raw['width']; - $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); - $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindexes[($i % 2)]]; - $pixelcounter++; - } - - } - } - break; - - default: - $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; - break; - } - break; - - - case 3: // BI_BITFIELDS - switch ($thisfile_bmp_header_raw['bits_per_pixel']) { - case 16: - case 32: - $redshift = 0; - $greenshift = 0; - $blueshift = 0; - if (!$thisfile_bmp_header_raw['red_mask'] || !$thisfile_bmp_header_raw['green_mask'] || !$thisfile_bmp_header_raw['blue_mask']) { - $ThisFileInfo['error'][] = 'missing $thisfile_bmp_header_raw[(red|green|blue)_mask]'; - return false; - } - while ((($thisfile_bmp_header_raw['red_mask'] >> $redshift) & 0x01) == 0) { - $redshift++; - } - while ((($thisfile_bmp_header_raw['green_mask'] >> $greenshift) & 0x01) == 0) { - $greenshift++; - } - while ((($thisfile_bmp_header_raw['blue_mask'] >> $blueshift) & 0x01) == 0) { - $blueshift++; - } - for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { - for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { - $pixelvalue = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset, $thisfile_bmp_header_raw['bits_per_pixel'] / 8)); - $pixeldataoffset += $thisfile_bmp_header_raw['bits_per_pixel'] / 8; - - $red = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['red_mask']) >> $redshift) / ($thisfile_bmp_header_raw['red_mask'] >> $redshift)) * 255)); - $green = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['green_mask']) >> $greenshift) / ($thisfile_bmp_header_raw['green_mask'] >> $greenshift)) * 255)); - $blue = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['blue_mask']) >> $blueshift) / ($thisfile_bmp_header_raw['blue_mask'] >> $blueshift)) * 255)); - $thisfile_bmp['data'][$row][$col] = (($red << 16) | ($green << 8) | ($blue)); - } - while (($pixeldataoffset % 4) != 0) { - // lines are padded to nearest DWORD - $pixeldataoffset++; - } - } - break; - - default: - $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; - break; - } - break; - - - default: // unhandled compression type - $ThisFileInfo['error'][] = 'Unknown/unhandled compression type value ('.$thisfile_bmp_header_raw['compression'].') - cannot decompress pixel data'; - break; - } - } - - return true; - } - - function IntColor2RGB($color) { - $red = ($color & 0x00FF0000) >> 16; - $green = ($color & 0x0000FF00) >> 8; - $blue = ($color & 0x000000FF); - return array($red, $green, $blue); - } - - function PlotPixelsGD(&$BMPdata, $truecolor=true) { - $imagewidth = $BMPdata['header']['raw']['width']; - $imageheight = $BMPdata['header']['raw']['height']; - - if ($truecolor) { - - $gd = @ImageCreateTrueColor($imagewidth, $imageheight); - - } else { - - $gd = @ImageCreate($imagewidth, $imageheight); - if (!empty($BMPdata['palette'])) { - // create GD palette from BMP palette - foreach ($BMPdata['palette'] as $dummy => $color) { - list($r, $g, $b) = $this->IntColor2RGB($color); - ImageColorAllocate($gd, $r, $g, $b); - } - } else { - // create 216-color websafe palette - for ($r = 0x00; $r <= 0xFF; $r += 0x33) { - for ($g = 0x00; $g <= 0xFF; $g += 0x33) { - for ($b = 0x00; $b <= 0xFF; $b += 0x33) { - ImageColorAllocate($gd, $r, $g, $b); - } - } - } - } - - } - if (!is_resource($gd)) { - return false; - } - - foreach ($BMPdata['data'] as $row => $colarray) { - @set_time_limit(30); - foreach ($colarray as $col => $color) { - list($red, $green, $blue) = $this->IntColor2RGB($color); - if ($truecolor) { - $pixelcolor = ImageColorAllocate($gd, $red, $green, $blue); - } else { - $pixelcolor = ImageColorClosest($gd, $red, $green, $blue); - } - ImageSetPixel($gd, $col, $row, $pixelcolor); - } - } - return $gd; - } - - function PlotBMP(&$BMPinfo) { - $starttime = time(); - if (!isset($BMPinfo['bmp']['data']) || !is_array($BMPinfo['bmp']['data'])) { - echo 'ERROR: no pixel data
    '; - return false; - } - set_time_limit(intval(round($BMPinfo['resolution_x'] * $BMPinfo['resolution_y'] / 10000))); - $im = $this->PlotPixelsGD($BMPinfo['bmp']); - if (headers_sent()) { - echo 'plotted '.($BMPinfo['resolution_x'] * $BMPinfo['resolution_y']).' pixels in '.(time() - $starttime).' seconds
    '; - ImageDestroy($im); - exit; - } else { - header('Content-Type: image/png'); - ImagePNG($im); - ImageDestroy($im); - return true; - } - return false; - } - - function BMPcompressionWindowsLookup($compressionid) { - static $BMPcompressionWindowsLookup = array( - 0 => 'BI_RGB', - 1 => 'BI_RLE8', - 2 => 'BI_RLE4', - 3 => 'BI_BITFIELDS', - 4 => 'BI_JPEG', - 5 => 'BI_PNG' - ); - return (isset($BMPcompressionWindowsLookup[$compressionid]) ? $BMPcompressionWindowsLookup[$compressionid] : 'invalid'); - } - - function BMPcompressionOS2Lookup($compressionid) { - static $BMPcompressionOS2Lookup = array( - 0 => 'BI_RGB', - 1 => 'BI_RLE8', - 2 => 'BI_RLE4', - 3 => 'Huffman 1D', - 4 => 'BI_RLE24', - ); - return (isset($BMPcompressionOS2Lookup[$compressionid]) ? $BMPcompressionOS2Lookup[$compressionid] : 'invalid'); - } - - - // from getid3.lib.php - - function trunc($floatnumber) { - // truncates a floating-point number at the decimal point - // returns int (if possible, otherwise float) - if ($floatnumber >= 1) { - $truncatednumber = floor($floatnumber); - } elseif ($floatnumber <= -1) { - $truncatednumber = ceil($floatnumber); - } else { - $truncatednumber = 0; - } - if ($truncatednumber <= 1073741824) { // 2^30 - $truncatednumber = (int) $truncatednumber; - } - return $truncatednumber; - } - - function LittleEndian2Int($byteword) { - $intvalue = 0; - $byteword = strrev($byteword); - $bytewordlen = strlen($byteword); - for ($i = 0; $i < $bytewordlen; $i++) { - $intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i)); - } - return $intvalue; - } - - function BigEndian2Int($byteword) { - return $this->LittleEndian2Int(strrev($byteword)); - } - - function BigEndian2Bin($byteword) { - $binvalue = ''; - $bytewordlen = strlen($byteword); - for ($i = 0; $i < $bytewordlen; $i++) { - $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT); - } - return $binvalue; - } - - function FixedPoint2_30($rawdata) { - $binarystring = $this->BigEndian2Bin($rawdata); - return $this->Bin2Dec(substr($binarystring, 0, 2)) + (float) ($this->Bin2Dec(substr($binarystring, 2, 30)) / 1073741824); - } - - function Bin2Dec($binstring, $signed=false) { - $signmult = 1; - if ($signed) { - if ($binstring{0} == '1') { - $signmult = -1; - } - $binstring = substr($binstring, 1); - } - $decvalue = 0; - for ($i = 0; $i < strlen($binstring); $i++) { - $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i); - } - return $this->CastAsInt($decvalue * $signmult); - } - - function CastAsInt($floatnum) { - // convert to float if not already - $floatnum = (float) $floatnum; - - // convert a float to type int, only if possible - if ($this->trunc($floatnum) == $floatnum) { - // it's not floating point - if ($floatnum <= 1073741824) { // 2^30 - // it's within int range - $floatnum = (int) $floatnum; - } - } - return $floatnum; - } - -} - -?> \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.class.php b/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.class.php deleted file mode 100644 index 8517f40ec..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.class.php +++ /dev/null @@ -1,3433 +0,0 @@ - // -// available at http://phpthumb.sourceforge.net /// -////////////////////////////////////////////////////////////// -/// // -// See: phpthumb.readme.txt for usage instructions // -// /// -////////////////////////////////////////////////////////////// - -ob_start(); -if (!include_once(dirname(__FILE__).'/phpthumb.functions.php')) { - ob_end_flush(); - die('failed to include_once("'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'")'); -} -ob_end_clean(); - -class phpthumb { - - // public: - // START PARAMETERS (for object mode and phpThumb.php) - // See phpthumb.readme.txt for descriptions of what each of these values are - var $src = null; // SouRCe filename - var $new = null; // NEW image (phpThumb.php only) - var $w = null; // Width - var $h = null; // Height - var $wp = null; // Width (Portrait Images Only) - var $hp = null; // Height (Portrait Images Only) - var $wl = null; // Width (Landscape Images Only) - var $hl = null; // Height (Landscape Images Only) - var $ws = null; // Width (Square Images Only) - var $hs = null; // Height (Square Images Only) - var $f = null; // Format - var $q = 75; // jpeg output Quality - var $sx = null; // Source crop top-left X position - var $sy = null; // Source crop top-left Y position - var $sw = null; // Source crop Width - var $sh = null; // Source crop Height - var $zc = null; // Zoom Crop - var $bc = null; // Border Color - var $bg = null; // BackGround color - var $fltr = array(); // FiLTeRs - var $goto = null; // GO TO url after processing - var $err = null; // default ERRor image filename - var $xto = null; // extract eXif Thumbnail Only - var $ra = null; // Rotate by Angle - var $ar = null; // Auto Rotate - var $aoe = null; // Allow Output Enlargement - var $far = null; // Fixed Aspect Ratio - var $iar = null; // Ignore Aspect Ratio - var $maxb = null; // MAXimum Bytes - var $down = null; // DOWNload thumbnail filename - var $md5s = null; // MD5 hash of Source image - var $file = null; // >>deprecated, do not use<< - - var $phpThumbDebug = null; - // END PARAMETERS - - - // public: - // START CONFIGURATION OPTIONS (for object mode only) - // See phpThumb.config.php for descriptions of what each of these settings do - - // * Directory Configuration - var $config_cache_directory = null; - var $config_cache_disable_warning = true; - var $config_cache_source_enabled = false; - var $config_cache_source_directory = null; - var $config_temp_directory = null; - var $config_document_root = null; - - // * Default output configuration: - var $config_output_format = 'jpeg'; - var $config_output_maxwidth = 0; - var $config_output_maxheight = 0; - var $config_output_interlace = true; - - // * Error message configuration - var $config_error_image_width = 400; - var $config_error_image_height = 100; - var $config_error_message_image_default = ''; - var $config_error_bgcolor = 'CCCCFF'; - var $config_error_textcolor = 'FF0000'; - var $config_error_fontsize = 1; - var $config_error_die_on_error = false; - var $config_error_silent_die_on_error = false; - var $config_error_die_on_source_failure = true; - - // * Anti-Hotlink Configuration: - var $config_nohotlink_enabled = true; - var $config_nohotlink_valid_domains = array(); - var $config_nohotlink_erase_image = true; - var $config_nohotlink_text_message = 'Off-server thumbnailing is not allowed'; - // * Off-server Linking Configuration: - var $config_nooffsitelink_enabled = false; - var $config_nooffsitelink_valid_domains = array(); - var $config_nooffsitelink_require_refer = false; - var $config_nooffsitelink_erase_image = true; - var $config_nooffsitelink_text_message = 'Off-server linking is not allowed'; - - // * Border & Background default colors - var $config_border_hexcolor = '000000'; - var $config_background_hexcolor = 'FFFFFF'; - - // * TrueType Fonts - var $config_ttf_directory = '.'; - - var $config_max_source_pixels = null; - var $config_use_exif_thumbnail_for_speed = false; - var $allow_local_http_src = false; - - var $config_imagemagick_path = null; - var $config_prefer_imagemagick = true; - - var $config_cache_maxage = null; - var $config_cache_maxsize = null; - var $config_cache_maxfiles = null; - var $config_cache_source_filemtime_ignore_local = false; - var $config_cache_source_filemtime_ignore_remote = true; - var $config_cache_default_only_suffix = false; - var $config_cache_force_passthru = true; - var $config_cache_prefix = ''; // default value set in the constructor below - - // * MySQL - var $config_mysql_query = null; - var $config_mysql_hostname = null; - var $config_mysql_username = null; - var $config_mysql_password = null; - var $config_mysql_database = null; - - // * Security - var $config_high_security_enabled = false; - var $config_high_security_password = null; - var $config_disable_debug = false; - var $config_allow_src_above_docroot = true; - var $config_allow_src_above_phpthumb = true; - var $config_allow_parameter_file = false; - var $config_allow_parameter_goto = false; - - // * Compatability - var $config_disable_pathinfo_parsing = false; - var $config_disable_imagecopyresampled = false; - var $config_disable_onlycreateable_passthru = false; - - var $config_http_user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7'; - - // END CONFIGURATION OPTIONS - - - // public: error messages (read-only) - var $debugmessages = array(); - var $debugtiming = array(); - var $fatalerror = null; - - - // private: (should not be modified directly) - var $thumbnailQuality = 75; - var $thumbnailFormat = null; - - var $sourceFilename = null; - var $rawImageData = null; - var $IMresizedData = null; - var $outputImageData = null; - - var $useRawIMoutput = false; - - var $gdimg_output = null; - var $gdimg_source = null; - - var $getimagesizeinfo = null; - - var $source_width = null; - var $source_height = null; - - var $thumbnailCropX = null; - var $thumbnailCropY = null; - var $thumbnailCropW = null; - var $thumbnailCropH = null; - - var $exif_thumbnail_width = null; - var $exif_thumbnail_height = null; - var $exif_thumbnail_type = null; - var $exif_thumbnail_data = null; - var $exif_raw_data = null; - - var $thumbnail_width = null; - var $thumbnail_height = null; - var $thumbnail_image_width = null; - var $thumbnail_image_height = null; - - var $cache_filename = null; - - var $AlphaCapableFormats = array('png', 'ico', 'gif'); - var $is_alpha = false; - - var $iswindows = null; - - var $phpthumb_version = '1.7.2-200606220757'; - - ////////////////////////////////////////////////////////////////////// - - // public: constructor - function phpThumb() { - $this->DebugTimingMessage('phpThumb() constructor', __FILE__, __LINE__); - $this->DebugMessage('phpThumb() v'.$this->phpthumb_version, __FILE__, __LINE__); - $this->config_max_source_pixels = round(max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576 * 0.20); // 20% of memory_limit - $this->iswindows = (bool) (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); - $this->config_temp_directory = realpath($this->config_temp_directory ? $this->config_temp_directory : (getenv('TMPDIR') ? getenv('TMPDIR') : getenv('TMP'))); - $this->config_document_root = (@$_SERVER['DOCUMENT_ROOT'] ? $_SERVER['DOCUMENT_ROOT'] : $this->config_document_root); - $this->config_cache_prefix = 'phpThumb_cache_'.@$_SERVER['SERVER_NAME']; - - $php_sapi_name = strtolower(function_exists('php_sapi_name') ? php_sapi_name() : ''); - if ($php_sapi_name == 'cli') { - $this->config_allow_src_above_docroot = true; - } - } - - // public: - function setSourceFilename($sourceFilename) { - $this->rawImageData = null; - $this->sourceFilename = $sourceFilename; - $this->src = $sourceFilename; - $this->DebugMessage('setSourceFilename('.$sourceFilename.') set $this->sourceFilename to "'.$this->sourceFilename.'"', __FILE__, __LINE__); - return true; - } - - // public: - function setSourceData($rawImageData, $sourceFilename='') { - $this->sourceFilename = null; - $this->rawImageData = $rawImageData; - $this->DebugMessage('setSourceData() setting $this->rawImageData ('.strlen($this->rawImageData).' bytes)', __FILE__, __LINE__); - if ($this->config_cache_source_enabled) { - $sourceFilename = ($sourceFilename ? $sourceFilename : md5($rawImageData)); - if (!is_dir($this->config_cache_source_directory)) { - $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not a directory'); - } elseif (!@is_writable($this->config_cache_source_directory)) { - $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not writable'); - } - $this->DebugMessage('setSourceData() attempting to save source image to "'.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).'"', __FILE__, __LINE__); - if ($fp = @fopen($this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename), 'wb')) { - fwrite($fp, $rawImageData); - fclose($fp); - } elseif (!$this->phpThumbDebug) { - $this->ErrorImage('setSourceData() failed to write to source cache ('.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).')'); - } - } - return true; - } - - // public: - function setSourceImageResource($gdimg) { - $this->gdimg_source = $gdimg; - return true; - } - - // public: - function setParameter($param, $value) { - if ($param == 'src') { - $this->setSourceFilename($this->ResolveFilenameToAbsolute($value)); - } elseif (@is_array($this->$param)) { - if (is_array($value)) { - foreach ($value as $arraykey => $arrayvalue) { - array_push($this->$param, $arrayvalue); - } - } else { - array_push($this->$param, $value); - } - } else { - $this->$param = $value; - } - return true; - } - - // public: - function getParameter($param) { - //if (property_exists('phpThumb', $param)) { - return $this->$param; - //} - //$this->DebugMessage('setParameter() attempting to get non-existant parameter "'.$param.'"', __FILE__, __LINE__); - //return false; - } - - - // public: - function GenerateThumbnail() { - - $this->setOutputFormat(); - $this->ResolveSource(); - $this->SetCacheFilename(); - $this->ExtractEXIFgetImageSize(); - if ($this->useRawIMoutput) { - $this->DebugMessage('Skipping rest of GenerateThumbnail() because $this->useRawIMoutput', __FILE__, __LINE__); - return true; - } - if (!$this->SourceImageToGD()) { - $this->DebugMessage('SourceImageToGD() failed', __FILE__, __LINE__); - return false; - } - $this->Rotate(); - $this->CreateGDoutput(); - - switch ($this->far) { - case 'L': - case 'TL': - case 'BL': - $destination_offset_x = 0; - $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); - break; - case 'R': - case 'TR': - case 'BR': - $destination_offset_x = round($this->thumbnail_width - $this->thumbnail_image_width); - $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); - break; - case 'T': - case 'TL': - case 'TR': - $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); - $destination_offset_y = 0; - break; - case 'B': - case 'BL': - case 'BR': - $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); - $destination_offset_y = round($this->thumbnail_height - $this->thumbnail_image_height); - break; - case 'C': - default: - $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); - $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); - } - -// // copy/resize image to appropriate dimensions -// $borderThickness = 0; -// if (!empty($this->fltr)) { -// foreach ($this->fltr as $key => $value) { -// if (ereg('^bord\|([0-9]+)', $value, $matches)) { -// $borderThickness = $matches[1]; -// break; -// } -// } -// } -// if ($borderThickness > 0) { -// //$this->DebugMessage('Skipping ImageResizeFunction() because BorderThickness="'.$borderThickness.'"', __FILE__, __LINE__); -// $this->thumbnail_image_height /= 2; -// } - $this->ImageResizeFunction( - $this->gdimg_output, - $this->gdimg_source, - $destination_offset_x, - $destination_offset_y, - $this->thumbnailCropX, - $this->thumbnailCropY, - $this->thumbnail_image_width, - $this->thumbnail_image_height, - $this->thumbnailCropW, - $this->thumbnailCropH - ); - - $this->DebugMessage('memory_get_usage() after copy-resize = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__); - ImageDestroy($this->gdimg_source); - $this->DebugMessage('memory_get_usage() after ImageDestroy = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__); - - $this->AntiOffsiteLinking(); - $this->ApplyFilters(); - $this->AlphaChannelFlatten(); - $this->MaxFileSize(); - - $this->DebugMessage('GenerateThumbnail() completed successfully', __FILE__, __LINE__); - return true; - } - - - // public: - function RenderOutput() { - if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { - $this->DebugMessage('RenderOutput() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); - return false; - } - if (!$this->thumbnailFormat) { - $this->DebugMessage('RenderOutput() failed because $this->thumbnailFormat is empty', __FILE__, __LINE__); - return false; - } - if ($this->useRawIMoutput) { - $this->DebugMessage('RenderOutput copying $this->IMresizedData ('.strlen($this->IMresizedData).' bytes) to $this->outputImage', __FILE__, __LINE__); - $this->outputImageData = $this->IMresizedData; - return true; - } - - $this->DebugMessage('RenderOutput() attempting Image'.strtoupper(@$this->thumbnailFormat).'($this->gdimg_output)', __FILE__, __LINE__); - ob_start(); - switch ($this->thumbnailFormat) { - case 'jpeg': - ImageJPEG($this->gdimg_output, null, $this->thumbnailQuality); - $this->outputImageData = ob_get_contents(); - break; - - case 'png': - ImagePNG($this->gdimg_output); - $this->outputImageData = ob_get_contents(); - break; - - case 'gif': - ImageGIF($this->gdimg_output); - $this->outputImageData = ob_get_contents(); - break; - - case 'bmp': - $ImageOutFunction = '"builtin BMP output"'; - if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { - $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__); - ob_end_clean(); - return false; - } - $phpthumb_bmp = new phpthumb_bmp(); - $this->outputImageData = $phpthumb_bmp->GD2BMPstring($this->gdimg_output); - unset($phpthumb_bmp); - break; - - case 'ico': - $ImageOutFunction = '"builtin ICO output"'; - if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) { - $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__); - ob_end_clean(); - return false; - } - $phpthumb_ico = new phpthumb_ico(); - $arrayOfOutputImages = array($this->gdimg_output); - $this->outputImageData = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages); - unset($phpthumb_ico); - break; - - default: - $this->DebugMessage('RenderToFile failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__); - ob_end_clean(); - return false; - } - ob_end_clean(); - if (!$this->outputImageData) { - $this->DebugMessage('RenderOutput() for "'.$this->thumbnailFormat.'" failed', __FILE__, __LINE__); - ob_end_clean(); - return false; - } - $this->DebugMessage('RenderOutput() completing with $this->outputImageData = '.strlen($this->outputImageData).' bytes', __FILE__, __LINE__); - return true; - } - - function RenderToFile($filename) { - if (eregi('^(f|ht)tps?\://', $filename)) { - $this->DebugMessage('RenderToFile() failed because $filename ('.$filename.') is a URL', __FILE__, __LINE__); - return false; - } - // render thumbnail to this file only, do not cache, do not output to browser - //$renderfilename = $this->ResolveFilenameToAbsolute(dirname($filename)).DIRECTORY_SEPARATOR.basename($filename); - $renderfilename = $filename; - if (($filename{0} != '/') && ($filename{0} != '\\') && ($filename{1} != ':')) { - $renderfilename = $this->ResolveFilenameToAbsolute($renderfilename); - } - if (!@is_writable(dirname($renderfilename))) { - $this->DebugMessage('RenderToFile() failed because "'.dirname($renderfilename).'/" is not writable', __FILE__, __LINE__); - return false; - } - if (@is_file($renderfilename) && !@is_writable($renderfilename)) { - $this->DebugMessage('RenderToFile() failed because "'.$renderfilename.'" is not writable', __FILE__, __LINE__); - return false; - } - - if ($this->RenderOutput()) { - if (file_put_contents($renderfilename, $this->outputImageData)) { - $this->DebugMessage('RenderToFile('.$renderfilename.') succeeded', __FILE__, __LINE__); - return true; - } - if (!@file_exists($renderfilename)) { - $this->DebugMessage('RenderOutput ['.$this->thumbnailFormat.'('.$renderfilename.')] did not appear to fail, but the output image does not exist either...', __FILE__, __LINE__); - } - } else { - $this->DebugMessage('RenderOutput ['.$this->thumbnailFormat.'('.$renderfilename.')] failed', __FILE__, __LINE__); - } - return false; - } - - - // public: - function OutputThumbnail() { - if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { - $this->DebugMessage('OutputThumbnail() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); - return false; - } - if (headers_sent()) { - return $this->ErrorImage('OutputThumbnail() failed - headers already sent'); - exit; - } - - if ($this->down) { - $downloadfilename = ereg_replace('[/\\:\*\?"<>|]', '_', $this->down); - if (phpthumb_functions::version_compare_replacement(phpversion(), '4.1.0', '>=')) { - $downloadfilename = trim($downloadfilename, '.'); - } - if ($downloadfilename != $this->down) { - $this->DebugMessage('renaming output file for "down" from "'.$this->down.'" to "'.$downloadfilename.'"', __FILE__, __LINE__); - } - if ($downloadfilename) { - header('Content-Disposition: attachment; filename="'.$downloadfilename.'"'); - } else { - $this->DebugMessage('failed to send Content-Disposition header because $downloadfilename is empty', __FILE__, __LINE__); - } - } - - if ($this->useRawIMoutput) { - - header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); - echo $this->IMresizedData; - - } else { - - $this->DebugMessage('ImageInterlace($this->gdimg_output, '.intval($this->config_output_interlace).')', __FILE__, __LINE__); - ImageInterlace($this->gdimg_output, intval($this->config_output_interlace)); - switch ($this->thumbnailFormat) { - case 'jpeg': - header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); - $ImageOutFunction = 'image'.$this->thumbnailFormat; - @$ImageOutFunction($this->gdimg_output, '', $this->thumbnailQuality); - break; - - case 'png': - case 'gif': - header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); - $ImageOutFunction = 'image'.$this->thumbnailFormat; - @$ImageOutFunction($this->gdimg_output); - break; - - case 'bmp': - if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { - $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__); - return false; - } - $phpthumb_bmp = new phpthumb_bmp(); - if (is_object($phpthumb_bmp)) { - $bmp_data = $phpthumb_bmp->GD2BMPstring($this->gdimg_output); - unset($phpthumb_bmp); - if (!$bmp_data) { - $this->DebugMessage('$phpthumb_bmp->GD2BMPstring() failed', __FILE__, __LINE__); - return false; - } - header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); - echo $bmp_data; - } else { - $this->DebugMessage('new phpthumb_bmp() failed', __FILE__, __LINE__); - return false; - } - break; - - case 'ico': - if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) { - $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__); - return false; - } - $phpthumb_ico = new phpthumb_ico(); - if (is_object($phpthumb_ico)) { - $arrayOfOutputImages = array($this->gdimg_output); - $ico_data = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages); - unset($phpthumb_ico); - if (!$ico_data) { - $this->DebugMessage('$phpthumb_ico->GD2ICOstring() failed', __FILE__, __LINE__); - return false; - } - header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); - echo $ico_data; - } else { - $this->DebugMessage('new phpthumb_ico() failed', __FILE__, __LINE__); - return false; - } - break; - - default: - $this->DebugMessage('OutputThumbnail failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__); - return false; - break; - } - - } - return true; - } - - - // public: - function CleanUpCacheDirectory() { - if (($this->config_cache_maxage > 0) || ($this->config_cache_maxsize > 0) || ($this->config_cache_maxfiles > 0)) { - $CacheDirOldFilesAge = array(); - $CacheDirOldFilesSize = array(); - if ($dirhandle = opendir($this->config_cache_directory)) { - while ($oldcachefile = readdir($dirhandle)) { - $fullfilename = $this->config_cache_directory.DIRECTORY_SEPARATOR.$oldcachefile; - if (eregi('^phpThumb_cache_', $oldcachefile) && file_exists($fullfilename)) { - $CacheDirOldFilesAge[$oldcachefile] = @fileatime($fullfilename); - if ($CacheDirOldFilesAge[$oldcachefile] == 0) { - $CacheDirOldFilesAge[$oldcachefile] = @filemtime($fullfilename); - } - - $CacheDirOldFilesSize[$oldcachefile] = @filesize($fullfilename); - } - } - } - asort($CacheDirOldFilesAge); - - if ($this->config_cache_maxfiles > 0) { - $TotalCachedFiles = count($CacheDirOldFilesAge); - $DeletedKeys = array(); - foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) { - if ($TotalCachedFiles > $this->config_cache_maxfiles) { - $TotalCachedFiles--; - if (@unlink($fullfilename)) { - $DeletedKeys[] = $oldcachefile; - } - } else { - // there are few enough files to keep the rest - break; - } - } - foreach ($DeletedKeys as $dummy => $oldcachefile) { - unset($CacheDirOldFilesAge[$oldcachefile]); - unset($CacheDirOldFilesSize[$oldcachefile]); - } - } - - if ($this->config_cache_maxage > 0) { - $mindate = time() - $this->config_cache_maxage; - $DeletedKeys = array(); - foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) { - if ($filedate > 0) { - if ($filedate < $mindate) { - if (@unlink($fullfilename)) { - $DeletedKeys[] = $oldcachefile; - } - } else { - // the rest of the files are new enough to keep - break; - } - } - } - foreach ($DeletedKeys as $dummy => $oldcachefile) { - unset($CacheDirOldFilesAge[$oldcachefile]); - unset($CacheDirOldFilesSize[$oldcachefile]); - } - } - - if ($this->config_cache_maxsize > 0) { - $TotalCachedFileSize = array_sum($CacheDirOldFilesSize); - $DeletedKeys = array(); - foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) { - if ($TotalCachedFileSize > $this->config_cache_maxsize) { - $TotalCachedFileSize -= $CacheDirOldFilesSize[$oldcachefile]; - if (@unlink($fullfilename)) { - $DeletedKeys[] = $oldcachefile; - } - } else { - // the total filesizes are small enough to keep the rest of the files - break; - } - } - foreach ($DeletedKeys as $dummy => $oldcachefile) { - unset($CacheDirOldFilesAge[$oldcachefile]); - unset($CacheDirOldFilesSize[$oldcachefile]); - } - } - - } - return true; - } - - ////////////////////////////////////////////////////////////////////// - - function ResolveSource() { - if (is_resource($this->gdimg_source)) { - $this->DebugMessage('ResolveSource() exiting because is_resource($this->gdimg_source)', __FILE__, __LINE__); - return true; - } - if ($this->rawImageData) { - $this->sourceFilename = null; - $this->DebugMessage('ResolveSource() exiting because $this->rawImageData is set', __FILE__, __LINE__); - return true; - } - if ($this->sourceFilename) { - $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->sourceFilename); - $this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'"', __FILE__, __LINE__); - } else { - $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src); - $this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'" from $this->src ('.$this->src.')', __FILE__, __LINE__); - } - if ($this->iswindows && ((substr($this->sourceFilename, 0, 2) == '//') || (substr($this->sourceFilename, 0, 2) == '\\\\'))) { - // Windows \\share\filename.ext - } elseif (eregi('^(f|ht)tps?\://', $this->sourceFilename)) { - // URL - if ($this->config_http_user_agent) { - ini_set('user_agent', $this->config_http_user_agent); - } - } elseif (!@file_exists($this->sourceFilename)) { - return $this->ErrorImage('"'.$this->sourceFilename.'" does not exist'); - } elseif (!@is_file($this->sourceFilename)) { - return $this->ErrorImage('"'.$this->sourceFilename.'" is not a file'); - } - return true; - } - - function setOutputFormat() { - static $alreadyCalled = false; - if ($this->thumbnailFormat && $alreadyCalled) { - return true; - } - $alreadyCalled = true; - - $AvailableImageOutputFormats = array(); - $AvailableImageOutputFormats[] = 'text'; - if (@is_readable(dirname(__FILE__).'/phpthumb.ico.php')) { - $AvailableImageOutputFormats[] = 'ico'; - } - if (@is_readable(dirname(__FILE__).'/phpthumb.bmp.php')) { - $AvailableImageOutputFormats[] = 'bmp'; - } - - $this->thumbnailFormat = 'ico'; - - // Set default output format based on what image types are available - if (function_exists('ImageTypes')) { - $imagetypes = ImageTypes(); - if ($imagetypes & IMG_WBMP) { - $this->thumbnailFormat = 'wbmp'; - $AvailableImageOutputFormats[] = 'wbmp'; - } - if ($imagetypes & IMG_GIF) { - $this->thumbnailFormat = 'gif'; - $AvailableImageOutputFormats[] = 'gif'; - } - if ($imagetypes & IMG_PNG) { - $this->thumbnailFormat = 'png'; - $AvailableImageOutputFormats[] = 'png'; - } - if ($imagetypes & IMG_JPG) { - $this->thumbnailFormat = 'jpeg'; - $AvailableImageOutputFormats[] = 'jpeg'; - } - } else { - //return $this->ErrorImage('ImageTypes() does not exist - GD support might not be enabled?'); - $this->DebugMessage('ImageTypes() does not exist - GD support might not be enabled?', __FILE__, __LINE__); - } - if ($this->ImageMagickVersion()) { - $IMformats = array('jpeg', 'png', 'gif', 'bmp', 'ico'); - $this->DebugMessage('Addding ImageMagick formats to $AvailableImageOutputFormats ('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__); - foreach ($IMformats as $key => $format) { - $AvailableImageOutputFormats[] = $format; - } - } - $AvailableImageOutputFormats = array_unique($AvailableImageOutputFormats); - $this->DebugMessage('$AvailableImageOutputFormats = array('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__); - - if (strtolower($this->config_output_format) == 'jpg') { - $this->config_output_format = 'jpeg'; - } - if (strtolower($this->f) == 'jpg') { - $this->f = 'jpeg'; - } - if (phpthumb_functions::CaseInsensitiveInArray($this->config_output_format, $AvailableImageOutputFormats)) { - // set output format to config default if that format is available - $this->DebugMessage('$this->thumbnailFormat set to $this->config_output_format "'.strtolower($this->config_output_format).'"', __FILE__, __LINE__); - $this->thumbnailFormat = strtolower($this->config_output_format); - } elseif ($this->config_output_format) { - $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->config_output_format ('.strtolower($this->config_output_format).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__); - } - if ($this->f && (phpthumb_functions::CaseInsensitiveInArray($this->f, $AvailableImageOutputFormats))) { - // override output format if $this->f is set and that format is available - $this->DebugMessage('$this->thumbnailFormat set to $this->f "'.strtolower($this->f).'"', __FILE__, __LINE__); - $this->thumbnailFormat = strtolower($this->f); - } elseif ($this->f) { - $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->f ('.strtolower($this->f).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__); - } - - // for JPEG images, quality 1 (worst) to 99 (best) - // quality < 25 is nasty, with not much size savings - not recommended - // problems with 100 - invalid JPEG? - $this->thumbnailQuality = max(1, min(99, ($this->q ? $this->q : 75))); - $this->DebugMessage('$this->thumbnailQuality set to "'.$this->thumbnailQuality.'"', __FILE__, __LINE__); - - return true; - } - - function setCacheDirectory() { - // resolve cache directory to absolute pathname - $this->DebugMessage('setCacheDirectory() starting with config_cache_directory = "'.$this->config_cache_directory.'"', __FILE__, __LINE__); - if (substr($this->config_cache_directory, 0, 1) == '.') { - if (eregi('^(f|ht)tps?\://', $this->src)) { - if (!$this->config_cache_disable_warning) { - $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') cannot be used for remote images. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); - } - } elseif ($this->src) { - // resolve relative cache directory to source image - $this->config_cache_directory = dirname($this->ResolveFilenameToAbsolute($this->src)).DIRECTORY_SEPARATOR.$this->config_cache_directory; - } else { - // $this->new is probably set - } - } - if (substr($this->config_cache_directory, -1) == '/') { - $this->config_cache_directory = substr($this->config_cache_directory, 0, -1); - } - if ($this->iswindows) { - $this->config_cache_directory = str_replace('/', DIRECTORY_SEPARATOR, $this->config_cache_directory); - } - if ($this->config_cache_directory) { - $real_cache_path = realpath($this->config_cache_directory); - if (!$real_cache_path) { - $this->DebugMessage('realpath($this->config_cache_directory) failed for "'.$this->config_cache_directory.'"', __FILE__, __LINE__); - if (!is_dir($this->config_cache_directory)) { - $this->DebugMessage('!is_dir('.$this->config_cache_directory.')', __FILE__, __LINE__); - } - } - if ($real_cache_path) { - $this->DebugMessage('setting config_cache_directory to realpath('.$this->config_cache_directory.') = "'.$real_cache_path.'"', __FILE__, __LINE__); - $this->config_cache_directory = $real_cache_path; - } - } - if (!is_dir($this->config_cache_directory)) { - if (!$this->config_cache_disable_warning) { - $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') does not exist. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); - } - $this->DebugMessage('$this->config_cache_directory ('.$this->config_cache_directory.') is not a directory', __FILE__, __LINE__); - $this->config_cache_directory = null; - } elseif (!@is_writable($this->config_cache_directory)) { - $this->DebugMessage('$this->config_cache_directory is not writable ('.$this->config_cache_directory.')', __FILE__, __LINE__); - } - return true; - } - - - function ResolveFilenameToAbsolute($filename) { - //if (eregi('^(f|ht)tps?\://', $filename)) { - if (eregi('^[a-z0-9]+\:/{1,2}', $filename)) { - // eg: http://host/path/file.jpg (HTTP URL) - // eg: ftp://host/path/file.jpg (FTP URL) - // eg: data1:/path/file.jpg (Netware path) - - //$AbsoluteFilename = $filename; - return $filename; - - } elseif ($this->iswindows && ($filename{1} == ':')) { - - // absolute pathname (Windows) - $AbsoluteFilename = $filename; - - } elseif ($this->iswindows && ((substr($filename, 0, 2) == '//') || (substr($filename, 0, 2) == '\\\\'))) { - - // absolute pathname (Windows) - $AbsoluteFilename = $filename; - - } elseif ($filename{0} == '/') { - - if (@is_readable($filename) && !@is_readable($this->config_document_root.$filename)) { - - // absolute filename (*nix) - $AbsoluteFilename = $filename; - - } elseif ($filename{1} == '~') { - - // /~user/path - if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) { - $AbsoluteFilename = $ApacheLookupURIarray['filename']; - } else { - $AbsoluteFilename = realpath($filename); - if (@is_readable($AbsoluteFilename)) { - $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath($filename)', __FILE__, __LINE__); - } else { - return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'". This has been known to fail on Apache2 - try using the absolute filename for the source image (ex: "/home/user/httpdocs/image.jpg" instead of "/~user/image.jpg")'); - } - } - - } else { - - // relative filename (any OS) - if (ereg('^'.preg_quote($this->config_document_root), $filename)) { - $AbsoluteFilename = $filename; - $this->DebugMessage('ResolveFilenameToAbsolute() NOT prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__); - } else { - $AbsoluteFilename = $this->config_document_root.$filename; - $this->DebugMessage('ResolveFilenameToAbsolute() prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__); - } - - } - - } else { - - // relative to current directory (any OS) - $AbsoluteFilename = $this->config_document_root.dirname(@$_SERVER['PHP_SELF']).DIRECTORY_SEPARATOR.$filename; - //if (!@file_exists($AbsoluteFilename) && @file_exists(realpath($this->DotPadRelativeDirectoryPath($filename)))) { - // $AbsoluteFilename = realpath($this->DotPadRelativeDirectoryPath($filename)); - //} - - if (substr(dirname(@$_SERVER['PHP_SELF']), 0, 2) == '/~') { - if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) { - $AbsoluteFilename = $ApacheLookupURIarray['filename'].DIRECTORY_SEPARATOR.$filename; - } else { - $AbsoluteFilename = realpath('.').DIRECTORY_SEPARATOR.$filename; - if (@is_readable($AbsoluteFilename)) { - $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath(.)/$filename', __FILE__, __LINE__); - } else { - return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'". This has been known to fail on Apache2 - try using the absolute filename for the source image'); - } - } - } - - } - if (is_link($AbsoluteFilename)) { - $this->DebugMessage('is_link()==true, changing "'.$AbsoluteFilename.'" to "'.readlink($AbsoluteFilename).'"', __FILE__, __LINE__); - $AbsoluteFilename = readlink($AbsoluteFilename); - } - if (realpath($AbsoluteFilename)) { - $AbsoluteFilename = realpath($AbsoluteFilename); - } - if ($this->iswindows) { - $AbsoluteFilename = eregi_replace('^'.preg_quote(realpath($this->config_document_root)), realpath($this->config_document_root), $AbsoluteFilename); - $AbsoluteFilename = str_replace(DIRECTORY_SEPARATOR, '/', $AbsoluteFilename); - } - if (!$this->config_allow_src_above_docroot && !ereg('^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath($this->config_document_root))), $AbsoluteFilename)) { - $this->DebugMessage('!$this->config_allow_src_above_docroot therefore setting "'.$AbsoluteFilename.'" (outside "'.realpath($this->config_document_root).'") to null', __FILE__, __LINE__); - return false; - } - if (!$this->config_allow_src_above_phpthumb && !ereg('^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__))), $AbsoluteFilename)) { - $this->DebugMessage('!$this->config_allow_src_above_phpthumb therefore setting "'.$AbsoluteFilename.'" (outside "'.dirname(__FILE__).'") to null', __FILE__, __LINE__); - return false; - } - return $AbsoluteFilename; - } - - function ImageMagickWhichConvert() { - static $WhichConvert = null; - if (is_null($WhichConvert)) { - if ($this->iswindows) { - $WhichConvert = false; - } else { - $WhichConvert = trim(phpthumb_functions::SafeExec('which convert')); - } - } - return $WhichConvert; - } - - function ImageMagickCommandlineBase() { - static $commandline = null; - if (is_null($commandline)) { - $commandline = (!is_null($this->config_imagemagick_path) ? $this->config_imagemagick_path : ''); - - if ($this->config_imagemagick_path && ($this->config_imagemagick_path != realpath($this->config_imagemagick_path))) { - if (@is_executable(realpath($this->config_imagemagick_path))) { - $this->DebugMessage('Changing $this->config_imagemagick_path ('.$this->config_imagemagick_path.') to realpath($this->config_imagemagick_path) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__); - $this->config_imagemagick_path = realpath($this->config_imagemagick_path); - } else { - $this->DebugMessage('Leaving $this->config_imagemagick_path as ('.$this->config_imagemagick_path.') because !is_execuatable(realpath($this->config_imagemagick_path)) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__); - } - } - $this->DebugMessage(' file_exists('.$this->config_imagemagick_path.') = '.intval( @file_exists($this->config_imagemagick_path)), __FILE__, __LINE__); - $this->DebugMessage('is_executable('.$this->config_imagemagick_path.') = '.intval(@is_executable($this->config_imagemagick_path)), __FILE__, __LINE__); - if (@file_exists($this->config_imagemagick_path)) { - $this->DebugMessage('using ImageMagick path from $this->config_imagemagick_path ('.$this->config_imagemagick_path.')', __FILE__, __LINE__); - if ($this->iswindows) { - $commandline = substr($this->config_imagemagick_path, 0, 2).' && cd "'.str_replace('/', DIRECTORY_SEPARATOR, substr(dirname($this->config_imagemagick_path), 2)).'" && '.basename($this->config_imagemagick_path); - } else { - $commandline = '"'.$this->config_imagemagick_path.'"'; - } - return $commandline; - } - - $which_convert = $this->ImageMagickWhichConvert(); - $IMversion = $this->ImageMagickVersion(); - - if ($which_convert && ($which_convert{0} == '/') && @file_exists($which_convert)) { - - // `which convert` *should* return the path if "convert" exist, or nothing if it doesn't - // other things *may* get returned, like "sh: convert: not found" or "no convert in /usr/local/bin /usr/sbin /usr/bin /usr/ccs/bin" - // so only do this if the value returned exists as a file - $this->DebugMessage('using ImageMagick path from `which convert` ('.$which_convert.')', __FILE__, __LINE__); - $commandline = 'convert'; - - } elseif ($IMversion) { - - $this->DebugMessage('setting ImageMagick path to $this->config_imagemagick_path ('.$this->config_imagemagick_path.') ['.$IMversion.']', __FILE__, __LINE__); - $commandline = $this->config_imagemagick_path; - - } else { - - $this->DebugMessage('ImageMagickThumbnailToGD() aborting because cannot find convert in $this->config_imagemagick_path ('.$this->config_imagemagick_path.'), and `which convert` returned ('.$which_convert.')', __FILE__, __LINE__); - $commandline = ''; - - } - } - return $commandline; - } - - function ImageMagickVersion($returnRAW=false) { - static $versionstring = null; - if (is_null($versionstring)) { - $commandline = $this->ImageMagickCommandlineBase(); - $commandline = (!is_null($commandline) ? $commandline : ''); - - $versionstring = array(0=>'', 1=>''); - if ($commandline) { - $commandline .= ' -version'; - $this->DebugMessage('ImageMagick version checked with "'.$commandline.'"', __FILE__, __LINE__); - $versionstring[1] = trim(phpthumb_functions::SafeExec($commandline)); - if (eregi('^Version: (.*) (http|file)\:', $versionstring[1], $matches)) { - $versionstring[0] = $matches[1]; - } else { - $versionstring[0] = false; - $this->DebugMessage('ImageMagick did not return recognized version string ('.$versionstring[1].')', __FILE__, __LINE__); - } - } - } - return @$versionstring[intval($returnRAW)]; - } - - function ImageMagickSwitchAvailable($switchname) { - static $IMoptions = null; - if (is_null($IMoptions)) { - $IMoptions = array(); - $commandline = $this->ImageMagickCommandlineBase(); - if (!is_null($commandline)) { - $commandline .= ' -help'; - $IMhelp_lines = explode("\n", phpthumb_functions::SafeExec($commandline)); - foreach ($IMhelp_lines as $line) { - if (ereg('^[\+\-]([a-z\-]+) ', trim($line), $matches)) { - $IMoptions[$matches[1]] = true; - } - } - } - } - if (is_array($switchname)) { - $allOK = true; - foreach ($switchname as $key => $value) { - if (!isset($IMoptions[$value])) { - $allOK = false; - break; - } - } - $this->DebugMessage('ImageMagickSwitchAvailable('.implode(';', $switchname).') = '.intval($allOK).'', __FILE__, __LINE__); - } else { - $allOK = isset($IMoptions[$switchname]); - $this->DebugMessage('ImageMagickSwitchAvailable('.$switchname.') = '.intval($allOK).'', __FILE__, __LINE__); - } - return $allOK; - } - - function ImageMagickThumbnailToGD() { - // http://www.imagemagick.org/script/command-line-options.php - - $this->useRawIMoutput = true; - if (phpthumb_functions::gd_version()) { - //$UnAllowedParameters = array('sx', 'sy', 'sw', 'sh', 'xto', 'ra', 'ar', 'bg', 'bc', 'fltr'); - $UnAllowedParameters = array('xto', 'ra', 'ar', 'bg', 'bc', 'fltr'); - foreach ($UnAllowedParameters as $dummy => $parameter) { - if ($this->$parameter) { - $this->DebugMessage('$this->useRawIMoutput=false because "'.$parameter.'" is set', __FILE__, __LINE__); - $this->useRawIMoutput = false; - break; - } - } - } - $outputFormat = $this->thumbnailFormat; - if (phpthumb_functions::gd_version()) { - if ($this->useRawIMoutput) { - switch ($this->thumbnailFormat) { - case 'gif': - $ImageCreateFunction = 'ImageCreateFromGIF'; - $this->is_alpha = true; - break; - case 'png': - $ImageCreateFunction = 'ImageCreateFromPNG'; - $this->is_alpha = true; - break; - case 'jpg': - case 'jpeg': - $ImageCreateFunction = 'ImageCreateFromJPEG'; - break; - default: - $outputFormat = 'png'; - $ImageCreateFunction = 'ImageCreateFromPNG'; - $this->is_alpha = true; - $this->useRawIMoutput = false; - break; - } - if (!function_exists(@$ImageCreateFunction)) { - // ImageMagickThumbnailToGD() depends on ImageCreateFromPNG/ImageCreateFromGIF - //$this->DebugMessage('ImageMagickThumbnailToGD() aborting because '.@$ImageCreateFunction.'() is not available', __FILE__, __LINE__); - $this->useRawIMoutput = true; - //return false; - } - } else { - $outputFormat = 'png'; - $ImageCreateFunction = 'ImageCreateFromPNG'; - $this->is_alpha = true; - $this->useRawIMoutput = false; - } - } - - // http://freealter.org/doc_distrib/ImageMagick-5.1.1/www/convert.html - if (!$this->sourceFilename) { - $this->DebugMessage('ImageMagickThumbnailToGD() aborting because $this->sourceFilename is empty', __FILE__, __LINE__); - $this->useRawIMoutput = false; - return false; - } - if (ini_get('safe_mode')) { - $this->DebugMessage('ImageMagickThumbnailToGD() aborting because safe_mode is enabled', __FILE__, __LINE__); - $this->useRawIMoutput = false; - return false; - } - - $commandline = $this->ImageMagickCommandlineBase(); - if ($commandline) { - if ($IMtempfilename = $this->phpThumb_tempnam()) { - - if (!eregi('('.implode('|', $this->AlphaCapableFormats).')', $outputFormat)) { - // not a transparency-capable format - $commandline .= ' -background "#'.($this->bg ? $this->bg : 'FFFFFF').'"'; - $commandline .= ' -flatten'; - } - $IMtempfilename = realpath($IMtempfilename); - if ($getimagesize = @GetImageSize($this->sourceFilename)) { - $this->DebugMessage('GetImageSize('.$this->sourceFilename.') returned [w='.$getimagesize[0].';h='.$getimagesize[1].';f='.$getimagesize[2].']', __FILE__, __LINE__); - $this->source_width = $getimagesize[0]; - $this->source_height = $getimagesize[1]; - $this->DebugMessage('source dimensions set to '.$this->source_width.'x'.$this->source_height, __FILE__, __LINE__); - $this->SetOrientationDependantWidthHeight(); - - $commandline .= ' -coalesce'; // may be needed for animated GIFs - if ($this->source_width || $this->source_height) { - if ($this->zc) { - - $borderThickness = 0; - if (!empty($this->fltr)) { - foreach ($this->fltr as $key => $value) { - if (ereg('^bord\|([0-9]+)', $value, $matches)) { - $borderThickness = $matches[1]; - break; - } - } - } - $wAll = intval(max($this->w, $this->wp, $this->wl, $this->ws)) - (2 * $borderThickness); - $hAll = intval(max($this->h, $this->hp, $this->hl, $this->hs)) - (2 * $borderThickness); - $imAR = $this->source_width / $this->source_height; - //$zcAR = (($wAll && $hAll) ? $wAll / $hAll : $imAR); - $zcAR = (($wAll && $hAll) ? $wAll / $hAll : 1); -//echo '
    \n"; - $o .= ewiki_format($hl.$src.$end); - - } - - } - - #-- otherwise print all paragraph headlines in ordered lists - else { - - $o .= "\n

    $id overview

    \n"; - - $ol_level = 0; - $first = 0; - $last = ""; - - $o .= "
      \n"; - - while (!feof($r)) { - - $line = fgets($r, 4096); - - if (strstr($line, $SECTIONSEP)) { - while($ol_level) { - $o .= "
    \n"; - $ol_level--; - } - $first=1; - } - - if (strstr($line, $UNDERLINE) && ($lastline!=="$id")) { - - $new_ol_level = 1 - $first + (strpos($line, $UNDERLINE)>2 ?1:0); - while($ol_level > $new_ol_level) { - $o .= "\n"; - $ol_level--; - } - while($ol_level < $new_ol_level) { - $o .= "
      \n"; - $ol_level++; - } - $first = 0; - - $o .= '
    1. $lastline)) . '">' . $lastline . - '
    2. ' . "\n"; - - $section=1; - } - - $lastline = trim($line); - } - - while($ol_level--) { - $o .= "
    \n"; - } - - $o .= "\n"; - - } - - } - - if ($n) { - $o .= ''. - 'prev << "'.trim($str_prev).'"
    '; - $o .= ''. - 'next >> "'.trim($str_next).'"
    '; - } - - $br = ewiki_script("", "BugReports"); - $us = ewiki_script("", "UserSuggestions"); - $dc = ewiki_script("", "{$id}.Discussion"); - $o .= " -
    -
    -You cannot modify the {$id} file, but anyhow any ideas or suggestion should -as usually get filed on BugReports, -UserSuggestions or even better the -{$id}.Discussion. -
    -"; - - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/aboutplugins.meta b/mods/wiki/plugins/page/aboutplugins.meta deleted file mode 100644 index ac69be5ed..000000000 --- a/mods/wiki/plugins/page/aboutplugins.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -title: AboutPlugins -description: interesting overview over loaded extension plugins (not a security risk?) -priority: extra -hooks: page -type: page diff --git a/mods/wiki/plugins/page/aboutplugins.php b/mods/wiki/plugins/page/aboutplugins.php deleted file mode 100644 index 49d8bc49f..000000000 --- a/mods/wiki/plugins/page/aboutplugins.php +++ /dev/null @@ -1,87 +0,0 @@ -$pclass plugins
    \n"; - - switch ($pclass) { - case "page": - $o .= "dynamically generated pages
    \n"; - break; - case "action": - $o .= "can be activated on each (real) page
    \n"; - break; - case "mpi": - $o .= "the markup plugins can be utilized to integrate dynamic content into pages (loaded on demand, so rarely shown here)
    \n"; - break; - default: - } - - if ($pf_a = $ewiki_plugins[$pclass]) { - ksort($pf_a); - if ($pclass=="action") { - $pf_a = array_merge($pf_a, $ewiki_plugins["action_always"]); - } - foreach ($pf_a as $i=>$pf) { - - switch ($pclass) { - case "page": - $i = ''.$i.''; - break; - case "action": - $i = ''.$i.''; - break; - case "mpi": - $i = '<?plugin '.$i.'?>'; - break; - default: - } - - $o .= "· $i via $pf
    \n"; - - } - } - - $o .= "
    \n"; - - } - - #-- task plugins - $o .= "task plugins (core stuff)
    \n"; - $o .= "enhance the wiki engine internally, with widely varying functionality enhancements or changes
    \n"; - foreach ($ewiki_plugins as $i=>$a) { - if (is_array($a)) { - foreach ($a as $n=>$pf) { - - if (is_int($n)) { - - $o .= "· $i via $pf
    \n"; - - } - } - } - } - $o .= "
    \n"; - - - return($o); - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/addnewpage.meta b/mods/wiki/plugins/page/addnewpage.meta deleted file mode 100644 index 1d67b4c56..000000000 --- a/mods/wiki/plugins/page/addnewpage.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -title: AddNewPage -description: newbies/office users like that -priority: bonus -hooks: page -type: page diff --git a/mods/wiki/plugins/page/addnewpage.php b/mods/wiki/plugins/page/addnewpage.php deleted file mode 100644 index 941197116..000000000 --- a/mods/wiki/plugins/page/addnewpage.php +++ /dev/null @@ -1,84 +0,0 @@ - ' - .'_{name of the new page} ' - .'
    ' - .'' - .'

    ' - .'' - .' _{link it from} ' - .'' - .'' - ); - - } - else { - $new_id = trim($_REQUEST["new_id"]); - - #-- add a link to new page - if ($_REQUEST["add_link_from"] && ($from = $_REQUEST["link_from"])) { - $row = ewiki_db::GET($from); - if ($row && $row["version"]) { - if (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) { - $row["version"]++; - $row["content"] .= "\n* [$new_id]"; - ewiki_scan_wikiwords($row["content"], $row["refs"], "_STRIP_EMAIL=1"); - $row["refs"] = "\n\n".implode("\n", array_keys($row["refs"]))."\n\n"; - } - else { - $row = false; - } - } - else { - $row = array( - "id" => $from, - "version" => 1, - "flags" => EWIKI_DB_F_TEXT, - "created" => time(), - "lastmodified" => time(), - "hits" => 0, - "meta"=>"", - "content" => "\n* [$new_id]", - "refs" => "\n\n$new_id\n\n", - ); - } - if ($row) { - ewiki_db::WRITE($row); - } - } - - #-- call edit
    - $o = ewiki_page($new_id); - } - - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/createnewpage.meta b/mods/wiki/plugins/page/createnewpage.meta deleted file mode 100644 index 66d364aad..000000000 --- a/mods/wiki/plugins/page/createnewpage.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -title: CreateNewPage -description: newbies/office users like that -priority: bonus -hooks: page -type: page diff --git a/mods/wiki/plugins/page/createnewpage.php b/mods/wiki/plugins/page/createnewpage.php deleted file mode 100644 index a9a8888d9..000000000 --- a/mods/wiki/plugins/page/createnewpage.php +++ /dev/null @@ -1,31 +0,0 @@ - ' - .'_{name of the new page} ' - .'
    ' - .'' - .'
    ' - ); - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/ewikilog.meta b/mods/wiki/plugins/page/ewikilog.meta deleted file mode 100644 index e0c4d9389..000000000 --- a/mods/wiki/plugins/page/ewikilog.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -priority: rare -hooks: page -type: page -title: ewikilog -description: Prints out /tmp/ewiki.log for debugging diff --git a/mods/wiki/plugins/page/ewikilog.php b/mods/wiki/plugins/page/ewikilog.php deleted file mode 100644 index c9f09ad6a..000000000 --- a/mods/wiki/plugins/page/ewikilog.php +++ /dev/null @@ -1,28 +0,0 @@ - -* @author andy fundinger (Minor contributions and maintenance) -*/ - -$ewiki_plugins["page"]["EWikiLog"] = "ewiki_page_ewikilog"; - -function ewiki_page_ewikilog($id, $data, $action) -{ - ob_start(); - echo ewiki_make_title($id, $id, 2); - echo '
    ';
    -    readfile(EWIKI_LOGFILE);
    -    echo '
    '; - $o = ob_get_contents(); - ob_end_clean(); - - return($o); -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/extractall.meta b/mods/wiki/plugins/page/extractall.meta deleted file mode 100644 index 9f501ab05..000000000 --- a/mods/wiki/plugins/page/extractall.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: page -hooks: page -type: page -config: - EWIKI_PAGE_EXALL="ExAllTodo" -title: ExtractAll -description: extracts todo items from every page in the wiki database -priority: bonus diff --git a/mods/wiki/plugins/page/extractall.php b/mods/wiki/plugins/page/extractall.php deleted file mode 100644 index 0b9361558..000000000 --- a/mods/wiki/plugins/page/extractall.php +++ /dev/null @@ -1,142 +0,0 @@ -

    Enter initials: -
    (Hint: For multiple users connect initials using "and" or "or")

    '; -$ewiki_t["en"]["EXALLERROR"] = "

    Error

    • Unable to complete query. Please do not combine the 'and' and 'or' operators.

    "; - -define("EWIKI_PAGE_EXALL", "ExAllTodo"); - -$ewiki_plugins["page"][EWIKI_PAGE_EXALL]="ewiki_page_exall"; - -function ewiki_page_exall($id=0, $data=0, $action=0){ - global $ewiki_plugins, $ewiki_config; - - //$timestart=getmicrotime(); - $action=str_replace("all", "", strtolower($id)); - $invalid=false; - - $initials=ewiki_get_uservar("Initials"); - $exinitials=ewiki_get_uservar("ExtractorInitials"); - - if(isset($_GET['q']) && $_GET['q']!=""){ - if($_GET['q']!='ALL'){ - $str_usr=str_replace(array("or", " ", "and"), array("|", "", "|"), $_GET['q']); - //$str_usr=$_GET['q']; //initials were entered - if(!(stristr($_GET['q'], "or")&& stristr($_GET['q'], "and"))){ - if(stristr($_GET['q'], "and")){ - $operator="and"; - } - $extractFor=$_GET['q']; - }else { - $invalid=true; - } - } - }elseif(strlen($initials)){ - $str_usr=$initials; - $extractFor=$str_usr; - }elseif(strlen($exinitials)){ - $str_usr=$exinitials; - $extractFor=$str_usr; - }else { - $str_usr="."; //no initials were entered - $o = ewiki_make_title($id, ewiki_t(strtoupper($action)."TITLE"), 2); - } - - if(isset($extractFor)){ - $o = ewiki_make_title($id, ewiki_t(strtoupper($action)."FOR").$extractFor, 2); - if(($extractFor != $exinitials)&&($extractFor != $initials)&&(strlen($extractFor)==2)){ - ewiki_set_uservar("ExtractorInitials",$extractFor); - } - } else { - $o = ewiki_make_title($id, ewiki_t(strtoupper($action)."TITLE"), 2); - } - - $o .= ewiki_t("EXALLCONTROLS", array("controlid"=>$id)); //prints text, textbox, and button - - $o.='

    '; - if(strlen($initials)){ - $o.= '$initials)) . '">' . ewiki_t(strtoupper($action)."FOR").$initials . " "; - } - if(strlen($exinitials)&&($exinitials!=$initials)){ - $o.= '$exinitials) ). '">' . ewiki_t(strtoupper($action)."FOR").$exinitials . " "; - } - $o.=''ALL')) . '">' . ewiki_t(strtoupper($action)."FORALL"). " ".'

    '; - - if($invalid){ - return($o.ewiki_t("EXALLERROR")); - } - //define types of todo/policy items - $ext_types = $ewiki_config["extracttypes"][$action]; - - //get data from database - $data = ewiki_db::GETALL(array("content", "pagename", "flags")); - - while ($content = $data->get()) { - $str_null=NULL; - - if (($content["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) { - //code hijacked from action_extracttodo and modified - preg_match_all("/^([;:#\*\- ]*)((@@(".implode("|",$ext_types).")) ((".$str_usr.")+.*)(:.*))$/im", $content["content"], $matches); - - if(!empty($matches[0])){ - $extractedContent=NULL; - for($index=0;$index"; - } - } - } - } - - $o.=$ewiki_plugins["render"][0](ewiki_t(strtoupper($action)."POSTSCRIPT")); - /*$timeend=getmicrotime(); - $o.="time: ".($timeend-$timestart);*/ - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/fortune.meta b/mods/wiki/plugins/page/fortune.meta deleted file mode 100644 index 8b74be446..000000000 --- a/mods/wiki/plugins/page/fortune.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -title: Fortune -description: nonsense -priority: rare -hooks: page -type: page diff --git a/mods/wiki/plugins/page/fortune.php b/mods/wiki/plugins/page/fortune.php deleted file mode 100644 index 2f9c84ad4..000000000 --- a/mods/wiki/plugins/page/fortune.php +++ /dev/null @@ -1,23 +0,0 @@ -$id\n"; - - $o .= "
    " . shell_exec("$ENV /usr/games/fortune") . "
    \n"; - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/hitcounter.meta b/mods/wiki/plugins/page/hitcounter.meta deleted file mode 100644 index aabb9ec0f..000000000 --- a/mods/wiki/plugins/page/hitcounter.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -title: HitCounter -description: displays sum of hits to all pages -hooks: page -type: page -priority: bonus diff --git a/mods/wiki/plugins/page/hitcounter.php b/mods/wiki/plugins/page/hitcounter.php deleted file mode 100644 index 8c4214ab7..000000000 --- a/mods/wiki/plugins/page/hitcounter.php +++ /dev/null @@ -1,40 +0,0 @@ -get()) { - if ($r["flags"] & EWIKI_DB_F_TEXT) { - $n += $r["hits"]; - } - } - - #-- output - $title = ewiki_make_title($id, $id, 2); - $AllPages = 'AllPages'; - $o = <<< ___ -$title -The overall hit score of $AllPages is: -
    - $n -
    -___ - ; - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/imagegallery.meta b/mods/wiki/plugins/page/imagegallery.meta deleted file mode 100644 index 88287450e..000000000 --- a/mods/wiki/plugins/page/imagegallery.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: page -title: ImageGallery -description: shows all uploaded pictures -priority: bonus -hooks: page -type: page -config: - EWIKI_GALLERY_WIDTH=3 - EWIKI_PAGE_IMAGEGALLERY="ImageGallery" diff --git a/mods/wiki/plugins/page/imagegallery.php b/mods/wiki/plugins/page/imagegallery.php deleted file mode 100644 index b51a9adc8..000000000 --- a/mods/wiki/plugins/page/imagegallery.php +++ /dev/null @@ -1,145 +0,0 @@ - - - contributor, added image mime-type filtering - jeffrey engleman - - removed database call in loop significantly increasing performance -*/ - - $ewiki_config["action_links"]["gallery"]["info"] = 'More Info'; - -define("EWIKI_GALLERY_WIDTH", 3); -define("EWIKI_PAGE_IMAGEGALLERY", "ImageGallery"); -$ewiki_plugins["page"][EWIKI_PAGE_IMAGEGALLERY] = "ewiki_page_image_gallery"; - -//The main gallery includes only uploaded images and cached images *not* images -// that have been uploaded as attachments to a page or into a section. -// Only pages with no section attribute are included. -$ewiki_plugins["page"]['MainGallery'] = "ewiki_page_image_gallery"; -$ewiki_config['image-galleries']['MainGallery']['section']=''; - -function ewiki_page_image_gallery($id, $data=0, $action) { - global $ewiki_config; - - $o = ewiki_make_title($id, $id, 2); - - $mwidth = 120; - $mscale = 0.7; - - #-- fetch and asort images - $sorted = array(); - $pages = array(); - $result = ewiki_db::GETALL(array("flags", "created", "meta", "refs")); - while ($row = $result->get()) { - if ((($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_BINARY) - && (strpos($row['meta']['Content-Type'], 'image/') === 0)) { - if(isset($ewiki_config['image-galleries'][$id])){ - foreach($ewiki_config['image-galleries'][$id]as $field=>$value){ - if($row['meta'][$field]!=$value){ - continue (2); - - } - } - } - if (!EWIKI_PROTECTED_MODE || (EWIKI_PROTECTED_MODE_HIDING <= .5)|| ewiki_auth($row["id"], $uu, "binary-get")) { - $sorted[$row["id"]] = $row["created"]; - $pages[$row["id"]] = $row; - } - } elseif (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT){ - $page_refs[$row["id"]]=$row["refs"]; - } - } - - arsort($sorted); - - #-- start table - $o .= '' . "\n"; - $n = 0; - $num_per_row = EWIKI_GALLERY_WIDTH; - foreach ($sorted as $image => $uu) { - - $row = $pages[$image]; - $meta = $row["meta"]; - - #-- height, width - $x = $x0 = $meta["width"]; - $y = $y0 = $meta["height"]; - if (! ($x && $y)) { - $x = $mwidth; - $y = (int) ($mwidth * $mscale); - } - $r = 1; - if ($y > $mwidth * $mscale) { - $r = $mwidth * $mscale / $y; - } - if ($r > $mwidth / $x) { - $r = $mwidth / $x; - } - $x = (int) ($x * $r); - $y = (int) ($y * $r); - - #-- get image references - $ref=array(); - foreach($page_refs as $pageid => $pageref) { - if(strstr($pageref, $image)){ - if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($pageid, $str_null, "view")) { - continue; - } - $ref[] = '' . $pageid . ''; - } - if (count($ref) >= 5) { - break; - } - } - - $ref = implode(", ", $ref); - - #-- table lines - (($n % $num_per_row) == 0) && ($o .= "\n"); - - #-- print a/img tag - $o .= '\n"; - - #-- table lines - $n++; - (($n % $num_per_row) == 0) && ($o .= "\n"); - - } - - #-- empty table cells - if ($n % $num_per_row) { - while (($n % $num_per_row) && ($n++)) { - $o .= "\n"; - } - $o .= "\n"; - } - $o .= "
    ' - . '' - . '' . $image . '' - . str_replace('/','/ ', urldecode($meta["Content-Location"])) - . '
    ' - . ($x0 && $y0 ? "{$x0}x{$y0}
    " : "") - . $ref - #-- gallery-actions - . '\n" - . "
     
    \n"; - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/interwikimap.meta b/mods/wiki/plugins/page/interwikimap.meta deleted file mode 100644 index c0052a44f..000000000 --- a/mods/wiki/plugins/page/interwikimap.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -title: InterWikiMap -description: shows list of all known InterMap: prefixes -priority: extra -hooks: page -type: page diff --git a/mods/wiki/plugins/page/interwikimap.php b/mods/wiki/plugins/page/interwikimap.php deleted file mode 100644 index 3b4af8e13..000000000 --- a/mods/wiki/plugins/page/interwikimap.php +++ /dev/null @@ -1,26 +0,0 @@ -) - - -$ewiki_plugins["page"]["InterWikiMap"] = "ewiki_page_interwikimap"; - - -function ewiki_page_interwikimap($id, $data, $action) { - - global $ewiki_config; - - $o = ewiki_make_title($id, $id, 1); - - $o .= '
    '."\n"; - foreach ($ewiki_config["interwiki"] as $shortcut=>$url) { - $o .= "
    $shortcut:
    \n". - "
    $url
    \n"; - } - $o .= "
    "; - - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/minidump.meta b/mods/wiki/plugins/page/minidump.meta deleted file mode 100644 index 586dc0df9..000000000 --- a/mods/wiki/plugins/page/minidump.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -category: page -hooks: page -type: page -title: MiniDump -description: instantly makes a source tarball from all text pages -depends: tarball -priority: bonus diff --git a/mods/wiki/plugins/page/minidump.php b/mods/wiki/plugins/page/minidump.php deleted file mode 100644 index 97c791557..000000000 --- a/mods/wiki/plugins/page/minidump.php +++ /dev/null @@ -1,183 +0,0 @@ -open(0); - - #-- convert all pages - while ($row=$result->get(0, 0x1037)) { - - $id = $row["id"]; - $row = ewiki_db::GET($id); - $content = &$row["content"]; - $fn = ($id); - - if (!$row || !$row["id"] || !$row["content"]) { - continue; - } - - #-- for tarball - $perms = array( - "mtime" => $row["lastmodified"], - "uname" => "ewiki", - "mode" => 0664 | (($row["flags"]&EWIKI_DB_F_WRITEABLE)?0002:0000), - ); - - #-- add file - $tarball->add( - $fn, - $content, - $perms - ); - } - - #-- end output - $tarball->close(); - } - - #-- fin - die(); -} - - - - -############################################################################ - - - -if (!class_exists("ewiki_virtual_tarball")) { - -#-- allows to generate a tarball from virtual files -# (supports no directories or symlinks and other stuff) -class ewiki_virtual_tarball { - - var $f = 0; - - function open($fn="/dev/stdout") { - - #-- init; - $this->f = 0; - - #-- file output? - if ($fn && ($fn != "-")) { - $this->f = gzopen("$fn", "wb9"); - } - else { - $_ENV["HTTP_ACCEPT_ENCODING"] = "gzip, deflate"; - $_SERVER["HTTP_ACCEPT_ENCODING"] = "gzip, deflate"; - ob_start("ob_gzhandler"); - } - } - - - function close() { - - #-- fill up file - $this->write(str_repeat("\000", 9*1024)); - - #-- close file handle - if ($this->f) { - gzclose($this->f); - } - } - - - function write($str) { - if ($this->f) { - gzwrite($this->f, $str); - fflush($this->f); - } - else { - echo $str; - ob_flush(); - } - } - - - function oct($int, $len) { - $o = "\000"; - while (--$len) { - $o = ($int & 0x07) . $o; - $int = $int >> 3; - } - return($o); - } - - - #-- add virtual file - function add($filename, $content, $args=array()) { - - $args = array_merge($args, array( - "mode" => 000664, - "mtime" => time(), - "ctime" => time(), - "uid" => 65534, #-- common for user "nobody" - "gid" => 65534, - "uname" => "nobody", - "gname" => "nobody", - "type" => "0", - )); - $args["mode"] |= 0100000; - $args["size"] = strlen($content); - $checksum = " "; - $magic = "ustar \000"; - $filename = substr($filename, 0, 99); - - #-- header record - $header = str_pad($filename, 100, "\000") # 0x0000 - . $this->oct($args["mode"], 8) # 0x0064 - . $this->oct($args["uid"], 8) # 0x006C - . $this->oct($args["gid"], 8) # 0x0074 - . $this->oct($args["size"], 12) # 0x007C - . $this->oct($args["mtime"], 12) # 0x0088 - . ($checksum) # 0x0094 - . ($args["type"]) # 0x009C - . str_repeat("\000", 100) # 0x009D - . ($magic) # 0x0101 - . str_pad($args["uname"], 32, "\000") # 0x0109 - . str_pad($args["gname"], 32, "\000") # 0x0129 - ; # 0x0149 - $header = str_pad($header, 512, "\000"); - - #-- calculate and add header checksum - $cksum = 0; - for ($n=0; $n<512; $n++) { - $cksum += ord($header[$n]); - } - $header = substr($header, 0, 0x0094) - . $this->oct($cksum, 7) . " " - . substr($header, 0x009C); - - #-- output - if ($fill = (512 - (strlen($content) % 512))) { - $content .= str_repeat("\000", $fill); - } - $this->write($header . $content); - } - - -} - -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/orphanedpages.meta b/mods/wiki/plugins/page/orphanedpages.meta deleted file mode 100644 index b42eb93cc..000000000 --- a/mods/wiki/plugins/page/orphanedpages.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: page -title: OrphanedPages -description: lists unlinked pages -hooks: page -type: page -config: - EWIKI_PAGE_ORPHANEDPAGES="OrphanedPages" -priority: extra diff --git a/mods/wiki/plugins/page/orphanedpages.php b/mods/wiki/plugins/page/orphanedpages.php deleted file mode 100644 index 6d6f3708a..000000000 --- a/mods/wiki/plugins/page/orphanedpages.php +++ /dev/null @@ -1,65 +0,0 @@ -get()) { - - $p = $row["id"]; - - #-- remove self-reference - $row["refs"] = str_replace("\n$p\n", "\n", $row["refs"]); - - #-- add to list of referenced pages - $rf = explode("\n", trim($row["refs"])); - $refs = array_merge($refs, $rf); - if ($n++ > 299) { - $refs = array_unique($refs); - $n=0; - } // (clean-up only every 300th loop) - - #-- add page name - if (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) { - $pages[] = $row["id"]; - } - } - $refs = array_unique($refs); - - #-- check pages to be referenced from somewhere - foreach ($pages as $p) { - if (!ewiki_in_array($p, $refs)) { - if (!EWIKI_PROTECTED_MODE || !EWIKI_PROTECTED_MODE_HIDING || ewiki_auth($p, $uu, "view")) { - $orphaned[] = $p; - } - } - } - - #-- output - $o .= ewiki_list_pages($orphaned, 0); - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/pageindex.meta b/mods/wiki/plugins/page/pageindex.meta deleted file mode 100644 index f232dec46..000000000 --- a/mods/wiki/plugins/page/pageindex.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -type: virtual -category: page -title: PageIndex -description: lists all pages -priority: deprecated diff --git a/mods/wiki/plugins/page/pageindex.php b/mods/wiki/plugins/page/pageindex.php deleted file mode 100644 index daae93b5a..000000000 --- a/mods/wiki/plugins/page/pageindex.php +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/page/phpinfo.meta b/mods/wiki/plugins/page/phpinfo.meta deleted file mode 100644 index f9b55491f..000000000 --- a/mods/wiki/plugins/page/phpinfo.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -title: PhpInfo -description: security risk -priority: deprecated -hooks: page -type: page diff --git a/mods/wiki/plugins/page/phpinfo.php b/mods/wiki/plugins/page/phpinfo.php deleted file mode 100644 index cbc7339d3..000000000 --- a/mods/wiki/plugins/page/phpinfo.php +++ /dev/null @@ -1,21 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/page/powersearch.meta b/mods/wiki/plugins/page/powersearch.meta deleted file mode 100644 index 4eaf19fa3..000000000 --- a/mods/wiki/plugins/page/powersearch.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: page -title: PowerSearch -description: a more featureful page search function -priority: standard -hooks: page, action -type: page -config: - EWIKI_PAGE_POWERSEARCH="PowerSearch" diff --git a/mods/wiki/plugins/page/powersearch.php b/mods/wiki/plugins/page/powersearch.php deleted file mode 100644 index 7656762f8..000000000 --- a/mods/wiki/plugins/page/powersearch.php +++ /dev/null @@ -1,144 +0,0 @@ - -
    - - - in -

    - -
    - '; - - return($o); - } - else { - $o .= ewiki_powersearch($q, $where); - return ($o); - } - - return(''); -} - - -function ewiki_powersearch($q, $where='content'){ - $q = ewiki_lowercase(preg_replace('/\s*[\000-\040]+\s*/', ' ', $q)); - - $found = array(); - $scored = array(); - - #-- initial scan - foreach (explode(" ", $q) as $search) { - - if (empty($search)) { - continue; - } - - $result = ewiki_db::SEARCH($where, $search); - - while ($row = $result->get()) { - if (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) { - - $id = $row["id"]; - $content = strtolower($row[$where]); - unset($row); - - #-- have a closer look - $len1 = strlen($content) + 1; - - if (!isset($scored[$id])) { - $scored[$id] = 1; - } - $scored[$id] += 800 * (strlen($search) / $len1); - $scored[$id] += 65 * (count(explode($search, $content)) - 2); - $p = -1; - while (($p = strpos($content, $search, $p+1)) !== false) { - $scored[$id] += 80 * (1 - $p / $len1); - } - - }#if-TXT - } - } - - - #-- output results - arsort($scored); - - $o = "
      \n"; - $n = 0; - foreach ($scored as $id => $score) { - - #-- refetch page for top 10 entries (still cached by OS or DB) - $row = ($n < 10) ? ewiki_db::GET($id) : NULL; - - #-- check access rights in protected mode - if (EWIKI_PROTECTED_MODE && !ewiki_auth($id, $row, "view", $ring=false, $force=0)) { - if (EWIKI_PROTECTED_MODE_HIDING) { - continue; - } else { - $row["content"] = ewiki_t("FORBIDDEN"); - } - } - - $o .= "
    1. \n"; - $o .= '
      ' - . '' . $id . " " - ## . "(#$score)" - . "\n"; - - #-- top 10 results are printed more verbosely - - if ($n++ < 10) { - - preg_match_all('/([_-\w]+)/', $row["content"], $uu); - $text = htmlentities(substr(implode(" ", $uu[1]), 0, 200)); - $o .= "
      \n$text\n" - . "
      " . strftime(ewiki_t("LASTCHANGED"), $row["lastmodified"]) - . "

      \n"; - } - - $o .= "
      \n"; - - $o .= "
    2. \n"; - - } - - $o .= "
    \n"; - return($o); - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/randompage.meta b/mods/wiki/plugins/page/randompage.meta deleted file mode 100644 index 95226aec0..000000000 --- a/mods/wiki/plugins/page/randompage.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: page -title: RandomPage -priority: optional -hooks: page -type: page -config: - EWIKI_PAGE_RANDOMPAGE="RandomPage" -description: this emits a randomly selected page diff --git a/mods/wiki/plugins/page/randompage.php b/mods/wiki/plugins/page/randompage.php deleted file mode 100644 index 8d56b6576..000000000 --- a/mods/wiki/plugins/page/randompage.php +++ /dev/null @@ -1,39 +0,0 @@ -get()) { - if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $uu, "view")) { - continue; - } - if (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) { - $pages[] = $row["id"]; - } - } - - $pages = array_merge($pages, $ewiki_plugins["page"]); - - $n = rand(0, count($pages)); - $id = $pages[$n]; - - return(ewiki_page($id)); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/recentchanges.meta b/mods/wiki/plugins/page/recentchanges.meta deleted file mode 100644 index 6f9a853cf..000000000 --- a/mods/wiki/plugins/page/recentchanges.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: page -priority: recommended -hooks: rc, page -type: page -config: - EWIKI_PAGE_RECENTCHANGES="RecentChanges" -title: recentchanges -description: gives a more standard RecentChanges (besides the ewiki built-in UpdatedPages) diff --git a/mods/wiki/plugins/page/recentchanges.php b/mods/wiki/plugins/page/recentchanges.php deleted file mode 100644 index 3c94e9d6e..000000000 --- a/mods/wiki/plugins/page/recentchanges.php +++ /dev/null @@ -1,222 +0,0 @@ -get(0, 0x0137, EWIKI_DB_F_TEXT)) { - - if ($row["lastmodified"] >= $timeframe) { - - #-- id->time array - $id = $row["id"]; - $changes[$id] = $row["lastmodified"]; - - #-- collect also info for previous changes of current page - $meta[$id] = array(); - ewiki_page_rc_more($row, $meta[$id], $timeframe, $minor_edits); - } - } - - #-- sort results into date catalogue - arsort($changes); - $last_date = ""; - $datestr = ewiki_t("DAY"); - $e = array(); - foreach ($changes as $id=>$date) { - - $date = strftime($datestr, $date); - if ($date != $last_date) { - $last_date = $date; - } - - $e[$date][] = $id; - unset($changes[$id]); - } - - - #-- mk output - $o .= $ewiki_plugins["rc"][0]($e, $meta); - - - #-- add an
    - if ($days == 7) { - $days = 30; - } - $url = ewiki_script("", $recentchanges); - $o .= ewiki_t(<< - - - _{show last} - - -
    -EOT - ); - - return($o); -} - - -/* - UseMod like list output -*/ -function ewiki_page_rc_usemod(&$e, &$meta) { - - $clockstr = ewiki_t("CLOCK"); - - foreach ($e as $datestr => $pages) { - - $o .= "\n

    $datestr

    \n"; - - foreach ($pages as $id) { - - $diff = '(diff)'; - $page = ''.htmlentities($id).''; - $time = strftime($clockstr, $meta[$id][0][2]); - $author = ewiki_author_html($meta[$id][0][0], 0); - $log = htmlentities($meta[$id][0][1]); - $changes = ""; - if (($n = count($meta[$id])) > 1) { - $changes = "($n ".'changes)'; - } - - $o .= '· ' - . $diff . ' ' - . $page - . ' ' . $time . ' ' - . $changes . ' ' - . ($log ? '[' . $log . ']' : '') - . ' . . . . . ' . $author - . '
    ' . "\n"; - } - } - $o .= "\n"; - return($o); -} - - -/* - MoinMoin table style changelog output -*/ -function ewiki_page_rc_moin(&$e, &$meta) { - - $clockstr = ewiki_t("CLOCK"); - - $o .= '' - . ''; - - foreach ($e as $datestr => $pages) { - $o .= "\n\n"; - foreach ($pages as $id) { - - $link = '' . htmlentities($id) . ''; - $time = strftime($clockstr, $meta[$id][0][2]); - $changes = $meta[$id]; - if (count($changes) >= 2) { - - #-- enum unique author names - $a = array(); - foreach ($changes as $i=>$str) { - $str = strtok($str[0], " <("); - $a[$str][] = ($i+1); - } - $str = ""; - foreach ($a as $author=>$i) { - $author = ewiki_author_html($author, 0); - $str .= $author. "[".implode(",",$i)."]
    "; - } - $author = $str; - - #-- enum log entries - $log = ""; - foreach ($meta[$id] as $i=>$str) { - if ($str = $str[1]) { - $log .= "#".($i+1)." " . htmlentities($str) . "
    \n"; - } - } - } - else { - $author = ewiki_author_html($meta[$id][0][0]); - $log = htmlentities($meta[$id][0][1]); - } - - $o .= '' - . '' - . '' - . '' . "\n"; - } - } - $o .= "

    $datestr

    · ' . $link . ' [' . $time . '] ' . $author . '' . $log . '
    \n"; - return($o); -} - - -/* - fills $list with changeLOG entries of previous page ($row) versions -*/ -function ewiki_page_rc_more(&$row, &$list, $timeframe, $minor_edits) { - - $id = $row["id"]; - $ver = $row["version"]; - while ($ver >= 1) { - - if ($row["lastmodified"] >= $timeframe) { - if ($minor_edits || !($row["flags"] & EWIKI_DB_F_MINOR)) { - $list[] = array( - 0 => $row["author"], - 1 => $row["meta"]["log"], - 2 => $row["lastmodified"], - ); - } - } - else { - return; - } - - $ver--; - if (!$ver || !($row = ewiki_db::GET($id, $ver))) { - return; // stops at revision holes - } - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/scandisk.meta b/mods/wiki/plugins/page/scandisk.meta deleted file mode 100644 index 8267232e3..000000000 --- a/mods/wiki/plugins/page/scandisk.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -title: ScanDisk -description: nonsense -priority: rare -hooks: page -type: page diff --git a/mods/wiki/plugins/page/scandisk.php b/mods/wiki/plugins/page/scandisk.php deleted file mode 100644 index 8f3d1d0a6..000000000 --- a/mods/wiki/plugins/page/scandisk.php +++ /dev/null @@ -1,68 +0,0 @@ -$id\n"; - - $s_fv = 0; - $s_files = 0; - $s_n_txt = 0; - $s_n_bin = 0; - $s_n_txt_r = 0; - $s_n_bin_r = 0; - $s_n_dis = 0; - $s_n_err = 0; - $s_n_htm = 0; - $s_n_ro = 0; - $s_n_wr = 0; - $s_holes = 0; - - $result = ewiki_db::GETALL(array("flags", "meta", "created", "version")); - - $s_files = $result->count(); - - while ($row = $result->get()) { - - $flags = $row["flags"]; - $s_n_txt += ($flags & EWIKI_DB_F_TEXT) ?1:0; - $s_n_bin += ($flags & EWIKI_DB_F_BINARY) ?1:0; - $s_n_txt_r += (($flags & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) ?1:0; - $s_n_bin_r += (($flags & EWIKI_DB_F_TYPE) == EWIKI_DB_F_BINARY) ?1:0; - $s_n_dis += ($flags & EWIKI_DB_F_DISABLED) ?1:0; - $s_n_err += (($flags & EWIKI_DB_F_TYPE) == 0) ?1:0; - $s_n_htm += ($flags & EWIKI_DB_F_HTML) ?1:0; - $s_n_ro += ($flags & EWIKI_DB_F_READONLY) ?1:0; - $s_n_wr += ($flags & EWIKI_DB_F_WRITEABLE) ?1:0; - - $s_fv += $row["version"]; - - $id = $row["id"]; - for ($v=1; $v<=$row["version"]; $v++) { - $r = ewiki_db::GET($id, $v); - if (empty($r["created"]) || empty($r["content"])) { - $s_holes += 1; - } - } - } - - $s_frag = ($s_fv ? (((int)(100*$s_holes/$s_fv))/100) ."%" : "N/A"); - - $o .= '' - . "\n" - . "\n" - . "\n" - . "\n" - . "
    number of wikipages$s_files
    text
    binary
    disabled pages
    errors
    $s_n_txt ($s_n_txt_r)
    $s_n_bin ($s_n_bin_r)
    $s_n_dis
    $s_n_err
    flagged read-only
    explicit writable
    html enabled pages
    $s_n_ro
    $s_n_wr
    $s_n_htm
    absolute page number
    version holes
    database fragmentation
    $s_fv
    $s_holes
    $s_frag
    \n"; - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/since_updates.meta b/mods/wiki/plugins/page/since_updates.meta deleted file mode 100644 index 70c0bde11..000000000 --- a/mods/wiki/plugins/page/since_updates.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: page -title: SinceUpdates -description: ... -priority: bonus -hooks: page -type: page -config: - EWIKI_PAGE_SINCEUPDATES="SinceUpdatedPages" diff --git a/mods/wiki/plugins/page/since_updates.php b/mods/wiki/plugins/page/since_updates.php deleted file mode 100644 index 45c3f930a..000000000 --- a/mods/wiki/plugins/page/since_updates.php +++ /dev/null @@ -1,45 +0,0 @@ - - - - define("EWIKI_PAGE_SINCEUPDATES", "SinceUpdatedPages"); - - $ewiki_plugins["page"][EWIKI_PAGE_SINCEUPDATES] = "ewiki_page_since_updates"; - - - -function ewiki_page_since_updates($id=0, $data=0) { - $orderby="lastmodified"; - $asc=-1; - $print="%02dT %02dH %02dM %02dS"; - $title="Aktualisierung seit"; - - $sorted = array(); - $result = ewiki_db::GETALL(array($orderby, "flags", "version")); - - while ($row = $result->get()) { - if (EWIKI_DB_F_TEXT == ($row["flags"] & EWIKI_DB_F_TYPE)) { - $sorted[$row["id"]] = $row[$orderby]; - } - } - - if ($asc != 0) { arsort($sorted); } - else { asort($sorted); } - - foreach ($sorted as $name => $value) { - $x = time() - $value; - $dy = (int)(($x) / 86400); - $hr = (int)(($x % 86400) / 3600); - $mn = (int)((($x % 86400) % 3600) / 60); - $se = (($x % 86400) % 3600) % 60; - $sorted[$name] = sprintf($print, $dy, $hr, $mn, $se); - } - $o .= ewiki_list_pages($sorted); - - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/sitemap.meta b/mods/wiki/plugins/page/sitemap.meta deleted file mode 100644 index 6e1588f10..000000000 --- a/mods/wiki/plugins/page/sitemap.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: page -priority: extra -hooks: page, action -type: page -config: - EWIKI_PAGE_SITEMAP="SiteMap" - EWIKI_SITEMAP_DEPTH=1 -title: SiteMap -description: will print a sitemap rooted at the given location diff --git a/mods/wiki/plugins/page/sitemap.php b/mods/wiki/plugins/page/sitemap.php deleted file mode 100644 index 077aa577c..000000000 --- a/mods/wiki/plugins/page/sitemap.php +++ /dev/null @@ -1,238 +0,0 @@ -".ewiki_t("VIEWSMFOR"); - - foreach($ewiki_config["SiteMap"]["RootList"] as $root){ - if(isset($a_validpages[$root])){ - $o.=''.$root.' '; - } - } - - $o.="

    "; - - //checks to see if the user is allowed to view the root page - if(!isset($a_validpages[$str_rootid])){ - $o .= ewiki_t("INVALIDROOT"); - return $o; - } - - //$timesitemap=getmicrotime(); - $a_sitemap=ewiki_sitemap_create($str_rootid, $a_validpages, EWIKI_SITEMAP_DEPTH); - - $timer=array(); - $level=-1; - $fordump=0; - $str_formatted="
      \n
    • ".$str_rootid."
    • "; - $fin_level=format_sitemap($a_sitemap, $str_rootid, $str_formatted, $level, $timer, $fordump); - $str_formatted.="
    ".str_pad("", $fin_level*6, "\n"); - $o.=$str_formatted; - - //$timesitemap_end=getmicrotime(); - - //$o.="GetAll: ".($time_end-$time)."\n"; - //$o.="SiteMap: ".($timesitemap_end-$timesitemap)."\n"; - //$o.="Total: ".($timesitemap_end-$time); - - - return($o); - -} - -function ewiki_valid_pages($bool_allowimages=0, $virtual_pages=0){ - //$time=getmicrotime(); - global $ewiki_plugins; - $result = ewiki_db::GETALL(array("flags", "refs", "meta")); - while ($row = $result->get()) { - if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $str_null, "view")) { - continue; - } - if (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT || ($bool_allowimages ? $row["meta"]["class"]=="image" : 0)) { - $temp_refs=explode("\n",$row["refs"]); - foreach($temp_refs as $key => $value) { - if(empty($value)) { - unset($temp_refs[$key]); - } - } - if($row["meta"]["class"]=="image"){ - $a_validpages[$row["id"]]=$temp_array=array("refs" => $temp_refs, "type" => "image", "touched" => FALSE); - } else { - $a_validpages[$row["id"]]=$temp_array=array("refs" => $temp_refs, "type" => "page", "touched" => FALSE); - } - unset($temp_refs); - } - } - - if($virtual_pages){ - #-- include virtual pages to the sitemap. - $virtual = array_keys($ewiki_plugins["page"]); - foreach($virtual as $vp){ - if(!EWIKI_PROTECTED_MODE || !EWIKI_PROTECTED_MODE_HIDING || ewiki_auth($vp, $str_null, "view")){ - $a_validpages[$vp]=array("refs" => array(), "type" => "page", "touched" => FALSE); - } - } - } - return $a_validpages; -} - -/* - Adds each of the pages in the sitemap to an HTML list. Each site is a clickable link. -*/ -function format_sitemap($a_sitemap, $str_rootpage, &$str_formatted, &$prevlevel, &$timer, &$fordump){ - - //get all children of the root format them and store in $str_formatted array - if($a_sitemap[$str_rootpage]["child"]){ - while($str_child = current($a_sitemap[$str_rootpage]["child"])){ - $str_mark=""; - if($a_sitemap[$str_rootpage]["level"]>$prevlevel){ - $str_mark="
      \n"; - } - elseif ($a_sitemap[$str_rootpage]["level"]<$prevlevel){ - //markup length is 6 characters - $str_mark=str_pad("", ($prevlevel-$a_sitemap[$str_rootpage]["level"])*6, "
    \n"); - } - $prevlevel=$a_sitemap[$str_rootpage]["level"]; - if($fordump){ - $str_formatted.=($str_mark."
  • ".$str_child."
  • \n"); - } else { - $str_formatted.=($str_mark."
  • ".$str_child."
  • \n"); - } - array_shift($a_sitemap[$str_rootpage]["child"]); - format_sitemap($a_sitemap, $str_child, $str_formatted, $prevlevel, $timer, $fordump); - } - return ($prevlevel+1); - } -} - - -/* - gets all children of the given root and stores them in the $a_children array -*/ -function ewiki_page_listallchildren($str_root, &$a_children, &$a_sitemap, &$a_validpages, $i_level, $i_maxdepth, $i_flatmap){ - if(($i_level<$i_maxdepth) && is_array($a_validpages[$str_root]["refs"])){ //controls depth the sitemap will recurse into - foreach($a_validpages[$str_root]["refs"] as $str_refs){ - if($str_refs){ //make sure $str_refs contains a value before doing anything - if(isset($a_validpages[$str_refs])){ //test page validity - if(!$a_validpages[$str_refs]["touched"]){ //check to see if page already exists - if($i_flatmap){ - $a_sitemap[]=$str_refs; - } - $a_validpages[$str_refs]["touched"]=TRUE; //mark page as displayed - $a_children[$str_refs]=""; - $a_currchildren[]=$str_refs; - } - } - } - } - if(!$i_flatmap){ - if($a_currchildren){ - $a_sitemap[$str_root]=array("level" => $i_level, "child" => $a_currchildren); - } else { - $a_sitemap[$str_root]=array("level" => $i_level); - } - } - } -} - - -/* - Creates the sitemap. And sends the data to the format_sitemap function. - Returns the HTML formatted sitemap. -*/ -function ewiki_sitemap_create($str_rootid, $a_validpages, $i_maxdepth, $i_flatmap=0){ - //map starts out with a depth of 0 - $i_depth=0; - $forcelevel=FALSE; - - //create entry for root in the sitemap array - if(!$i_flatmap){ - $a_sitemap[$str_rootid]=array("parent" => "", "level" => $i_depth, "child" => $str_rootid); - } else { - $a_sitemap[]=$str_rootid; - } - //mark the root page as touched - $a_validpages[$str_rootid]["touched"]=TRUE; - //list all of the children of the root - ewiki_page_listallchildren($str_rootid, $a_children, $a_sitemap, $a_validpages, $i_depth, $i_maxdepth, $i_flatmap); - $i_depth++; - - if($a_children){ - end($a_children); - $str_nextlevel=key($a_children); - reset($a_children); - - while($str_child = key($a_children)){ - //list all children of the current child - ewiki_page_listallchildren($str_child, $a_children, $a_sitemap, $a_validpages, $i_depth, $i_maxdepth, $i_flatmap); - - //if the child is the next level marker... - if($str_child==$str_nextlevel){ - //increment the level counter - $i_depth++; - //determine which child marks the end of this level - end($a_children); - $str_nextlevel=key($a_children); - //reset the array counter to the beginning of the array - reset($a_children); - //we are done with this child...get rid of it - } - array_shift($a_children); - } - } - - return $a_sitemap; -} -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/textupload.meta b/mods/wiki/plugins/page/textupload.meta deleted file mode 100644 index 7fec6143b..000000000 --- a/mods/wiki/plugins/page/textupload.meta +++ /dev/null @@ -1,11 +0,0 @@ -api: ewiki -category: page -title: TextUpload -description: allows to upload text pages from various file formats -priority: optional -hooks: page -type: page -config: - EWIKI_UNTAR="tar" // GNU/Linux tar, Cygwin tar.exe - EWIKI_UNZIP="unzip" // unzip or pkunzip.exe - EWIKI_DEV_STDOUT="/dev/stdout" // Unix diff --git a/mods/wiki/plugins/page/textupload.php b/mods/wiki/plugins/page/textupload.php deleted file mode 100644 index 619c77431..000000000 --- a/mods/wiki/plugins/page/textupload.php +++ /dev/null @@ -1,872 +0,0 @@ -"). - - Some of these filters are usually already available with modern UNIX - distros. As fallback text data gets ripped out from binary files - (garbage will remain in the page), or the file could be rejected - completely. -*/ - - -#-- plugin registration -$ewiki_plugins["page"]["TextUpload"] = "ewiki_page_textupload"; - - - - -/* this prints the - upload
    -*/ -function ewiki_page_textupload($id, $data, $action) { - - $o = ewiki_make_title($id, $id, 2); - - if (empty($_FILES["upload_text_file"])) { - - $ACCEPT="text/plain,text/wiki,text/html,text/*,application/x-tar,application/x-gtar,application/x-ustar,application/zip"; - - $url = ewiki_script("", $id); - $o .= ewiki_t(<< -
    - - file -

    - -

    - overwrite existing page -
    - assume file is text/plain, - if no .ext -
    - brute-force extract text data from binary file -

    - strip file name extension(s), and use the remaining string as destination page name -
    - or store file as (page name) - -END - ); - } - else { - $o .= ewiki_textfile_save($_FILES["upload_text_file"]); - } - - return($o); -} - - -/* This code is responsible for checking the parameters of uploaded - $_FILES, unpacking zip archives and tarballs, and finally converting - (from *.* into text/wiki) and storing individual files as wikipages - into the database. -*/ -function ewiki_textfile_save($file=array()) { - - #set_time_limit(+30); - $o = ""; - - #-- upload file vars - $fn = $file["tmp_name"]; - $fn_orig = $file["name"]; - $mime = $file["type"]; - - #-- pre-guess content - if ($_REQUEST["textfile_assume_text"] && !strpos($fn_orig, ".") && ($mime=="application/octet-stream")) { - $mime = "text/plain"; - } - - #-- is current file an archive? - if (strpos($fn_orig,".sx")) { - $mime = "application/vnd.sun.xml.writer"; - } - $untar = (preg_match("#^application/(x-)?(g|us)tar$#", $mime) || preg_match("#\.tar|\.tgz#", $fn_orig)) ? EWIKI_UNTAR : ""; - $unzip = (($mime=="application/zip") || strpos($file["name"],".zip")) ? EWIKI_UNZIP : ""; - $multimime = (strstr($mime, "multipart/")); - - #-- tarball or zip archive ------------------------------------------------ - if ($untar || $unzip) { - - #-- create temporary dir - $tmp_dir = EWIKI_TMP."/ewiki-txtupl-$untar$unzip-".time()."-".rand(0,523555).".tmp.d"; - mkdir($tmp_dir); - $cwd = getcwd(); chdir($tmp_dir); - - #-- archive extraction - if ($untar) { - { exec("$untar xzf '$fn'", $uu, $error); } - if ($error) { exec("$untar xjf '$fn'", $uu, $error); } - if ($error) { exec("$untar xf '$fn'", $uu, $error); } - } - elseif ($unzip) { - `$unzip "$fn"`; - } - - #-- go throgh directory - chdir($cwd); - $o .= ewiki_textupload_readdir($tmp_dir); - - #-- remove temporary directory - `rm -rf "$tmp_dir"`; - - } - - #-- multipart/ mime archive ----------------------------------------------- - elseif ($multimime) { - } - - #-- plain file -------------------------------------------------------- - else { - - #-- extract wiki content from file - $content = ewiki_textfile_convert( - $fn, $fn_orig, $mime, - $_REQUEST["textfile_brute_force"], - $_REQUEST["textfile_assume_text"], - $_REQUEST["textfile_noext_is_text"] - ); - - #-- make short filename - $fn_orig = strtr($fn_orig, "\\", "/"); - if ($p = strrpos($fn_orig, "/")) { - $fn_orig = substr($fn_orig, $p+1); - } - if (!$fn_orig) { - $fn_orig = ""; - } - - #-- destination filename - $dest_id = trim($_REQUEST["textfile_saveas"]); - if (!$dest_id) { - $dest_id = trim(trim($fn_orig), "."); - if ($_REQUEST["textfile_strip_ext"] == 2) { - $dest_id = strtok($fn_orig, "."); - } - if ($_REQUEST["textfile_strip_ext"] == 1) { - if ($p = strrpos($dest_id, ".")) { - $dest_id = substr($dest_id, 0, $p); - } - } - $dest_id = trim($dest_id); - } - - #-- reject - if (!$dest_id) { - return($o . "· Could not store '$fn_orig', please specify a page name to use as destination.
    \n"); - } - - - #-- store ----------------------------------------------------------- - if ($content) { - $ahref_dest = '' . $dest_id . ''; - - $data = ewiki_db::GET($dest_id); - if ($data && !$_REQUEST["textfile_overwrite_pages"]) { - $o .= "· did not overwrite existing page '$ahref_dest' with content from file '$fn_orig'
    \n"; - } - else { - if (empty($data)) { - $data = array( - "id" => $dest_id, - "version" => 0, - "created" => time(), - "meta" => "", - "flags" => EWIKI_DB_F_TEXT, - "refs" => "", - "hits" => 0, - ); - } - $data["version"]++; - $data["lastmodified"] = time(); - $data["author"] = ewiki_author("TextUpload"); - $data["content"] = $content; - ewiki_scan_wikiwords($data["content"], $ewiki_links, "_STRIP_EMAIL=1"); - $data["refs"] = "\n\n".implode("\n", array_keys($ewiki_links))."\n\n"; - - if (ewiki_db::WRITE($data)) { - $o .= "· extracted text from '$fn_orig' into page '$ahref_dest'
    \n"; - -## $o .= "

    src

    " . ($data["content"])."

    page

    " . ewiki_format($data["content"]); - } - else { - $o .= "· database error occoured, when writing to '$ahref_dest' from file '$fn_orig'
    \n"; - } - } - } - else { - $o .= "· couldn't detect format (and text content) of '$fn_orig'
    \n"; - } - - } - - return($o); -} - - - -/* reads a directory (from unpackked tarballs), and re-calls the - _textfile_save() function for storing individual files. -*/ -function ewiki_textupload_readdir($tmp_dir) { - - $o = ""; - - $dh = opendir($tmp_dir); - while ($fn = readdir($dh)) { - - if ($fn[0]==".") { - continue; - } - elseif (is_dir("$tmp_dir/$fn")) { - $o .= ewiki_textupload_readdir("$tmp_dir/$fn"); - } - else { - $o .= ewiki_textfile_save(array( - "tmp_name" => "$tmp_dir/$fn", - "name" => "$fn", - "type" => ewiki_get_mime_type("$tmp_dir/$fn"), - )); - } - } - closedir($dh); - - return($o); -} - - -#========================================================================== - - -/* Guesses a files mime type using magic data, or the file extension - mapping list in /etc/mime.types -*/ -function ewiki_get_mime_type($fn) { - - global $mime_ext; - - #-- default - $mime = "application/octet-stream"; - - #-- by content - if (function_exists("mime_content_type")) { - $mime = mime_content_type($fn); - } - - #-- by ext - if (($mime == "application/octet-stream") && strpos($fn, ".")) { - if (empty($mime_ext) && ($list=file("/etc/mime.types"))) - foreach ($list as $line) { - $line = trim($line); - $m = strtok($line, " \t"); - if (strpos($m, "/") && $e=explode(" ", trim(strtr(strtok("\n"), ".\t", " "))) ) { - foreach ($e as $ext) if ($ext) { - $mime_ext[$ext] = $m; - } - } - } - $ext = explode(".", $fn); unset($ext[0]); - foreach ($ext as $e) { - if ($m = $mime_ext[$e]) { - $mime = $m; - } - } - } - - return($mime); -} - - - -#========================================================================== - - -/* This function tries to convert a uploaded plain file into a text/plain - (we here call it text/wiki) page. It uses some filters to convert from - file format to file format (usually converting into text/html and then - into Wiki format). -*/ -function ewiki_textfile_convert($fn, $fn_orig, $mime, $extr_bin=0, $is_text=0, $noext2text=1) -{ - global $ewiki_textfilters; - - #-- handled by ewiki_unformat() - $html_variants = array( - "text/html", "text/xhtml", "text/wap", "application/vnd.wap.wml", - "text/xml+html", - "text/x.office.content.xml", # an extracted OpenOffice content.xml - ); - - #-- read in complete file - if ($f = fopen($fn, "rb")) { - $content = fread($f, 1<<18); #-- max 256K - fclose($f); - } - else { - return(false); - } - - #-- get mime-type - if ($mime == "application/octet-stream") { - $mime = ewiki_get_mime_type($fn_orig); - } - if ($is_text && ($mime == "application/octet-stream")) { - $mime = "text/plain"; - } - if ($noext2text && !strpos($fn_orig,".") && ($mime == "application/octet-stream")) { - $mime = "text/plain"; - } - - #-- go thru installed filters - foreach ($ewiki_textfilters as $filter_row) { - list($f_from, $f_into, $f_prog) = $filter_row; - if (($f_from==$mime) || ($f_from=="*/*")) { - - $tmpf = EWIKI_TMP."/ewiki-txtupl-filter-".time()."-".rand(0,564595).".tmp"; - if ($f = fopen($tmpf, "wb")) { - fwrite($f, $content); - fclose($f); - } - else { continue; } - - #-- replace placeholders "%f" and "%o" - if (!strpos($f_prog, "%f")) { - $f_prog .= " < '%f' "; - } - $f_prog = str_replace("%o", EWIKI_DEV_STDOUT, $f_prog); - $f_prog = str_replace("%f", $tmpf, $f_prog); - - #-- exec, unlink temporary file - $new_content = `$f_prog`; - unlink($tmpf); - - #-- success? - if ($new_content) { - $content = $new_content; - $mime = $f_into; - unset($new_content); - } - } - } - -# -#... -# - - #-- brute force text extraction from binary files - if ($extr_bin && (strtok($mime, "/") == "application")) { - # ??? # - preg_match_all("/([\n\r\t\040-\176\177-\237\260-\377]{7,})/", $content, $uu); - if ($uu) { - $content = implode("\n", $uu[1]); - $mime = "text/plain"; - } - } - - #-- HTML->Wiki-source transformation - if (in_array($mime, $html_variants)) { - $content = ewiki_unformat($content); - $mime = "text/wiki"; - } - - #-- file reached text status - if ($mime == "text/plain") { - #- this is simple - $mime = "text/wiki"; - } - - #-- finish - if ($mime == "text/wiki") { - return($content); - } -} - - - -#=========================================================================== - -/**************** -#echo - ewiki_unformat(' - - - -

    HeadLine

    - -See also WikiText or somehwere __else__. - -We\'ll expect some magic here? - -
      -
    • list ==entry== 1 -
    • list entry **2** -
      1. list entry 2-1
      -
    - - - -'); -********************/ - - -/* This function is believed to backconvert pages from .html into - WikiMarkup. As it shall be used to convert any .html file (and not only - ewiki exported ones), it cannot convert tables back (think of layout - tables). - It has limited support for openoffice xml (for full support this needed - to be an xml parser). -*/ -function ewiki_unformat($html) { - - $src = ""; - - $tagmap = array( - "b" => "**", - "i" => "''", - "strong" => "__", - "em" => "''", - "tt" => "==", - "big" => "##", - "small" => "µµ", - "sup" => "^^", - "br" => "\n%%%\n", - "hr" => "\n\n----\n\n", - ); - $standalone_tags = array( - "img", "br", "hr", "input", "meta", "link", - ); - $xml = array(); - $xml_i = false; - -#-- TODO -# table -# pre -# .. - - - - #-- walk through all tags ---------------------------------------------- - $tag_level = 0; - $close_css = array(); - $len = strlen($html); - $pos = 0; - $loop = 500; - $in_table = 0; // ignore such?? - $in_pre = 0; - $in_list = 0; - $list = ""; - while (($pos < $len) && $loop--) { - - #-- decode step by step - list($pretext, $tagstr, $tagattr) = ewiki_htmlparser_get($html,$pos,$len,$in_pre); - $tagname = ltrim($tagstr, "/"); - - #-- add pre-text (no linebreaks in it) - if ($pretext) { - $src .= $pretext; - } - $src .= $post; - $post = ""; - - #-- handle things we have WikiMarkup for - if ($tagstr) switch ($tagstr) { - - #-- paragraphes - case "p": - $src .= "\n"; - $tag_level=0; $close_css=array(); - break; - case "/p": - $src .= "\n\n"; - break; - - #-- headlines - case "h1": - case "h2": - $src .= "\n\n!!! "; break; - case "h3": - $src .= "\n\n!! "; break; - case "h4": - $src .= "\n\n! "; break; - case "h5": - case "h6": - $src .= "\n\n__"; break; - - case "/h1": - case "/h2": - case "/h3": - case "/h4": - case "/h5": - $src .= "\n\n"; break; - case "/h5": - case "/h6": - $src .= "__\n\n"; break; - - - #-- lists - case "ul": - case "ol": - if (!$in_list) { - $src .= "\n\n"; - } - $in_list++; - $list .= ($tagstr=="ul") ? "*" : "#"; - break; - - case "/ul": - case "/ol": - $in_list--; - $list = substr($list, 0, $in_list); - if (!$in_list) { - $src .= "\n\n"; - } - break; - - case "li": - $src .= "\n" . $list; - - - #-- hyperlinks - case "a": - $name = $tagattr["name"]; - $href = $tagattr["href"]; - if ($href || $name) { - $text = ""; - do { - list($t,$tagstr,$tagattr) = ewiki_htmlparser_get($html,$pos,$len); - $text = trim("$text$t"); - } - while ($tagstr!="/a"); - - if (empty($text)) { - $text = "$name$href"; - } - - #-- define anchor - if ($name) { - $src .= "[#$name \"$text\"]"; - } - #-- link to anchor - elseif ($href[0] == "#") { - $src .= "[.#$href \"$text\"]"; - } - #-- hyperlink - else { - #-- check for InterWikiLink - foreach ($ewiki_config["interwiki"] as $abbr=>$url) { - $url = str_replace("%s", "", $url); - if (substr($href, 0, strlen($url)) === $url) { - $href = "?id=".$abbr.":".substr($href, strlen($url)); - } - } - #-- binary link (should rarely happen) - if ($p=strpos($href, EWIKI_IDF_INTERNAL)) { - $href = strtok(substr($href, $p), "&"); - $src .= "[$href \"$text\"]"; - } - #-- www link - elseif (strpos($href, "://")) { - if ($href == $text) { - $src .= "$href"; - } else { - $src .= "[$href \"$text\"]"; - } - } - else { - $wikilink = ""; - #-- ewiki URL - if (preg_match('#\?(?:id|page|file|name)=(.+)(&(?>!amp;)|$)#', urldecode($href), $uu)) { - $wikilink = $uu[1]; - } - #-- ewiki .html export filenames - elseif (preg_match('#^([^/:]+)(\.html?)?$#', urldecode($href), $uu)) { - $wikilink = $uu[1]; - } - #-- looks like wikilink - if ($wikilink) { - if (strpos($wikilink, "view/")===0) { - $wikilink = substr($wikilink, 5); - $src .= "[$text|$wikilink]"; - } - if (($wikilink == $text) || ($wikilink == str_replace(" ", "", $text))) { - if (preg_match('/(['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+){2}/', $wikilink)) { - $src .= $wikilink; - } - else { - $src .= "[$wikilink]"; - } - } - else { - $src .= "[$wikilink \"$text\"]"; - } - } - #-- absolute URL - elseif ($href[0] == "/") { - $src .= "[url:$href \"$text\"]"; - } - #-- should eventually drop this - else { - $src .= "[$href \"$text\"]"; - } - } - } - } - break; - - - #-- images - case "img": - if ($href = $tagattr["src"]) { - ($alt = $tagattr["alt"]) or ($alt = $tagattr["title"]) or ($alt = ""); - $src .= "[$alt|$src]"; - } - break; - - - #-- yet unsupported - case "code": - if ($end = strpos($html, '', $end); - $src .= "\n\n" . substr($html, $pos, $end-$pos); - $pos = $end + 1; - } - break; - - - #-- pre - case "pre": - $src .= "\n
    \n";
    -            $in_pre = 1;
    -            break;
    -         case "/pre":
    -            $src .= "\n
    \n"; - $in_pre = 0; - break; - - - #-- OpenOffice ----------------------------------------------------- - case "office:document-content": - if ($tagattr["xmlns:office"] && $tagattr["xmlns:text"] && ($tagattr["office:class"]=="text")) { - $xml["office"] = 1; - } - break; - #-- formatting - case "style:style": - case "style:properties": - if ($xml["office"]) { - if ($uu = $tagattr["style:name"]) { - $xml_i = $uu; # style selector - $xml[$uu] = array(); - } - if ("bold" == $tagattr["fo:font-weight"]) { - $xml[$xml_i][0] .= "__"; - } - if ("italic" == $tagattr["fo:font-style"]) { - $xml[$xml_i][0] .= "''"; - } - if (strpos($tagattr["style:parent-style-name"], "eadline")) { - $xml[$xml_i][1] = "\n!"; - } - } - break; - #-- content - case "text:p": - case "text:span": - $xml_i = $tagattr["text:style-name"]; - $src .= $xml[$xml_i][1] - . $xml[$xml_i][0]; - break; - case "/text:p": - case "/text:span": - $src .= strrev($xml[$xml_i][0]); - $xml_i == false; - if (!$xml["list"] && ($tagstr == "/text:p")) { - $src .= "\n"; - } - break; - #-- headlines - case "text:h": - $level = $tagattr["text:level"]; - $src .= "\n" . str_repeat("!", 1 + ($level>4)?1:0 + ($level>6)?1:0); - break; - case "/text:h": - $src .= "\n"; - break; - #-- links - case "text:a": - if ($href = $tagattr["xlink:href"]) { - $src .= "[$href \"";# . $pretext; - } - break; - case "/text:a": - $src .= "\"]"; - break; - #-- lists - case "text:list-item": - $src .= "\n" . $xml["list"] . " "; - break; - case "text:ordered-list": - $xml["list"] .= "#"; - break; - case "text:unordered-list": - $xml["list"] .= "*"; - break; - case "/text:ordered-list": - case "/text:unordered-list": - $xml["list"] = substr($xml["list"], 0, -1); - $src .= "\n"; # there aren't nested lists in OO anyhow - break; - - - #-- anything else -------------------------------------------------- - default: - #-- one of the standard tags? - if ($add = @$tagmap[$tagname]) { - $src .= $add; - } - break; - - }#- switch(tag) - - - #-- count tags - if ($tagstr[0] == "/") { - $tag_level--; - if ($tag_level<0) { $tag_level=0; } - } - elseif (!in_array($tagname, $standalone_tags)) { - $tag_level++; - } - - #-- markup_css - if (($css=@$tagattr["class"]) || ($css=strtr($tagattr["class"], " \r\t\n", " "))) { - $css = strtr($css, " ", "-"); - $src .= "@@$css "; - $close_css[$tag_level-1]++; - } - if (($css=@$tagattr["style"]) || ($css=strtr($tagattr["style"], " \r\t\n", " "))) { - $css = str_replace($css, " ", ""); - $src .= "@@$css "; - $close_css[$tag_level-1]++; - } - while (@$close_css[$tag_level]) { - $src .= "@@ "; - $close_css[$tag_level]--; - } - - $src .= $post; - } - - return($src); -} - - -/* Fetches (step by step) next html from the input string, and - also returns text content prepending it. -*/ -function ewiki_htmlparser_get(&$html, &$pos, &$len, $pre=0) { - - $text=$tagstr=$tagattr=""; - - #-- search next tag - $l = strpos($html, "<", $pos); - $r = strpos($html, ">", $l); - if (($l===false) or ($r===false)) { - #-- finish - $text = substr($html, $pos); - $pos = $len; - } - - #-- text part - if ($l >= $pos) { - $text = substr($html, $pos, $l-$pos); - if (!$pre) { - $text = strtr($text, "\r\n", " "); - } - $pos = $l; - } - - #-- any tag here? - if ($r >= $pos) { - $pos = $r + 1; - $tag = substr($html, $l + 1, $r - $l - 1); - - #-- split into name and attributes - $tagstr = strtolower(rtrim(strtok($tag, " \t\n>"),"/")); - $tagattr = array(); - if (($tattr=strtok(">")) && strpos($tattr,"=")) { - preg_match_all('/([-:\w]+)=(\".*?\"|[^\s]+)/', $tag, $uu); - if ($uu) { - foreach ($uu[1] as $i=>$a) { - $tagattr[$uu[1][$i]] = trim($uu[2][$i], '"'); - } - } - } - }#- tag - - return( array($text, $tagstr, $tagattr) ); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/wantedpages.meta b/mods/wiki/plugins/page/wantedpages.meta deleted file mode 100644 index 76a7fd566..000000000 --- a/mods/wiki/plugins/page/wantedpages.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -title: WantedPages -description: lists absent pages, where however links to exist -hooks: page -type: page -priority: optional diff --git a/mods/wiki/plugins/page/wantedpages.php b/mods/wiki/plugins/page/wantedpages.php deleted file mode 100644 index f27f802e8..000000000 --- a/mods/wiki/plugins/page/wantedpages.php +++ /dev/null @@ -1,51 +0,0 @@ -# $ewiki_plugins["page"]["DanglingSymlinks"] = "ewiki_page_wantedpages"; - - -function ewiki_page_wantedpages($id, $data, $action) { - - #-- collect referenced pages - $result = ewiki_db::GETALL(array("refs")); - while ($row = $result->get()) { - if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $uu, "view")) { - continue; - } - $refs .= $row["refs"]; - } - - #-- build array - $refs = array_unique(explode("\n", $refs)); - - #-- strip existing pages from array - $refs = ewiki_db::FIND($refs); - foreach ($refs as $id=>$exists) { - if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $uu, "view")) { - continue; - } - if (!$exists && !strstr($id, "://") && strlen(trim($id))) { - $wanted[] = $id; - } - } - - #-- print out - $o .= "
      \n"; - foreach ($wanted as $page) { - - $o .= "
    • " . ewiki_link($page) . "
    • \n"; - - } - $o .= "
        \n"; - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/weekdiff.meta b/mods/wiki/plugins/page/weekdiff.meta deleted file mode 100644 index c34030198..000000000 --- a/mods/wiki/plugins/page/weekdiff.meta +++ /dev/null @@ -1,2 +0,0 @@ -title: weekdiff -description: Shows the diffs for all pages in a given time frame (one week per diff --git a/mods/wiki/plugins/page/wikidump.meta b/mods/wiki/plugins/page/wikidump.meta deleted file mode 100644 index 95b8c8035..000000000 --- a/mods/wiki/plugins/page/wikidump.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -title: WikiDump -description: generates .zip/tarball from all pages -priority: rare -hooks: page -type: page diff --git a/mods/wiki/plugins/page/wikidump.php b/mods/wiki/plugins/page/wikidump.php deleted file mode 100644 index 4cf73ee4a..000000000 --- a/mods/wiki/plugins/page/wikidump.php +++ /dev/null @@ -1,342 +0,0 @@ -0) ? '.links':''). $html_ext . '">' . $title . ''; - } - $version = EWIKI_VERSION; - - return << - - - - $head_title - - - -

        $title

        -$content - - -EOT; -} - - - -function ewiki_page_wiki_dump_tarball($id, $data, $action) { - - #-- return legacy page - if (empty($_REQUEST["download_tarball"])) { - $url = ewiki_script("", $id); - return(ewiki_make_title($id, $id, 2) . ewiki_t(<<
        -
        - - -

        - _{with images}
        - _{include virtual pages}
        - _{complete .html files}
        -      _{with backlink pages}
        -
        -END - )); - } - #-- tarball generation - else { - $di = $_REQUEST["dump_images"]; - $fh = $_REQUEST["dump_fullhtml"]; - $bl = $_REQUEST["dump_linksto"]; - $vp = $_REQUEST["dump_virtual"]; - $_REQUEST = $_GET = $_POST = array(); - set_time_limit(180); - ewiki_page_wiki_dump_send($di, $fh, $vp, $bl); - } -} - - -function ewiki_page_wiki_dump_send($imgs=1, $fullhtml=0, $virtual=0, $linksto=0) { - - global $ewiki_config, $ewiki_plugins; - - #-- reconfigure ewiki_format() to generate offline pages and files - $html_ext = ".htm"; - if ($fullhtml) { - $html_ext = ".html"; - } - $ewiki_config["script"] = "%s$html_ext"; - $ewiki_config["script_binary"] = "%s"; - $ewiki_config["print_title"] = 0; - - #-- fetch also dynamic pages - if ($virtual) { - $virtual = array_keys($ewiki_plugins["page"]); - } else { - $virtual = array(); - } - - - #-- get all pages / binary files - $result = ewiki_db::GETALL(array("id", "version", "flags")); - if ($result) { - - #-- HTTP headers - header("Content-Type: application/x-tar"); - header("Content-Disposition: attachment; filename=\"WikiDump.tar.gz\""); - - #-- start tar file - $tarball = new ewiki_virtual_tarball(); - $tarball->open(0); - - #-- convert all pages - while (($row=$result->get()) || count($virtual)) { - - $content = ""; - - #-- fetch page from database - if ($id = $row["id"]) { - $row = ewiki_db::GET($id); - } - #-- virtual page plugins - elseif ($id = array_pop($virtual)) { - $pf = $ewiki_plugins["page"][$id]; - $content = $pf($id, $content, "view"); - $row = array( - "flags" => EWIKI_DB_F_TEXT|EWIKI_DB_F_HTML, - "lastmodified" => time(), - ); - } - else { - break; - } - - #-- file name - $fn = $id; - $fn = urlencode($fn); - - #-- post process for ordinary pages / binary data - if (empty($content)) - switch ($row["flags"] & EWIKI_DB_F_TYPE) { - - case (EWIKI_DB_F_TEXT): - $content = ewiki_format($row["content"]); - break; - - case (EWIKI_DB_F_BINARY): - if (($row["meta"]["class"]=="image") && ($imgs)) { - $content = &$row["content"]; - } - else { - return; - } - break; - - default: - # don't want it - continue; - } - - #-- size check - if (empty($content)) { - continue; - } - - #-- for tarball - $perms = array( - "mtime" => $row["lastmodified"], - "uname" => "ewiki", - "mode" => 0664 | (($row["flags"]&EWIKI_DB_F_WRITEABLE)?0002:0000), - ); - - #-- html post process - if (!($row["flags"] & EWIKI_DB_F_BINARY)) { - - #-- use page template - if ($fullhtml) { - $content = ewiki_dump_template($id, $content, $linksto); - } - - #-- add links/ page - if ($linksto) { - $tarball->add( - "$fn.links$html_ext", - ewiki_dump_template( - $id, - ewiki_page_links($id, $row, "links"), - $lto=-1 - ), - $perms - ); - } - - $fn .= $html_ext; - } - - #-- add file - $tarball->add( - $fn, - $content, - $perms - ); - } - - #-- end output - $tarball->close(); - - } - - #-- fin - die(); -} - - - - -############################################################################ - - - - -#-- allows to generate a tarball from virtual files -# (supports no directories or symlinks and other stuff) -class ewiki_virtual_tarball { - - var $f = 0; - - function open($fn="/dev/stdout") { - - #-- init; - $this->f = 0; - - #-- file output? - if ($fn && ($fn != "-")) { - $this->f = gzopen("$fn", "wb9"); - } - else { - $_ENV["HTTP_ACCEPT_ENCODING"] = "gzip, deflate"; - $_SERVER["HTTP_ACCEPT_ENCODING"] = "gzip, deflate"; - ob_start("ob_gzhandler"); - } - } - - - function close() { - - #-- fill up file - $this->write(str_repeat("\000", 9*1024)); - - #-- close file handle - if ($this->f) { - gzclose($this->f); - } - } - - - function write($str) { - if ($this->f) { - gzwrite($this->f, $str); - fflush($this->f); - } - else { - echo $str; - ob_flush(); - } - } - - - function oct($int, $len) { - $o = "\000"; - while (--$len) { - $o = ($int & 0x07) . $o; - $int = $int >> 3; - } - return($o); - } - - - #-- add virtual file - function add($filename, $content, $args=array()) { - - $args = array_merge($args, array( - "mode" => 000664, - "mtime" => time(), - "ctime" => time(), - "uid" => 65534, #-- common for user "nobody" - "gid" => 65534, - "uname" => "nobody", - "gname" => "nobody", - "type" => "0", - )); - $args["mode"] |= 0100000; - $args["size"] = strlen($content); - $checksum = " "; - $magic = "ustar \000"; - $filename = substr($filename, 0, 99); - - #-- header record - $header = str_pad($filename, 100, "\000") # 0x0000 - . $this->oct($args["mode"], 8) # 0x0064 - . $this->oct($args["uid"], 8) # 0x006C - . $this->oct($args["gid"], 8) # 0x0074 - . $this->oct($args["size"], 12) # 0x007C - . $this->oct($args["mtime"], 12) # 0x0088 - . ($checksum) # 0x0094 - . ($args["type"]) # 0x009C - . str_repeat("\000", 100) # 0x009D - . ($magic) # 0x0101 - . str_pad($args["uname"], 32, "\000") # 0x0109 - . str_pad($args["gname"], 32, "\000") # 0x0129 - ; # 0x0149 - $header = str_pad($header, 512, "\000"); - - #-- calculate and add header checksum - $cksum = 0; - for ($n=0; $n<512; $n++) { - $cksum += ord($header[$n]); - } - $header = substr($header, 0, 0x0094) - . $this->oct($cksum, 7) . " " - . substr($header, 0x009C); - - #-- output - if ($fill = (512 - (strlen($content) % 512))) { - $content .= str_repeat("\000", $fill); - } - $this->write($header . $content); - } - - -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/wikidump2.meta b/mods/wiki/plugins/page/wikidump2.meta deleted file mode 100644 index d88159ec3..000000000 --- a/mods/wiki/plugins/page/wikidump2.meta +++ /dev/null @@ -1,11 +0,0 @@ -api: ewiki -category: page -hooks: page, action, link_url -type: page -config: - EWIKI_WIKIDUMP_ARCNAME="WikiDump_" - EWIKI_WIKIDUMP_DEFAULTTYPE="TAR" - EWIKI_WIKIDUMP_MAXLEVEL=1 -title: WikiDump+ -description: for downloading a tarball with all WikiPages and images that relate to the current -priority: bonus diff --git a/mods/wiki/plugins/page/wikidump2.php b/mods/wiki/plugins/page/wikidump2.php deleted file mode 100644 index fcd70b7dc..000000000 --- a/mods/wiki/plugins/page/wikidump2.php +++ /dev/null @@ -1,456 +0,0 @@ - When you are ready, click the \"_{DOWNLOAD_ARCHIVE}\" button."; -$ewiki_t["en"]["DOWNLOAD_ARCHIVE"] = "Download WikiDump"; - -define("EWIKI_WIKIDUMP_ARCNAME", "WikiDump_"); -define("EWIKI_WIKIDUMP_DEFAULTTYPE", "TAR"); -define("EWIKI_WIKIDUMP_MAXLEVEL", 1); -define('EWIKI_DUMP_FILENAME_REGEX',"/\W/"); - -#-- glue -if((function_exists(gzcompress) && EWIKI_WIKIDUMP_DEFAULTTYPE=="ZIP") || EWIKI_WIKIDUMP_DEFAULTTYPE=="TAR"){ - $ewiki_plugins["page"]["WikiDump"] = "ewiki_page_wiki_dump_tarball"; - $ewiki_plugins["action"]['wikidump'] = "ewiki_page_wiki_dump_tarball"; -} - -$ewiki_t["c"]["EWIKIDUMPCSS"] = ' - - '; - - -function ewiki_page_wiki_dump_tarball($id=0, $data=0, $action=0) { - - #-- return legacy page - if (empty($_REQUEST["download_tarball"])) { - if($action=="wikidump"){ - $url = ewiki_script("", "WikiDump"); - return(ewiki_make_title($id, $id, 2) . ewiki_t(<<
        -
        - - - -

        - _{with images}
        - -
        -Archive Format: - - -
        -END - )); - } else { - return ""; - } - } - #-- tarball generation - else { - $di = $_REQUEST["dump_images"]; - $fh = $_REQUEST["dump_fullhtml"]; - $vp = $_REQUEST["dump_virtual"]; - $rp = $_REQUEST["dump_id"]; - - #-- $_REQUEST["dump_depth"]==100 will give a complete dump - if(($_REQUEST["dump_depth"]>EWIKI_WIKIDUMP_MAXLEVEL) && ($_REQUEST["dump_depth"]!=100)){ - $dd=EWIKI_WIKIDUMP_MAXLEVEL; - } else { - $dd = $_REQUEST["dump_depth"]; - } - $at = $_REQUEST["dump_arctype"]; - $al = 9;#$_REQUEST["dump_arclevel"]; - $_REQUEST = $_GET = $_POST = array(); - if(!ewiki_auth($rp, $str_null, "view")){ - return ewiki_make_title($id, $id, 2)."

        You either do not have permission to access the page $rp or it does not exist.

        "; - } - ewiki_page_wiki_dump_send($di, $fh, $vp, $rp, $dd, $at, $al); - } -} - - -function ewiki_page_wiki_dump_send($imgs=1, $fullhtml=0, $virtual=0, $rootid, $depth=1, $arctype=EWIKI_WIKIDUMP_DEFAULTTYPE, $complevel=1) { - - global $ewiki_config, $ewiki_plugins; - - #-- disable protected email - foreach($ewiki_plugins["link_url"] as $key => $linkplugin){ - if($linkplugin == "ewiki_email_protect_link"){ - unset($ewiki_plugins["link_url"][$key]); - } - } - - #-- set uservars - $a_uservars = ewiki_get_uservar("WikiDump", array()); - if(!is_array($a_uservars)){ - $a_uservars = unserialize($a_uservars); - } - $a_uservars[$rootid] = $depth; - ewiki_set_uservar("WikiDump", $a_uservars); - - #-- if $fullhtml - $HTML_TEMPLATE = ' - '.ewiki_t("EWIKIDUMPCSS").' - $title - - -
        -

        $title

        - $content -
        - - - '; - - #-- reconfigure ewiki_format() to generate offline pages and files - $html_ext = ".htm"; - if ($fullhtml) { - $html_ext = ".html"; - } - $ewiki_config["script"] = "%s$html_ext"; - $ewiki_config["script_binary"] = "%s"; - - #-- fetch also dynamic pages - $a_virtual = array_keys($ewiki_plugins["page"]); - - - #-- get all pages / binary files - $a_validpages = ewiki_valid_pages(1, $virtual); - $a_pagelist = ewiki_sitemap_create($rootid, $a_validpages, $depth, 1); - - foreach($a_pagelist as $key => $value){ - if(is_array($a_validpages[$value]["refs"])){ - foreach($a_validpages[$value]["refs"] as $refs){ - if($a_validpages[$refs]["type"]=="image"){ - $a_pagelist[]=$refs; - } - } - } - } - - foreach($a_pagelist as $key => $value){ - if($a_validpages[$value]["type"]=="image"){ - $a_images[]=urlencode($value); - $a_rimages[]=urlencode(preg_replace(EWIKI_DUMP_FILENAME_REGEX, "", $value)); - unset($a_validpages[$value]); - } - } - - $a_sitemap = ewiki_sitemap_create($rootid, $a_validpages, $depth, 0); - - if ($a_pagelist) { - #-- create new zip file - if($arctype == "ZIP"){ - $archivename=EWIKI_WIKIDUMP_ARCNAME."$rootid.zip"; - $archive = new ewiki_virtual_zip(); - } elseif ($arctype == "TAR") { - $archivename=EWIKI_WIKIDUMP_ARCNAME."$rootid.tar"; - $archive = new ewiki_virtual_tarball(); - } else { - die(); - } - - $a_pagelist = array_unique($a_pagelist); - - #-- convert all pages - foreach($a_pagelist as $pagename){ - if ((!in_array($pagename, $a_virtual))) { - $id = $pagename; - #-- not a virtual page - $row = ewiki_db::GET($pagename); - $content = ""; - } elseif($virtual) { - $id = $pagename; - #-- is a virtual page - $pf = $ewiki_plugins["page"][$id]; - $content = $pf($id, $content, "view"); - if ($fullhtml) { - $content = str_replace('$content', $content, str_replace('$title', $id, $HTML_TEMPLATE)); - } - $fn = urlencode($id); - $fn = preg_replace(EWIKI_DUMP_FILENAME_REGEX, "", $fn); - $fn = $fn.$html_ext; - } else { - continue; - } - - if (empty($content)){ - switch ($row["flags"] & EWIKI_DB_F_TYPE) { - case (EWIKI_DB_F_TEXT): - $content = ewiki_format($row["content"]); - $content = str_replace($a_images, $a_rimages, $content); - $fn = preg_replace(EWIKI_DUMP_FILENAME_REGEX, "", urlencode($id)); - $fn = $fn.$html_ext; - if ($fullhtml) { - $content = str_replace('$content', $content, str_replace('$title', $id, $HTML_TEMPLATE)); - } - break; - - case (EWIKI_DB_F_BINARY): - if (($row["meta"]["class"]=="image") && ($imgs)) { - $fn = urlencode(preg_replace(EWIKI_DUMP_FILENAME_REGEX, "", $id)); - $content = &$row["content"]; - } - else { - #-- php considers switch statements as loops so continue 2 is needed to - #-- hit the end of the for loop - continue(2); - } - break; - - default: - # don't want it - continue(2); - } - } - - $content=preg_replace_callback( - '/()/', - create_function( - // single quotes are essential here, - // or alternative escape all $ as \$ - '$matches', - 'return($matches[1].preg_replace(EWIKI_DUMP_FILENAME_REGEX,"",$matches[2]).$matches[3]);' - ), - $content - ); - - #-- add file - $archive->add($content, $fn, array( - "mtime" => $row["lastmodified"], - "uname" => "ewiki", - "mode" => 0664 | (($row["flags"]&EWIKI_DB_F_WRITEABLE)?0002:0000), - ), $complevel); - } - - #-- create index page - $timer=array(); - $level=-1; - $fordump=1; - $str_formatted="
          \n
        • ".$rootid."
        • "; - $fin_level=format_sitemap($a_sitemap, $rootid, $str_formatted, $level, $timer, $fordump); - $str_formatted.="
        ".str_pad("", $fin_level*6, "
      \n"); - $str_formatted=preg_replace_callback( - '/()/', - create_function( - // single quotes are essential here, - // or alternative escape all $ as \$ - '$matches', - 'return($matches[1].preg_replace(EWIKI_DUMP_FILENAME_REGEX,"",$matches[2]).$matches[3]);' - ), - $str_formatted - ); - - #-- add index page - $archive->add($str_formatted, "Index_$rootid".$html_ext, array( - "mtime" => $row["lastmodified"], - "uname" => "ewiki", - "mode" => 0664 | (($row["flags"]&EWIKI_DB_F_WRITEABLE)?0002:0000), - ), $complevel); - - #-- Headers - Header("Content-type: application/octet-stream"); - Header("Content-disposition: attachment; filename=\"$archivename\""); - Header("Cache-control: private"); - Header("Original-Filename: $archivename"); - Header("X-Content-Type: application/octet-stream"); - Header("Content-Location: $archivename"); - - - #-- end output - echo $archive->close(); - - } - - #-- fin - die(); -} - - - - -############################################################################ - - - - -#-- allows to generate a tarball from virtual files -# (supports no directories or symlinks and other stuff) -class ewiki_virtual_tarball { - - var $f = 0; - var $datasec = array(); - - function close() { - #-- fill up file - $this->write(str_repeat("\000", 9*1024)); - $data = implode("", $this -> datasec); - return $data; - } - - - function write($str) { - $this ->datasec[] = $str; - } - - - function oct($int, $len) { - $o = "\000"; - while (--$len) { - $o = ($int & 0x07) . $o; - $int = $int >> 3; - } - return($o); - } - - - #-- add virtual file - function add($content, $filename, $args=array(), $ignored) { - $args = array_merge($args, array( - "mode" => 000664, - "mtime" => time(), - "ctime" => time(), - "uid" => 65534, #-- common for user "nobody" - "gid" => 65534, - "uname" => "nobody", - "gname" => "nobody", - "type" => "0", - )); - $args["mode"] |= 0100000; - $args["size"] = strlen($content); - $checksum = " "; - $magic = "ustar \000"; - $filename = substr($filename, 0, 99); - - #-- header record - $header = str_pad($filename, 100, "\000") # 0x0000 - . $this->oct($args["mode"], 8) # 0x0064 - . $this->oct($args["uid"], 8) # 0x006C - . $this->oct($args["gid"], 8) # 0x0074 - . $this->oct($args["size"], 12) # 0x007C - . $this->oct($args["mtime"], 12) # 0x0088 - . ($checksum) # 0x0094 - . ($args["type"]) # 0x009C - . str_repeat("\000", 100) # 0x009D - . ($magic) # 0x0101 - . str_pad($args["uname"], 32, "\000") # 0x0109 - . str_pad($args["gname"], 32, "\000") # 0x0129 - ; # 0x0149 - $header = str_pad($header, 512, "\000"); - - #-- calculate and add header checksum - $cksum = 0; - for ($n=0; $n<512; $n++) { - $cksum += ord($header[$n]); - } - $header = substr($header, 0, 0x0094) - . $this->oct($cksum, 7) . " " - . substr($header, 0x009C); - - #-- output - if ($fill = (512 - (strlen($content) % 512))) { - $content .= str_repeat("\000", $fill); - } - $this->write($header . $content); - } -} - - -class ewiki_virtual_zip -{ - var $datasec = array(); - var $ctrl_dir = array(); - var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00"; - var $old_offset = 0; - - function add($data, $name, $ignored, $complevel) { - $name = str_replace("\\", "/", $name); - $unc_len = strlen($data); - $crc = crc32($data); - $zdata = gzcompress($data, $complevel); - $zdata = substr ($zdata, 2, -4); - $c_len = strlen($zdata); - $fr = "\x50\x4b\x03\x04"; - $fr .= "\x14\x00"; - $fr .= "\x00\x00"; - $fr .= "\x08\x00"; - $fr .= "\x00\x00\x00\x00"; - $fr .= pack("V",$crc); - $fr .= pack("V",$c_len); - $fr .= pack("V",$unc_len); - $fr .= pack("v", strlen($name) ); - $fr .= pack("v", 0 ); - $fr .= $name; - $fr .= $zdata; - $fr .= pack("V",$crc); - $fr .= pack("V",$c_len); - $fr .= pack("V",$unc_len); - - $this -> datasec[] = $fr; - $new_offset = strlen(implode("", $this->datasec)); - - $cdrec = "\x50\x4b\x01\x02"; - $cdrec .="\x00\x00"; - $cdrec .="\x14\x00"; - $cdrec .="\x00\x00"; - $cdrec .="\x08\x00"; - $cdrec .="\x00\x00\x00\x00"; - $cdrec .= pack("V",$crc); - $cdrec .= pack("V",$c_len); - $cdrec .= pack("V",$unc_len); - $cdrec .= pack("v", strlen($name) ); - $cdrec .= pack("v", 0 ); - $cdrec .= pack("v", 0 ); - $cdrec .= pack("v", 0 ); - $cdrec .= pack("v", 0 ); - $cdrec .= pack("V", 32 ); - $cdrec .= pack("V", $this -> old_offset ); - - $this -> old_offset = $new_offset; - - $cdrec .= $name; - $this -> ctrl_dir[] = $cdrec; - } - - function close() { - $data = implode("", $this -> datasec); - $ctrldir = implode("", $this -> ctrl_dir); - - return - $data . - $ctrldir . - $this -> eof_ctrl_dir . - pack("v", sizeof($this -> ctrl_dir)) . - pack("v", sizeof($this -> ctrl_dir)) . - pack("V", strlen($ctrldir)) . - pack("V", strlen($data)) . - "\x00\x00"; - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/wikinews.meta b/mods/wiki/plugins/page/wikinews.meta deleted file mode 100644 index a74c79cb0..000000000 --- a/mods/wiki/plugins/page/wikinews.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -title: WikiNews -description: summarizes newly created pages -priority: extra -hooks: page -type: page diff --git a/mods/wiki/plugins/page/wikinews.php b/mods/wiki/plugins/page/wikinews.php deleted file mode 100644 index 2ccda59ce..000000000 --- a/mods/wiki/plugins/page/wikinews.php +++ /dev/null @@ -1,110 +0,0 @@ -get()) { - - if (EWIKI_DB_F_TEXT == ($row["flags"] & EWIKI_DB_F_TYPE)) { - - if ($c_regex && !preg_match($c_regex, $row["id"])) { - continue; - } - - $sorted[$row["id"]] = $row["lastmodified"]; - } - } - - #-- sort - arsort($sorted); - - $displayed = 0;//$displayed will count pages successfully displayed - - #-- gen output - $o = ""; - foreach ($sorted as $id=>$uu) { - - $row = ewiki_db::GET($id); - - #-- require auth - if (EWIKI_PROTECTED_MODE && !ewiki_auth($id, $row, "view", $ring=false, $force=0)) { - if (EWIKI_PROTECTED_MODE_HIDING) { - continue; - } else { - $row["content"] = ewiki_t("FORBIDDEN"); - } - } - - $text = "\n".substr($row["content"], 0, $n_len); - $text = str_replace("[internal://", "[ internal://", $text); - $text .= " [...[read more | $id]]\n"; - - #-- title mangling (from ewiki.php) - $title=$id; - if ($ewiki_config["split_title"] && $may_split) { - $title = ewiki_split_title($title, $ewiki_config["split_title"], 0&($title!=$ewiki_title)); //Why 0&? - } - else { - $title = htmlentities($title); - } - if ($pf_a = @$ewiki_plugins["title_transform"]) { - foreach ($pf_a as $pf) { $pf($id, $title, $go_action); } - } - - if($ewiki_config["wm_publishing_headers"]){ - $text = preg_replace("/^!([^!])/m","!! \$1",$text); - $o .= "\n" . - "! [\"$title\"$id]"; - }else{ - $text = preg_replace("/^!!!/m","!!",$text); - $o .= "\n" . - "!!! [\"$title\"$id]"; - } - $o .=" µµ". strftime(ewiki_t("LASTCHANGED"), $row["lastmodified"])."µµ\n"; - $o .= " $text\n"; - $o .= "----\n"; - - if (!($n_num--)) { - break; - } - } - - - #-- render requested wiki page <-- goal !!! - $render_args = array( - "scan_links" => 1, - "html" => (EWIKI_ALLOW_HTML||(@$data["flags"]&EWIKI_DB_F_HTML)), - ); - $o = $ewiki_plugins["render"][0] ($o, $render_args); - - return($o); -} - -?> diff --git a/mods/wiki/plugins/page/wikiuserlogin.meta b/mods/wiki/plugins/page/wikiuserlogin.meta deleted file mode 100644 index ef78253a0..000000000 --- a/mods/wiki/plugins/page/wikiuserlogin.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -title: WikiUserLogin -description: allows to set an unverified username -priority: bonus -hooks: page -type: page diff --git a/mods/wiki/plugins/page/wikiuserlogin.php b/mods/wiki/plugins/page/wikiuserlogin.php deleted file mode 100644 index 08ec8b281..000000000 --- a/mods/wiki/plugins/page/wikiuserlogin.php +++ /dev/null @@ -1,51 +0,0 @@ -$id\n"; - - if (empty($_GET["wikiauthor"])) { - $o .= ' -
      - your WikiName -

      - - -

      - make cookie persistent forever -
      - '; - } - else { - $o .= ' - Your author name is now set to "'.$_GET["wikiauthor"].'". Please go ahead and - start editing pages. - '; - if ($_REQUEST["forever"]) { - setcookie("wikiauthor", $_GET["wikiauthor"]); - } - else { - setcookie("wikiauthor", $_GET["wikiauthor"], time()*1.2); - } - } - - return($o); - } - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/page/wordindex.meta b/mods/wiki/plugins/page/wordindex.meta deleted file mode 100644 index 00f844fd2..000000000 --- a/mods/wiki/plugins/page/wordindex.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: page -title: WordIndex -description: prints words used in page names -hooks: page -type: page -config: - EWIKI_PAGE_WORDINDEX="WordIndex" -priority: recommended diff --git a/mods/wiki/plugins/page/wordindex.php b/mods/wiki/plugins/page/wordindex.php deleted file mode 100644 index f8ebf8cc7..000000000 --- a/mods/wiki/plugins/page/wordindex.php +++ /dev/null @@ -1,62 +0,0 @@ -get()) { - if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $uu, "view")) { - continue; - } - if (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) { - $src .= " " . $row["id"]; - } - } - - $src = ewiki_split_title($src, "SPLIT", 0); - $chars = strtr(EWIKI_CHARS_U.EWIKI_CHARS_L, "_", " "); - $src = preg_replace("/[^$chars]/", " ", $src); - $src = explode(" ", $src); - $src = array_unique($src); //@ADD: word counting - unset($src[""]); - - natcasesort($src); - - $sorted = array(); - foreach ($src as $i => $word) { - - if (strlen($word) >= 2) { - - $sorted[] = array( - EWIKI_PAGE_POWERSEARCH, - array("where"=>"id", "q"=>$word), - $word, "" //@ADD: display word count - ); - - } - } - unset($src); - - $pf_list_pages = $ewiki_plugins["list_dict"][0]; - $o .= ewiki_list_pages($sorted, $limit=0, $vat=1, $pf_list_pages); - - return($o); - -} - - - ?> \ No newline at end of file diff --git a/mods/wiki/plugins/passwd_expire.php b/mods/wiki/plugins/passwd_expire.php deleted file mode 100644 index 7f970bcb8..000000000 --- a/mods/wiki/plugins/passwd_expire.php +++ /dev/null @@ -1,13 +0,0 @@ -isLoggedIn()){ - return ewiki_make_title($id, "Change Password:")."

      You password has expired

      ".ewiki_t("CHPW_FORM"); - } - return 0; -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/patchsaving.meta b/mods/wiki/plugins/patchsaving.meta deleted file mode 100644 index cdbb4d47e..000000000 --- a/mods/wiki/plugins/patchsaving.meta +++ /dev/null @@ -1,8 +0,0 @@ -hooks: edit_patch -type: edit_patch -funcs: ewiki_edit_patch -api: ewiki -title: PatchSaving -description: tries to merge concurrent edits with the 'patch' system utility -priority: recommended -category: feature diff --git a/mods/wiki/plugins/patchsaving.php b/mods/wiki/plugins/patchsaving.php deleted file mode 100644 index 4b690a514..000000000 --- a/mods/wiki/plugins/patchsaving.php +++ /dev/null @@ -1,88 +0,0 @@ -$id, "version"=>$_REQUEST["version"]) - ); - if (!$base) { - return(false); - } - - $fn_base = EWIKI_TMP."/ewiki.base.".md5($base["content"]); - $fn_requ = EWIKI_TMP."/ewiki..requ.".md5($_REQUEST["content"]); - $fn_patch = EWIKI_TMP."/ewiki.patch.".md5($base["content"])."-".md5($_REQUEST["content"]); - $fn_curr = EWIKI_TMP."/ewiki.curr.".md5($data["content"]); - - if ($f = fopen($fn_base, "w")) { - fwrite($f, $base["content"]); - fclose($f); - } - else { - return(false); - } - - if ($f = fopen($fn_requ, "w")) { - fwrite($f, $_REQUEST["content"]); - fclose($f); - } - else { - unlink($fn_base); - return(false); - } - - if ($f = fopen($fn_curr, "w")) { - fwrite($f, $data["content"]); - fclose($f); - } - else { - unlink($fn_base); - unlink($fn_requ); - return(false); - } - - exec("diff -c $fn_base $fn_requ > $fn_patch", $output, $retval); - if ($retval) { - - exec("patch $fn_curr $fn_patch", $output, $retval); - if (!$retval) { - - $_REQUEST["version"] = $curr["version"]; - $_REQUEST["content"] = implode("", file($fn_curr)); - $r = true; - - } - } - - unlink($fn_base); - unlink($fn_requ); - unlink($fn_patch); - unlink($fn_curr); - - ewiki_log("patchsaving of {$id}[{$data[version]}] was ".($r?"":"un")."successful", 2); - - return($r); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/pluginloader.meta b/mods/wiki/plugins/pluginloader.meta deleted file mode 100644 index fbbb42ecd..000000000 --- a/mods/wiki/plugins/pluginloader.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -type: page -hooks: dl, dl, view_init, page, dl -funcs: ewiki_dynamic_plugin_loader -title: PluginLoader-1 -description: loads action and page plugins dynamically using pre-compiled list -priority: rare -category: feature diff --git a/mods/wiki/plugins/pluginloader.php b/mods/wiki/plugins/pluginloader.php deleted file mode 100644 index 962dbdfc3..000000000 --- a/mods/wiki/plugins/pluginloader.php +++ /dev/null @@ -1,168 +0,0 @@ - array("", "", 0), - "links" => array("", "", 0), - "info" => array("", "", 0), -# "edit" => array("spellcheck.php", "", 0), - "raw" => array("action/raw.php", "ewiki_action_raw", 0), - "diff" => array("action/diff.php", "ewiki_page_stupid_diff", 0), -# "diff" => array("action/diff_gnu.php", "ewiki_page_gnu_diff", 0), - "like" => array("action/like_pages.php", "ewiki_page_like", 0), -# "verdiff" => array("action/verdiff.php", "ewiki_action_verdiff", 0), -# "extodo" => array("action/extract.php", "ewiki_extract", 0), -# "control" => array("admin/control.php", "ewiki_action_control_page", 0), -# "imageappend" => array("aview/imgappend.php", "ewiki_action_image_append", 0), -# "addpost" => array("aview/posts.php", "ewiki_add_post", 0), -# "addthread" => array("aview/threads.php", "ewiki_add_thread", 0), -# "updformatheader" => array("markup/update_format.php", "ewiki_header_format_swap", 0), -# "calendar" => array("module/calendar.php", "ewiki_page_calendar", 0), -# "binary" => array("module/downloads.php", "ewiki_binary", 0), -# "attachments" => array("module/downloads.php", "ewiki_action_attachments", 0), -# "tour" => array("module/tour.php", "ewiki_tour", 0), - "search" => array("page/powersearch.php", "ewiki_action_powersearch", 0), -); - -$ewiki_plugins["dl"]["page"] = array( -# "SearchAndReplace" => array("admin/page_searchandreplace.php", "ewiki_page_searchandreplace", 0), -# "SearchCache" => array("admin/page_searchcache.php", "ewiki_cache_generated_pages", 0), -# "ImageGallery" => array("aview/aedit_pageimage.php", "ewiki_page_image_gallery", 0), -# "MainGallery" => array("aview/aedit_pageimage.php", "ewiki_page_image_gallery", 0), - "LinkDatabase" => array("linking/linkdatabase.php", "ewiki_linkdatabase", 0), -# "PageCalendar" => array("module/calendar.php", "ewiki_page_calendar", 0), -# "PageYearCalendar" => array("module/calendar.php", "ewiki_page_year_calendar", 0), -# "FileUpload" => array("module/downloads.php", "ewiki_page_fileupload", 0), -# "FileDownload" => array("module/downloads.php", "ewiki_page_filedownload", 0), - "README" => array("page/README.php", "ewiki_page_README", 0), -# "README.de" => array("page/README.php", "ewiki_page_README", 0), -# "plugins/auth/README.auth" => array("page/README.php", "ewiki_page_README", 0), -# "AboutPlugins" => array("page/aboutplugins.php", "ewiki_page_aboutplugins", 0), -# "EWikiLog" => array("page/ewikilog.php", "ewiki_page_ewikilog", 0), -# "Fortune" => array("page/fortune.php", "ewiki_page_fortune", 0), - "HitCounter" => array("page/hitcounter.php", "ewiki_page_hitcounter", 0), - "InterWikiMap" => array("page/interwikimap.php", "ewiki_page_interwikimap", 0), - "OrphanedPages" => array("page/orphanedpages.php", "ewiki_page_orphanedpages", 0), -# "PageIndex" => array("page/pageindex.php", "ewiki_page_index", 0), -# "PhpInfo" => array("page/phpinfo.php", "ewiki_page_phpinfo", 0), - "PowerSearch" => array("page/powersearch.php", "ewiki_page_powersearch", 0), - "RandomPage" => array("page/randompage.php", "ewiki_page_random", 0), -# "ScanDisk" => array("page/scandisk.php", "ewiki_page_scandisk", 0), -# "SinceUpdatedPages" => array("page/since_updates.php", "ewiki_page_since_updates", 0), -# "TextUpload" => array("page/textupload.php", "ewiki_page_textupload", 0), - "WantedPages" => array("page/wantedpages.php", "ewiki_page_wantedpages", 0), -# "WikiDump" => array("page/wikidump.php", "ewiki_page_wiki_dump_tarball", 0), -# "WikiNews" => array("page/wikinews.php", "ewiki_page_wikinews", 0), -# "WikiUserLogin" => array("page/wikiuserlogin.php", "ewiki_page_wikiuserlogin", 0), - "WordIndex" => array("page/wordindex.php", "ewiki_page_wordindex", 0), -# "AddNewPage" => array("page/addnewpage.php", "ewiki_addpage", 0), -# "CreatePage" => array("page/addnewpage.php", "ewiki_addpage", 0), -# "EineSeiteHinzufügen" => array("page/addnewpage.php", "ewiki_addpage", 0), -# "CreateNewPage" => array("page/createnewpage.php", "ewiki_createpage", 0), - "RecentChanges" => array("page/recentchanges.php", "ewiki_page_recentchanges", 0), -# "ExAllTodo" => array("page/extractall.php", "ewiki_page_exall", 0), -); - -global $ewiki_config; -$ewiki_config["dl"]["action_links"]["view"]["raw"] = "raw"; -$ewiki_config["dl"]["action_links"]["view"]["verdiff"] = "verdiff"; -$ewiki_config["dl"]["action_links"]["view"]["extodo"] = "EXTTODO"; -$ewiki_config["dl"]["action_links"]["view"]["control"] = "page control"; -$ewiki_config["dl"]["action_links"]["view"]["addpost"] = "Add a post"; -$ewiki_config["dl"]["action_links"]["view"]["updformatheader"] = "UPDHEADERFORMAT"; -$ewiki_config["dl"]["action_links"]["view"]["calendar"] = "PageCalendar"; -$ewiki_config["dl"]["action_links"]["view"]["attachments"] = "Attachments"; -$ewiki_config["dl"]["action_links"]["view"]["tour"] = "PageTour"; -$ewiki_config["dl"]["action_links"]["view"]["pdf"] = "pdf"; -$ewiki_config["dl"]["action_links"]["info"]["raw"] = "raw"; -$ewiki_config["dl"]["action_links"]["info"]["diff"] = "diff"; -$ewiki_config["dl"]["action_links"]["extodo"]["raw"] = "raw"; -$ewiki_config["dl"]["action_links"]["extodo"]["verdiff"] = "verdiff"; -$ewiki_config["dl"]["action_links"]["extodo"]["view"] = "VIEWCOMPL"; -$ewiki_config["dl"]["action_links"]["tour"]["view"] = "ViewFullPage"; -$ewiki_config["dl"]["action_links"]["tour"]["links"] = "BACKLINKS"; -$ewiki_config["dl"]["action_links"]["tour"]["info"] = "PAGEHISTORY"; - - - - - -############################################################################## - - - -#-- plugin glue -$ewiki_plugins["view_init"][] = "ewiki_dynamic_plugin_loader"; - - -function ewiki_dynamic_plugin_loader(&$id, &$data, &$action) { - - global $ewiki_plugins, $ewiki_id, $ewiki_title, $ewiki_t, - $ewiki_ring, $ewiki_author, $ewiki_config, $ewiki_auth_user, - $ewiki_action; - - #-- check for entry - if (empty($ewiki_plugins["page"][$id])) { - $load = $ewiki_plugins["dl"]["page"][$id]; - } - elseif (empty($ewiki_plugins["action"][$action])) { - $load = $ewiki_plugins["dl"]["action"][$action]; - } - - #-- load plugin - if ($load) { - if (!is_array($load)) { - $load = array($load, ""); - } - if (!($pf=$load[1]) || !function_exists($pf)) { - include_once(dirname(__FILE__)."/".$load[0]); - } - } - - #-- fake static pages - foreach ($ewiki_plugins["dl"]["page"] as $name) { - if (empty($ewiki_plugins["page"][$name])) { - $ewiki_plugins["page"][$name] = "ewiki_dynamic_plugin_loader"; - } - } - - #-- show action links - foreach ($ewiki_plugins["dl"]["action"] as $action=>$uu) { - foreach ($ewiki_config["dl"]["action_links"] as $where) { - if ($title = $ewiki_config["dl"]["action_links"][$where][$action]) { - $ewiki_config["action_links"][$where][$action] = $title; - } - } - } - - return(NULL); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/spages.meta b/mods/wiki/plugins/spages.meta deleted file mode 100644 index 034178a46..000000000 --- a/mods/wiki/plugins/spages.meta +++ /dev/null @@ -1,11 +0,0 @@ -api: ewiki -type: intercept -hooks: page -funcs: ewiki_spage, ewiki_init_spages -category: feature -priority: standard -title: StaticPages -description: provides virtual pages from static files or dynamic scripts -config: - EWIKI_SPAGES_DIR="./spages/" // directory with files or plugins - EWIKI_SPAGES_BIN=0|1 // allow serving static files as binary entries diff --git a/mods/wiki/plugins/spages.php b/mods/wiki/plugins/spages.php deleted file mode 100644 index 2fb21622a..000000000 --- a/mods/wiki/plugins/spages.php +++ /dev/null @@ -1,175 +0,0 @@ - and parts (if any) - if ($clean_html) { - $r = preg_replace('#^.+]*>(.+).+$#is', '$1', $r); - } - - #-- return body (means successfully handled) - return($r); -} - - - -#-- init -function ewiki_init_spages($dirs, $idprep="") { - - global $ewiki_spages, $ewiki_plugins; - - if (!is_array($dirs)) { - $dirs = array($dirs); - } - - #-- go through list of directories - foreach ($dirs as $dir) { - - if (empty($dir)) { - continue; - } - - #-- read in one directory - $dh = opendir($dir); - while ($fn = readdir($dh)) { - - #-- skip over . and .. - if ($fn[0] == ".") { continue; } - - #-- be recursive - if ($fn && is_dir("$dir/$fn")) { - if ($fn != trim($fn, ".")) { - $fnadd = trim($fn, ".") . "."; - } - else { - $fnadd = "$fn/"; - } - - ewiki_init_spages(array("$dir/$fn"), "$idprep$fnadd"); - - continue; - } - - #-- strip filename extensions - $id = str_replace( - array(".html", ".htm", ".php", ".txt", ".wiki", ".src"), - "", - basename($fn) - ); - - #-- register spage file and as page plugin (one for every spage) - $ewiki_spages[strtolower("$idprep$id")] = "$dir/$fn"; - $ewiki_plugins["page"]["$idprep$id"] = "ewiki_spage"; - - } - closedir($dh); - } - -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/spam/antibot_captcha.meta b/mods/wiki/plugins/spam/antibot_captcha.meta deleted file mode 100644 index 8a1c06979..000000000 --- a/mods/wiki/plugins/spam/antibot_captcha.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: spam -hooks: edit_form_append, edit_hook -type: intercept -title: CAPTCHA -description: graphical riddle that prevents automated page corruption from spambots -priority: rare diff --git a/mods/wiki/plugins/spam/antibot_captcha.php b/mods/wiki/plugins/spam/antibot_captcha.php deleted file mode 100644 index c96de7c2a..000000000 --- a/mods/wiki/plugins/spam/antibot_captcha.php +++ /dev/null @@ -1,39 +0,0 @@ - -$ewiki_plugins["edit_form_append"][] = "ewiki_aedit_antibot_checkbox"; -function ewiki_aedit_antibot_checkbox($id, &$data, $action) { - if (!$GLOBALS["ewiki_no_bot"]) { - include_once("plugins/lib/captcha.php"); - return captcha::form(); - } -} - -#-- reject if not checked -$ewiki_plugins["edit_save"][] = "ewiki_edit_save_antibot_checkbox"; -function ewiki_edit_save_antibot_checkbox(&$save, &$data) { - global $ewiki_errmsg; - - if (!$GLOBALS["ewiki_no_bot"]) { - include_once("plugins/lib/captcha.php"); - if (!captcha::check()) { - $save = NULL; - $ewiki_errmsg = "Access Forbidden. You did not successfully pass the captcha."; - } - else { - $GLOBALS["ewiki_no_bot"] = 1; - } - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/spam/antibot_checkbox.meta b/mods/wiki/plugins/spam/antibot_checkbox.meta deleted file mode 100644 index 8a69db2ca..000000000 --- a/mods/wiki/plugins/spam/antibot_checkbox.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -category: spam -hooks: edit_form_append, edit_hook -type: intercept -title: antibot-CheckBox -description: most simple blog/comment spam attacks can already be prevented with this simple checkbox -depends: captcha -priority: rare diff --git a/mods/wiki/plugins/spam/antibot_checkbox.php b/mods/wiki/plugins/spam/antibot_checkbox.php deleted file mode 100644 index efaf1be09..000000000 --- a/mods/wiki/plugins/spam/antibot_checkbox.php +++ /dev/null @@ -1,34 +0,0 @@ - -$ewiki_plugins["edit_form_append"][] = "ewiki_aedit_antibot_checkbox"; -function ewiki_aedit_antibot_checkbox($id, &$data, $action) { - if (!isset($GLOBALS["ewiki_no_bot"])) { - return(ewiki_t('
      ')); - } -} - -#-- reject if not checked -$ewiki_plugins["edit_save"][] = "ewiki_edit_save_antibot_checkbox"; -function ewiki_edit_save_antibot_checkbox(&$save, &$data) { - global $ewiki_errmsg; - - if ((!$_REQUEST["antibot_check"]) && !isset($GLOBALS["ewiki_no_bot"])) { - $save = NULL; - $ewiki_errmsg = ewiki_t("ANTIBOT_FAILED"); - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/spam/antibot_delay.meta b/mods/wiki/plugins/spam/antibot_delay.meta deleted file mode 100644 index e02c63e44..000000000 --- a/mods/wiki/plugins/spam/antibot_delay.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: spam -hooks: edit_form_append, edit_save -type: intercept -title: antibot-DelaySave -description: hinders autonomous script attacks by enforcing a save delay -priority: rare diff --git a/mods/wiki/plugins/spam/antibot_delay.php b/mods/wiki/plugins/spam/antibot_delay.php deleted file mode 100644 index 1afa44836..000000000 --- a/mods/wiki/plugins/spam/antibot_delay.php +++ /dev/null @@ -1,41 +0,0 @@ -. -*/ - - -#-- config -define("EWIKI_UP_SAVE_DELAY", "e_g_t"); -define("EWIKI_EDIT_SAVE_DELAY", 5); - - -#-- embed timestamp -$ewiki_plugins["edit_form_append"][] = "ewiki_aedit_antibot_delay"; -function ewiki_aedit_antibot_delay($id, &$data, $action) { - return(''); -} - - -#-- check timespan -$ewiki_plugins["edit_save"][] = "ewiki_edit_save_antibot_delay"; -function ewiki_edit_save_antibot_delay(&$save, &$data) { - global $ewiki_errmsg; - - if (!isset($GLOBALS["ewiki_no_bot"])) { - if (time() < $_REQUEST[EWIKI_UP_SAVE_DELAY] + EWIKI_EDIT_SAVE_DELAY) { - $save = NULL; - $ewiki_errmsg = ewiki_t("Too hasty saving rejected. Please go back, wait 3 seconds and hit [save] again."); - } - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/spam/cookieusers.meta b/mods/wiki/plugins/spam/cookieusers.meta deleted file mode 100644 index 0f1b932fe..000000000 --- a/mods/wiki/plugins/spam/cookieusers.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: spam -hooks: init -type: intercept -title: CookieUsers -description: disables AntiSpam-plugins for probably real users -priority: rare diff --git a/mods/wiki/plugins/spam/cookieusers.php b/mods/wiki/plugins/spam/cookieusers.php deleted file mode 100644 index 0f54a7381..000000000 --- a/mods/wiki/plugins/spam/cookieusers.php +++ /dev/null @@ -1,33 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/spam/limitlinks.ln b/mods/wiki/plugins/spam/limitlinks.ln deleted file mode 100644 index 427832ea5..000000000 --- a/mods/wiki/plugins/spam/limitlinks.ln +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/spam/watchonly.meta b/mods/wiki/plugins/spam/watchonly.meta deleted file mode 100644 index 0248119c3..000000000 --- a/mods/wiki/plugins/spam/watchonly.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: spam -hooks: handler -type: intercept -title: watchonly -description: disables spam plugins, but for a few specified pages (limited set of targets) -priority: rare diff --git a/mods/wiki/plugins/spam/watchonly.php b/mods/wiki/plugins/spam/watchonly.php deleted file mode 100644 index 64ce918ed..000000000 --- a/mods/wiki/plugins/spam/watchonly.php +++ /dev/null @@ -1,35 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/sql/arrowadmin.meta b/mods/wiki/plugins/sql/arrowadmin.meta deleted file mode 100644 index bd090b902..000000000 --- a/mods/wiki/plugins/sql/arrowadmin.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -type: include -categroy: custom -title: ArrowAdmin -description: can delete pages, and rename pages, with the option of replacing the renamed page with a reference to the new one -author: Menno Lodder -homepage: http://www.arrowproject.net/ -priority: never -note: requires modification prior use -category: fragments diff --git a/mods/wiki/plugins/sql/arrowadmin.php b/mods/wiki/plugins/sql/arrowadmin.php deleted file mode 100644 index cb4d97e1c..000000000 --- a/mods/wiki/plugins/sql/arrowadmin.php +++ /dev/null @@ -1,232 +0,0 @@ - -require_once('header.php'); - -//ARROW if statement checks if the persion has permission -if(!has_perm("WIKI_ADMIN")) -{ - echo("No permission"); - include('footer.php'); - exit(); -} -//************************************** -//ARROW to use this outside of arrow, comment out the above and the footer.php include at the bottom -// then uncomment the following 2 methods, and set the settings variables. -//************************************** - -$wikitable = "wiki"; //the table name of the table containing the wiki info (ewiki by default) -$wikiurl = "../wiki.php"; //the relative URL of the wiki pages to the admin page, this is used to allow linking to the wiki pages - -/* -These functions are untested - -//logs a message -function logMsg($type, $message) -{ - //log whatever you want here, or do nothing -} - -//connects to the db -function connect_db() -{ - //set these variables - $db = "dbname"; - $dbhost = "localhost"; - $dbuser = "username"; - $dbpass = "password"; - - $conn = mysql_connect($dbhost,$dbuser,$dbpass) or die("Error - Connection to database is not established !"); - @mysql_select_db($db, $conn) or die("Error - Can't open the database !"); -} -*/ - - -$showdetails = false; -$showindex = false; - -//set the page in advance, so it can be changed by the functions below -$page = false; -if(isset($_REQUEST['page'])) -{ - $page = $_REQUEST['page']; -} - -if(isset($_REQUEST['function'])) -{ - if($_REQUEST['function'] == "details") - { - $showdetails = true; - } - else if(($_REQUEST['function'] == "rename") && isset($_REQUEST['oldname']) && isset($_REQUEST['newname'])) - { - $old = $_REQUEST['oldname']; - $new = $_REQUEST['newname']; - - $shadow = isset($_REQUEST['leaveshadow']); - - $shadowtext = "not making shadow topic"; - if($shadow) - { - $shadowtext = "making shadow topic"; - } - //ARROW makes a database connection to the mysql database (which is from now on the default one) - connect_db(); - //check if the name already exists - $checkresult = mysql_query("SELECT * FROM $wikitable WHERE pagename = '".addslashes($new)."'") or die("Error check if name already exists: ".mysql_error()); - if(!mysql_fetch_assoc($checkresult)) - { - - //get the last version of the old page - $oldresult = mysql_query("SELECT * FROM $wikitable WHERE pagename = '".addslashes($old)."' ORDER BY version DESC LIMIT 1") or die("Error check if name already exists: ".mysql_error()); - - if($oldpage = mysql_fetch_assoc($oldresult)) - { - //old page exists - mysql_query("UPDATE $wikitable SET pagename= '".addslashes($new)."' WHERE pagename= '".addslashes($old)."'") or die("Error renaming the page: ".mysql_error()); - echo("Renamed $old to $new $shadowtext,
      "); - - //ARROW logs a message under the header "wikiadmin" - logMsg("wikiadmin", "Renamed $old to $new $shadowtext"); - - if($shadow) - { - $shadowcontent = "This page was renamed to [$new]"; - //this just takes the last author and meta info, cause thats rather complicated to change - mysql_query("INSERT INTO $wikitable (pagename, version, flags, content, author, created, lastmodified, refs, meta, hits)". - " VALUES ('".addslashes($old)."', '".($oldpage['version']+1)."', '".$oldpage['flags']."', '". - addslashes($shadowcontent)."', '".$oldpage['author']."', '".$oldpage['created']."', '".time()."', '"."\n\n".addslashes($new)."\n\n\n"."', '". - $oldpage['meta']."', '".$oldpage['hits']."')") or die("Error making shadow page: ".mysql_error()); - } - } - else - { - echo("Page named $old not found.
      "); - } - } - else - { - //name already exists - echo("A page named $new already exists
      "); - } - - //change the page to show - $page = $new; - $showdetails = true; - } - elseif(($_REQUEST['function'] == "delete") && isset($_REQUEST['page'])) - { - $page = $_REQUEST['page']; - - mysql_query("DELETE FROM $wikitable WHERE pagename = '".addslashes($page)."'") or die("Error deleting page: ".mysql_error()); - - echo("
      Deleted $page"); - } - else - { - echo("Unknown function or not enough parameters"); - } - -} -else -{ - //no function show index - $showindex = true; -} - -if($showdetails) -{ - //show the details of a page - - //check if a page is given - if($page) - { - connect_db(); - //select the pages with the given name, first is the most recent one - $pagequery = "SELECT * FROM $wikitable WHERE pagename = '".addslashes($page)."' ORDER BY version DESC"; - $pageresult = mysql_query($pagequery) or die("Error getting page: ".mysql_error()); - - if($recentpagerow = mysql_fetch_assoc($pageresult)) - { - echo("
      Wiki Index"); - echo("

      ".$recentpagerow['pagename']."

      \n"); - echo("Rename\n"); - echo("
       \n"); - echo("Leave shadow page \n"); - echo("
      \n"); - echo("Shadow page is a page in the place of the old name, that points to the new name."); - echo("

      \n"); - echo("
      \n"); - echo("\n"); - echo("\n"); - echo("
      "); - //put pointer back to start of results - mysql_data_seek($pageresult, 0); - } - else - { - echo("No page found with that title: ". $page); - } - } - else - { - //no pagename given - echo("No page field found"); - } -} - -if($showindex) -{ - //show index - - //ARROW makes a database connection to the mysql database (which is from now on the default one) - connect_db(); - $pagesquery = "SELECT pagename, MAX(version) AS version, MAX(lastmodified) AS lastmodified FROM $wikitable GROUP BY pagename"; - $pagesresult = mysql_query($pagesquery) or die("Error getting pages: ".mysql_error()); - - //echo the table - echo("\n"); - echo("\n"); - echo("\n"); - echo("\n"); - while($row = mysql_fetch_assoc($pagesresult)) - { - $name = $row['pagename']; - $time = timeString($row['lastmodified']); - $version = $row['version']; - - echo("\n"); - echo("\n"); - //ARROW ../wiki.php?id= is the base of the link to the added wiki page. - echo("\n"); - echo("\n"); - echo("\n"); - echo("\n"); - } - echo("
      NameviewVersionLastUpdate
      ".htmlspecialchars($name)."view".$version."".$time."
      \n"); -} - - -//ARROW closes all html of the header.php -include('footer.php'); -?> diff --git a/mods/wiki/plugins/user/dbpref.meta b/mods/wiki/plugins/user/dbpref.meta deleted file mode 100644 index c556990f5..000000000 --- a/mods/wiki/plugins/user/dbpref.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: user -title: db -description: provides user/preferences support by storing/loading the $_EWIKI[] to database -type: data -priority: never diff --git a/mods/wiki/plugins/user/dbpref.php b/mods/wiki/plugins/user/dbpref.php deleted file mode 100644 index 7dc915104..000000000 --- a/mods/wiki/plugins/user/dbpref.php +++ /dev/null @@ -1,9 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/user/sessionpref.meta b/mods/wiki/plugins/user/sessionpref.meta deleted file mode 100644 index 7fecb7d05..000000000 --- a/mods/wiki/plugins/user/sessionpref.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: user -title: session -description: load this if yoursite already uses PHPs` session extension -type: data -priority: never diff --git a/mods/wiki/plugins/user/sessionpref.php b/mods/wiki/plugins/user/sessionpref.php deleted file mode 100644 index df26abdc6..000000000 --- a/mods/wiki/plugins/user/sessionpref.php +++ /dev/null @@ -1,9 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/side_menu.inc.php b/mods/wiki/side_menu.inc.php deleted file mode 100644 index 94e91e82f..000000000 --- a/mods/wiki/side_menu.inc.php +++ /dev/null @@ -1,13 +0,0 @@ - - -hello world - -assign('dropdown_contents', ob_get_contents()); -ob_end_clean(); - -$savant->assign('title', _AT('hello_world')); // the box title -$savant->display('include/box.tmpl.php'); -?> \ No newline at end of file diff --git a/mods/wiki/spages/AbandonedPages.php b/mods/wiki/spages/AbandonedPages.php deleted file mode 100644 index 2c8b26999..000000000 --- a/mods/wiki/spages/AbandonedPages.php +++ /dev/null @@ -1,8 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/spages/HitCounter.php b/mods/wiki/spages/HitCounter.php deleted file mode 100644 index 9ff7bcaf0..000000000 --- a/mods/wiki/spages/HitCounter.php +++ /dev/null @@ -1,28 +0,0 @@ -get()) { - if ($r["flags"] & EWIKI_DB_F_TEXT) { - $n += $r["hits"]; - } - } - - #-- output - $AllPages = 'AllPages'; - echo <<< EOT -$title -The overall hit score of $AllPages is: -
      - $n -
      -EOT; - -?> \ No newline at end of file diff --git a/mods/wiki/spages/LeastPopular.php b/mods/wiki/spages/LeastPopular.php deleted file mode 100644 index d3767096e..000000000 --- a/mods/wiki/spages/LeastPopular.php +++ /dev/null @@ -1,8 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/spages/LinkLessPages.php b/mods/wiki/spages/LinkLessPages.php deleted file mode 100644 index 2c2615055..000000000 --- a/mods/wiki/spages/LinkLessPages.php +++ /dev/null @@ -1,28 +0,0 @@ -Pages without links to anywhere else. Often this are unwanted ShallowPages.

      \n"; - -#-- find / analyze db -$result = ewiki_db::GETALL(array("refs")); -$ll = array(); -while ($row = $result->get(0, 0x0137, EWIKI_DB_F_TEXT)) -{ - $id = $row["id"]; - $refs = trim($row["refs"]); - - #-- no links to anywhere else? - if ((!$refs) || (strtolower($refs) == strtolower($id))) { - $ll[] = $id; - } -} - -#-- bring up list -echo ewiki_list_pages($ll, 0, 0, 0); - -?> \ No newline at end of file diff --git a/mods/wiki/spages/OrphanedPages.php b/mods/wiki/spages/OrphanedPages.php deleted file mode 100644 index 896f263fe..000000000 --- a/mods/wiki/spages/OrphanedPages.php +++ /dev/null @@ -1,52 +0,0 @@ -get()) { - - $p = $row["id"]; - - #-- remove self-reference - $row["refs"] = str_replace("\n$p\n", "\n", $row["refs"]); - - #-- add to list of referenced pages - $rf = explode("\n", trim($row["refs"])); - $refs = array_merge($refs, $rf); - if ($n++ > 299) { - $refs = array_unique($refs); - $n=0; - } // (clean-up only every 300th loop) - - #-- add page name - if (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) { - $pages[] = $row["id"]; - } - } - $refs = array_unique($refs); - - #-- check pages to be referenced from somewhere - foreach ($pages as $p) { - if (!ewiki_in_array($p, $refs)) { - if (!EWIKI_PROTECTED_MODE || !EWIKI_PROTECTED_MODE_HIDING || ewiki_auth($p, $uu, "view")) { - $orphaned[] = $p; - } - } - } - - #-- output - echo ewiki_list_pages($orphaned, 0); - -?> \ No newline at end of file diff --git a/mods/wiki/spages/PageLinks.php b/mods/wiki/spages/PageLinks.php deleted file mode 100644 index 0fa0d0167..000000000 --- a/mods/wiki/spages/PageLinks.php +++ /dev/null @@ -1,31 +0,0 @@ -get(0, 0x0137, EWIKI_DB_F_TEXT)) { - $list[$r["id"]] = count(explode("\n", trim($r["refs"]))); - } - - #-- beatify list - if (isset($_REQUEST["desc"])) { - asort($list); - } - else { - arsort($list); - } - $r = array(); - foreach ($list as $id=>$num) { - $r[] = array($id, "", "", "($num)"); - } - unset($list); - - #-- output - echo ewiki_list_pages($r, 0); - -?> \ No newline at end of file diff --git a/mods/wiki/spages/PageRefs.php b/mods/wiki/spages/PageRefs.php deleted file mode 100644 index 1359fb8d4..000000000 --- a/mods/wiki/spages/PageRefs.php +++ /dev/null @@ -1,39 +0,0 @@ -get(0, 0x0137, EWIKI_DB_F_TEXT)) { - $id = $r["id"]; - $exist[strtolower($id)] = 1; - foreach (explode("\n", trim($r["refs"])) as $i) { - $refs[$i]++; - } - } - unset($refs[0]); - - #-- beatify list - if (isset($_REQUEST["desc"])) { - asort($refs); - } - else { - arsort($refs); - } - - #-- output - foreach ($refs as $id=>$num) { - echo "· " - . "($num) " - . ($exist[strtolower($id)] - ? ("$id") - : ("$id") ) - . "
      \n"; - } - -?> \ No newline at end of file diff --git a/mods/wiki/spages/PageSize.php b/mods/wiki/spages/PageSize.php deleted file mode 100644 index a1154c7ab..000000000 --- a/mods/wiki/spages/PageSize.php +++ /dev/null @@ -1,31 +0,0 @@ -get(0, 0x0137, EWIKI_DB_F_TEXT)) { - $list[$r["id"]] = strlen($r["content"]); - } - - #-- beatify list - if (isset($_REQUEST["desc"])) { - asort($list); - } - else { - arsort($list); - } - $r = array(); - foreach ($list as $id=>$size) { - $r[] = array($id, "", "", "$size octets"); - } - unset($list); - - #-- output - echo ewiki_list_pages($r, 0); - -?> \ No newline at end of file diff --git a/mods/wiki/spages/WantedPages.php b/mods/wiki/spages/WantedPages.php deleted file mode 100644 index 76e92b0b2..000000000 --- a/mods/wiki/spages/WantedPages.php +++ /dev/null @@ -1,41 +0,0 @@ -get()) { - if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $uu, "view")) { - continue; - } - $refs .= $row["refs"]; - } - - #-- build array - $refs = array_unique(explode("\n", $refs)); - - #-- strip existing pages from array - $refs = ewiki_db::FIND($refs); - foreach ($refs as $id=>$exists) { - if (!$exists && !strstr($id, "://") && strlen(trim($id))) { - $wanted[] = $id; - } - } - - #-- print out - echo "
        \n"; - foreach ($wanted as $page) { - - echo "
      • " . ewiki_link($page) . "
      • \n"; - - } - echo "
          \n"; - - -?> \ No newline at end of file diff --git a/mods/wiki/spages/WordIndex.php b/mods/wiki/spages/WordIndex.php deleted file mode 100644 index e6ba00e20..000000000 --- a/mods/wiki/spages/WordIndex.php +++ /dev/null @@ -1,46 +0,0 @@ -get(0, 0x0037, EWIKI_DB_F_TEXT)) { - $src .= " " . $row["id"]; - } - - $src = ewiki_split_title($src, "SPLIT", 0); - $chars = strtr(EWIKI_CHARS_U.EWIKI_CHARS_L, "_", " "); - $src = preg_replace("/[^$chars]/", " ", $src); - $src = explode(" ", $src); - $src = array_unique($src); //@ADD: word counting - unset($src[""]); - - natcasesort($src); - - $sorted = array(); - foreach ($src as $i => $word) { - - if (strlen($word) >= 2) { - - $sorted[] = array( - EWIKI_PAGE_POWERSEARCH, - array("where"=>"id", "q"=>$word), - $word, "" //@ADD: display word count - ); - - } - } - unset($src); - - $pf_list_pages = $ewiki_plugins["list_dict"][0]; - echo ewiki_list_pages($sorted, $limit=0, $vat=1, $pf_list_pages); - - -?> \ No newline at end of file diff --git a/mods/wiki/tlogo.png b/mods/wiki/tlogo.png deleted file mode 100644 index 9d65240890a4fe18d443fbb3d4554051a481a6f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2072 zcmV+z2zW7(iA)(g{ZEnbjn1x2A~711w( z_{k!uUj&gNRS?lH2EVk5*s0Lsp|#soYhqouX_IXl*<8ArW|F<{&dm?!f3nY>oy>K2 zQ~JU%=RIfM%m00z=l@*JIBY=6Ko9VDV7G3485jV*t^TnzJQ^AEFJP~_-$}!7YpoM! zW10h`fLqjW13FB@Kl9$27r&N`+ML%LjcbJCtCuO2~OrQ;31vTPT=tjdMF4w&hmE)aJ_Z~GW_8~Y zwRUR0u)oPXpEK9a4c6+{vjQ+_D81U4hQJKTR%}ZUNM^>|>k@!)(GCL!0k73Uhk7+K z_nJ}j2hDZKTz?3dH}^Utj<3_$N4;P|6?|I+v36iG!PkCs>*r=udyPtjo9{A`XcUYq z8w_c?u-1}sfm@AKo&nx5o9!_t7=pp5S$6|qQU?5mh!(5~n7G+c8CWozceR1JDqwmV z0JFmSp|zQk0n-ry)7=7?-R62?Jz}%CHXTZ)9EpOHRV0&a&}KHTH<*|a zy#w?`oNU}|GAfy*kxWUkKPNCSkzj8=%@EaIwns zha)jw(<#7aqjn*n*&DD|()5?~sW-Y_sIL=qKO*Pr9l`Tfgb={2H{(+WSS-5k#tZou_4c=O?Rulr=((?O-QC9 zm`GBWUz4;s6C`NiVlPDeN0>-WO7A-xAb>?vfvE=OSJn312p9+WK9H6wJrD`iL;Jg| z05zobg-ZGzX;~$HRly7fb2ps=lxsYnsi2PU+<+u%fw`_`nL3lPM!=M7fGSnk=t7iM zjbp9W>;Y_RmStl#ym2WK354I}cpGjaxiVCD9P(|+m2<}1a1R{fPRCgeTDvyU*Opj8 zpEY5SLTqY$F z=*s6wInHvpvTY}y%oae7*$hbfN98l%uHXs>uaojlh5X_a!yt1^wKuEU} zXZcOBKs$jW3lNsbEzC2%!mvu@E}moB+FgE$Ini<0zp8Y3XSs}f>I8nd%yd`*oxaL( zU{ox56mYUbj1u_0vz{N!9hWrj13s#-WCj=m#_~(-P$h=kWxi(UbGndcqC)5~16*r@ z%~p^=xx8}T`B^4`=Yba$SsYa5Xb^ZUJH($npUF6IM82a0JgY%Dpin9@5`s}hGHj!Y zljd~dAu&wrQ*N-#w2Gdi4?X`nDNSXE7||X+Cspmw4)Mzv@DasU&jU|+K9@b8f(H9H z@ZQg+m#NrRQbI7zNG4lnNQ38t=QFJ`Z=Rrp{9w$4A;k**{76TZU(;QRe z92WITS|?P?X~l5iJQp?A&O2^`%G@e32BbA$V!G2#c8Kl3Hx+M|sXrNd`*S{HQUiy;l(tS0t-AMkml@>hW0c|NBd^P_Iyu8G{=jBZr&Zq)MF%aE}6a$PP~d{{Y4-Mab_OFtWuq zsn22HknD02cv+4(+o-xa8w?;ODcm7j*e7NhRbB4QF#2ewIUA%#?V{EJ;7-x}8^9~T zDbKI@mf+@r5r8&=_ml$)hf=_s1n=|5JbzW;y diff --git a/mods/wiki/tools/cron.d/HOWTO b/mods/wiki/tools/cron.d/HOWTO deleted file mode 100644 index e593698e0..000000000 --- a/mods/wiki/tools/cron.d/HOWTO +++ /dev/null @@ -1,174 +0,0 @@ - -This is an advanced extension; and most people won't need it. It is -meant for big Wiki installations, where automating tasks makes sense. -Don't worry if it looks ugly and overly complex or even useless to -you - it then most likely is. - - -what is it? -¯¯¯¯¯¯¯¯¯¯¯ -The scripts in the cron.d/ are to be executed regularily to automatically -do certain administration tasks. Scripts that shall be executed MUST have -a name like "Snn______.php" to be detected by the "run-parts.php" script. - -Put all the configuration setting into run-parts.php, or simply create a -"S02myconfig.php" to override settings from all the other snippets (which -all too often are disabled per default). You can get a list of all possible -config settings with `grep define * | sort | uniq ` or so. - -Coding is less clean than in ewiki, but works for what is to be achieved. - - -how often? -¯¯¯¯¯¯¯¯¯¯ -It is recommended that you activate the run-parts every day, if you can -automate this via a cron daemon. But running them once a week (or depending -on activity on your wiki even rarer) would do too. - -There is an internal dispatcher ("anacron") which ensures that certain -parts are run only once a week/month anyhow, so it doesn't hurt if this -got triggered hourly or so. - - -local cron activation -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -If your provider gives you shell access and a real cron service, then -use this to get your cron scripts running (use "EDITOR=joe crontab -e" -on the commandline): - -00 03 * * 5 \ - php -q /www/u54321/example.com/htdocs/ewiki/tools/cron.d/run-parts.php - -(will run everything on Fridays at 03:00 - once a week is enough for -most tasks) - - -remote cron activation -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -If you have a cron daemon running somewhere, then you can start the cron -scripts in here with it too, by simply setting up a remote activation -with wget: - -00 03 * * * \ - wget -o /dev/null -O /dev/stdout \ - http://example.net/ewiki/tools/cron.d/run-parts.php - -Will give you a log of what was run (-O /dev/stdout, cron will mail it -automatically for correctly configured server accounts). - -There are also free services which provide this form of web based -cron activation. - - -Using plugins/feature/anacron.php -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -If you seriously can't get a real cron service, then use your Windows -box` built-in task planner! ;) - -No seriously, you can then simply use the script we provide as "anacron" -extension. It hooks into ewiki and enables itself once a day, whenever -a person or a search engine or spam bot visits your site. It does not -delay page delivery by that, because it runs after the page has been -finished. - -It is highly recommended to use this, but as usual you can forget it if -your provider has no PHP installed and only gives you "Safe-Mode-PHP". - - -Or even starting by hand -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -If there is not all that much activity on your Wiki, you may even want -to start the scripts yourself every while in a month or so. Just point -your browser to the directory, the index.php script will show up a form -which eases starting. (This is only made so we can add an entry on the -admin tools/ overview page.) - - -password protection -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -There is no need to "protect" these scripts from getting run by anyone. -Nobody can do you harm if he activates it, because the tools herein -run automated and do only what they were configured to do and don't -accept commands from outside. Also they run locked, cannot be interrupted -once started and then typically don't slow down the server any much. - -If you really want it, then please just create a file like "S04auth.php" -and place a link - an include("...") or require statement - to the usual -'../../fragments/funcs/auth.php' script. - - -numbering scheme -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The S** ("start") scripts are run in their numeric order, -the Z** and K** ("kill") scripts get run in reverse order. - -The numbering scheme has been designed to group actions into how -often they are to be executed. The "anacron" scripts and everything -with two underscores in its name controls this behaviour - it has -little to do with how the "run-parts.php" script operates. - -There are however a few special ranges (subject to change at any -later time): - - S00-S09 pre-init - S10-S19 config - - start, preparations - - locking, "anacron" stop watch init - --- - S20-S29 ALWAYS executed - - on every run - S30-S49 HOURLY run scripts - - email2wiki gateway/import - S50-S69 DAILY run scripts - - creation of cache files, - - preparing data for certain plugins - - automated page deletion and cache file purging - - syncing with other wikis - S70-S89 WEEKLY run scripts - - collecting statistical info, diffs - - sending out mails where users signed on for (RecentNotify - and WeekDiff, ...) - - exchanging blacklists (spam) - S90-S98 MONTHLY run scripts - - backups - S98,S99 ALWAYS executed - - final actions - --- - Z00-S99 shutdown stuff - K00-K99 hard clean-up - -There is no requirement that you don't do something completely different -in any stage as you see fit. And you can have two different files with -the same numeric entry - in that case you just didn't know 102%-exactly -which one of the two was started first. - - -rearrangement tricks (COMPLICATED READING, UNINTERESTING NOTES) -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -If it happens that you want one of the actions in a different time slice -than it is per default, then you must use a trick if you don't want to -rearrange the cron.d/ script directory after every update. - -For example, if you want S92mimebackup to activate __weekly__ instead of -__monthly__, you simply make a symlink (get the according utility for -NT/Win32, or use include-wrapper there) to let's say "S82mybackup.php". - -Then you only have to ensure that the "S92mimebackup.php" doesn't actually -gets activated twice in every fourth week, so you create a "S92_jump93.php" -script with simply "" in it. This will skip the other -two existing "S92*" parts, because it is sorted (alphabetically) exactly -before the other two. - - HintTwo: If you needed the "S92binbackup" as well for some obscure - reasons, then a name like "S92jump93.php" would do the trick, because it - is alphabetically directly in between "...binback" and "...mimebackup". - Typically the 'ls -l' directory listing shows exactly how PHPs asort() - would order the scripts as well. - -Though it's a bit complicated, this should work in most cases. Else you -could simply create a "mycron/" directory and symlink only the plugins -you really need and order them however you want. You could also use -multiple such directories and start each collection by a different cron -daemon timing rule to achieve the same our "anacron scheduler" script -parts were meant to. - diff --git a/mods/wiki/tools/cron.d/S01env.php b/mods/wiki/tools/cron.d/S01env.php deleted file mode 100644 index de7833280..000000000 --- a/mods/wiki/tools/cron.d/S01env.php +++ /dev/null @@ -1,15 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S01textplainout.php b/mods/wiki/tools/cron.d/S01textplainout.php deleted file mode 100644 index f02538b3d..000000000 --- a/mods/wiki/tools/cron.d/S01textplainout.php +++ /dev/null @@ -1,14 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S10config.php b/mods/wiki/tools/cron.d/S10config.php deleted file mode 100644 index bc91e06be..000000000 --- a/mods/wiki/tools/cron.d/S10config.php +++ /dev/null @@ -1,42 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S11defaults.php b/mods/wiki/tools/cron.d/S11defaults.php deleted file mode 100644 index 7954265e2..000000000 --- a/mods/wiki/tools/cron.d/S11defaults.php +++ /dev/null @@ -1,18 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S16nohup.php b/mods/wiki/tools/cron.d/S16nohup.php deleted file mode 100644 index 1e28cb527..000000000 --- a/mods/wiki/tools/cron.d/S16nohup.php +++ /dev/null @@ -1,11 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S17anacron.php b/mods/wiki/tools/cron.d/S17anacron.php deleted file mode 100644 index d2f458e45..000000000 --- a/mods/wiki/tools/cron.d/S17anacron.php +++ /dev/null @@ -1,44 +0,0 @@ - 0, - "minute" => 0, - "hour" => 0, - "day" => 0, - "week" => 0, - "month" => 0, - ); -} - -#-- check _PAUSE -if ($anacron["last"]+ANACRON_PAUSE >= time()) { - echo "[$cron]: oooops, we're beeing called to often, the minimum interleave is " . ANACRON_PAUSE . " seconds\n"; - $HALT = 2; -} - -#-- prepare state flags? -else { - // ... - - // we define this a third time here, in case it really was missed - // somehow (?) - @define("EWIKI_CRON", time()); -} - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S18lock.php b/mods/wiki/tools/cron.d/S18lock.php deleted file mode 100644 index 4d1ebe6dc..000000000 --- a/mods/wiki/tools/cron.d/S18lock.php +++ /dev/null @@ -1,37 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S20__start__.php b/mods/wiki/tools/cron.d/S20__start__.php deleted file mode 100644 index 596b28adb..000000000 --- a/mods/wiki/tools/cron.d/S20__start__.php +++ /dev/null @@ -1,4 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S30__hourly__.php b/mods/wiki/tools/cron.d/S30__hourly__.php deleted file mode 100644 index 654c11d23..000000000 --- a/mods/wiki/tools/cron.d/S30__hourly__.php +++ /dev/null @@ -1,22 +0,0 @@ -= time()) { - $GOTO = 50; //go testing if __daily__ scripts are to be run again - echo "[$cron]: overstepping parts\n"; -} - -#-- proceed, update time -else { - $anacron["hour"] = EWIKI_CRON; - echo "[$cron]: proceeding\n"; -} - - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S35mail2wiki.php b/mods/wiki/tools/cron.d/S35mail2wiki.php deleted file mode 100644 index 2ace36148..000000000 --- a/mods/wiki/tools/cron.d/S35mail2wiki.php +++ /dev/null @@ -1,194 +0,0 @@ - MAIL2WIKI_ATONCE * 1.1) { - $msg_count = MAIL2WIKI_ATONCE; - echo "[$cron]: proeccsing only $msg_count now\n"; - } - for ($msg=1; $msg<=$msg_count; $msg++) { - - #-- get complete msg - $mbox = imap_fetchheader($server, $msg, FT_PREFETCHTEXT); - imap_delete($server, $msg); - - #-- into our spool array - $incoming[] = $mbox; - } - - #-- close, delete messages - imap_expunge($mx); - imap_close($mx); - } -} - - -#-- read on Unix server -if (defined("MAIL2WIKI_MBOX")) { - // open for read-write or forget it - if ($f = fopen(MAIL2WIKI_MBOX, "rw")) { - flock($f, LOCK_EX); - - #-- try to read 2MB file, - # but fail if we really can do that (this is far too large!!) - $mbox = fread($f, 1<<21); - if (strlen($mbox) >= (1<<21)) { - unset($mbox); - } - - #-- split mbox file into individual messages, append to $incoming[] list - elseif ($mbox - and ($mbox = preg_split("/^From [^\s]+@[^\s]+ \w\w\w?,? \w\w\w \d\d \d\d:\d\d:\d\d \d\d\d\d$/m", - $mbox)) ) { - #-- append to processing list - $incoming = array_merge($incoming, $mbox); - unset($mbox); - - #-- clear inbox file completely - fseek($f, 0); - ftruncate($f, 0); - } - - #-- go away - flock($f, LOCK_UN); - fclose($f); - } -} - - -#-- store it -------------------------------------------------------------- -if ($incoming) { - echo "[$cron]: storing " . count($incoming) . " pages\n"; - $rx_wiki = "/^([".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L."]+){2,})$/"; - - foreach ($incoming as $mbox) { - - #-- convert line breaks - $mbox = preg_replace('/(\r\n|\r)/', "\n", $mbox); - $page = substr($mbox, strpos($mbox, "\n\n")+2); // content body - - #-- check for WikiWord - $ok = 0; - if (preg_match('/^To:\s*"(.+)"|^To:\s*\"\'", " "); - $l = strpos($from, "@"); - if ($l = strrpos($from, " ", $l)) { - $name = substr($from, 0, $l); - $mail = substr($from, $l+1); - $wiki = str_replace(" ", "", $name); - if (ewiki_db::GET($wiki)) { - return($wiki); - } - else { - $mail = trim($mail); - return("$wiki|$email"); - } - } - else { - return($from); - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S50__daily__.php b/mods/wiki/tools/cron.d/S50__daily__.php deleted file mode 100644 index 3165465b8..000000000 --- a/mods/wiki/tools/cron.d/S50__daily__.php +++ /dev/null @@ -1,19 +0,0 @@ -= time()) { - $GOTO = 70; //skips to __weekly__ parts, instead of doing hard $HALT - echo "[$cron]: not running again\n"; -} - -#-- or update time -else { - $anacron["day"] = EWIKI_CRON; - echo "[$cron]: proceeding\n"; -} - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S53sync.php b/mods/wiki/tools/cron.d/S53sync.php deleted file mode 100644 index 34107fb3c..000000000 --- a/mods/wiki/tools/cron.d/S53sync.php +++ /dev/null @@ -1,51 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S56gagalinks.php b/mods/wiki/tools/cron.d/S56gagalinks.php deleted file mode 100644 index 3216db411..000000000 --- a/mods/wiki/tools/cron.d/S56gagalinks.php +++ /dev/null @@ -1,63 +0,0 @@ - creates a cache entry for pages with single-word and non-wiki names -*/ - -#-- cfg (already in the according plugin) -// define("EWIKI_AUTOLINKING_CACHE", "system/tmp/autolinking"); - - -#-- start if plugin loaded / constant defined -if (defined("EWIKI_AUTOLINKING_CACHE")) { - - #-- start list - $pages = array(); - - #-- find AllPages - $result = ewiki_db::GETALL(array("id", "flags")); - while ($row = $result->get()) { - - if (EWIKI_DB_F_TEXT != ($row["flags"] & EWIKI_DB_F_TYPE)) { - continue; - } - $id = $row["id"]; - - #-- only care about pagenames, which are words but no WikiWords - if (!strpos($id, " ") && preg_match('/^\w+$/', $id) - && !preg_match('/^(['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+){2,}[\w\d]*$/', $id)) - { - $pages[] = $id; - } - - } - - #-- save found pages in cache entry - $DEST = EWIKI_AUTOLINKING_CACHE; - $save = array( - "id" => $DEST, - "version" => 1, - "flags" => EWIKI_DB_F_SYSTEM, - "created" => time(), - "lastmodified" => time(), - "author" => ewiki_author("PrepareAutolinking"), - "content" => "", - "meta" => "", - "refs" => "\n\n" . implode("\n", $pages) . "\n\n", - ); - $ok = ewiki_db::WRITE($save, true); - - #-- output results - if ($ok) { - echo "[$cron]: Written informations about ".count($pages)." pages into the database cache entry '$DEST'" - . "\n These pages will then get autolinked by the according plugin.\n"; - } - else { - echo "[$cron]: Error writing the database cache entry '$DEST'. Autolinking pages won't work now.\n"; - } - -} - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S61keptpages.php b/mods/wiki/tools/cron.d/S61keptpages.php deleted file mode 100644 index d8df2e79d..000000000 --- a/mods/wiki/tools/cron.d/S61keptpages.php +++ /dev/null @@ -1,11 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S63deletedpage.php b/mods/wiki/tools/cron.d/S63deletedpage.php deleted file mode 100644 index f9c57bddb..000000000 --- a/mods/wiki/tools/cron.d/S63deletedpage.php +++ /dev/null @@ -1,77 +0,0 @@ -get()) { - - #-- check that it wasn't modified lately - if (time() >= $row["lastmodified"] + $keptpages) { - - #-- check page content for trigger words - $id = $row["id"]; - $row = ewiki_db::GET($id); - $text = strtolower(trim($row["content"])); - $refs = trim($row["refs"]); - if (in_array($text, $triggers) - or ewiki_in_array($refs, $triggers)) - { - #-- purge it, no mercy!!!!! - echo " $id"; - for ($v=$row["version"]; $v>=1; $v--) { - if (ewiki_db::GET($id, $v)) { - echo " [$v]"; - ewiki_db::DELETE($id, $v); - } - } - echo "\n"; - } - } - - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S64trashcan.php b/mods/wiki/tools/cron.d/S64trashcan.php deleted file mode 100644 index b7d8ee07e..000000000 --- a/mods/wiki/tools/cron.d/S64trashcan.php +++ /dev/null @@ -1,70 +0,0 @@ -= $row["lastmodified"] + $last) { - break; // done with version comparisions - } - - #-- remove anything that isn't listed in all TrashCan page versions - $cmplist = explode("\n", trim($data["refs"])); - $listed = array_intersect($listed, $cmplist); - } - - #-- delete anything that's still in the purge list - foreach ($listed as $id) { - - #-- walk through all versions - if ($row = ewiki_db::GET($id)) { - echo " $id"; - - $version = $row["version"]; - for ($version; $version >= 1; $version--) { - - #-- don't kill revisions that have borought lifetime ($keptpages) - if ($row["lastmodified"] >= $keepuntil) { - continue; - } - - #-- oh, so sad! - echo " [$version]"; - ewiki_db::DELETE($id, $version); - - } - - echo "\n"; - } - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S67versionholes.php b/mods/wiki/tools/cron.d/S67versionholes.php deleted file mode 100644 index e2926d629..000000000 --- a/mods/wiki/tools/cron.d/S67versionholes.php +++ /dev/null @@ -1,75 +0,0 @@ -get()) { - - $id = $row["id"]; - if ($row["flags"] & EWIKI_DB_F_ARCHIVE) { continue; } - - $verZ = $row["version"] - $end; - $verA = $start; - - #-- walk versions (top..down) - for ($ver=$verZ; $ver>=$verA; $v--) { - - #-- interleave - if ($leave && !($ver % $leave)) { - continue; - } - - #-- skip if too fresh - $row = ewiki_db::GET($id, $ver); - if ($row["lastmodified"] >= $t_skip) { - continue; - } - - #-- check flags - if ($row["flags"] & EWIKI_DB_F_ARCHIVE) { - continue; - } - if ($row["flags"] & EWIKI_DB_F_READONLY) { - // has no meaning here(?!) - } - - #-- else really delete it - ewiki_db::DELETE($id, $ver); - echo " $id[$ver]\n"; - - } - - } // GETALL -} - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S70__weekly__.php b/mods/wiki/tools/cron.d/S70__weekly__.php deleted file mode 100644 index 432169931..000000000 --- a/mods/wiki/tools/cron.d/S70__weekly__.php +++ /dev/null @@ -1,19 +0,0 @@ -= time()) { - $GOTO = 90; //skews to __monthly__ - echo "[$cron]: no week elapsed, overstepping\n"; -} - -#-- update timestamp -else { - $anacron["week"] = EWIKI_CRON; - echo "[$cron]: proceeding\n"; -} - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S77metadb.php b/mods/wiki/tools/cron.d/S77metadb.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/mods/wiki/tools/cron.d/S80recentnotify.php b/mods/wiki/tools/cron.d/S80recentnotify.php deleted file mode 100644 index 45c9ac506..000000000 --- a/mods/wiki/tools/cron.d/S80recentnotify.php +++ /dev/null @@ -1,108 +0,0 @@ -$x) { - if (strpos($str, "@")) { - if (strpos($str, "notify:")!==false) { - $str = substr($str, strpos($str, ":")); - } - $subscribers[] = $str; - } - } - - #-- only calc the RC if we have at least one interested - if ($subscribers) { - echo "[$cron]: ".count($subscribers)." listed (".implode(", ", $subscribers).")\n"; - $min_time = time() - RECENTNOTIFY_DAYS * 24 * 3600; - $rc = array(); - $vers = array(); - $mail = ""; - - #-- find pages changed in given timeframe - $all = ewiki_db::GETALL(array("id", "version", "flags", "lastmodified")); - while ($row = $all->get(0, 0x137f)) { - - if ($row["lastmodified"] >= $min_time) { - $rc[$row["id"]] = $row["lastmodified"]; - $vers[$row["id"]] = $row["version"]; - } - } - - #-- go through rc list - echo "[$cron]: generating RC list\n"; - arsort($rc); - $lastdatestr = ""; - do { - - #-- get entry - reset($rc); - list($id, $lm) = each($rc); - $ver = $vers[$id]; - array_shift($rc); - - #-- output - $row = ewiki_db::GET($id, $ver); - $m_ver = $row["version"]; - ($m_log = $row["meta"]["log"]) and ($m_log = " . [{$m_log}] . ."); - $m_author = $row["author"]; - $m_ua = $row["meta"]["user-agent"]; - $m_time = strftime("%H:%M", $lm); - $m_flags = ""; - if ($row["flags"] & EWIKI_DB_F_MINOR) { - $m_flags .= " MINOR EDIT"; - } - if ($row["flags"] & EWIKI_DB_F_APPENDONLY) { - $m_flags .= " (append-only)"; - } - if ($row["flags"] & EWIKI_DB_F_HIDDEN) { - $m_flags .= " (hidden page)"; - } - $datestr = strftime("%Y-%m-%d, %a", $lm); - if ($lastdatestr != $datestr) { - $lastdatestr = $datestr; - $mail .= "\n$datestr\n"; - } - $mail .= "· {$id} - [{$m_ver}]{$m_flags} {$m_time} . . .{$m_log} by {$m_author} / {$m_ua}\n"; - - #-- check previous version of this page - if (($ver--) && ($row = ewiki_db::GET($id, $ver))) { - if ($row["lastmodified"] >= $min_time) { - $vers[$id] = $row["version"]; - $rc[$id] = $row["lastmodified"]; - arsort($rc); - } - } - } - while ($rc); - - #-- send it - echo "$mail"; - $subj = RECENTNOTIFY ." on ". EWIKI_NAME; - $to = implode(", ", $subscribers); - $mail = "This is the full list of latest changes on " . EWIKI_NAME . ".\n" - . ewiki_script_url("", EWIKI_PAGE_INDEX) . "\n" - . "Unsubscribe yourself on " . ewiki_script_url("edit", RECENTNOTIFY) . "\n" - . "\n" - . $mail - . "\n\n-- \nThere is no Web like WikiWikiWeb.\n"; - mail($to, $subj, $mail); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S81weekdiff.php b/mods/wiki/tools/cron.d/S81weekdiff.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/mods/wiki/tools/cron.d/S90__monthly__.php b/mods/wiki/tools/cron.d/S90__monthly__.php deleted file mode 100644 index ae402f0c3..000000000 --- a/mods/wiki/tools/cron.d/S90__monthly__.php +++ /dev/null @@ -1,16 +0,0 @@ -= time()) { - $GOTO = 98; // skip most __monthly__ scripts without '$HALT'ing rest - echo "[$cron]: no month has elapsed since last run yet, not running any script now\n"; -} -else { - $anacron["month"] = EWIKI_CRON; - echo "[$cron]: proceeding\n"; -} - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S92binbackup.php b/mods/wiki/tools/cron.d/S92binbackup.php deleted file mode 100644 index a033941bf..000000000 --- a/mods/wiki/tools/cron.d/S92binbackup.php +++ /dev/null @@ -1,60 +0,0 @@ -get()) { - - $id = $row["id"]; - for ($v=$row["version"]; $v>0; $v--) { - - $row = ewiki_db::GET($id, $v); - - if (BINBACKUP_TEXTONLY && !(EWIKI_DB_F_TEXT & $row["flags"])) - { - continue; - } - - if ($row && ($row = serialize($row))) { - $mail .= "\n" . strlen($row) . "\n" . $row; - } - - } - } - - #-- send - $mail = gzencode($mail); - $mail = base64_encode($mail); - mail( - BINBACKUP_TO, - "[backup] " . EWIKI_NAME . ":", - $mail, - "Content-Transfer-Encoding: base64\n" - ."Content-Encoding: deflate\n" - ."Content-Type: application/x.vnd.ewiki.transfer-file\n" - ."X-Mailer: ewiki/".EWIKI_VERSION."\n" - ."From: ewiki@$_SERVER[SERVER_NAME]\n" - ."Reply-To: trashbin@example.com\n" - ); - unset($mail); - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S92mimebackup.php b/mods/wiki/tools/cron.d/S92mimebackup.php deleted file mode 100644 index ea78f953c..000000000 --- a/mods/wiki/tools/cron.d/S92mimebackup.php +++ /dev/null @@ -1,103 +0,0 @@ -get(0, 0x1037)) { - - $row = ewiki_db::GET($row["id"]); - if (!$row || !$row["id"] || !$row["content"]) { - continue; - } - - #-- add (we could run out of memory with this!) - $parts[] = $row; - } - echo "[$cron]: Found " . count($parts) . " pages\n"; - - #-- send - $BND = "cut-here-".md5(time())."-cut-here"; - $mail = "--$BND\n" - ."Content-Type: text/plain\n" - ."\n" - ."This is a backup of " . EWIKI_NAME . ". All text pages are contained\n" - ."in this mail as MIME/multipart embedded files; use a better mail reader\n" - ."if you cannot decompose it easily.\n" - ."\n--$BND\n" - . multipart_parallel($parts, $boundary, $inj_header) - . "\n--$BND--\n"; - unset($parts); - echo "[$cron]: Sending backup data to " . MIMEBACKUP_TO . "\n"; - mail( - MIMEBACKUP_TO, - "[backup] " . EWIKI_NAME . ":", - $mail, - "Content-Type: multipart/mixed; boundary=$BND\n" - ."X-Mailer: $ewiki_config[ua] run-parts/$cron\n" - ."From: ewiki@$_SERVER[SERVER_NAME]\n" - ."Reply-To: trashbin@example.com\n" - ); - unset($mail); - -} - - - -#-- produces a (probably invalid) multipart stream -function multipart_parallel(&$parts) { - global $ewiki_t; - $boundary = preg_replace("/(........)/", '$1-', md5(serialize($parts))) - . "ewiki-mimebackup"; //@FIXME: must be checked for being unique - $text = ""; - foreach ($parts as $i=>$row) { - $fn = urlencode($row["id"]); - $created = gmstrftime($ewiki_t["C"]["DATE"], $row["created"]); - $lm = gmstrftime($ewiki_t["C"]["DATE"], $row["lastmodified"]); - $text .= "--$boundary\n" - . "Content-Type: text/x-wiki; variant=ewiki; charset=iso-8859-1\n" - . "Content-Disposition: inline; filename=\"$fn\"\n" - . "X-Flags: $row[flags]\n" - . "Content-Version: $row[version]\n" // HTTP header, but hey! - . "X-Created: $created\n" - . "Last-Modified: $lm\n" // also only allowed in HTTP exactly - . "\n" - . $row["content"] - . "\n"; - unset($parts[$i]); - } - $text .= "--$boundary--\n"; - - #-- encode - $text = wordwrap(base64_encode(gzencode($text)), 78, "\n", 1); - - #-- prep headers - $text - = "Content-Type: x-multipart/parallel; boundary=$boundary\n" - . "Content-Disposition: attachment; filename=".EWIKI_NAME.".mar.gz\n" - . "Content-Encoding: gzip\n" - . "Content-Transfer-Encoding: base64\n" - . "\n" . $text; - - return($text); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/S93checklinks.php b/mods/wiki/tools/cron.d/S93checklinks.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/mods/wiki/tools/cron.d/S99__end__.php b/mods/wiki/tools/cron.d/S99__end__.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/mods/wiki/tools/cron.d/Z17anacron.php b/mods/wiki/tools/cron.d/Z17anacron.php deleted file mode 100644 index 33a084892..000000000 --- a/mods/wiki/tools/cron.d/Z17anacron.php +++ /dev/null @@ -1,26 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/Z18unlock.php b/mods/wiki/tools/cron.d/Z18unlock.php deleted file mode 100644 index b9be3e308..000000000 --- a/mods/wiki/tools/cron.d/Z18unlock.php +++ /dev/null @@ -1,10 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/tools/cron.d/index.php b/mods/wiki/tools/cron.d/index.php deleted file mode 100644 index e3b97cf9e..000000000 --- a/mods/wiki/tools/cron.d/index.php +++ /dev/null @@ -1,109 +0,0 @@ - - - - cron.d/ centre - - - - -

          manual cron.d/ run-parts activation

          - - - - - - -
          -$fn [$size]
          "; - } - -?> -
          - -If you seriously cannot afford a provider with cron support, then you -can as last resort start the scripts in the cron.d/ directory by hand. -
          -
          - -
          - -
          - -
          -> -
          - -
          -
          - -It is safe to leave this open to get started by anyone, because it is already -secured against concurrent execution and interruption and after all does -nothing what is not configured/wanted anyhow. See also the -HOWTO file for more notes on this. - - -
          -
          - - - -
          - -
          - -
          -
          -
          -
          - - diff --git a/mods/wiki/tools/cron.d/run-parts.php b/mods/wiki/tools/cron.d/run-parts.php deleted file mode 100644 index aeb370ed1..000000000 --- a/mods/wiki/tools/cron.d/run-parts.php +++ /dev/null @@ -1,77 +0,0 @@ -= 2. - There is also a $GOTO variable available, which allows to overstep a - few scripts by numeric id (the anacron snippets use that). - - Please see the HOWTO on more notes on how to activate this. -*/ - - -#-- read in current directory -$dir = dirname(__FILE__); -$startparts = array(); -$killparts = array(); -if ($dh = opendir($dir)) { - while ($fn = readdir($dh)) { - if (preg_match("/^[SKZ]\d\d.+\.php$/", $fn)) { - if ($fn[0]=="S") { - $startparts[] = "$dir/$fn"; - } - else { - $killparts[] = "$dir/$fn"; - } - } - } - closedir($dh); - $dh = NULL; -} - -#-- run 'S'tart-scripts -$STOP=$HALT=false; -if ($startparts) { - asort($startparts); - foreach ($startparts as $fn) { - - #-- make script id string from filename - $cron = strtok(substr($fn, strrpos($fn, "/") + 1), "."); - - #-- overstep a few scripts, if instructed to do so - $num = substr($cron, 1, 2); - if ($GOTO && ($num<$GOTO)) { - continue; - } - - #-- run current - include($fn); - - #-- stop processing - if ($STOP |= $HALT) { - break; - } - } -} - -#-- reverse order for 'K'ill and 'Z'leep -scripts -if ($killparts && ($HALT < 2)) { - arsort($killparts); - foreach ($killparts as $fn) { - $cron = strtok(substr($fn, strrpos($fn, "/") + 1), "."); - include($fn); - } -} - - -#-- fin -$startparts=$killparts=$cron=$fn=$STOP=$HALT=NULL; -// something else may follow here - -?> \ No newline at end of file diff --git a/mods/wiki/tools/ewikictl b/mods/wiki/tools/ewikictl deleted file mode 100755 index fb1f1c551..000000000 --- a/mods/wiki/tools/ewikictl +++ /dev/null @@ -1,812 +0,0 @@ -#!/usr/local/bin/php -Cq -ewikictl is a command line tool! (you need a shell account)"); - } - - #-- load ewiki library / open database - $_SERVER["PHP_AUTH_USER"]=$_SERVER["PHP_AUTH_PW"]="localhost"; - $PWD=getcwd(); - chdir(dirname(__FILE__)); - foreach (array("config.php", "ewiki.php", "t_config.php") as $inc) { - foreach (array('./', '../') as $dir) { - if (file_exists("$dir$inc")) { - include("$dir$inc"); - } - if (class_exists("ewiki_db")) break 2; - } - } - chdir($PWD); - if (!class_exists("ewiki_db")) { - echo "You cannot move around this utility, it needs to be located nereby the\nother ewiki tools/ (or at least ewiki.php or some config.php)!\n"; - } - - @include_once("plugins/lib/upgrade.php"); - } - - - #-- cmdline options - $config = regex_getopts( - array( - "help" => "/^-+(h|help)$/i", - "backup" => "/^-+(b|backup)$/i", - "all" => "/^-+(a|all)$/i", - "format" => "/^-+(f|format)$/i", - "insert" => "/^-+(insert|i|in|backdown|read|init|load|read)$/i", - "keep" => "/^-+(keep|hold|old|keepold|noappend|current)$/i", - "urlencode" => "/^-+(url|url.+code|enc|dec|win|dos|crlf|backslash)$/i", - "holes" => "/^-+(holes|strip|empty|air)$/i", - "dest" => "/^-+(dest|destination|path|d|dir|source|from|to)$/i", - "force" => "/^-+force/i", - "db" => "/^-+(db|database)$/i", - "ls" => "/^-+(ls|list|ll|la)$/i", - "file" => "/^-+(page|file|name|pagename|id)$/i", - "chmod" => "/^-+(chmod|ch|mode?|set|flags|flag)\s.+$/i", - "unlink" => "/^-+(unlink|purge|remove|rm|del)$/i", - "rename" => "/^-+(rename|move|mv|ren|cp)$/i", - )); - - - #-- db connect, if necessary - if ($config["db"]) { - preg_match('/^([^:@\/]+)[:]?([^:@\/]*?)[@]?([^:@\/]*?)\/(.+)$/', $config["db"], $uu); - $user = $uu[1]; $pw = $uu[2]; - $host = $uu[3]; $dbname = $uu[4]; - mysql_connect($host, $user, $pw); - mysql_query("USE $dbname"); - } - - - #-- often used stuff - set_options_global(); - - - #-- work - if ($config["help"]) { - echo <<< EOH - -usage: ewikictl [--command param] [--option2 ...] [page names ...] - --help -h shows up this help screen - --backup -b save pages from database - --all -a all page versions (not only newest) - --format -f file format for --backup, --holes and --insert - -f plain only page content into the text files - -f flat (default) page files in the db_flat_files format - -f fast files in the binary db_fast_files format - -f meta plain format + companion .meta files - -f xml in xml-like files - -f sql mysql INSERT statement script (only for --backup) - --holes create page version holes in the database (but save the - deleted file versions, if --backup is given) - --holes 2..-10 is the default and tells ewikictl to purge - page versions 2 until 10 before the last - --insert -i read files into database, requires --all if multiple versions - exist; pages in the database won't be overwritten, so you may - need to do an "--unlink *" before the actual --insert, - the --format option is important for this! - --insert insert just the given file instead of a whole dir - --keep do not --insert page if already in the database (only single - page version mode - e.g. no version numbers in filenames) - --dest specifes the in/output directory (defaults to './backup-%c' - for --backup, and './holes' for --holes) - --urlencode create/read backup filenames assuming Win4 restrictions - --force proceed after warnings and error messages - --db user:pw@host/dbname - if the ewiki.php couldn't be loaded automatically - -page operations: - --list -ls show pages - --chmod NN set page flags to the given (decimal/0xHex/Oct) value, - or use a mix of page flag names (TEXT,BIN,DISABLED,HIDDEN, - PART,READONLY,RO,WRITE,RW,APPEND,MINOR,EXEC) to add/set/revoke values: - --chmod +TXT,HTML,-OFF or --chmod =SYS or --chmod 0x001 - --unlink -rm delete specified page (all versions), can use * - --rename -mv assign a new name to a page --mv OldPage NewName -Page names to work on (with one of the above operations) can be specified as -standard arguments or via a --page or --file parameter. - - -EOH; - } - - elseif ($config["holes"]) { - - (empty($config["dest"])) and ($dest = "holes"); - @mkdir($dest); - - holes(); - - } - - elseif ($config["insert"]) { - - command_insert(); - - } - - elseif ($config["backup"]) { #-------------------------------------- - - command_backup(); - } - - elseif ($fn = $config["ls"]) { - - func_ls($fn); - - } - - #-- change page database flags - elseif ($config["chmod"]) { - - $files = array_merge( - filenames(), - fn_from(array("file")) - ); - if (empty($files)) { - die("no --file or page name specifed!\nplease see --help\n"); - } - - $fnames = array( - "/(T[EXT]+|WI[KI]*|RE[SET]*|DEF[AULT]*)/" => EWIKI_DB_F_TEXT, - "/BIN/" => EWIKI_DB_F_BINARY, - "/SYS/" => EWIKI_DB_F_PART, - "/(DIS?|OFF)/" => EWIKI_DB_F_DISABLED, - "/P(ART?|T)/" => EWIKI_DB_F_PART, - "/HT[ML]*/" => EWIKI_DB_F_HTML, - "/(RO|READ)/" => EWIKI_DB_F_READONLY, - "/(WR|RW)/" => EWIKI_DB_F_WRITEABLE, - "/AP/" => EWIKI_DB_F_APPENDONLY, - "/U+9/" => 1<<9, - "/U+10/" => 1<<10, - "/U+11/" => 1<<11, - "/U+12/" => 1<<12, - "/EX/" => EWIKI_DB_F_EXEC, - "/(HI[DDEN]*|H$|INV[ISIBLE]*)/" => EWIKI_DB_F_HIDDEN, - "/(MIN?)/" => EWIKI_DB_F_HIDDEN, - ); - - #-- walk through given page names - foreach ($files as $id) { - - $data = ewiki_db::GET($id); - if ($data["version"]) { - - #-- decode +"TXT,HTML" or "15" strings - $mode = strtoupper($config["chmod"]); - if (substr($mode, 0, 2) == "0X") { - $flags = base_convert(substr($mode, 2), 16, 10); - } - elseif (($mode[0]=="0") || ($mode[0]=="O")) { - $flags = octdec(substr($mode, 1)); - } - elseif (preg_match('/^[0-9]+$/', $mode)) { - $flags = $mode; - } - #-- per flag names - else { - $flags = $data["flags"]; - $m = "="; - preg_match_all('/([-=+,:;])(\w+)/', "=$mode", $uu); - foreach ($uu[2] as $i=>$str) { - switch ($uu[1][$i]) { - case "+": - case "-": - $m = $uu[1][$i]; - break; - case "=": - $m = "+"; - $flags = 0x0000; - break; - } - foreach ($fnames as $find=>$val) { - if (preg_match($find, $str) || ($str > 0) && ($val = 1 << $str)) { - if ($m == "-") { - $flags &= (0x7FFFFFFF ^ $val); - } - else { - $flags |= $val; - } - } - } - }#-- foreach(+FLAG,-FLAG) - } - $data["flags"] = $flags; - - #-- save - $data["author"] = ewiki_author("ewikictl"); - $data["lastmodified"] = time(); - $data["version"]++; - ewiki_db::WRITE($data); - - #-- say what's going on - echo "new page flags are 0x" . str_pad(dechex($data["flags"]), 4, "0", STR_PAD_LEFT) . "\n"; - func_ls($id); - - } - }#--foreach ($files) - - }#-- chmod - - - #-- deletion - elseif ($file = $config["unlink"]) { - - $regex = preg_quote($file); - $regex = str_replace("\\\\*", ".*", $regex); - - if (($file == "*") || !strlen($regex)) { - chk_forced("don't want to delete all files"); - } - - $result = ewiki_db::GETALL(array()); - while ($row = $result->get()) { - - $id = $row["id"]; - if (($file != $id) && (!preg_match("\007$regex\007i", $id))) { - continue; - } - else { - echo "[DELETE] " . $id . "\n"; - } - - for ($v=1; $v<=$row["version"]; $v++) { - ewiki_db::DELETE($id, $v); - } - - } - - } - - #-- page moving / renaming - elseif ($file = $config["rename"]) { - - $fn1 = $file; - $fn2 = $config[0]; - echo "rename from $fn1 to $fn2\n"; - if ($data = ewiki_db::GET($fn1)) { - $ver = $data["version"]; - } - else { - chk_forced("source page does not exist"); - } - if (ewiki_db::GET($fn2)) { - chk_forced("destination page name already exists"); - echo "(won't overwrite existing versions)\n"; - } - - #-- from current to earliest version - $n1 = $n0 = 0; - while ($ver) { - if ($data = ewiki_db::GET($fn1, $ver)) { - $data["id"] = $fn2; - if ($ok = ewiki_db::WRITE($data)) { - ewiki_db::DELETE($fn1, $ver); - $n1++; - } else { - $n0++; - } - } - $ver--; - } - echo "moved $n1 versions correctly ($n0 errors/version doublettes)\n"; - } - - elseif ($lib) { - - } - - else { - - echo "ewikictl: please use --help\n"; - } - - - - #---------------------------------------------------------------------- - - function func_ls($fn = 1) { - - $result = ewiki_db::GETALL(array()); - - if ($fn == 1) { - echo $result->count()." pages\n"; - } - - while ($row = $result->get()) { - - $id = $row["id"]; - if (($fn != 1) & ($fn != $id)) { - continue; - } - $row = ewiki_db::GET($id); - - echo "-" - . ($row["flags"] & EWIKI_DB_F_DISABLED ? "-" : "r") - . ($row["flags"] & EWIKI_DB_F_READONLY ? "-" : "w") - . ($x = ($row["flags"] & EWIKI_DB_F_BINARY) ? "x" : "-") - . "--" - . ($row["flags"] & EWIKI_DB_F_TEXT ? "t" : "-") - . "-" - . ($row["flags"] & EWIKI_DB_F_WRITEABLE ? "w" : "-") - . ($row["flags"] & EWIKI_DB_F_HTML ? "h" : "-") - . " "; - - echo str_pad($row["version"], 4, " ", STR_PAD_LEFT); - - echo " " . str_pad(substr($row["author"], 0, 16), 16, " "); - - echo str_pad(strlen($row["content"]), 10, " ", STR_PAD_LEFT); - - echo str_pad(strftime("%b %e %H:%M", $row["lastmodified"]), 14, " ", STR_PAD_LEFT); - - if ($row["flags"] & EWIKI_DB_F_BINARY) { - echo " " . $id . ""; - } - else { - echo " " . $id; - } - - echo "\n"; - } - } - - #---------------------------------------------------------------------- - - function command_insert() { - global $config, $allv, $save_format, $dest; - - if ($config["backup"] && !$config["force"]) { - die("cannot do --backup AND --insert at the same time!\n"); - } - - #-- read files - $files = array(); - $versioned_files = 0; - - $dir = array(); - if (($fn = $config["insert"]) != "1") { #-- just one file - $dest = "."; - $dir[] = $fn; - } - else { - $dh = opendir($dest); - while ($fn = readdir($dh)) { - $dir[] = $fn; - } - closedir($dh); - } - - foreach ($dir as $fn) { - if ($fn[0] == ".") { - continue; - } - $id = $fn; - if ((DIRECTORY_SEPARATOR=="/") && (!$config["urlencode"])) { - $id = strtr($fn, "\\", "/"); - } - else { - $id = urldecode($fn); - } - - $files[$fn] = $id; - - if (preg_match('/\.\d+$/', $id)) { - $versioned_files++; - } - } - unset($dir); - - #-- security check - if ((!$allv) && ($versioned_files * 2 >= count($files))) { - echo "WARNING: the input files are versioned ones, you must give the --all\noption, or this will probably lead to errors.\n"; - if (!$config["force"]) { - die("I would proceed with --force\n"); - } - } - - #-- go thru files - foreach ($files as $fn=>$id) { - - if ($allv) { - $p = strrpos($id, "."); - $ver = substr($id, $p + 1); - $id = substr($id, 0, $p); - if ((!$p) || empty($id) || empty($fn) || ($ver <= 0)) { - echo "[SKIP] $id ($fn)\n"; - continue; - } - } - else { - if ($config["keep"]) { - $ver = 1; - } - else { - $current = ewiki_db::GET($id); - $ver = $current["version"] + 1; - } - } - - $content = read_file($fn); - - switch ($save_format) { - - case "plain": - if (strstr($id, "://")) { - $flags = EWIKI_DB_F_BINARY; - $meta = array("Content-Type" => "application/octet-stream"); - } - else { - $flags = EWIKI_DB_F_TEXT; - $meta = array(); - } - $data = array( - "id" => $id, - "content" => $content, - "version" => $ver, - "flags" => $flags, - "created" => filectime("$dest/$fn"), - "lastmodified" => filemtime("$dest/$fn"), - "author" => ewiki_author("ewikictl"), - "meta" => &$meta, - "hits" => 0, - ); - break; - - case "flat": - case "fast": - $data = read_meta_format_dbff($content); - break; - - default: - die("FAILURE: unsupported --format!\n"); - } - - if ($uu = $data["id"]) { - $id = $uu; - } - - if (empty($data["content"]) || empty($data["flags"])) { - echo "[EMPTY] $id ($fn)\n"; -print_r($data); - continue; - } - - $res = ewiki_db::WRITE($data); - if ($res) { - echo "[OK] $id ($fn)\n"; - } - else { - echo "[ERROR] $id ($fn)\n"; - } - - } - echo "finished.\n"; - - } - - #---------------------------------------------------------------------- - - function holes() { - global $config, $allv, $save_format, $dest; - - $vers = $config["holes"]; - if (preg_match('/^(\d+)[-.:_]+(\d+)$/', trim($vers), $uu)) { - $vers = array($uu[1], $uu[2]); - if ($vers[0] <= 1) { - echo "WARNING: you should never purge version 1, as it sometimes (dbff) holds\ncontrol data!\n"; - if (!$control["force"]) { - die("\nuse --force if you really want this\n"); - } - } - if ($vers[1] <= 0) { - die("REFUSE to delete the latest page versions.\n"); - } - } - else { - $vers = array(2, 10); - } - echo "will remove page versions ".$vers[0]." until -".$vers[1]."\n"; - - $result = ewiki_db::GETALL(array()); - while ($row = $result->get()) { - - $id = $row["id"]; - $ver0 = $vers[0]; - $ver1 = $row["version"] - $vers[1]; - $delete = true; - - for ($v=$ver0; $v <= $ver1; $v++) { - - if ($config["backup"]) { - $allv = 1; - $delete = backup($id, $v); - } - - if ($delete) { - echo "deleting $id.$v\n"; - ewiki_db::DELETE($id, $v); - } - - } - - } - - } - - #---------------------------------------------------------------------- - - function command_backup() { - - global $dest, $allv, $config; - - if (!file_exists($dest)) { - mkdir($dest); - } - - $result = ewiki_db::GETALL(array()); - while ($row = $result->get()) { - - $id = $row["id"]; - $data = ewiki_db::GET($id); - $ver0 = $verZ = $data["version"]; - if ($allv) { $ver0 = 1; } - - echo "$id "; - for ($v = $verZ; $v >= $ver0; $v--) { - - backup($id, $v); - - } - } - echo "\n"; - } - - - function backup($id, $v) { - global $allv, $save_format, $dest, $config; - - $save = ewiki_db::GET($id, $v); - if (empty($save)) { - return(false); - } - $content = $save["content"]; - - #-- base filename for current page - $filename = $id; - if ((DIRECTORY_SEPARATOR=="/") && (!$config["urlencode"])) { - $filename = strtr($filename, '/', '\\'); - } - else { - $filename = urlencode($filename); - } - if ($allv) { - $filename .= "." .$save["version"]; - } - - #-- save style - switch ($save_format) { - - case "meta": - save_file($filename . ".meta", save_meta_format_flat($save)); - case "plain": - default: - save_file($filename, $content); - break; - - case "flat": - $content = save_meta_format_flat($save) . $content; - save_file($filename, $content); - break; - - case "fast": - save_file($filename, save_meta_format_fast($save)); - break; - - case "xml": - $content = save_meta_format_xml($save, "BACKUP"); - save_file($filename, $content); - break; - - case "xmlmeta": - save_file($filename . ".meta", save_meta_format_xml($save)); - save_file($filename, $content); - break; - - case "sql": - case "mysql": - save_file($filename . ".sql", save_meta_format_sql($save), ($save_format=="mysql"?"REPLACE":"INSERT")); - break; - } - - touch("$dest/$filename", $save["lastmodified"]); - - return(true); - - } - - #---------------------------------------------------------------------- - - function xml____entities($s) { - $map = array("&"=>"&", ">"=>">", "<"=>"<", '"'=>""", "'"=>"'", "\000"=>"�"); - $s = strtr($s, $map); - return($s); - } - - function save_file($filename, $content) { - if (is_array($content)) { $content = $content["content"]; } - $f = fopen($filename = $GLOBALS["dest"] . "/" . $filename, "wb"); - fwrite($f, $content); - fclose($f); - } - - function save_meta_format_xml($data, $t = "META") { - if ($t=="META") unset($data["content"]); - $xml = "\n\n"; - foreach ($data as $field=>$value) { - $xml .= " <$field>" . xml____entities($value) . "\n"; - } - $xml .= "\n"; - return($xml); - } - - function save_meta_format_flat($data) { - unset($data["content"]); - $flat = ""; - foreach ($data as $field=>$value) { - $flat .= "$field: " . str_replace("\n", EWIKI_DBFILES_NLR, $value) . "\015\012"; - } - $flat .= "\015\012"; - return($flat); - } - - function save_meta_format_fast($data) { - $data = serialize($data); - if (function_exists("gzencode")) { - $data = gzencode($data); - } - return($data); - } - #---------------------------------------------------------------------- - - - - #------------------------------------------------------------------------ - - function read_file($filename) { - $f = fopen($GLOBALS["dest"] . "/" . $filename, "rb"); - $content = fread($f, 1<<21-1); - fclose($f); - return($content); - } - - #------------------------------------------------------------------------ - - function read_meta_format_dbff($ct) { - - $r = array(); - - if (function_exists("gzdecode") && ($uu = gzdecode($ct))) { - if (($uu = unserialize($uu)) && is_array($uu)) { - return($uu); - } - } - - $p = strpos($ct, "\012\015\012"); - $p2 = strpos($ct, "\012\012"); - if ((!$p2) || ($p) && ($p < $p2)) { - $p = $p + 3; - } - else { - $p = $p2 + 2; - } - $r["content"] = substr($ct, $p); - $ct = substr($ct, 0, $p); - - foreach (explode("\012", $ct) as $h) { - if ($h = trim($h)) { - $r[trim(strtok($h, ":"))] = str_replace(EWIKI_DBFILES_NLR, "\n", trim(strtok("\000"))); - } - } - - return($r); - } - - #------------------------------------------------------------------------ - - #------------------------------------------------------------------------ - - function chk_forced($err) { - global $config; - if ($config["forced"]) { - echo "$err: but --force'd to proceed\n"; - } - else { - die("$err: giving up, use --force next try\n"); - } - } - - #------------------------------------------------------------------------ - - #-- often used stuff - function set_options_global() - { - global $dest, $allv, $save_format, $lib, $config; - - ($dest = $config["dest"]) and ($dest != "1") - or (is_dir($dest = fn_from(array("backup", "insert", "holes")))) - or (!$lib) && ($dest = strftime("backup-%G%m%d%H%M", time())); - - $allv = $config["all"]; - - ($save_format = strtolower($config["format"])) and ($save_format != "1") - or ($save_format = "flat"); - } - - #---------------------------------------------------------------------- - - function fn_from($in, $config=false) { - if ($config === false) { - $config = $GLOBALS["config"]; - } - foreach ($in as $i) { - if (($r = $config[$i]) && ($r !== 1)) { - return($r); - } - } - } - - function filenames() { - global $config; - $r = array(); - for ($n=0; $n<1000; $n++) { - if (!isset($config[$n])) break; - $r[] = $config[$n]; - } - return($r); - } - - #------------------------------------------------------------------------ - - function regex_getopts($regexopts) { - if (empty($_SERVER)) { - $_SERVER = $GLOBALS["HTTP_SERVER_VARS"]; - } - if (!empty($GLOBALS["argc"])) { - $_SERVER["argc"] = $GLOBALS["argc"]; - $_SERVER["argv"] = $GLOBALS["argv"]; - } - $opts = array(); - for ($n = 1; $n < $_SERVER["argc"]; $n++) { - foreach ($regexopts as $opts_id => $optsregex) { - $value = false; - $next = @$_SERVER["argv"][$n+1]; - if (preg_match($optsregex, $_SERVER["argv"][$n]." ".$next)) { - $opts[$opts_id] = $next; - continue 2; - } - elseif (preg_match($optsregex, $_SERVER["argv"][$n])) { - $value = 1; - if ($next && ($next[0] != "-")) { - $value = $next; - $n++; - } - $opts[$opts_id] = $value; - continue 2; - } - } - $opts[] = $_SERVER["argv"][$n]; - } - return($opts); - } - #------------------------------------------------------------------------- - - -?> \ No newline at end of file diff --git a/mods/wiki/tools/ewikictl.bat b/mods/wiki/tools/ewikictl.bat deleted file mode 100755 index c635bb12e..000000000 --- a/mods/wiki/tools/ewikictl.bat +++ /dev/null @@ -1,13 +0,0 @@ -@ECHO OFF -GOTO _dos -echo This program requires DOS. -exit - -:_dos -set PHP=PHP.EXE -IF EXIST C:\PHP\PHP-CGI.EXE set PHP=C:\PHP\PHP-CGI.EXE -If EXIST C:\PHP\PHP.EXE set PHP=C:\PHP\PHP.EXE -IF EXIST C:\PHP\PHP-CLI.EXE set PHP=C:\PHP\PHP-CLI.EXE - -%PHP% ewikictl %1 %2 %3 %4 %5 %6 %7 %8 %9 - diff --git a/mods/wiki/tools/index.html b/mods/wiki/tools/index.html deleted file mode 100644 index 2706fa24a..000000000 --- a/mods/wiki/tools/index.html +++ /dev/null @@ -1,259 +0,0 @@ - - - ewiki administration + database tools - - - - - -

          - - admin+database tools/ -

          - - The following web-based utilities provide raw access to your Wikis - database and allow for common administration tasks. They are separate from - the main wiki and are inaccessible without password for obvious reasons. - You can however use the account "readonly" with password - "test" on your local computer or our demo site. - -
          -
          - - - - -
          - - -
          - flags -

          page flags

          - Every page can have multiple control flags and feature settings - enabled, like _DISABLED, _READONLY, _APPENDONLY, ... But this tool - does not show all of them. -
          - -
          -
          - cross -

          remove pages

          - You can completely delete unused or unwanted pages from the database. - This tool even analyzes all entries and gives you recommendations on - which pages to purge. -
          - -
          -
          - fire -

          strip old versions

          - Every page edit adds an "archive version", which is good to revert - unwanted changes. You should however clean up a few and free database - space from time to time. -
          - -
          -
          - glass -

          check link directory

          - Can check external hyperlinks, if you have pages which collect such - (link directories). -
          - -
          -
          -

          control

          - This tool from the plugins/admin/ section allows to delete and - rename a , or to set the - flags or meta data fields in it:
          -
          - - -
          -
          - -
          -
          - text+ -

          text insert

          - Insert a collection of plain text files as wiki pages into the database - (no versioned files). The files must already reside on the Web server - (like files init-pages/ dir). -
          - -
          -
          - loadin -

          TextUpload

          - If you don't have this powerful plugin loaded, then you can access it - at least from here, and upload pages from many different file formats - and even multiple pages packed in .zip or .tar files. -
          - - - - -
          - -
          - disk+ -

          backup

          - Archives all your pages in backup files (available in different - formats) for archival / later emergency restoration. You need a - writeable data directory on your Web server. -
          - -
          -
          - disk↓ -

          restore

          - Restore your database from archived backup files, which you must - upload before into a directory on the Web server. -
          - -
          -
          - suitcase -

          transfer file

          - Use this tool to quickly get a backup of all Wiki pages or to restore - it later. You directly upload or get a data file in binary format, - which eases moving pages from one installation to another. With the - MiniDump plugin you could get a tar. -
          - -
          -
          - A→E -

          database convert

          - This tool can migrate pages from a few known foreign Wiki databases to - the DB scheme used by ewiki. It can also export back to PhpWiki now. -
          - -
          -
          - SPAM -

          mass revert

          - Use this tool to undo mass changes made by an attacker or an automated - wiki garbaging script. The offending revisions are discovered by - providing the IP or host name under which the edits were stored. -
          - -
          -
          -

          search and replace

          - Provides a global search feature, which can even use regex to find - string occourences and replace them with defined text fragments. It - can run a safe dry test. -
          - -
          -
          - antenna -

          sync

          - Transfer the contents of this Wikis database onto a remote - installation or the other way round. Useful for editing pages offline, - while keeping a public Wiki installation up-to-date. -
          - - - - -
          - -

          power toys

          - - Some of the older and more simple tools on the left have been surpassed - by more powerful/combined ones (which on the other hand are then not - easier to use for everyone). - -
          - -
          -
          -

          commander

          - The WikiCommander provides an easy file viewer like interface - to inspect and modify pages and all their internal flags and fields. - You can also delete, rename or duplicate pages. It even provides a - shell-like interface for inserting common actions into a - "commandline". -
          - So this effectively replaces a few of the early utilities. -
          - -
          -
          -

          ewikctl/web

          - ewikictl is a powerful commandline utility, but you need - shell (ssh) access on the Web server to use it. There is however - now this web-based frontend for all other users, which gives access - to most of its commands. -
          - -
          -
          -

          setup wizard

          - With the SetupWizard you can more easily create a custom - config.php script or even a monsterwiki.php file - (combination of the ewiki core and plugin files). This saves you - looking into README.plugins if you - can live without a few advanced features. -
          - -
          -
          -

          run cron.d/

          - If you haven't a cron daemon you can start the automated database - admin tools by hand on occassion. They however need a bit - configuraton prior use (very little of it is enabled per default). -
          - - -
          -
          -

          WikiTools

          - - If you had the right plugins loaded, you'd also get in-Wiki - powertools like: -
          - · WikiDump and the enhanced - WikiDump2 can make a tarball with static - .html files from all your pages
          - · use TextUpload for uploading many pages - in a ZIP or Tarball
          - · MiniDump to get a tarball with raw text - of all pages (for later reinsertion)
          -
          - -
          - - -
          - -
          - - - diff --git a/mods/wiki/tools/mergeplugins b/mods/wiki/tools/mergeplugins deleted file mode 100755 index f77fff5f5..000000000 --- a/mods/wiki/tools/mergeplugins +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/local/bin/php -qC - \ No newline at end of file diff --git a/mods/wiki/tools/metacache b/mods/wiki/tools/metacache deleted file mode 100755 index c8438a49c..000000000 --- a/mods/wiki/tools/metacache +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/local/bin/php -qC -$i) if ($_) { - echo " $_ = $i\n"; -} -echo "\n"; - - - -#-- debug -#print_r($ewiki_pmd); - -#$list = array_keys($ewiki_pmd); -#$i = ewiki_pmd_get_plugin_files($list); -#print_r($i); - -?> \ No newline at end of file diff --git a/mods/wiki/tools/mkhuge b/mods/wiki/tools/mkhuge deleted file mode 100755 index c96bb7bc9..000000000 --- a/mods/wiki/tools/mkhuge +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/sh -# -# a shell script, which combines the ewiki.php library and some -# default plugins into a huger includeable script file -# - - -HUGE_FILE="monsterwiki.php" -CORE_FILE="ewiki.php" - -PLUGINS3=" - markup_phpwiki.php markup_bbcode.php spellcheck.php - page_orphanedpages.php page_aboutplugins.php search_highlight.php - mpi/mpi.php downloads.php contrib/page_wikinews.php - contrib/aview_imgappend.php contrib/page_phpinfo.php - " -PLUGINS2=" - contrib/more_interwiki.php contrib/page_imagegallery.php - contrib/page_hitcounter.php title_calendar.php - page_wantedpages.php contrib/f_fixhtml.php - " -PLUGINS1=" - diff.php page_randompage.php markup_footnotes.php - page_wordindex.php calendar.php notify.php - " -PLUGINS0=" - ../fragments/strip_wonderful_slashes.php - ../fragments/strike_register_globals.php - imgresize_gd.php markup_css.php patchsaving.php - email_protect.php like_pages.php - page_pageindex.php page_powersearch.php - " - - - -#-- current dir -if [ -e "ewiki.php" ] ; then - DWP=. -else - DWP=.. -fi - - -#-- help -if [ "$1" == "-h" -o "$1" == "--help" ] ; then - echo "syntax: mkhuge [3|2|1|0]" - echo "combines many of the plugins and the core ewiki.php file into a bigger lib" - exit -fi - - -#-- choose size -N=$1 -if [ -z "$N" ] ; then - N=2 -fi -if [ "$N" -ge "3" ] ; then - PLUGINS="$PLUGINS3 $PLUGINS" -fi -if [ "$N" -ge "2" ] ; then - PLUGINS="$PLUGINS2 $PLUGINS" -fi -if [ "$N" -ge "1" ] ; then - PLUGINS="$PLUGINS1 $PLUGINS" -fi -PLUGINS="$PLUGINS0 $PLUGINS" - - -#-- proceed -D="$DWP/$HUGE_FILE" -rm -f "$D" -touch "$D" -echo "combining: " -for ADD in $PLUGINS -do - echo " +$ADD" - for SUB in plugins fragments ; do - if [ -e "$DWP/$SUB/$ADD" ] ; then - ADD=$DWP/$SUB/$ADD - fi - done - cat $ADD >> $D -done -echo " +$CORE_FILE" -cat $DWP/$CORE_FILE >> $D -echo "into $D" - - diff --git a/mods/wiki/tools/mkpageplugin b/mods/wiki/tools/mkpageplugin deleted file mode 100755 index f75a9fa76..000000000 --- a/mods/wiki/tools/mkpageplugin +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/local/bin/php -qC -" - . $c - . "<"."?php\n\n" - . " \$o = ob_get_contents();\n" - . " ob_end_clean();\n\n" - . " headers(implode(\"\n\", \$ewiki_headers));\n" - . " return(\$o);"; - } - $cn2.= "\n\n}\n\n?".">"; - - #-- output file name - $fn2 = "page_{$id}.php"; - if (($r = strrpos($file, "/")) !== false) { - $fn2 = substr($file, 0, $r + 1) . $fn2; - } - - #-- write dest plugin - echo "converting $file to $fn2 plugin...\n"; - if ($f = fopen($fn2, "w")) { - fwrite($f, $cn2); - fclose($f); - } - else { - echo "ERROR: cannot write to '$fn2'\n"; - } - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/tools/mkpluginmap b/mods/wiki/tools/mkpluginmap deleted file mode 100755 index a13261f9d..000000000 --- a/mods/wiki/tools/mkpluginmap +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/local/bin/php -qC -# $sect = strtok($sect, "_"); - foreach ($a as $name=>$pf) { - $found[$sect][] = array($name, $fn, $pf, 0); - } - } - - } - -} - - -function mkpm_dump($found) { - global $ewiki_config; - foreach (array("action", "action_always", "page") as $sect) { - if ($list = @$found[$sect]) { - echo "\$ewiki_plugins[\"dl\"][\"{$sect}\"] = array(\n"; - foreach ($list as $a) { - echo "#\t\"{$a[0]}\" => array(\"{$a[1]}\", \"{$a[2]}\", {$a[3]}),\n"; - } - echo ");\n\n"; - } - } - foreach ($ewiki_config["action_links"] as $where=>$a) { - foreach ($a as $action=>$title) { - echo "\$ewiki_config[\"dl\"][\"action_links\"][\"$where\"][\"$action\"] = \"$title\";\n"; - } - } - echo "\n"; -} - - - -function ewiki_t($a,$b=0) { - return($a); -} - -?> \ No newline at end of file diff --git a/mods/wiki/tools/mkxpi b/mods/wiki/tools/mkxpi deleted file mode 100755 index 48aacc2aa..000000000 --- a/mods/wiki/tools/mkxpi +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/local/bin/php -Cq - tags. - For "page" plugins it is simply the code (no function definition!) that - would normally be put into a page plugin func, but that you cannot use - return() and instead throw all output via the '$o' variable (workaround). - - For "init" (any type: string will do) xpi plugins, you can add function - definitions and ewiki_plugin[] registry settings as usual. The execution - of that code is however not guaranteed to happen in global scope - most - of the ewiki_* vars are however accessible. - - The special "jpi" type plugins are "page" plugins, but you must use - JavaScript code, so it can safely be executed in a sandbox (phpjs) - with the limited WikiApi functionality. Then however everybody can - install those .jpi plugins. (not yet ready) -*/ - - -function srcxpi2xpi($str) { - - $xpi = array( - "XPI" => "0.1", - "engine" => "ewiki", - ); - - $uu = preg_split('/^(\w+):/m', $str, $uu, PREG_SPLIT_DELIM_CAPTURE); - for ($i=1; $i/', '', $xpi["code"])); - } - - #-- .jpi - if ($xpi["type"] == "jpi") { - $xpi["JPI"] = $xpi["XPI"]; - } - - return($xpi); -} - - -if ($file = $_SERVER["argv"][1]) { - echo "reading '$file'..."; - if ($src = implode("", file($file))) { - $r = srcxpi2xpi($src); - if ($fn = $r["id"]) { - echo " passed.\n"; - $fn .= ($r["JPI"] ? ".jpi" : ".xpi"); - echo "writing '".$fn."'..."; - if ($f = gzopen($fn, "wb9")) { - gzwrite($f, serialize($r)); - gzclose($f); - echo " done."; - } - echo "\n"; - } - else { - echo " invalid sorce file.\n"; - } - } -} -else { - echo "syntax: mkxpi xpi-src-file\n"; -} - -?> \ No newline at end of file diff --git a/mods/wiki/tools/setup b/mods/wiki/tools/setup deleted file mode 100755 index 741d4ba29..000000000 --- a/mods/wiki/tools/setup +++ /dev/null @@ -1,815 +0,0 @@ -#!/usr/local/bin/php -qC - "ewiki.ini", - ".\$php" => "config.php", - ".\$mwiki" => "monsterwiki.php", - "DB_INIT" => "mysql_connect(localhost,user,password) && mysql_query(dbname)", - "EWIKI_DB_TABLE_NAME" => "ewiki", - "EWIKI_DB_UTF8" => 0, - "EWIKI_DB_BIN64" => 0, - "EWIKI_DBFILES_DIRECTORY" => "./files/", - "EWIKI_DBFILES_GZLEVEL" => 0, - "EWIKI_DB_FAST_FILES" => 0, - "EWIKI_DBFF_ACCURATE" => 0, - "DZF2_HIT_COUNTING" => 1, - "EWIKI_DBA" => "/tmp/mywiki.flatfile", -); -$set = $set_init; -$priority_1 = "core,required,standard,default,important"; -m_reset(); // initial settings -m_load_dat(); // load backup values - - -#-- menus ---------------------------------------------------------------- -$menus = array( - "MAIN" => array( - array("PLUGINS", "Select plugins", "List available extension plugins to enable or disable them.", ""), - array("OPTIONS", "Tweak configuration options and plugin settings", "Override and pre-define constants and configuration variables.", "m_options"), - array("DATABASE", "Choose and configure database backend", "Unlike the backend selection under plugins, this entry is for auto-initialization.", "m_database"), - array("SAVE_PHP", "Generate \"config.php\"", "Exports a ready-to-use ewiki config include script.", "m_save_php"), - array("SAVE_INI", "Generate \"ewiki.ini\"", "An .ini file can contain all plugin and configuration options.", "m_save_ini"), - array("SAVE_WIKI", "Generate \"monsterwiki.php\" script", "All plugins and settings get merged into one script.", "m_save_mwiki"), - array("LOAD_PHP", "Decipher settings from \"config.php\"", "Reading from .php scripts is not reliable.", "m_load_php"), - array("LOAD_INI", "Load settings from \"ewiki.ini\"", "Save settings into an reusable .ini-style configuration file.", "m_load_ini"), - array("DONE", "Exit this tool", "Automatically saves current plugin and config settings. Press ^C else.", "m_exit"), - array("HELP", "Documentation", "Additional usage informations for this utility.", "m_help"), -/* array("IDENTIFIER", // denotes next/sub menu - * "Title", "Help text", // for display - * "func_handler(arg2)", // entry handler, if no sub menu - * "func_mangle_display_menu", // callback, tweaks title with $set values */ - ), - "OPTIONS" => array( - // automatically emptied sub menu, so the menu() selection ignores it - ), - "PLUGINS" => array( - array("PLUGINLIST", "All plugins in one list", "Gives complete overview over available plugins, alphabetical but rough listing.", "m_checklist_plugins()"), - array("FAVORITES", "Enable plugins by priority / favorites", "Selects multiple plugins/features at once.", ""), - ), - "FAVORITES" => array( - array("PR_core", "priority: core - plugins that must be loaded", "Core and required plugins.", "m_enable_by_priority(core,required)"), - array("PR_standard", "add standard plugins - loaded in default setup", "", "m_enable_by_priority(core,required,standard,default)"), - array("PR_important", "add important plugins - highly recommended", "", "m_enable_by_priority(important)"), - array("PR_recommended", "add recommended plugins", "", "m_enable_by_priority(recommended)"), - array("PR_optional", "add optional plugins", "", "m_enable_by_priority(optional)"), - array("PR_extra", "add extra plugins", "", "m_enable_by_priority(extra)"), - array("RESET", "Reset plugin list and options (to standard)", "All core plugins will be selected.", "m_reset"), - array("FAV_mario", "personal favorites of: Mario", "http,rss,qdiff,mpi,flat_files,textupload,limit_links,rc,wikinews,...", "m_enable_list(fix,http,http_cache,xml,feed,feedparse,raw,diff,rss,like_pages,htm,info_qdiff,email_protect,jump,notify,fancy_list_dict,flat_files,imgresize_gd,search_highlight,editable,xmlrpc,opensearch,linkdatabase,css,,definitionlinks,mpi,mpi_backtree,mpi_embed,mpi_insert,mpi_survey,mpi_syndicate,mpi_backlinks,mpi_localsitemap,mpi_tableeditor,mpi_addlink,aboutplugins,powersearch,textupload,wikinews,recentchanges,authorname,limitlinks,ewiki)"), - ), - "DATABASE" => array( - array("DB_PLUGIN", "Choose database backend", "Only one generic plugin/backend should be chosen.", "m_checklist_plugins(database)"), - array("DB_INIT", "Define how to initialize database / connect to it", "Initialization is mostly necessary for SQL databases only.", "m_set_option2(Set the SQL/DBA database initialization using its generic initialization function call, but that the syntax is restricted here - absolutely NO spaces and quotation marks around the arguments. For MySQL you`d use mysql_connect(, for PgSql you say anydb_connect( or pg_connect( and for Berkely/Sleepycat DBA files you set this to dba_open( instead."), - array("DB_OPTIONS", "Set other parameters for your database plugin", "Unsorted list, not all constants/settings apply to all database types.", ""), - ), - "DB_OPTIONS" => array( - array("EWIKI_DB_TABLE_NAME", "SQL table name (ewiki)", "[sql] database table name", "m_set_option(mysql)"), - array("EWIKI_DB_UTF8", "Code UTF-8 from/to database (Postgres)", "[pgsql] unicode2latin", "m_set_option(anydb)"), - array("EWIKI_DB_BIN64", "Encipher binary entries in the database (Postgres)", "[pgsql] binary as base64 encoded TEXT columns", "m_set_option(anydb)"), - array("EWIKI_DBFILES_DIRECTORY", "where to store flat files (./files/)", "[flat_files] storage directory", "m_set_option(flat_files)"), - array("EWIKI_DB_FAST_FILES", "fast file format, php serializiation (0)", "[flat_files] use `application/vnd.php.serialized` format", "m_set_option(flat_files)"), - array("EWIKI_DBFILES_GZLEVEL", "compress flat files (0)", "[flat_files] compression", "m_set_option(flat_files)"), - array("EWIKI_DBFF_ACCURATE", "more correct return values {slower} for some functions (dzf2)", "[flat_files/dzf2] correctness vs. speed", "m_set_option(dzf2)"), - array("DZF2_HIT_COUNTING", "count page acccess (dzf2)", "[flat_files/dzf2] hits", "m_set_option(dzf2)"), - array("EWIKI_DBA", "Berkely/Sleepycat DBA storage file", "[dba] filename", "m_set_option(dba)"), - ), -); -#-- append plugin list menus -foreach (ewiki_pmd_by_category() as $cat=>$ls) { - $menus["PLUGINS"][] = array("$cat/", "category $cat", "", "m_checklist_plugins($cat)"); -} - - - -#-- main loop ------------------------------------------------------------ -$menu="MAIN"; -do { - menu(); -} -while (true); - -#-- display and switch between menus, call menu functions, dialog interface -function menu($GOTO="", $BACK="MAIN") -{ - global $menus, $menu, $dialog_exit; - static $menu_stack = array(); - - #-- display - $next = dialog::menu($menus[$menu], "ewiki setup/config tool", "$menu menu"); - - #-- see what to do - if ($menus[$next]) { - array_push($menu_stack, $menu); - $menu = $next; - } - elseif ($dialog_exit=="1") { - $menu = array_pop($menu_stack); - if (!$menu || !$menus[$menu]) { - $menu = $BACK; - } - } - else { - #-- search selected entry - foreach ($menus[$menu] as $l) { - if ($l[0] == $next) { - $selected = $l; - } - } - #-- call - if ($selected) { - m_call_func($selected[3], $next); - } - } -} - - - - -#== control code ($set plugins) ========================================== - - -#-- enable/disable single plugin -function m_switch_plugin($id, $id2) { - global $set; - if ($set[$id]) { - $set[$id] = false; - } - else { - $set[$id] = true; - } -} - - -#-- set plugin state from (inclusion) priority class -function m_reset() -{ - global $set, $ewiki_pmd, $priority_1; - foreach ($ewiki_pmd as $id=>$row) { - $set[$id] = false; - } - m_enable_by_priority("", $priority_1); -} - - -#-- set plugins from comma separated priority list -function m_enable_by_priority($next, $priority) -{ - global $set, $ewiki_pmd; - $priority = ",,,$priority,"; - foreach ($ewiki_pmd as $id=>$row) { - if (strpos($priority, ",$row[priority],")) { - $set[$id] = true; - } - } -} - - -#-- enable plugins by name (favorite lists) -function m_enable_list($next, $list) -{ - global $set, $ewiki_pmd; - foreach (explode(",", $list) as $id) { - $set[trim($id)] = true; - } -} - - -#-- load setup.dat from last session -function m_load_dat() { - if ($dat = file_get_contents("tools/setup.dat")) { - $GLOBALS["set"] = unserialize($dat); - } -} - - -#-- handles function calls in menus -function m_call_func($funcdef, $arg1) { - $func = strtok($funcdef, "("); - $args = array($arg1, strtok(")")); - call_user_func_array($func, $args); -} - - -#-- callback function, which mangles the displayed title for -# menu entries in the plugin section (injects values from $set[]) -function m_inj_menu_set(&$title, $row) { - global $set; - $id = $row[0]; - if (isset($set[$id])) { - $title = str_pad($title, 30, " ") - . " " . ($set[$id]? "[YES]":"[NO]"); - } -} - - -#-- show checkboxes to enable plugins from a category -function m_checklist_plugins($next, $cat) { - global $set, $ewiki_pmd; - $list = array(); - foreach (ewiki_pmd_by_category() as $c=>$ls) { - if (!$cat || ($cat==$c)) { - foreach ($ls as $id=>$row) if (!ewiki_pmd_hidden($row)) { - $list[$id] = array($id, $row["title"], $row["description"]); - } - } - } - ksort($list); - dialog::check($list, $set, "ewiki setup/config tool", "enable or disable $cat plugins"); -} - - -#-- help screen for plugins -function m_plugin_info($id) { - global $ewiki_pmd; - if (!$ewiki_pmd[$id]) { - $id = preg_replace("/[^\w\d]/", "", $id); - foreach ($ewiki_pmd as $i=>$row) { - if ($id == preg_replace("/[^\w\d]/", "", $row["description"])) { - $id = $i; - break; - } - } - } - if ($row = $ewiki_pmd[$id]) { - $text = "id: $id\n"; - foreach ($row as $i=>$v) { - $text .= "$i: $v\n"; - } - $text = strtr($text, "'", "`"); - dialog::real("--title '$id' --msgbox '$text' 18 70"); - } -} - - - - -#== $set options ========================================================= - - -#-- dynamic sub-menu -function m_options() { - global $menu, $menus, $opts_l; - global $set, $ewiki_pmd; - - #-- hack, calls main menu() function for display - $menu = "OPTIONS"; - do { - - #-- regenerate menu (in case something changed) - $opts_l = get_option_list(); - $menus["OPTIONS"] = array(); - foreach ($opts_l as $row) { - list($name, $val, $help, $id, $default) = $row; - if (OPTIONS_SPACING && ($id != $last_id)) { - $menus["OPTIONS"][] = array(" [$id]", "", "", ""); - $last_id = $id; - } - $menus["OPTIONS"][] = array($name, "$val", "[$id] $help (default=$default)", "m_set_option($id)"); - } - - menu(); - } while (($menu != "MAIN") - && ($menus["OPTIONS"])); - $menus["OPTIONS"] = array(); -} - - -#-- settings from all enabled and auto plugins -function get_option_list() { - $ls = array(); - foreach (final_plugin_list() as $id) { - foreach (get_config_options($id) as $row) { - $ls[$row[0]] = $row; - } - } - return($ls); -} -function get_config_options($id) { - global $ewiki_pmd, $set; - $r = array(); - foreach (explode("\n", $ewiki_pmd[$id]["config"]) as $line) { - if (preg_match("#^(.+?)=(.*?)(?:\s//(.+))?$#", trim($line), $uu)) { - $name = trim($uu[1]); - $value = trim($uu[2]); - $value = preg_replace("#^(\d)\|\d$#", "$1", $value); // for "0|1" - $value = preg_replace("#^\"([^\d].*)\"$#", "$1", $value); - $help = trim($uu[3]); - if (!isset($set[$name])) { - $set[$name] = $value; // set default config value - } - $r[] = array($name, $set[$name], $help, $id, $value); - } - } - return($r); -} - - -#-- edit config setting -function m_set_option($name, $id) { - global $set, $opts_l; - dialog::edit("$name", $set[$name], "Change configuration option/constant", "This setting is defined/used by the `$id` plugin.\n\n" . $opts_l[$name][2] . "\n\n"); -} - -#-- help from 2nd parameter (instead of $opts_l) -function m_set_option2($name, $help) { - global $set; - dialog::edit("$name", $set[$name], "Set option", $help); -} - - - - - -#-- safe+load code ------------------------------------------------------- - - -#-- save ewiki.ini -function m_save_ini() { - global $set, $dialog_exit; - dialog::edit(".\$ini", $set[".\$ini"], "Save configuration as ewiki.ini file", "Give the filename under which to save the current settings. Beware, that any existing file will be overwritten."); - if ($dialog_exit) { return; } - file_put_contents($set[".\$ini"], m_mk_ini()); -} - - -#-- generate ewiki.ini -function m_mk_ini() { - global $set, $ewiki_pmd; - - #-- start ewiki.ini - $T = "; automatically generated configuration summary\n; see ewiki config wizard\n"; - $T .= "\n[db]\n"; - if ($set["DB_INIT"]) { - $T .= "init = ".$set["DB_INIT"]."\n"; - } - else { - $T .= "; no initialization necessary, or no database backend specified\n"; - } - - #-- config - $T .= "\n[settings]\n"; - foreach (get_option_list() as $row) { - $T .= "$row[0] = $row[1]\n"; - } - - #-- plugins - $T .= "\n[plugins]\n"; - foreach (final_plugin_list() as $id) { - if ($fn = $ewiki_pmd[$id]["fn"]) { - $T .= "load = $fn\n"; - } - else { - $T .= ";load = $id\n"; - } - } - return($T . "\n"); -} - - -#-- save config.php -function m_save_php() { - global $set, $dialog_exit; - dialog::edit(".\$php", $set[".\$php"], "Save configuration as config.php file", "To which filename do you wish the configuration script to be written? This will overwrite any existing file."); - if ($dialog_exit) { return; } - file_put_contents($set[".\$php"], m_mk_php()); -} - - -#-- generate config.php body -function m_mk_php($with_plugins=1) { - global $set, $ewiki_pmd; - - #-- start config.php - $T = ""); -} - - -#-- save config.php -function m_save_mwiki() { - global $set, $ewiki_pmd, $dialog_exit; - dialog::edit(".\$mwiki", $set[".\$mwiki"], "Export a MonsterWiki", "Merge all plugins and configuration data into one giant PHP script."); - if ($dialog_exit) { return; } - - #-- merge everything together - $f = fopen($mwiki=$set[".\$mwiki"], "wb"); - fwrite($f, m_mk_php($_with_plugins=0)); - $list = final_plugin_list(); - foreach ($list as $n=>$id) { - if (file_exists($fn = $ewiki_pmd[$id]["fn"])) { - fwrite($f, file_get_contents($fn)); - } - d_gauge($n, count($list), "assembling $mwiki", 75000, 2); - } - fclose($f); - d_gauge(0,0); -} - - -#-- add dependencies to $set array, send list -function final_plugin_list($add_required=1) { - global $set, $ewiki_pmd; - if ($add_required) { - m_enable_by_priority(".FINALIZE", "core,required"); - } - $list = array(); - foreach ($set as $id=>$state) { - if ($id && $state && $ewiki_pmd[$id]) { - $list[] = $id; - } - } - ewiki_pmd_resolve_dependencies($list, $_add_suggested=0); - return($list); -} - - - - -#== loading ============================================================== - - -#-- load from ewiki.ini file (without [para] dissection) -function m_load_ini() { - global $set, $set_init, $dialog_exit, $ewiki_pmd; - $pmd_by_fn = ewiki_pmd_by("fn"); - - #-- from which file - $new = array(); - dialog::edit(".\$ini", $set[".\$ini"], "Import configuration settings from .ini file", "Select the .ini file to load. Most current configuration settings will be forgotten."); - if ($dialog_exit) { return; } - - #-- read in - if ($txt = file_get_contents($set[".\$ini"])) { - #-- database - if (preg_match("/^ *init *= *([^\n]+)/m", $txt, $uu)) { - $new["DB_INIT"] = $uu[1]; - } - #-- plugins - if (preg_match_all("/^ *load *= *([^\s]+)/m", $txt, $uu)) { - foreach ($uu[1] as $i=>$fn) { - if (! ($id = $pmd_by_fn[$fn])) { - if (preg_match("/(^|\/)([-\d\w_]+)\.php$/m", $fn, $uu)) { - $id = $uu[2]; - } - else { - $id = $fn; // (useless) - } - } - $new[$id] = true; - } - } - #-- config - if (preg_match_all("/^ *([A-Z\$][^\s]+) *= *([^\n]+)/m", $txt, $uu)) { - foreach ($uu[1] as $i=>$v) { - $new[$uu[1][$i]] = trim(trim($uu[2][$i]), "\""); - } - } - } - - #-- merge in old/minumum data - foreach ($set_init as $i=>$v) { - if (!isset($new[$i])) { - $new[$i] = isset($set[$i]) ? $set[$i] : $set_init[$i]; - } - } - $set = $new; -} - - -#-- import settings from config.php (mostly guessing) -function m_load_php() { - global $set, $set_init, $dialog_exit, $ewiki_pmd; - $pmd_by_fn = ewiki_pmd_by("fn"); - - #-- from which file - $new = array(); - dialog::edit(".\$php", $set[".\$php"], "Guess configuration settings from config.php script", "Choose the ewiki config script. Currently made plugin selections and option settings will get unset/replaced."); - if ($dialog_exit) { return; } - - #-- read in - if ($txt = file_get_contents($set[".\$php"])) { - #-- database - if (preg_match("/\b(@*(mysql_p?connect|anydb_connect|dba_open)\(.+?\))\b/m", $txt, $uu)) { - $new["DB_INIT"] = preg_replace("/[\s+\"\']/", "", $uu[1]); - } - #-- plugins - if (preg_match_all("/^ *@*include(?:_once)? *\(? *[\"\']([^\s\"\']+)/m", $txt, $uu)) { - foreach ($uu[1] as $i=>$fn) { - if ($id = $pmd_by_fn[$fn]) { - $new[$id] = true; - } - elseif (preg_match("/(^|\/)([-\d\w_]+)\.php$/m", $fn, $uu)) { - $new[$uu[2]] = true; - } - } - } - #-- config - if (preg_match_all("/^ *(\$[^\s]+) *= *([^\n]+) *;/m", $txt, $uu)) { - foreach ($uu[1] as $i=>$v) { - $new[$uu[1][$i]] = trim(trim($uu[2][$i]), "\""); - } - } - if (preg_match_all("/^ *@*define *\( *[\"\']([A-Z][^\s]+)[\"\'] *,([^\n]+)\) *;/m", $txt, $uu)) { - foreach ($uu[1] as $i=>$v) { - $new[$uu[1][$i]] = trim(trim($uu[2][$i]), "\""); - } - } - } - - #-- merge in old/minumum data - foreach ($set_init as $i=>$v) { - if (!isset($new[$i])) { - $new[$i] = isset($set[$i]) ? $set[$i] : $set_init[$i]; - } - } - $set = $new; -} - - - - -#== menu helper code ===================================================== - -#-- wrapper -function m_exit() { - @header("ewiki-setup: 0.7"); - file_put_contents("tools/setup.dat", serialize($GLOBALS["set"])); - echo "- settings saved.\n"; - exit; -} - -#-- does nothing -function m_nop() { -} - -#-- show readme -function m_help() { - dialog::text("doc/SetupTool", "Help"); -} - - - - -#== terminal dialog ====================================================== -class dialog { - - - #-- preparations - function init() - { - global $dialog_bin, $dialog_add, $dialog_exit, $dialog_help, $dialog_fix, $dialog_nobg; - - #-- tweak PATH env variable for distributed `whiptail` - putenv("PATH=$_ENV[PATH]:".dirname(__FILE__)); - - #-- available tools - $progs = $_ENV["DISPLAY$_ENV[NO_X]"] - ? array( - "Xdialog" => array("--wrap --ignore --stderr", 1), -## "gdialog" => array("", 0, -1), // new zenity wrapper is incompatible -## "kdialog" => array("", 0, -1), // slow if KDE isn't already running -## "zenity" => array("", 0), // totally incompatible (a GNUish project) - ) - : array( - "$_ENV[DIALOG]" => array("--stderr", 0), - "dialog" => array("--stderr ", 1), - "whiptail" => array("", 0), - "cdialog" => array("--stderr", 1), - array_shift(glob("/usr/src/*-2.*/scripts/lxdialog/lxdialog")) => array("", 0, 0, "_INJ_BOGUS_UNDOC_PARAM_MENU"), - ); - - #-- search binary - foreach ($progs as $d=>$args) { - if ($dialog_bin = trim(`which $d`)) { - list($dialog_add, $dialog_help, $dialog_nobg, $dialog_fix) = $args; - return; - } - } - die("This script requires one of the dialog utilities (cdialog, whiptail, Xdialog).\n"); - } - - - #-- invoke dialog binary - function real($args, $adv="", $bg="ewiki setup/control tool") - { - global $dialog_bin, $dialog_add, $dialog_exit, $dialog_nobg; - - $keytmp = "/tmp/php.dialog.keystroke.tmp." . getmypid(); - if (!$dialog_add) { - $adv = ""; // this variant only supports most basic args - } - $cmd = "$dialog_bin"; - if (!$dialog_nobg) { $cmd .= " --backtitle '$bg'"; } - $cmd .= " $dialog_add $adv $args"; - -#echo "CMD: $cmd\n"; - system("$cmd >/dev/stdin 2>$keytmp", $dialog_exit); - $ret = trim(file_get_contents($keytmp)); - - unlink($keytmp); - return($ret); - } - - #-- escape param list into exec string - function params() { - $s = ""; - foreach (func_get_args() as $a) { - $s .= " '" . strtr($a, "'", "`") . "'"; - } - return($s); - } - - - #-- show list - function menu($list, $title, $text) - { - global $dialog_bin, $dialog_add, $dialog_exit, $dialog_help, $dialog_fix; - if ($dialog_help) { $adv = " --item-help"; } - $args = "--title '$title' --menu '$text' 20 70 11 $dialog_fix"; - foreach ($list as $n=>$l) { - list ($name, $line, $help, $_hfunc, $_mangle) = $l; -// if ($_mangle) { $_mangle($line, $l); } - $args .= dialog::params($name, $line); - if ($dialog_help) { $args .= dialog::params($help); } - } - return dialog::real($args, $adv); - } - - - #-- checkbox list - function check($list, &$states, $title, $text) - { - global $dialog_bin, $dialog_add, $dialog_exit, $dialog_help; - $current = $states; - - #-- args - $args = "--title '$title' --checklist '$text' 20 70 11"; - if ($dialog_help) { $adv = " --help-button --item-help"; } - $names = array(); - foreach ($list as $n=>$l) { - list ($name, $line, $help, $_hfunc, $_mangle) = $l; - $args .= dialog::params($name, $line, ($current[$name]? "on":"off")); - if ($dialog_help) { $args .= dialog::params($help); } - $names[] = $name; - } - - #-- display - do { - $rs = dialog::real($args, $adv); - if ($dialog_exit == "0") { - foreach ($names as $name) { - $current[$name] = strpos(" $rs", "\"$name\"")?true:false; - $set = $current; - } - } - if (substr($rs, 0, 5) == "HELP ") { - m_plugin_info(substr($rs, 5)); - $rs="HELP"; - } - } - while ($rs == "HELP"); - - #-- store - if (($dialog_exit == "0") && isset($set)) { - foreach ($names as $name) { - $current[$name] = strpos(" $rs", "\"$name\"")?true:false; - } - $states = $current; - } - } - - - #-- input box - function edit($name, &$var, $title="Change", $help="") - { - global $dialog_bin, $dialog_add, $dialog_exit; - $var = dialog::real("--title '$title' --inputbox '\n$help\n' 14 70 '$var'"); - } - - - #-- flags - function yesno($name, &$var, $title="Change", $help="") - { - global $dialog_bin, $dialog_add, $dialog_exit; - dialog::real("--title '$title' --yesno '$help' 15 60"); - $c = $dialog_exit; - if (($c==0)||($c==1)) { - $var = 1 - $c; //0=Yes, 1=No - } - } - - - #-- show file - function text($file, $title) - { - global $dialog_bin, $dialog_add, $dialog_exit; -# $file = dialog::params(file_get_contents($file)); - dialog::real("--title '$title' --textbox $file 21 72"); - } - -} - - -#-- gauge display -function d_gauge($i=0, $max=0, $title="initializing from *.meta data files", $pause=15000, $every=15) -{ - global $dialog_bin; - static $p, $last_max; - - #-- clean up again - if ($p && !$max) { - pclose($p); - $p = NULL; - $last_max = 0; - return; - } - #-- init - elseif (!isset($p) || ($last_max != $max)) { - $p = popen("$dialog_bin --gauge '$title' 7 72 000", "w"); - $last_max = $max; - } - - #-- output - if ($i && $max) { - $percent = (int) (100 * $i / $max); - fwrite($p, "$percent\n"); - - #-- delay - if (0 == $i % $every) { - if (function_exists("usleep")) { usleep($pause); } - } - } -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/tools/setup.dat b/mods/wiki/tools/setup.dat deleted file mode 100644 index 5563452cc..000000000 --- a/mods/wiki/tools/setup.dat +++ /dev/null @@ -1 +0,0 @@ -a:191:{s:5:".$ini";s:9:"ewiki.ini";s:5:".$php";s:16:"ewiki-config.php";s:7:".$mwiki";s:15:"monsterwiki.php";s:7:"DB_INIT";s:61:"mysql_connect(localhost,user,password) && mysql_query(dbname)";s:19:"EWIKI_DB_TABLE_NAME";s:0:"";s:13:"EWIKI_DB_UTF8";i:0;s:14:"EWIKI_DB_BIN64";i:0;s:23:"EWIKI_DBFILES_DIRECTORY";s:8:"./files/";s:21:"EWIKI_DBFILES_GZLEVEL";i:0;s:19:"EWIKI_DB_FAST_FILES";i:0;s:19:"EWIKI_DBFF_ACCURATE";i:0;s:17:"DZF2_HIT_COUNTING";i:1;s:9:"EWIKI_DBA";s:20:"/tmp/mywiki.flatfile";s:13:"auth_liveuser";b:0;s:16:"auth_method_http";b:0;s:14:"auth_perm_ring";b:0;s:14:"auth_perm_unix";b:0;s:11:"auth_phplib";b:0;s:14:"password_locks";b:0;s:19:"session_ip_verifier";b:0;s:16:"userdb_anonymous";b:0;s:12:"userdb_array";b:0;s:10:"userdb_sql";b:0;s:19:"userdb_systempasswd";b:0;s:19:"userdb_userregistry";b:0;s:15:"userdb_xprofile";b:0;s:10:"users_ldap";b:0;s:3:"you";b:0;s:7:"captcha";b:0;s:4:"core";b:1;s:4:"feed";b:0;s:9:"feedparse";b:0;s:3:"fix";b:0;s:4:"http";b:0;s:10:"http_cache";b:0;s:11:"libxprofile";b:0;s:10:"mime_magic";b:0;s:7:"minidav";b:0;s:10:"opensearch";b:0;s:14:"page_delegator";b:0;s:6:"phprpc";b:0;s:8:"protmode";b:0;s:14:"save_storevars";b:0;s:8:"shutdown";b:0;s:15:"spamblock_whois";b:0;s:11:"subpagelist";b:0;s:4:"sync";b:0;s:7:"upgrade";b:0;s:14:"uservars_pages";b:0;s:7:"wikiapi";b:0;s:3:"xml";b:0;s:6:"xmlrpc";b:0;s:10:"like_pages";b:0;s:7:"manpage";b:0;s:3:"raw";b:0;s:14:"relatedchanges";b:0;s:3:"rss";b:0;s:11:"translation";b:0;s:7:"verdiff";b:0;s:21:"page_searchandreplace";b:0;s:15:"fancy_list_dict";b:0;s:12:"listpages_br";b:0;s:13:"listpages_tbl";b:0;s:12:"listpages_ul";b:0;s:14:"title_calendar";b:0;s:9:"backlinks";b:0;s:4:"blog";b:0;s:8:"control2";b:0;s:12:"downloadlist";b:0;s:15:"fpage_copyright";b:0;s:10:"fpage_logo";b:0;s:9:"imgappend";b:0;s:8:"linktree";b:0;s:9:"pagetrail";b:0;s:12:"piclogocntrl";b:0;s:5:"posts";b:0;s:8:"subpages";b:0;s:7:"threads";b:0;s:3:"toc";b:0;s:3:"any";b:0;s:12:"binary_store";b:0;s:3:"dba";b:0;s:4:"dzf2";b:0;s:10:"flat_files";b:0;s:5:"mysql";b:1;s:7:"anacron";b:0;s:13:"announcements";b:0;s:14:"appendcomments";b:0;s:10:"appendonly";b:0;s:11:"appendwrite";b:0;s:8:"calendar";b:0;s:15:"collectuserdata";b:0;s:9:"downloads";b:0;s:9:"fset_blog";b:0;s:14:"imgfile_naming";b:0;s:12:"imgresize_gd";b:0;s:13:"imgresize_gd2";b:0;s:16:"imgresize_magick";b:0;s:8:"pingback";b:0;s:10:"refererlog";b:0;s:4:"tour";b:0;s:12:"uservars_gui";b:0;s:3:"xpi";b:0;s:4:"xpi0";b:0;s:9:"1emphasis";b:0;s:4:"abbr";b:0;s:8:"asciitbl";b:0;s:9:"braceabbr";b:0;s:3:"css";b:0;s:12:"css_singleat";b:0;s:15:"definitionlinks";b:0;s:9:"footnotes";b:0;s:9:"htmltable";b:0;s:12:"naturallists";b:0;s:10:"rescuehtml";b:0;s:7:"smilies";b:0;s:13:"table_colspan";b:0;s:13:"table_rowspan";b:0;s:3:"tex";b:0;s:9:"timestamp";b:0;s:13:"update_format";b:0;s:6:"usemod";b:0;s:13:"block_chinese";b:0;s:17:"builtincategories";b:0;s:7:"f_title";b:0;s:4:"meta";b:0;s:3:"mpi";b:0;s:11:"mpi_addlink";b:0;s:13:"mpi_backlinks";b:0;s:12:"mpi_backtree";b:0;s:8:"mpi_blog";b:0;s:13:"mpi_bugreport";b:0;s:18:"mpi_bugreportstate";b:0;s:9:"mpi_embed";b:0;s:12:"mpi_fallback";b:0;s:14:"mpi_farinclude";b:0;s:12:"mpi_honeypot";b:0;s:15:"mpi_inlineframe";b:0;s:10:"mpi_insert";b:0;s:16:"mpi_localsitemap";b:0;s:14:"mpi_multimedia";b:0;s:11:"mpi_phpwiki";b:0;s:17:"mpi_redirectlinks";b:0;s:16:"mpi_registerspam";b:0;s:16:"mpi_removedlinks";b:0;s:12:"mpi_settitle";b:0;s:15:"mpi_sparsetable";b:0;s:10:"mpi_survey";b:0;s:13:"mpi_syndicate";b:0;s:15:"mpi_tableeditor";b:0;s:14:"mpi_wikiscript";b:0;s:12:"aboutplugins";b:0;s:10:"addnewpage";b:0;s:13:"createnewpage";b:0;s:8:"ewikilog";b:0;s:10:"extractall";b:0;s:7:"fortune";b:0;s:10:"hitcounter";b:0;s:12:"imagegallery";b:0;s:12:"interwikimap";b:0;s:8:"minidump";b:0;s:13:"orphanedpages";b:0;s:11:"powersearch";b:0;s:10:"randompage";b:0;s:13:"recentchanges";b:0;s:8:"scandisk";b:0;s:13:"since_updates";b:0;s:7:"sitemap";b:0;s:10:"textupload";b:0;s:11:"wantedpages";b:0;s:8:"wikidump";b:0;s:9:"wikidump2";b:0;s:8:"wikinews";b:0;s:13:"wikiuserlogin";b:0;s:9:"wordindex";b:0;s:12:"EWIKI_SCRIPT";s:4:"?id=";s:10:"EWIKI_NAME";s:11:"UnnamedWiki";s:16:"EWIKI_PAGE_INDEX";s:9:"FrontPage";s:18:"EWIKI_DEFAULT_LANG";s:2:"en";s:17:"EWIKI_SPLIT_TITLE";s:1:"0";s:17:"EWIKI_PRINT_TITLE";s:1:"2";s:16:"EWIKI_LIST_LIMIT";s:2:"20";s:18:"EWIKI_CONTROL_LINE";s:1:"1";s:16:"EWIKI_ALLOW_HTML";s:1:"0";s:18:"EWIKI_HTTP_HEADERS";s:1:"0";s:14:"EWIKI_NO_CACHE";s:1:"1";s:15:"EWIKI_AUTO_EDIT";s:1:"1";s:19:"EWIKI_EDIT_REDIRECT";s:1:"1";s:22:"EWIKI_CASE_INSENSITIVE";s:1:"1";s:18:"EWIKI_HIT_COUNTING";s:1:"1";s:17:"EWIKI_RESOLVE_DNS";s:1:"1";} \ No newline at end of file diff --git a/mods/wiki/tools/t_backup.php b/mods/wiki/tools/t_backup.php deleted file mode 100644 index 417be01a6..000000000 --- a/mods/wiki/tools/t_backup.php +++ /dev/null @@ -1,92 +0,0 @@ - - - - generate backup files from ewiki pages - - - -

          database/page backup

          - - - - This tool is not intended to make a complete and safe backup of your ewiki - database, use PHPMySQLAdmin for such purposes; or save raw serialized(SQL - query results) with a dedicated script. -

          - -
          - - directory to save backup files:
          - -
          (either absolute or relative to location of ewiki.php)
          -
          - - backup format:
          - -
          Note that only the first three variants can be reinserted later.
          -
          - - versions store behaviour:
          -
          -
          - - other settings:
          - urlencode, write dbff-filenames assuming DOS filesystem restrictions (not required on UNIX systems)
          - enforce, override problems (use this only if first try failed)
          -
          - - -

          - - - - - ewikictl:
          \n
          \n\n\n"; - - $config["dest"] = $_REQUEST["dest"]; - $config["format"] = $_REQUEST["format"]; - $config["force"] = $_REQUEST["force"]; - $config["urlencode"] = $_REQUEST["urlencode"]; - - if ($_REQUEST["behaviour"]=="all") { - $config["all"] = 1; - } - - set_options_global(); - - command_backup(); - - - - echo "\n"; - - } - - -?> - - \ No newline at end of file diff --git a/mods/wiki/tools/t_checklinks.php b/mods/wiki/tools/t_checklinks.php deleted file mode 100644 index d4874ea71..000000000 --- a/mods/wiki/tools/t_checklinks.php +++ /dev/null @@ -1,116 +0,0 @@ - - - - check http:// links of a wiki page - - - -

          link check

          -
          -
          - - -

          - -

          - -
          -
          -
          -
          -'; - - } - else { - - echo "

          link checking starts...

          \n"; - set_time_limit(0); - - $ext404 = $_REQUEST["opt"]["404"]; - $modify = $_REQUEST["opt"]["modify"]; - - #-- single page mode - if ($_REQUEST["page_pattern"]==1) { - $id = $_REQUEST["page"]; - check_links_for($id, $ext404, $modify); - } - - #-- multiple pages - else { - $pat = trim($_REQUEST["page"], "*"); - $result = ewiki_db::SEARCH("id", $pat); - while ($row = $get->result) { - check_links_for($row["id"], $ext404, $modify); - } - } - - echo "
          done.

          "; - } - - -function check_links_for($id, $ext404=1, $modify=1) { - - echo "$id
          \n"; - - $get = ewiki_db::GET($id); - $content = $get["content"]; - - preg_match_all('_(http://[^\s"\'<>#,;]+[^\s"\'<>#,;.])_', $content, $links); - $badlinks = array(); - foreach ($links[1] as $href) { - - set_time_limit(20); - $d = @implode("", @file($href)); - - if ($ext404) { - if (strstr($d, "Apache/") && (stristr($d, "file not found") || stristr($d, "error 404"))) { - $d = ""; - } - } - if (empty($d) || !strlen(trim($d))) { - echo "[DEAD] $href
          \n"; - $badlinks[] = $href; - } - else { - echo "[OK] $href
          \n"; - } - } - - #-- if sometihng found, modify on request - if ($modify) { - #-- replace dead links - foreach ($badlinks as $href) { - $content = preg_replace("\377^(.*$href)\377m", ' µµ__~[OFFLINE]__µµ $1', $content); - } - - #-- compare against db content - if ($content != $get["content"]) { - - $get["content"] = $content; - $get["version"]++; - $get["author"] = ewiki_author("ewiki_checklinks"); - $get["lastmodified"] = time(); - - ewiki_db::WRITE($get); - echo "(updated)
          "; - } - } -} - - -?> - - \ No newline at end of file diff --git a/mods/wiki/tools/t_commander/80x25.css b/mods/wiki/tools/t_commander/80x25.css deleted file mode 100644 index 948dc12de..000000000 --- a/mods/wiki/tools/t_commander/80x25.css +++ /dev/null @@ -1,129 +0,0 @@ - -html,body{ - margin: 0px; - padding: 0px; -} - -/* --- basic colors --- */ -body { - background: #222722; - color: #dddddd; -} - -body,input,textarea { - font-family: monospace; - font-size: 18px; - line-height: 20px; -} - -a { - text-decoration: none; -} - - -/* --- special color schemes --- */ -.Menu { - background: #00a0b0; -} -.Menu a { - color: #000000; - padding: 0px 10px; -} -.KeyMenu { - background: #222722; -} -.KeyMenu a { - background: #00a0b0; -} - -.Exec, .CommandLine { - background: #222f22; - color: #cccccc; -} -.CommandLine { height: 24px; line-height: 20px; } -.CommandLine form { display:inline; } -.CommandLine input { - background:#202620; - font: 17px monospace; - line-height: 21px; - height: 22px; - color:#eeeeee; - border:0px; - width:70% -} - - - -/* --- generic blue panels --- */ -.Panel { - background: #0000c0; - border: 2px solid #cccccc; - color: #eeeeee; - padding: 2px; -} -.Panel th { - color: #c0c000; -} -.Panel td.fn { - overflow: cut; -} -.Panel td, .Panel th { - border-right: 2px solid #aaaaaa; -} -.Panel tr.selected, .Panel tr.selected td { - background: #20b0c0; -} -.Panel a { - color: #fff7f7; -} - -.SplashScreen { - padding: 5px; - color: #ffffff; -} -.SplashScreen td { - font-size: 60%; - font-family: sans-serif; -} - - -/* --- edit screen --- */ -.Edit { - border: 0px; -} -.Edit a {} -.Edit input, .Edit textarea, .Edit select { - background: #309090; - color: #ffffff; - font-size: 16px; - line-height: 16px; - border: 1px solid #206060; - border-width: 1px 0px 0px 1px; -} -.Edit input[type=submit] { - background: #906000; - font-size: 14px; - border: 1px outset red; -} -.Edit label { - color: #c0c010; - font-size: 75%; - font-weight: 600; -} -.Edit small input[type=checkbox] { - width: 13px; - height: 11px; -} - - - -/* --- in-page stuff --- */ -.msg { - background: #773322; - border: 1px solid #cc9922; - color: #eeeeee; - font-family: sans-serif; - margin: 7px; - padding: 2px; - display: block; -} diff --git a/mods/wiki/tools/t_commander/action.php b/mods/wiki/tools/t_commander/action.php deleted file mode 100644 index 8c9bac9c4..000000000 --- a/mods/wiki/tools/t_commander/action.php +++ /dev/null @@ -1,334 +0,0 @@ - - - - WikiCommander:CommandExec - - - - "cmd_ls", - "ll" => "cmd_ll", - "rm" => "cmd_rm", - "mv" => "cmd_mv", - "ren" => "cmd_ren", - "cp" => "cmd_cp", - "cat" => "cmd_cat", - "touch" => "cmd_touch", - "?" => "cmd_help", - "help" => "cmd_help", - "del" => "cmd_rm", - "move" => "cmd_ren", - "copy" => "cmd_cp", - "type" => "cmd_cat", - ); - $help = array( - "cmd_mv" => "syntax: mv FromPage ToPage\n

          \nrenames a page, and overwrites target page versions by that", - "cmd_ren" => "ren: works similar to 'mv' but refuses to overwrite existing page versions
          \n('move' is an alias to 'ren')", - "cmd_ls" => "ls: lists existing pages, accepts glob parameters", - "cmd_ll" => "ll: long/verbose page listing (see also 'ls --help')", - "cmd_cp" => "cp: duplicates a page completely to another name, and overwrites any existing target page versions", - "cmd_rm" => "rm: completely deletes pages so that even no backup version will remain in the database (irreversible)", - "cmd_touch" => "touch: updates {lastmodified} field of given pages - but beware: RecentChanges may get you!", - "cmd_help" => "syntax: help [command]
          or even [command] --help
          \n
          shows some notes on the given command", - "cmd_cat" => "syntax: help [command]
          or even [command] --help
          \n
          shows some notes on the given command", - ); - - #-- do - $pf = $funcs[$action]; - if (!$action) { - echo "nothing to do"; - } - elseif ($help[$pf] && (($args[0] == "--help") or ($args[0] == "-h") or ($args[0] == "-?"))) { - echo $help[$pf]; - } - elseif ($pf && function_exists($pf)) { - $pf($args); - } - elseif ($pf == "cmd_help") { - if ($args[0]) { - ($text = $help[$funcs[$args[0]]]) or ($text = "$args[0]: no help available"); - echo $text; - } - else { - echo "following commands are defined:
          \n"; - echo implode(", ", array_keys($funcs)); - } - } - else { - echo "unknown command '$action'\n"; - } - - } - - #-- oooops - else { - echo "unknown command() call\n
          "; - } - - - - - -#-- action calls / commands ----------------------------------------------- - - -#-- delete page completely -function cmd_rm($ls) { - foreach ($ls as $id) { - echo "deleting page '$id' ("; - while ($data = get_almost_latest($data, $id)) { - $version = $data["version"]; - if (ewiki_db::DELETE($id, $version)) { - echo "error/"; - } - echo "#$version "; - } - echo ")
          \n"; - } -} - - -#-- output page contents -function cmd_cat($ls) { - foreach ($ls as $id) { - if ($data = ewiki_db::GET($id)) { - echo htmlentities($data["content"]); - } - } -} - - -#-- directory listing -function cmd_ls($ls) { - if ((count($ls)==1) && ($ls[0]=="-l")) { - cmd_ll(NULL); - } - else { - $rx = preg_glob($ls); - $all = ewiki_db::GETALL(array("id")); - while ($row = $all->get()) { - if ($rx && !preg_match($rx, $row["id"])) { - continue; - } - echo $row["id"] . "\n"; - } - } -} - - -function cmd_ll($ls) { - echo "ll: not implemented"; -} - - -#-- renaming -function cmd_mv($ls, $bad=1) { - cmd_ren($ls, $bad); -} -function cmd_ren($ls, $overwrite=0) { - if (count($ls) != 2) { - echo "mv: needs exactly two arguments\n"; - } - else { - $old = $ls[0]; - $new = $ls[1]; - echo htmlentities("$old -> $new "); - if (bad_old_new($old, $new)) { - return; - } - while ($data = get_almost_latest($data, $old)) { - - $data["id"] = $new; - - if (ewiki_db::WRITE($data, $overwrite)) { - if (ewiki_db::DELETE($old, $data["version"])) { - echo "."; - } - else { - echo "(DE#$data[version])"; - $de += 1; - } - } - else { - echo "(WE#$data[version])"; - $we += 1; - } - - } - echo "\n

          \n"; - if ($we) { - echo "- $we write errors (target page existed)
          \n"; - } - if ($de) { - echo "- $de errors deleting source page versions (uh, bad!)
          \n"; - } - } -} - - -#-- duplication -function cmd_cp($ls) { - if (count($ls) != 2) { - echo "cp: needs exactly two arguments\n"; - } - else { - $old = $ls[0]; - $new = $ls[1]; - echo htmlentities("$old => $new "); - if (bad_old_new($old, $new, "TARGET_EXIST_WARN")) { - return; - } - while ($data = get_almost_latest($data, $old)) { - $data["id"] = $new; - if (ewiki_db::GET($new, $data["version"])) { - echo "(OW#$data[version])"; - $ow += 1; - } - if (ewiki_db::WRITE($data)) { - echo ". "; - } - else { - echo "(WE#$data[version])"; - $we += 1; - } - } - echo "\n

          \n"; - if ($ow) { - echo "- $ow target page versions overwritten
          \n"; - } - if ($we) { - echo "- $we write errors (uh, bad!)
          \n"; - } - } -} - - -#-- updated {lastmodified} stamps -function cmd_touch($ls) { - foreach ($ls as $id) { - if ($data = ewiki_db::GET($id)) { - echo "$data[id]
          \n"; - $data["lastmodified"] = time(); - ewiki_db::WRITE($data, $overwrite=1); - } - else { - echo "'$id' does not exist
          \n"; - } - } -} - - - - - -#-- helper calls --------------------------------------------------------- - - -function split_input($s) { - - $r = array(); - - while (strlen($s = ltrim($s))) { - - if (preg_match("/^\"([^\"]+|\\\")\"|^'([^']+|\\')'|^([^\s]+)/", $s, $uu)) { - if (($e = $uu[1]) || ($e = $uu[2])) { - $r[] = stripslashes($uu[1]); - } - else { - $r[] = $uu[3]; - } - } - else { - $r[] = $s; - } - - $s = substr($s, strlen($uu[0])); - } - - return($r); -} - - -function preg_glob($ls=NULL) { - foreach ((array)$ls as $glob) { - $rx[] = str_replace("\\*", ".*", preg_quote($glob)); - } - if ($rx) { - return( "/^(" . implode("|", $rx) . ")$/" ); - } -} - - -#-- fetch version after version (decreasing), -# skip over remaining ones (when deleting fails) -function get_almost_latest($data, $id) { - if (!$data) { - $data = ewiki_db::GET($id); - } - else { - $last_ver = $data["version"]; - $data = NULL; - while ((--$last_ver) > 0) { - if ($data = ewiki_db::GET($id, $last_ver)) { - break; - } - - } - } - return($data); -} - - -function bad_old_new($old, $new, $tt=0) { - if (! ewiki_db::GET($old)) { - echo "
          src page not found!\n"; - return 1; - } - else { - echo "
          hmm, no - won't do that (same page name)\n"; - return 1; - } - if ($tt && ewiki_db::GET($new)) { - echo "
          warning: target page exists, and latest versions may not get overwritten by this copy process\n
          \n"; - } -} - -?> - - \ No newline at end of file diff --git a/mods/wiki/tools/t_commander/commandline.php b/mods/wiki/tools/t_commander/commandline.php deleted file mode 100644 index 41d42989a..000000000 --- a/mods/wiki/tools/t_commander/commandline.php +++ /dev/null @@ -1,15 +0,0 @@ - - - - WikiCommander:CommandLine - - - -
          -ewiki@ - -
          - diff --git a/mods/wiki/tools/t_commander/edit.php b/mods/wiki/tools/t_commander/edit.php deleted file mode 100644 index f55bb0efe..000000000 --- a/mods/wiki/tools/t_commander/edit.php +++ /dev/null @@ -1,232 +0,0 @@ - - - - WikiCommander:PageDetails:<?php echo $id; ?> - - - -deleted version #'.$version.''."\n"; - } - $data = ewiki_db::GET($id); - $id = $data["id"]; - $version = $data["version"]; - } - - - #-- show errors - if (!$data || !$version) { - echo "
          page does not exist
          \n"; - } - - - #-- save edited page data -------------------------------------------- - if ($_REQUEST["save"] && $_REQUEST["new"]["id"]) { - - // read in given fields as-is - $data; - foreach ($_REQUEST["new"] as $field=>$value) { - $data[$field] = $value; - } - // {id} - $id = $data["id"]; - // {meta} - $data["meta"] = recreate_meta($_REQUEST["new"]["meta"]); - // {flags} - $data["flags"] = 0x0000; - foreach ($_REQUEST["new_flags"] as $bit=>$state) { - if ($state) { - $data["flags"] += (1<<$bit); - } - } - // {lastmodified} - if ($_REQUEST["update"]["lastmodified"]) { - $data["lastmodified"] = time(); - } - // {refs} - if ($_REQUEST["update"]["refs"]) { - ewiki_scan_wikiwords($data["content"], $links, "_STRIP_EMAIL=1"); - $data["refs"] = "\n\n" . implode("\n", array_keys($links)) . "\n\n"; - } - else { - $data["refs"] = "\n\n" . trim(trim($data["refs"], "\n"), "\r") . "\n\n"; - } - // {content} - if ($data["flags"] & EWIKI_DB_F_TEXT) { - $data["content"] = preg_replace("/\r*(\n)\r?/", "$1", $data["content"]); - } - - #-- ok, throw into DB - if (ewiki_db::WRITE($data, $overwrite=1)) { - echo "
          page written into database
          \n\n"; - } - else { - echo "
          error writing entry to db
          \n\n"; - } - } - - - #-- fill with inital data - if ($_REQUEST["create"] && !$data) { - $data = ewiki_db::CREATE($id); - } - - - #-- start output - echo '
          '; - echo ''; - - #-- {id} - print_field($data, "id", 32); - - #-- {version} - print_field($data, "version", 3, "", ""); - echo ' '; - echo ' ... '; - echo '
          ' . "\n"; - - #-- {flags} - print_flags($data); - - #-- {author} and {hits}, {created}, {lastmodified} - print_field($data, "author", 26); - print_field($data, "hits", 4); - print_field($data, "created", 11); - print_field($data, "lastmodified", 11, "", ""); - echo '
          '; - - #-- [save] - echo "\n
          \n" - . '' - . "\n

          \n"; - - #-- {content} - if (($data["flags"]&EWIKI_DB_F_BINARY) && !$_REQUEST["show_content"]) { - echo '
          ' - . '

          '; - } - else { - print_textfield($data["content"], "content", 16); - } - - #-- {meta} - print_textfield(flatten_meta($data["meta"]), "meta", 5); - - #-- {refs} - $inj = '  ' - . '
          '; - print_textfield(ltrim($data["refs"]), "refs", 4, $inj); - - // done - - - - -#------------------------------------------------------- helper functions --- - - #-- output tag for one of the database {field}s - function print_field(&$data, $name, $size, $inj="", $add="
          ") { - echo "" - . "$add\n"; - } - - #-- output checkboxes for {flags} - function print_flags(&$data) { - $names = array("txt", "bin", "off", "htm", "ro", "wr", "app", "sys", - "prt", "min", "hid", - "arv", "u12", - // 13=>"u13", "u14", "u15", "u16", - 17=>"exe", - // 18=>"u18", "u19", "u20" - ); - echo " "; - foreach ($names as $i=>$str) { - echo " "; - } - echo "
          \n"; - } - - #-- output $add\n"; - } - - #-- fold {meta} array into block - function flatten_meta(&$a, $base="") { - $text = ""; - $a = (array)$a; - foreach ($a as $name=>$value) { - if (is_array($value) && is_int($name)) { - $value = implode(", ", $value); // for {meta}{meta} fields - } - if (is_array($value)) { - $text .= flatten_meta($value, "$base$name:"); - } - else { - $text .= "$base$name: $value\n"; - } - } - } - - - #-- fold {meta} array into block - function recreate_meta($text) { - $m = array(); - foreach (explode("\n", $text) as $line) { - $line = preg_replace("/\s+/", " ", rtrim($line)); - if ($r = strpos($line, " ")) { - $l = strrpos(substr($line, 0, $r), ":"); - } - else { - $l = strrpos($line, ":"); - } - if (!$l) { - continue; - } - $name = substr($line, 0, $l); - $line = substr($line, $l + 1); - $sub = explode(":", $name); - if ($sub[0] == "meta") { - $m["meta"][$sub[1]] = preg_split("/\s*,\s*/", $line); - } - else { - $p = & $m; - foreach ($sub as $name) { - if (!isset($m[$name])) { - $p[$name] = array(); - } - $p = & $p[$name]; - } - $p[$name] = $line; - } - } - return $m; - } - -?> - - - diff --git a/mods/wiki/tools/t_commander/filemenu.php b/mods/wiki/tools/t_commander/filemenu.php deleted file mode 100644 index 7d31820ab..000000000 --- a/mods/wiki/tools/t_commander/filemenu.php +++ /dev/null @@ -1,71 +0,0 @@ - - - - WikiCommander:FileMenu - - - -
          - array( - "Reload" => "parent.page.location.reload()", - "Disable" => "parent.left_off=1, parent.page.location.href='action.php?nop=1'", - "EditorOn" => "parent.left_off=0", - ), - "File" => array( - "Edit" => "parent.page.location.href='edit.php?id='+escape(parent.id)", - "New" => "parent.new_page()", - "Rename" => "parent.rename_page()", - "Copy" => "parent.copy_page()", - "Delete" => "parent.delete_page()", - ), - "Command" => array( - "CmdLineHelp" => "parent.page.location.href='action.php?cmd=1&input=help'", - "Backup" => "", - "Upload" => "", - "Transfer" => "", - ), - "Option" => "0==0", - "Right" => array( - "Select" => "parent.list_selection()", - "Filter" => "parent.show_filtered_list()", - "Reload" => "parent.list.location.reload()", - ), - ); -# if ($e = $_REQUEST["which"]) { -# $menu = $menu[$e]; -# } - - #-- output first-level menu - echo "\n"; - foreach ($menu as $id=>$js) { - if (is_array($js)) { - $href = "#$id"; - $old = 'filemenu.php?which='.$id; - echo "$id\n"; - } - else { - echo "$id\n"; - } - } - - #-- output second-level menus - foreach ($menu as $id=>$ent) { - if (is_array($ent)) { - echo "\n\n

          \n"; - echo "$id\n"; - echo "back\n"; - foreach ($ent as $id=>$js) { - echo "$id\n"; - } - } - } - -?> -
          - - diff --git a/mods/wiki/tools/t_commander/index.html b/mods/wiki/tools/t_commander/index.html deleted file mode 100644 index 572a2ea36..000000000 --- a/mods/wiki/tools/t_commander/index.html +++ /dev/null @@ -1,185 +0,0 @@ - - - WikiCommander - - - - - - - - - - - - - - - Go to our <a href="list.php">PageList</a> to use this tool. - But you were better off using a frames-capable browser (try the text-only - <a href="http://google.com/search?q=w3m">w3m</a> today)! - - diff --git a/mods/wiki/tools/t_commander/info.php b/mods/wiki/tools/t_commander/info.php deleted file mode 100644 index ebb2a7364..000000000 --- a/mods/wiki/tools/t_commander/info.php +++ /dev/null @@ -1,79 +0,0 @@ - - - - WikiCommander:SplashScreen - - -
          - -WikiCommander™ 1.0
          -
          -operating sys: $os
          -WebServer: $web
          -environment: $_SERVER[GATEWAY_INTERFACE], $_SERVER[SERVER_PROTOCOL]
          -PHP interpreter: $php
          -ewiki version: $ver
          -database type: $db
          -
          -This tool accesses your database directly, all actions are irreversible. -
          -
          -
          -This utility allows for raw database editing. You can select pages in the right -pane and then edit page contents, flags or misc. settings in the left. -
          -Following database flags are used currently: - - - - - - - - - - - - - - -
          Ttxt_TEXTtype of ordinary wikipages
          Bbin_BINARYnon-text entries
          Zsys_SYSTEMspecial/secret data and control pages
          doff_DISABLEDinaccesible, forbidden entries
          Pprt_PARTincomplete data fragments
          rro_READONLYedit-locked
          wrw_WRITEABLEalways unlocked pages
          xexe_EXECdb entry with script code
          aapp_APPENDONLYcan only add text at bottom
          mmin_MINORminor edits don't appear on RC
          hhid_HIDDENpages don't appear in listings, searches
          varv_ARCHIVEautomatic page deletion (cron) won't do
          Hhtm_HTMLraw html allowed in page text
          -
          -Unless you increase the {version} number by hand, saving edited pages will -overwrite the same revision. You can simply duplicate a page under another -name by editing the {id} field there - the original page+version will remain -unchanged. Use [refr] to load a different version. The [del] button always -deletes only the shown version. The "..." brings you to a complete version -history of the current database entry. The checkbox behind {lastmodified} -will correctly update it using the system time() when saving. -
          -
          -You also can use typical *nix calls in the commandline (just try -"help" for a complete list).
          -
            rm PageName
          -  ls -l
          -  mv OldName "New Name"
          -  exit
          -
          -
          -It is all very rough still and both menus heavily depend on enabled JS. You -can select multiple files (for deletion e.g.) if you hold the Ctrl key down, -but you must take care to click beside the filename/link, because Mozilla and -Co. would otherwise always open a new tab for it. -

          -
          -
          -END; -?> -
          - diff --git a/mods/wiki/tools/t_commander/keymenu.php b/mods/wiki/tools/t_commander/keymenu.php deleted file mode 100644 index ef5bda58c..000000000 --- a/mods/wiki/tools/t_commander/keymenu.php +++ /dev/null @@ -1,35 +0,0 @@ - - - - WikiCommander:KeyMenu - - - -
          - array("Help", '"info.php" target="page"'), - 2 => array("Save", ""), //"window.PageDetails.form[0].submit()" - 3 => array("Show", "parent.page.location.href='../../?id='+parent.id"), - 4 => array("Edit", "parent.page.location.href='edit.php?id='+parent.id"), - 5 => array("Copy", "parent.copy_page()"), - 6 => array("Move", "parent.rename_page()"), - 8 => array("Del ", "parent.delete_page()"), - 9 => array("Menu", '"filemenu.php" target="menu"'), - 10 => array("Quit", '".." target="_parent"'), - ); - foreach ($menu as $num=>$uu) { - list($id, $href) = $uu; - if (strpos($href, '"')===false) { - $href = '"javascript:void('.$href.');"'; - } - echo " $num" . "$id\n"; - } - -?> -
          - - diff --git a/mods/wiki/tools/t_commander/list.php b/mods/wiki/tools/t_commander/list.php deleted file mode 100644 index c2a016603..000000000 --- a/mods/wiki/tools/t_commander/list.php +++ /dev/null @@ -1,59 +0,0 @@ - - - - WikiCommander:PageList - - - -filter regex /^$regex$/i\n"; - $regex = ":^$regex$:i"; - } - -?> - - - - - - - -GET()) { - - #-- prep - $id = $row["id"]; - $url_id = urlencode($id); - $title = htmlentities(substr($id, 0, 32)); - - #-- filter? - if ($regex && !preg_match($regex, $id)) { - continue; - } - - #-- out - echo "" - . '" - . '' - . '' - . "\n"; - } - - - -?> -
          NameFlagsMTime
          ' - . "$title' . flag_text($row["flags"]) . '' . strftime("%Y-%m-%d", $row["lastmodified"]) . '
          - - diff --git a/mods/wiki/tools/t_commander/list_vers.php b/mods/wiki/tools/t_commander/list_vers.php deleted file mode 100644 index ae91eef91..000000000 --- a/mods/wiki/tools/t_commander/list_vers.php +++ /dev/null @@ -1,51 +0,0 @@ - - - - WikiCommander:PageDetails:<?php echo $id; ?> - - - -$id
          \n"; -?> - - - - - - - - - -=1; $ver--) { - - $row = ewiki_db::GET($id, $ver); - if (!$row) { - continue; - } - - $href = 'edit.php?id='.urlencode($id)."&version=$ver"; - echo '' - . "" - . "" - . "" - . "" - . "" - . "\n"; - - } - -?> -
          VerMTimeFlagsSizeAuthor
          #$ver" . strftime("%Y-%m-%d", $row["lastmodified"]) . "".flag_text($row["flags"])."".strlen($row["content"])."".$row["author"]."
          - \ No newline at end of file diff --git a/mods/wiki/tools/t_commander/t_config.php b/mods/wiki/tools/t_commander/t_config.php deleted file mode 100644 index ea6f1c9a1..000000000 --- a/mods/wiki/tools/t_commander/t_config.php +++ /dev/null @@ -1,39 +0,0 @@ - "H", - EWIKI_DB_F_HIDDEN => "h", - EWIKI_DB_F_MINOR => "m", - EWIKI_DB_F_READONLY => "r", - EWIKI_DB_F_WRITEABLE => "w", - EWIKI_DB_F_EXEC => "x", - EWIKI_DB_F_APPENDONLY => "a", - EWIKI_DB_F_DISABLED => "d", - EWIKI_DB_F_PART => "P", - EWIKI_DB_F_SYSTEM => "Z", - EWIKI_DB_F_BINARY => "B", - EWIKI_DB_F_TEXT => "T", - ); - $s = ""; - foreach ($str as $bit=>$add) { - if ($flags & $bit) { - $s .= $add; - } - } - if (!strlen($s)) { - $s = "0"; - } - return $s; - } - -// ewiki_db::$readonly = true; -?> \ No newline at end of file diff --git a/mods/wiki/tools/t_config.css b/mods/wiki/tools/t_config.css deleted file mode 100644 index 153cd3cd1..000000000 --- a/mods/wiki/tools/t_config.css +++ /dev/null @@ -1,57 +0,0 @@ -html, body { - padding: 0px; - margin: 0px; -} -body { - border: 10px solid #ffcc88; - border-width: 10px 5px 30px 20px; - background: #ffaa55; - color: #442206; - padding: 3px; -} - -h1,h3,h4 { - background: #aa551c;//#cc7733;#aa551c; - color: #ffffff; - padding: 5px 20px; - margin: 0px; - font-family: "Verdana", "Helvetica", sans-serif; - font-size: 32px; - border: 2px solid #cc7733;//#aa551c; - margin-bottom: 5px; - letter-spacing: +3pt; -} -h3 {font-size: 22px;} -h4 {font-size: 16px;} - -input, textarea, select { - border: 2px groove #cc7733; - background: #ee9944; -} -label { - border: 1px dashed transparent; - font-size: 85%; -} -label:hover{ - border-color: #cc8844; -} - -.add-border-right { - padding-right:2px; - margin-right:5px; - border-right:2px solid #f0a050; -} - -table.list td { - border: 0px solid #995511; - border-width: 1px 0px 0px 1px; -} - -.message { - border: 2px solid #cc7711; - background: #ee8811; - color: #ffffff; - margin: 3px; - padding: 5px; -} - diff --git a/mods/wiki/tools/t_config.php b/mods/wiki/tools/t_config.php deleted file mode 100644 index 51eb864f6..000000000 --- a/mods/wiki/tools/t_config.php +++ /dev/null @@ -1,68 +0,0 @@ - "...", - ); - - - - #-- tools/ are run standalone? - if (!function_exists("ewiki_database")) { - - - #-- enable readonly:test play account? - $test = ($_SERVER["SERVER_NAME"] == "erfurtwiki.sourceforge.net") - || ($_SERVER["REMOTE_ADDR"] == "127.0.0.1") && (!strpos($_SERVER["SERVER_NAME"], ".")); - if ($test && !$_REQUEST["test"]) { - $passwords["readonly"] = "test"; - } - - - #-- simplest authentication: - require("../fragments/funcs/auth.php"); - - if ($_a_user == "readonly") { - define("EWIKI_DB_LOCK", 1); // disable write-access - } - - - #-- normalize cwd (stupid approach) - if (!file_exists($LIB="ewiki.php")) { - chdir(".."); - define("EWIKI_SCRIPT", "../?"); - define("EWIKI_SCRIPT_BINARY", "../?binary="); - } - - - #-- open db connection, load 'lib' - include("./config.php"); - - - #-- PHP fixes - include("plugins/lib/fix.php"); - include("plugins/lib/upgrade.php"); - - } - - - #-- we now seem to run from inside ewiki (via the StaticPages plugin e.g.) - else { - - #-- this terminates ewiki from within the spages plugin - if (!EWIKI_PROTECTED_MODE || !ewiki_auth($id, $data, $action, 0, 2) || ($ewiki_ring>0) || !isset($ewiki_ring)) { - die("Only the administrator can use this function."); - } - - #-- some tools/ must be excluded nevertheless (because they override security-related settings, like t_control.php does) - define("CONCURRENT_INCLUDE", 1); // just don't ask for an explaination ;) - - } - - - -?> \ No newline at end of file diff --git a/mods/wiki/tools/t_control.php b/mods/wiki/tools/t_control.php deleted file mode 100644 index 3179cf67e..000000000 --- a/mods/wiki/tools/t_control.php +++ /dev/null @@ -1,38 +0,0 @@ - - - - single page control (combined admin features) - - - -control page '" .htmlentities($id) . "'\n\n"; - - #-- exec plugin - if ($data = ewiki_db::GET($id)) { - $action = "control"; - echo str_replace("
          ", "", ewiki_action_control_page($id, $data, $action)); - } - else { - echo "error: page does not exist\n
          \n\n

          \n"; - } - -?> - - diff --git a/mods/wiki/tools/t_convertdb.php b/mods/wiki/tools/t_convertdb.php deleted file mode 100644 index 7f6bb4761..000000000 --- a/mods/wiki/tools/t_convertdb.php +++ /dev/null @@ -1,424 +0,0 @@ - - - - database conversion (wiki engine transition) - - - -

          database conversion

          - - This tool can be used to convert an existing (foreign) wiki database with - all its pages to the ewiki database and page format. It is very experimental - and you should consider using the export utility of your previous Wiki with - ewikictl afterwards to reimport it here. - -
          - -
          - Some of the databases you can export from need more parameters, and if you - transfer data from one SQL-based database scheme to another, you need to - have source and target tables in the same database (cannot cross-convert - from/to different servers/dbms). And the target tables for foreign schemes - must already exist. - -
          -
          - You must have your target ewiki database and plugin already defined - in your config.php. If you want a special target, then you must - edit this script (t_convertdb.php) - and uncomment the other targets and insert correct define() or assignment - statements to make it work yourself. -
          - -
          -
          - - - - - - -
          - -

          convert from

          - - -
          - -
          - - - -
          -
          - miscellaneous database access options -
          - - -
          - - -
          - - - -
          -
          - - -

          -
          - - notes -
          - - If you access the 'configured $ewiki_db' then you do not need to - set any option, because this refers to whatever you configured in your - 'config.php' script as default database. Always the best option. -
          - - For PmWiki you must set the 'subwiki identifier' (to "Main" at best), so - the conversion utility can extract one of the database fragments. You - also need to define the 'file/directory' setting to the exact position - of PmWikis 'wiki.d' or 'wikilib.d' data dirs (relative to the ewiki - installations base directory; and separate multiple dir names using - spaces, commas or colons). -
          -
          - - -
          - -

          into

          - - -
          - -
          - - - -
          - - -
          - and - - - (or copied page will simply be appended as newest) - -
          -
          - - -
          -
          - - "", - "mysql" => "", - "pmwiki10" => "read_pmwiki1.php", - "phpwiki13" => "phpwiki13.php", - "dba" => "dba.php", - "flat" => "flat_files.php", - "fast" => "fast_files.php", - "dzf2" => "dzf2.php", - "zip" => "zip.php", - "anydb" => "anydb.php", - "xmlrpc" => "xmlrpc.php", - ); - $t_api = array( - "ewiki" => "$", - "mysql" => "ewiki_database_mysql", - "pmwiki10" => "ewiki_database_pmwiki", - "phpwiki13" => "ewiki_database_phpwiki13", - "dba" => "ewiki_database_dba", - "flat" => "ewiki_database_files", - "fast" => "ewiki_database_files", - "dzf2" => "ewiki_database_DirZlibFiles2", - "zip" => "ewiki_database_zip", - "anydb" => "ewiki_database_anydb", - "xmlrpc" => "ewiki_database_xmlrpc", - ); - $t_init = array( // auto-create database scheme (::INIT) - "ewiki" => 1, - "mysql" => 1, - "dba" => 1, - "flat" => 1, - "fast" => 1, - "dzf2" => 1, - "anydb" => 1, - ); - $t_in_convert = array( - "phpwiki13" => array("phpwiki.php"), - "usemod" => array("usemod.php"), - ); - $t_out_convert = array( - "phpwiki13" => array(), // nothing ready yet - ); - - #-- preparations - define("PHPWIKI13_WRITEACCESS", 1); - - - #-- open databases - if ($script = $t_scr[$from_type]) include_once("plugins/db/$script"); - $FROM = instantiate_db_api($t_api[$from_type]); - echo "- source database module loaded/instantiated
          \n"; - if ($read) { - read_test(); - } - if ($script = $t_scr[$from_to]) include_once("plugins/db/$script"); - $DEST = instantiate_db_api($t_api[$to_type]); - echo "- target database module loaded/instantiated
          \n"; - - - #-- set up options for $FROM database - if ($grp = $_REQUEST["from_subwiki"]) { - $FROM->group = $grp; - } - if ($dir = $_REQUEST["from_dir"]) { - $FROM->zip = $dir; - $FROM->dir = $dir; - $FROM->dirs = preg_split("/[\s:;,]+/", $dir); - } - if ($tbl = $_REQUEST["from_sqltable"]) { - $FROM->table = $tbl; - } - - - - #-- load markup conversion scripts - $ewiki_plugins["format_source"] = array(); // kill default ones - if ($from_convert) - if ($scr_a = $t_in_convert[$from_type]) { - foreach ($scr_a as $script) { - echo "- loading markup conversion module '$script'
          \n"; - include_once("../plugins/markup/$script"); - } - } - $ewiki_plugins["markup_convert"] = array(); - if ($to_convert) - if ($scr_a = $t_out_convert[$from_type]) { - foreach ($scr_a as $script) { - echo "- loading markup export plugin '$script'
          \n"; - include_once("plugins/markup/$script"); - } - } - - - #-- creating ewiki database - if ($t_init[$to_type]) { - echo "- creating destination target database scheme/whatever...
          \n"; - $DEST->INIT(); - } - else { - echo "- cannot create database scheme for that target type [SKIPPED]
          \n"; - } - echo "
          \n"; - - - #-- start -------------------------------------------------------- - echo "\n\n
          \n

          copying pages:

          \n\n"; - - $result = $FROM->GETALL(array("flags", "version")); // not "id"!, we're doing raw access here, and need to obey the internal rules - while ($row = $result->get()) { - - #-- run forever, if necessary - set_time_limit(2000); - - #-- page id - $id = $row["id"]; - echo htmlentities("$id"); - - - #-- read - $data = $FROM->GET($id); - - - #-- operation mode - if ($all_versions) { - - #-- copy all page versions - for ($ver=$data["version"]; $version>=1; $version--) { - if ($data = $FROM->GET($id, $version)) { - markup_convert($data); - if ($DEST->WRITE($data, $overwrite)) { - echo ".$version"; - } - else { - echo ".E"; - } - } - - } - - } - else { - - #-- check for existence of current page - $old = $DEST->GET($id); - if (!$old["version"]) { - $data["version"] = 1; - } - elseif ($overwrite && $old) { - $data["version"] = $old["version"] + 1; - } - else { - continue; - } - - markup_convert($data); - if ($DEST->WRITE($data)) { - echo "[" . $data["version"] . "]"; - } - else { - echo "[ERROR]"; - } - - } - - - echo ",\n"; - } - - #-- fin - echo "

          done\n"; - - } - - - - - - -#----------------------------------------------------------- utility code --- - - - - -#-- rewriting of page content to match target wiki engines markup -function markup_convert() { - global $ewiki_plugins; - - #-- in-conversion - if ($pf_a = $ewiki_plugins["format_source"]) foreach ($pf_a as $pf) { - $pf($data["content"]); - } - - #-- out-conversion - if ($pf_a = $ewiki_plugins["markup_convert"]) foreach ($pf_a as $pf) { - $pf($data["content"]); - } - - #-- update {refs} (helpful for PmWiki, which does not have an equivalent) - ewiki_scan_wikiwords($data["content"], $ewiki_links, "_STRIP_EMAIL=1"); - $data["refs"] = "\n\n".implode("\n", array_keys($ewiki_links))."\n\n"; - - //fin -} - - -#-- submodule -function read_test() { - global $FROM; - echo "- now performing only an
          \n
          \n

          read test

          \n"; - $all = $FROM->GETALL(array("version","flags")); - $list = array(); - echo "- following pages were found in that database:
          \n"; - while ($row = $all->get()) { - echo $row["id"] . "[" . $row["version"] . "], "; - $list[] = $row["id"]; - } - echo "\n

          \n

          randomly chosen entry

          \n"; - $id = $list[rand(0,count($list)-1)]; - $row = $FROM->GET($id); - echo "
          ";
          -   print_r($row);
          -   echo "
          \n\n
          \n"; - die(); -} - - - -#-- create database object (or simply return reference to default $ewiki_db) -function & instantiate_db_api($class) { - global $ewiki_db; - if ((!$class) || ($class=="$")) { - if (!isset($ewiki_db)) { - $ewiki_db = & new ewiki_database_mysql(); - } - $db = & $ewiki_db; - } - else { - $db = & new $class; - } - return($db); -} - - -?> - \ No newline at end of file diff --git a/mods/wiki/tools/t_ewikictl.php b/mods/wiki/tools/t_ewikictl.php deleted file mode 100644 index 202c4afdf..000000000 --- a/mods/wiki/tools/t_ewikictl.php +++ /dev/null @@ -1,311 +0,0 @@ - - - - ewikictl (www-only interface) - - - -

          ewikictl/web

          - - - - ewikictl is a commandline tool, ought to be used from within - a shell account on your Web server. If your provider doesn't give you - that you have to stick to the features that can be provided through - this www-only interface. -
          -
          - You often need to prepare a www-deamon writeable directory, into - which you upload files before or download from after execution of one - of the actions. Inconvinient as it is, this is the only way to work - with this tool. -
          - - -
          - - - - -
          -

          --backup

          - array("", "", "directory", "(must exist on web server and be world-writeable)"), - "format" => array(array( - "fast" => "fast files (recommended)", - "flat" => "flat files (rfc822 format)", - "plain" => "plain text pages", - "meta" => "plain text companion .meta", - "xmlmeta" => "plain with .meta in xml", - "xml" => "XML-like format", - "sql" => "MySQL INSERT (backup only)", - ), "select", "file format", "(not all can be imported again!)
          "), - "all" => array("1", "x", "all versions", "backs up database fully"), - "enc" => array("1", "x", "urlencode", "makes filenames DOS/Win-compatible"), - "force" => array("1", "checkbox", "force", "don't stop on errors"), - ) - ); - ?> -
          -

          --insert

          - array("", "", "directory", "(you must upload the backed up files there beforehand)"), - "format" => array(array( - "fast" => "fast files (serialized)", - "flat" => "flat files (message/http)", - "plain" => "plain text pages", - ), "select", "file format", "
          "), - "all" => array("1", "x", "versioned files", "if they have .NNN extensions"), - "keep" => array("1", "x", "keep", "don't overwrite existing page versions"), - "dec" => array("1", "x", "urldecode filenames", "from Win-sys"), - "force" => array("1", "checkbox", "force", "don't stop on errors"), - ) - ); - ?> -
          - - -
          - - - - -
          -

          --holes

          - Removes older revisions (in given range) from all pages. It can - automatically make a backup of the killed data. -

          - array("2", "", "keep versions", "how many of the first few versions to keep (no 1 must remain for flat file databases!)"), - "holes_end" => array("-10", "", "kill from end", "that many versions shall remain at the end (minimum is 1 here of course!)
          "), - "dest" => array("", "", "backup dir", "(must exist on web server and be world-writeable)"), - "format" => array(array( - "fast" => "fast files", - "flat" => "flat files", - "plain" => "plain text", - ), "select", "backup format", "
          "), - "all" => array("1", "x", "backup all", "(implicit)"), - "enc" => array("1", "x", "backup filnames encode", ""), - "force" => array("1", "checkbox", "force", "don't stop on errors"), - ) - ); - ?> -
          -

          --help

          - to learn about new features in the commandline version ;) -

          - -
          - - - -
          - - - - - - -
          -

          --list

          - shows a wide list of all existing pages, including flags, size - author name and timestamp (like 'ls -l' under Unix) - -
          -

          --rename

          - array("", "", "from", "(pagenames)"), - "1" => array("", "", "to"), - ) - ); - ?> -
          -

          --chmod

          - array("SandBox", "", "page", ""), - "0" => array("+TEXT,-OFF", "", "flags", "can be either decimal (54), octal (0377) or hex (0x137f) - or a combination of flag abbreviations separated by comma, + or a - sign
            like +HTM,WRITE,-OFF"), - ) - ); - ?> -
          -

          --unlink

          - deletes a page completely (with all its versions)

          - array("SandBox", "", "page", ""), - ) - ); - ?> -
          - - -
          -
          - - There are equations for some of the above commands in the collection - of database tools, that sometimes provide more options - or are easier to use. - -
          -
          - - $str) { - if (is_int($field) && $str) { - $argv[] = $str; - } - } - - // take common --args asis - foreach (array("force", "dest", "source", "dir", "all", - "urlencode", "urldecode", "keep", "db", "file") - as $field) - { - if ($str = $_REQUEST[$field]) { - $argv[] = "--$field"; - if ($str !== "1") { - $argv[] = $str; - } - } - } - - - #-- perform - echo "

          --$action

          \n
          \n"; - - ob_start(); - $GLOBALS["argv"] = $_SERVER["argv"] = $argv; - $GLOBALS["argv"] = $_SERVER["argc"] = count($argv); - $_SERVER["SERVER_SOFTWARE"] = 0; - include("ewikictl"); - - #-- output - $text = ob_get_contents(); - ob_end_clean(); - #-- transform - $text = htmlentities($text); - $text = preg_replace('/\033\[([\d;]+)m/e', 'ansiesc2font("$1")', $text); - echo '
          '
          -        . "\n\n$text\n\n"
          -        . "
          "; - - - - }// end of everything here - - - - -#-- output form for one action -function aform($action, $args) { - static $xn=0; - echo '
          '; - echo "\n\n"; - foreach ($args as $i=>$l) { - echo " "; - if (is_array($l[0])) { - echo "\n"; - } - else { - if (!strlen($l[1])) { - $l[1] = "text"; - } - elseif ($l[1]=="x") { - $l[1] = 'checkbox" checked="checked'; - } - echo "\n"; - } - echo "$l[3]\n
          \n"; - } - echo ''; - echo "
          \n"; - $xn++; -} - - - -function ansiesc2font($str) { - $cols = array( - "black", "red", "green", "magenta", "blue", "yellow", "grey", "white", - ); - foreach (explode(";", $str) as $n) { - $col = $cols[0 + ((0+$n) % 10)]; - if (($n == "37") or ($n == "0") or ($n == "27")) { - return ""; - } - elseif ($n >= 40) { - return ""; - } - elseif ($n >= 30) { - return ""; - } - } -} - -?> - - - \ No newline at end of file diff --git a/mods/wiki/tools/t_flags.php b/mods/wiki/tools/t_flags.php deleted file mode 100644 index 5e2e141aa..000000000 --- a/mods/wiki/tools/t_flags.php +++ /dev/null @@ -1,101 +0,0 @@ - - - - edit ewiki page flags - - - -

          edit page flags

          - "TXT", - EWIKI_DB_F_BINARY => "BIN", - EWIKI_DB_F_DISABLED => "OFF", - EWIKI_DB_F_HTML => "HTM", - EWIKI_DB_F_READONLY => "RO", - EWIKI_DB_F_WRITEABLE => "WR", - ); - - if (empty($_REQUEST["set"])) { - - $result = ewiki_db::GETALL(array("version", "flags")); - - echo '
          '; - echo '' . "\n"; - - while ($row = $result->get()) { - $id = $row["id"]; - - $data = ewiki_db::GET($row); - - echo ''; - - echo '"; - - echo "\n"; - - } - - echo '
          '; - if ($data["flags"] & EWIKI_DB_F_TEXT) { - echo ''; - } - else { - echo ''; - } - echo htmlentities($id) . '' . (".".$row["version"]) . ''; - foreach ($FD as $n=>$str) { - echo ''.$str. ' '; - } - echo "
          '; - - } - else { - - foreach($_REQUEST["set"] as $page=>$fa) { - - $page = rawurldecode($page); - - $flags = 0; - $fstr = ""; - foreach($fa as $num=>$isset) { - if ($isset) { - $flags += $num; - $fstr .= ($fstr?",":""). $FD[$num]; - } - } - - echo "· ".htmlentities($page)." ({$flags}=[{$fstr}])"; - - $data = ewiki_db::GET($page); - - if ($data["flags"] != $flags) { - $data["flags"] = $flags; - $data["author"] = "ewiki-tools, " . ewiki_author(); - $data["version"]++; - ewiki_db::WRITE($data); - echo " [set]"; - } - else { - echo " [not changed]"; - } - - echo "
          \n"; - - } - - } - - - function strong_htmlentities($str) { - return preg_replace('/([^-., \w\d])/e', '"&#".ord("\\1").";"', $str); - } - -?> \ No newline at end of file diff --git a/mods/wiki/tools/t_holes.php b/mods/wiki/tools/t_holes.php deleted file mode 100644 index 69fb21290..000000000 --- a/mods/wiki/tools/t_holes.php +++ /dev/null @@ -1,112 +0,0 @@ - - - - strip old versions of ewiki pages - - - - -

          create page version holes

          -
          -Please note, that the right number is always treated as count from the -last existing version. So "2..-10" would delete anything from the 2nd to -the "LAST minus 10"-th version. -

          -
          - -'; - - $result = ewiki_db::GETALL(array()); - while ($row = $result->get()) { - - if (($n=$row["version"]) >= N_PAGE_VERSIONS) { - - $id = $row["id"]; - - echo ''; - echo ""; - $n2 = $n - 10; - echo ''; - echo "\n"; - - } - - } - - echo ' -
          ".htmlentities($id)." (#$n) '. - ' delete versions ' . - '
          -

          -
          -
          -[select all] -
          -
          -Eventually you should consider using the ewikictl cmdline -utility in favour of this www script. -

          - '; - - } - else { - - echo "purging page versions:
          "; - - $range = $_REQUEST["range"]; - - foreach ($_REQUEST["id"] as $id_ue => $go) { - $id = rawurldecode($id_ue); - - if ($go) { - - if (preg_match('/^(\d+)[-\s._:]+(\d+)$/', trim($range[$id_ue]), $uu)) { - - $versA = $uu[1]; - $versZ = $uu[2]; - echo "'".htmlentities($id)."' versions {$versA}..{$versZ}
          \n"; - - for ($v=$versA; $v<=$versZ; $v++) { - - ewiki_db::DELETE($id, $v); - - } - - } - else { - - echo "wrong range param for '$id'!
          \n"; - - } - - } - } - - } - - - -?> \ No newline at end of file diff --git a/mods/wiki/tools/t_remove.php b/mods/wiki/tools/t_remove.php deleted file mode 100644 index 25b7db78f..000000000 --- a/mods/wiki/tools/t_remove.php +++ /dev/null @@ -1,148 +0,0 @@ - - - - delete ewiki pages - - - -

          delete pages from DB

          -unreferenced pages
          will be listed here. And - because the ewiki engine itself does only limited testing if a page is - referenced it may miss some of them here.
          - If you however empty a page first, it will get listed here too. - Various other database diagnostics are made as well.

          \n"; - - - $result = ewiki_db::GETALL(array("version")); - - $selected = array(); - - if (@$_REQUEST["listall"]) { - while ($row = $result->get()) { - $selected[$row["id"]] = "listall
          "; - } - } - else - while ($page = $result->get()) { - - $id = $page["id"]; - if (!strlen($id)) { continue; } - $page = ewiki_db::GET($id); - $flags = $page["flags"]; - - if (!strlen(trim(($page["content"])))) { - @$selected[$id] .= "EMPTY
          "; - } - - $res2 = ewiki_db::SEARCH("content", $id); - if ($res2 && $res2->count()) { - $check2 = 1; - while ($row = $res2->get()) { - $check = ewiki_db::GET($row["id"]); - $check = strtolower($check["content"]); - $check2 &= (strpos($check, strtolower($id)) !== false); -#echo "rc({$row['id']})==>($id): $check2
          "; - } - $check = $check2; - } - if (empty($check)) { - @$selected[$id] .= "UNREFerenced
          "; - } - - if ($flags & EWIKI_DB_F_DISABLED) { - @$selected[$id] .= "disabled_page
          "; - } - - if (($flags & 3) == 3) { - @$selected[$id] .= "errFLAGS(bin+txt)
          "; - } - - if (!($flags & 3)) { - @$selected[$id] .= "errFLAGS(notype)
          "; - } - - if ($flags & EWIKI_DB_F_HTML) { - @$selected[$id] .= "warning(HTML)
          "; - } - - if (($flags & EWIKI_DB_F_READONLY) && !($flags & EWIKI_DB_F_BINARY)) { - @$selected[$id] .= "readonly
          "; - } - - if (($flags & EWIKI_DB_F_READONLY) && ($flags & EWIKI_DB_F_WRITEABLE)) { - @$selected[$id] .= "errFLAGS(readonly+writable)
          "; - } - - if (strlen($page["content"]) >= 65536) { - @$selected[$id] .= "size >= 64K
          "; - } - - if (preg_match("/\nDelete(d?Page|Me|This)\n/", $page["refs"])) { - @$selected[$id] .= "DeleteMe
          "; - } - - } - - - - echo '
          '; - echo ''; - echo '' . "\n"; - echo "\n"; - - foreach ($selected as $id => $reason) { - - echo ''; - - #-- print reason - echo '"; - - echo "\n"; - - } - - echo '
          page nameerror / reason
          '; - - #-- checkbox - echo '  '; - - #-- link & id - if (strpos($id, EWIKI_IDF_INTERNAL) === false) { - echo ''; - } - else { - echo ''; - } - echo htmlentities($id) . '' . $reason . "

          '; - - } - else { - - echo "
            \n"; - foreach ($_REQUEST["remove"] as $id => $uu) { - - $id = rawurldecode($id); - - echo "
          • purging »".htmlentities($id)."«...
          • "; - - $data = ewiki_db::GET($id); - for ($version=1; $version<=$data["version"]; $version++) { - - ewiki_db::delete($id, $version); - - } - - } - echo "
          \n"; - - } - -?> \ No newline at end of file diff --git a/mods/wiki/tools/t_restore.php b/mods/wiki/tools/t_restore.php deleted file mode 100644 index 367997494..000000000 --- a/mods/wiki/tools/t_restore.php +++ /dev/null @@ -1,107 +0,0 @@ - - - - restore database entries from backup - - - -

          restore database

          - - - - This is a wrapper script around ewikictl to reinsert saved - database entries back into the database. It also incorporates functions - from the previous "backdown" utility. -
          - To use it you must first upload a bunch of db files to a directory on - your webserver you have access to. - -

          - -
          - - directory containing backup files:
          - -
          (either absolute or relative to location of ewiki.php)
          -
          - - backup format:
          -
          -
          - - versions insert behaviour:
          -
          -
          - - other settings:
          - - overwrite, - replace existing versions (see multiple versions above)
          - - urldecode, - read dbff-filenames assuming DOS filesystem restrictions
          - (only matters for plain text files, because dbff files - always carry an unencoded $id inside)
          - - enforce, - override problems (use this only if first try failed)
          - -
          - - -

          - -
          - - ewikictl
          :
          ";
          -
          -     $config["dest"] = $_REQUEST["incoming"];
          -     $config["format"] = $_REQUEST["format"];
          -     $config["force"] = $_REQUEST["force"];
          -     $config["urlencode"] = $_REQUEST["urlencode"];
          -     $config["insert"] = "1";
          -
          -     if ($_REQUEST["behaviour"]=="all") {
          -        $config["all"] = 1;
          -        $config["keep"] = (!$_REQUEST["overwrite"]);
          -     }
          -     else {
          -        $config["all"] = 0;
          -        $config["keep"] = ($_REQUEST["behaviour"] != "append");
          -     }
          -
          -     set_options_global();
          -
          -     command_insert();
          -
          -     echo "
          "; - - } - -?> - - - \ No newline at end of file diff --git a/mods/wiki/tools/t_revert.php b/mods/wiki/tools/t_revert.php deleted file mode 100644 index 24f329605..000000000 --- a/mods/wiki/tools/t_revert.php +++ /dev/null @@ -1,119 +0,0 @@ - - - - Revert changes - - - -

          RevertChanges

          -Warning: running in dummy mode (--no-act), nothing will happen, all following messages are lies:\n

          \n"; - } - - #-- params - $m_author = $_REQUEST["match_author"]; - $m_time = $_REQUEST["time_slice"] * 3600; - $action = $_REQUEST["action"]; - ($depth = $_REQUEST["version_depth"] - 1) or ($depth = 0); - - #-- walk through - $result = ewiki_db::GETALL(array("id", "author", "lastmodified")); - while ($row = $result->get()) { - - $id = $row["id"]; - - #-- which versions to check - $verZ = $row["version"]; - if ($action=="lastonly") { - $verA = $verZ; - } - else { - $verA = $verZ-$depth; - if ($verA <= 0) { - $verA = 1; - } - } - - - for ($ver=$verA; $ver<=$verZ; $ver++) { - - #-- load current $ver database entry - if ($verA != $verZ) { - $row = ewiki_db::GET($id, $ver); - } - - #-- match - if (stristr($row["author"], $m_author) && ($row["lastmodified"] + $m_time > time())) { - echo "rm($id"; - #-- delete multiple versions - if ($action=="allsince") { - while ($ver<=$verZ) { - echo " .$ver"; - if ($do) { - ewiki_db::DELETE($id, $ver); - } - $ver++; - } - } - #-- or just the affected one - else { - echo " .$ver"; - if ($do) { - ewiki_db::DELETE($id, $ver); - } - } - echo ")
          \n"; - break; - } - - }#-- for($ver) - - }#-- while($row) - - -} -else { - - ?> - If someone garbaged lots of pages in your Wiki, you may want to - automatically revert those changes, by making this script delete any - page versions that carry a certain string in the {author} field - (usually the IP address or host name).

          -
          - {author} field pattern -
          - This must be a fixed string (you cannot use * or regex), at - best use the attackers` IP address or host name, but don't include - the port number (because it increased with every http access). - -

          - changes within the last hours -

          - how to operate:
          - -
          - delete the last versions at max -

          - - -
          - - - diff --git a/mods/wiki/tools/t_searchandreplace.php b/mods/wiki/tools/t_searchandreplace.php deleted file mode 100644 index a0acc85eb..000000000 --- a/mods/wiki/tools/t_searchandreplace.php +++ /dev/null @@ -1,29 +0,0 @@ - - - - global search and replace - - - -

          SearchAndReplace

          - -

          - - diff --git a/mods/wiki/tools/t_setupwiz.php b/mods/wiki/tools/t_setupwiz.php deleted file mode 100644 index c5691079e..000000000 --- a/mods/wiki/tools/t_setupwiz.php +++ /dev/null @@ -1,682 +0,0 @@ - NULL, - "server" => "localhost", - "dbname" => "test", - "table" => "ewiki", - "dir" => "/tmp", - "dba" => "/tmp/wiki.dbm", - ); -} - -#-- read in ewiki.ini, if one was uploaded (POST ) -if ($li = $_FILES["load_ini"]["tmp_name"]) { - $ini = array(); - $uu = preg_split('/^\[(\w+)\]/m', implode("",file($li)), -1, PREG_SPLIT_DELIM_CAPTURE); - for ($i=1; $i<=count($uu); $i+=2) { - $sect = $uu[$i]; - preg_match_all('/^\s*(\w[^\s]+)\s*=[\t ]*(.+?)(\s;.+)?\s*$/m', $uu[$i+1], $rows); - foreach ($rows[1] as $r=>$name) { - $ini[$sect][$name][] = trim($rows[2][$r]); - } - } - - #-- pre-set the separate $db[] hash - if ($ini["db"]) { - foreach ($ini["db"] as $i=>$val) { - $db[$i] = $val[0]; - } } -} - -#-- data -$default_priority_level = array( - "core"=>"1", "required"=>"1", - "default"=>1, "standard"=>1, - "recommended"=>1, "important"=>1, -); - - -#-- heavily mixed list of features and options -# -# - an array of arrays -# - each entry gives a 'feature' or simply a text fragment -# - first level subarrays have following entries -# [0] type setting, "!"=headline, "="=always_enabled_feature, -# 0=disabled, 1=enabled, "..."=text_fragment_only -# [1] title -# [2] text / description -# [3] list of plugin file names (without .php) -# [4] another subarray of option settings -# - an option setting subarray has following structure: -# [0] field type -# [1] title -# [2] EWIKI_ constant or $ewiki_ var name -# [3] default setting (value) -# [4] text / description -# [5] options for - If you don't need to open the database connection in the config.php - if a MySQL connection was already established somewhere else -
          -
          -
          - (with anydb_ wrapper) -
          -
          -
          -
          -
          - will be created automatically, when you activate ewiki for the first time
          -
          -
          - database backend
          - (compressed)
          - (provides case-insensitive storage, plattform compatible, but more complicated structure) -
          - - Note: the directory "/tmp" exists on most -Unix/Linux webservers, but will be purged on reboot; so you normally want to -use a different location for your pages. Choose a relative path name -(like for example "./files") and create that directory ("mkdir -files" in FTP/shell) and give it world-write permissions -("chmod 777 files" in FTP/shell). -
          -
          - Berkely database file
          -
          - - The file name extension must be one of: - .dbm, .db2, .db3, .db4, .ndbm, .gdbm or .flatfile, and the file must - be world-writable of course -
          -EOT -); - - - - - - -#--------------------------------------------------------------------------- - - - -/* - -#-- read in plugins/ dir -function find_plugin_files($realdir, $dirname) { - $r = array(); - $dh = opendir($realdir); - while ($dh && ($fn = readdir($dh))) { - if ($fn[0] == ".") { - continue; - } - elseif (is_dir("$realdir/$fn")) { - $r = array_merge($r, find_plugin_files("$realdir/$fn", "$dirname/$fn")); - } - elseif ($len = strrpos($fn, ".")) { - $fn = substr($fn, 0, $len); - if (isset($r[$fn]) && $_SERVER["REQUEST_METHOD"]=="GET") { - echo "WARNING: two same named plugins '$fn' in two different locations!
          \n"; - } - $r[$fn] = "$dirname/$fn"; - } - } - closedir($dh); - return($r); -} - -$uu = dirname(__FILE__)."/../plugins"; -$plugin_files = find_plugin_files($uu, "plugins"); - -#-- adjust incomplete filenames in feature $list -foreach ($list as $i1=>$d) { - if (is_array($d[3])) foreach($d[3] as $i2=>$fn) { - if (!strpos($fn, "/")) { - if ($fullfn = $plugin_files[$fn]) { - $list[$i1][3][$i2] = $fullfn; - } - else { - echo "WARNING: could not determine real file name for plugin '$fn'
          \n"; - } - } - } -} - - -*/ - -#--------------------------------------------------------------------------- - - - - -#-- inject values (into $list[]) imported from earlier loaded ewiki.ini -if ($ini) { - foreach ($list as $fid=>$row) { - - #-- enable feature, if all requ/mentioned plugins were loaded in .ini - if (($row[0]===0) || ($row[0]===1)) { - $is = all_in_array($row[3], $ini["plugins"]["load"]); - $list[$fid][0] = ($is ? 1 : 0); - } - - #-- set feature options - if ($row[4]) { - foreach ($row[4] as $oid=>$opts) { - $name = $opts[2]; - $val = $ini["settings"][$name][0]; - if (strlen($val)) { - $list[$fid][4][$oid][3] = $val; - } } } -} } - - -#-- compare two arrays, all elements of first must be in second -function all_in_array($a1, $a2) { - $a3 = array_intersect($a1, $a2); - return(count($a1) == count($a3)); -} - - -#--------------------------------------------------------------------------- - - - -#-- prepare generation of config.php or ewiki.ini -# (builds plugin and constant/var lists from _REQUEST settings) -# -if ($_REQUEST["feature"]) { - - $set = &$_REQUEST["feature"]; - $opt = &$_REQUEST["option"]; - - $c_plugins = array(); - $c_settings = array(0=>array(), 1=>array()); - - #-- go through hardcoded feature $list - foreach ($list as $fid=>$row) { - - #-- compare if feature array enabled in _REQUEST - $enabled = ($row[0] === "=") || ($set[$fid]); - if ($enabled) { -#echo "ENABLED=$set[$fid] feature[$fid], r0=$row[0], r1=$row[1],\n"; - - #-- list of plugins (always triggered) - $c_plugins[] = $row[3]; - - #-- settings, individual $_REQUEST entries - if ($options = $row[4]) { - foreach ($options as $oid=>$row) { - $i = $row[2]; - $v = $opt[$fid][$oid]; - if (strlen($v)) { - $var = ($i[0] == "$") ? 1 : 0; - $c_settings[$var][$i] = preg_match('/^\d+$/', $v) ? "$v" : "'$v'"; - } - } - } - - } - }#--if($enabled) - - #-- cleanup plugin list (in case one was injected twice) - $c_plugins = array_unique($c_plugins); - -}#--if() - - -#--------------------------------------------------------------------------- - - -function config_php_db() { - - global $db; - - echo "#-- database connection/plugins\n"; - switch ($db["type"]) { - case "mysql": - echo "// MySQL support is built-in, we only open the connection\n"; - echo "define(\"EWIKI_DB_TABLE_NAME\", \"$db[table]\");\n"; - echo "mysql_connect('$db[server]', '$db[user]', '$db[pw]');\n"; - echo "mysql_query('USE $db[dbname]');\n\n"; - break; - - case "pgsql": - echo "define(\"EWIKI_DB_TABLE_NAME\", \"$db[table]\");\n"; - echo "define(\"EWIKI_DB_UTF8\", 0); //depends on your Postgres db\n"; - echo "include_once(\"plugins/db/any.php\");\n"; - echo "\$db = anydb_connect('', '$db[user]', '$db[pw]', '$db[dbname]', 'pgsql');\n\n"; - break; - - case "fast": - echo "define(\"EWIKI_DB_FAST_FILES\", 1);\n"; - case "flat": - echo "define(\"EWIKI_DBFILES_DIRECTORY\", \"$db[dir]\");\n"; - echo "include_once(\"plugins/db/flat_files.php\");\n"; - echo "// the given directory must exist and be world-writable (chmod 777)\n\n"; - break; - - case "dzf2": - echo "define(\"EWIKI_DBFILES_DIRECTORY\", \"$db[dir]\");\n"; - echo "define(\"EWIKI_DBFF_ACCURATE\", 1);\n"; - echo "define(\"DZF2_HIT_COUNTING\", 1);\n"; - echo "include_once(\"plugins/db/dzf2.php\");\n"; - echo "// the given directory must exist and be world-writable (chmod 777)\n\n"; - break; - - case "dba": - echo "define(\"EWIKI_DBA\", \"$db[dba]\");\n"; - echo "include_once(\"plugins/db/dba.php\");\n"; - break; - - default: - echo "// you must open a connection (MySQL) outside of the config.php,\n"; - echo "// it has not been configured with the setup wizard\n\n"; - break; - } -} - - -function config_php_settings() { - - global $c_settings; - - echo "#-- constants\n"; - foreach ($c_settings[0] as $id=>$val) { - echo "define(\"$id\", $val);\n"; - } - - echo "\n#-- set a few configuration variables\n"; - foreach ($c_settings[1] as $id=>$val) { - echo "$id = $val;\n"; - } -} - - -#--------------------------------------------------------------------------- - - - -#-- write out "config.php" file -# -if ($_REQUEST["config_php"]) { - header("Content-Type: application/x-httpd-php"); - header("Content-Disposition: attachment; filename=\"config.php\""); - - #-- write out config.php - echo <<"; - die(); -} - - -#--------------------------------------------------------------------------- - - - -#-- write out as "ewiki.ini" file -# -if ($_REQUEST["ewiki_ini"]) { - header("Content-Type: text/x-ini-file"); - header("Content-Disposition: attachment; filename=\"ewiki.ini\""); - out_ewiki_ini(); - die(); -} - -#-- write out config.php -function out_ewiki_ini() { - global $db, $c_settings, $c_plugins, $ewiki_pmd; - echo "; automatically generated configuration summary\n; see ewiki config wizard\n"; - echo "\n[db]\n"; - echo ";init = \n"; - foreach ($db as $id=>$val) { - echo "$id = $val\n"; - } - echo "\n[settings]\n"; - $c_settings = array_merge($c_settings[0], $c_settings[1]); - foreach ($c_settings as $id=>$val) { - $val = trim($val, "'"); - echo "$id = $val\n"; - } - echo "\n[plugins]\n"; - foreach ($c_plugins as $id) { - if ($fn = $ewiki_pmd[$id]["fn"]) { - echo "load = $fn\n"; - } - else { - echo ";not found = $id\n"; - } - } - echo "\n\n"; -} - - - -#--------------------------------------------------------------------------- - - - -#-- generate a "monsterwiki.php" script (all-in-one) -# -if ($_REQUEST["monsterwiki_php"]) { - header("Content-Type: application/x-httpd-php"); - header("Content-Disposition: attachment; filename=\"monsterwiki.php\""); - - #-- begin output - echo << -#\n\n -EOT; - - config_php_db(); - config_php_settings(); - - echo "\n#-- end of settings,\n# plugins follow\n\n/*-- config summary in .ini format:\n"; - out_ewiki_ini(); - echo "--*/\n\n" . "?".">"; - - #-- write plugins - $PREFIX = "../"; - foreach ($c_plugins as $fn) { - if (($fn != "core") && ($fn != "ewiki")) { - if ($fn = $ewiki_pmd[$fn]["fn"]) { - readfile($PREFIX . $fn); - } - } - } - #-- write core - readfile($PREFIX."ewiki.php"); - - die(); -} - - - -#--------------------------------------------------------------------------- -# page output otherwise - -?> - - - ewiki configuration wizard - - -
          -
           
          -
           
          -
           
          -
           
          -
           
          -
          -
          -
          -

          ewiki configuration wizard

          - Generates an initial ewiki.ini or config.php for you. - The plugin list is unfiltered and therefore rather long. Skip all the - settings and options that don't look interesting or senseful at first. -

          - - Note: This wizard has not yet been fully updated to handle the - new plugin *.meta files. Please use the 'tools/setup' console program - if you can. -

          - - You can reuse an earlier ewiki.ini, if you kept a copy of your - previously choosen settings: -
          -
          - -

          - -$row) { - - #-- print main feature field - switch ($row[0]) { - - case "0": - case "1": - echo " \n"; - echo " \n"; - if ($row[2]) { - echo " $row[2]"; - } - echo "
          \n"; - break; - - case "=": - echo " \n"; - echo " $row[1]\n"; - if ($row[2]) { - echo " $row[2]"; - } - echo "
          \n"; - break; - - case "!": - echo "

          $row[1]

          \n"; - default: - echo " $row[2]\n"; - break; - } - - #-- show up associated options - if ($options = $row[4]) - foreach ($options as $oid=>$row) { - $id = "option-$fid-$oid"; - echo '
          '; - echo "     "; - switch($row[0]) { - case "checkbox": - $checked = ($row[3] ? " checked" : ""); - echo ""; - break; - case "select": - echo ""; - break; - default: - echo ""; - } - echo " $row[4]
          \n"; - } - } - -?> -
          -

          fin

          - Now, that you've finished clicking around, you can save your configuration - settings. A save dialog will open, and you should store the files directly - into your ewiki/ directory. -

          - - is - what you should do now; you can use it as replacement for the example - file distributed with ewiki. -

          - - is - useful to later come back and reuse the settings you've made here. -

          - - with - above options and extensions merged in; use this script instead of ewiki.php - then (it is believed to run a bit faster) -

          - -
          -
          - - diff --git a/mods/wiki/tools/t_sync.php b/mods/wiki/tools/t_sync.php deleted file mode 100644 index ac912ee7e..000000000 --- a/mods/wiki/tools/t_sync.php +++ /dev/null @@ -1,195 +0,0 @@ - "ewiki_db", - "ewiki.sync" => "ewiki_sync_local", - ); - phprpc_server(); - xmlrpc_server(); - die("Request Missed."); -} - -#-- start -$action = $_REQUEST["action"]; -$proto = $_REQUEST["proto"]; -$url = $_REQUEST["url"]; -if ($url) { // save as preference - setcookie("last_sync_url", $url, time() + 90*24*60*60, dirname($_SERVER["REQUEST_URI"])); -} - -?> - - - syncing with remote wiki database - - - -

          WikiSync™

          - - -This tool allows you to maintain some pages of a public Wiki in a separate -installation but keep both synchronized. You of course must have the sync -interface installed on both systems (or at least have the XML-RPC service -enabled on the other site). - -
          -
          - -There is currently no conflict resolution code built-in, so you have to -correct these yourself, whenever you edited a page that also was edited -(by someone else) on the remote WikiWikiWeb server. So this is very safe -as it never overwrites stuff, and quick as it typically only copies the -latest version of every page. - -
          -
          - -
          - - -
          - - "> -
          - - Must be either the URL to a remote z.php script or better - to a remote t_sync.php. - -
          -
          - - - -
          -info: " . count($locall) . " pages found in local Wiki database
          \n"; - echo "      and " . count($rlist) . " are on remote server
          \n"; - echo "\n\n"; - flush(); - - - #-- upload - if (in_array($action, array("upload", "sync", "exact"))) { - echo "
          \n

          upload

          \n"; - ewiki_sync_start( - "upload", - $ls_local, $ls_remote, - "ewiki_sync_local", "ewiki_sync_remote" - ); - } - - #-- download - if (in_array($action, array("download", "sync", "exact"))) { - echo "
          \n

          download

          \n"; - ewiki_sync_start( - "download", - $ls_remote, $ls_local, - "ewiki_sync_remote", "ewiki_sync_local" - ); - } - - #-- do an in-deepth analyzation of remaining files - if ($action == "exact") { - echo "
          \n

          sync - exact comparison

          \n"; - foreach ($ls_local as $id=>$ver) { - if ($ls_remote[$id] == $ver) { - - echo htmlentities($id); - flush(); - - $L = ewiki_sync_local("::GET", array($id)); - $R = ewiki_sync_remote("::GET", array($id)); - - if (!ewiki_sync_half_identical($L, $R)) { - echo " - conflict"; - } - else { - echo " - ok"; - } - echo "
          \n"; - } - } - } - - - - - - } - - -?> -
          -
          - - diff --git a/mods/wiki/tools/t_textinsert.php b/mods/wiki/tools/t_textinsert.php deleted file mode 100644 index b4ec6d697..000000000 --- a/mods/wiki/tools/t_textinsert.php +++ /dev/null @@ -1,149 +0,0 @@ - - - - insert plain text files as pages into ewiki db - - - -

          text file insertion util

          - - - - Use this tool to (re)insert text files as pages into the database (like the - automatic initialization if ewiki.php, when it is run for the very first - time). Before it overwrites anything you must first select the files to be - inserted from the list of found files, in the subdirectory you can select - now:

          - -
          - subdir with page files: -

          - -
          - - ' . - ''; - - echo ''; - - foreach ($files as $fn) { - - $sel = 0; - $reason = ""; - - $data = ewiki_db::GET($fn); - - if (empty($data)) { - $sel = 1; - $reason .= "not yet in database
          \n"; - } - elseif (!strlen(trim($data["content"]))) { - $sel = 1; - $reason .= "database entry empty
          \n"; - } - elseif ($data["lastmodified"] < filemtime($from.$fn)) { - $sel = 1; - $reason .= "database entry is older
          \n"; - } - elseif (strlen($data["content"]) < filesize($from.$fn)) { - $sel = 1; - $reason .= "database entry is shorter
          \n"; - } - - if (strlen($data["content"]) > filesize($from.$fn)) { - $sel = 0; - $reason .= "database entry is longer!
          \n"; - } - - if ($data["lastmodified"] >= filemtime($from.$fn)) { - $sel = 0; - $reason .= "database entry is newer!
          \n"; - } - - if (!filesize($from . $fn)) { - $sel = 0; - $reason .= "empty file
          \n"; - } - - echo '\n" . '\n"; - - } - - echo '
          '; - echo ''; - echo " " . $fn; - echo "'; - echo $reason . "
          ' . - '' . - ''; - - } - else { - - $from = $_REQUEST["from"]; - $files = $_REQUEST["file"]; - if (strstr(substr($from, 3), "/")) die("unallowed subdir name"); - $from .= "/"; - - foreach ($files as $fn => $uu) { - - if (strstr($fn, "/") ||strstr($fn, ".") || (!$uu)) { - echo "filename '$fn' not allowed (NOTE: no versioned pages!)...
          \n"; - continue; - } - - $ctime = filectime($from . $fn); - $content = implode("", file($from . $fn)); - - $prev = ewiki_db::GET($fn); - - $data = array( - "id" => $fn, - "version" => 1+ @$prev["version"], - "author" => ewiki_author("ewiki_backdown"), - "flags" => EWIKI_DB_F_TEXT | @$prev["flags"], - "content" => $content, - "created" => $ctime, - "lastmodified" => time(), - "refs" => "\n", - "meta" => "", - "hits" => 0+ @$prev["hits"], - ); - - $r = (ewiki_db::WRITE($data) ? "ok" : "error"); - - echo "writing '$fn'... [$r]
          \n"; - } - - } - -?> - - \ No newline at end of file diff --git a/mods/wiki/tools/t_textupload.php b/mods/wiki/tools/t_textupload.php deleted file mode 100644 index 4b1b00ee0..000000000 --- a/mods/wiki/tools/t_textupload.php +++ /dev/null @@ -1,29 +0,0 @@ - - - - Upload text files as WikiPage - - - -

          TextUpload

          - -

          - - diff --git a/mods/wiki/tools/t_transfer.php b/mods/wiki/tools/t_transfer.php deleted file mode 100644 index 2626db0de..000000000 --- a/mods/wiki/tools/t_transfer.php +++ /dev/null @@ -1,149 +0,0 @@ -get()) { - $n++; - - $id = $row["id"]; - for ($v=$row["version"]; $v>0; $v--) { - - $row = ewiki_db::GET($id, $v); - - if ($_REQUEST["textonly"] - && (EWIKI_DB_F_TEXT != ($row["flags"] & EWIKI_DB_F_TYPE)) ) - { - continue; - } - - if ($row && ($row = serialize($row))) { - echo "\n" . strlen($row) . "\n" . $row; - } - - } - - if ($gzip && !($n % 15)) { - ob_flush(); - } - } -} - -#-- uploading -elseif (!empty($_FILES["data"])) { - -#error_reporting(E_ALL); - if ($i = gzopen($_FILES["data"]["tmp_name"], "rb")) { - $feof = "gzeof"; - $fgets = "gzgets"; - $fread = "gzread"; - } - elseif ($i = fopen($_FILES["data"]["tmp_name"], "rb")) { - $feof = "feof"; - $fgets = "fgets"; - $fread = "fread"; - } - else { - die("could not open incoming file"); - } - - $n = 0; - - while ($i && !$eof($i)) { - - /*stripCRLF*/ $idf = $fgets($i, 4096); - if ($n==0) { - $idf = trim($idf); - if ($idf != EWIKI_TRANSFER_IDF) { - die("This is not an ewiki transfer binary. (wrong magic code 0x".bin2hex($idf).")"); - } - } - - $count = $fgets($i, 4096); - if (($count === false) || (($count = trim($count)) <= 0)) { - - if ($feof($i)) { - $fclose($i); - die("
          finished reading $n entries"); - } - else { - die("
          file broken (zero count block) after $n entries"); - } - } - - $row = $fread($i, $count); - $row = unserialize($row); - - if (ewiki_db::WRITE($row)) { - echo $row["id"] .".". $row["version"] . "  \n"; - } - - $n++; - } - -} - -#-- activation form -else { - ?> - - - make binary backup of whole database - - - - -

          database dump

          - If you cannot make use of the ewikictl cmdline utility, and need - a way to transfer the whole database from one server to another, you - can make a downloadable binary dump using this util. -

          - -

          generate dump

          -
          " method="GET" enctype="application/x-www-form-urlencoded"> - - -
          -
          -
          - -

          reinsert dump

          -
          " method="POST" enctype="multipart/form-data"> - -
          -
          -
          - - - \ No newline at end of file diff --git a/mods/wiki/tools/upgrade-r101d b/mods/wiki/tools/upgrade-r101d deleted file mode 100755 index 99e2a09a1..000000000 --- a/mods/wiki/tools/upgrade-r101d +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/perl -w -- -# -# This script can convert the include() commands of an old "config.php" to -# point to the plugins new filenames then. - - -if ($#ARGV < 0) { - print "syntax: tools/upgrade config.php\n\n"; exit; -} -$file = shift @ARGV; - -#-- read in -$content = ""; -open FH, "< $file"; -while () { - $content .= $_; -} -close FH; - - -#-- run regexs on it -$content =~ s#(include\(["'].*?plugins/)contrib/(.+?\.php["']\))#$1$2#gix; -$content =~ s#(include\(["'].*?plugins/)(db|aview|page|action|contrib|markup)_(.+?\.php["']\))#$1$2/$3#gix; -# -$content =~ s#(include\(["'].*?plugins/)(diff|verdiff|like_|transl)(.*?\.php["']\))#$1action/$2$3#gix; -$content =~ s#(include\(["'].*?plugins/)(fancy|listp|title_cal)(.*?\.php["']\))#$1appearance/$2$3#gix; -$content =~ s#(include\(["'].*?plugins/)(aedit_|toc)(.*?\.php["']\))#$1aview/$2$3#gix; -$content =~ s#(include\(["'].*?plugins/)(binary_stor)(.*?\.php["']\))#$1db/$2$3#gix; -$content =~ s#(include\(["'].*?plugins/)(append|imgresize|spellch)(.*?\.php["']\))#$1feature/$2$3#gix; -$content =~ s#(include\(["'].*?plugins/)(f_|fun_|search_)(.*?\.php["']\))#$1filter/$2$3#gix; -$content =~ s#(include\(["'].*?plugins/)more_interwiki()(.*?\.php["']\))#$1interwiki/intermap$3#gix; -$content =~ s#(include\(["'].*?plugins/)(cache|mime_magic|navbar|speed|save_store)(.*?\.php["']\))#$1lib/$2$3#gix; -$content =~ s#(include\(["'].*?plugins/)(autoli|linkex|link_|plural|tcn)(.*?\.php["']\))#$1linking/$2$3#gix; -$content =~ s#(include\(["'].*?plugins/)(calendar|downloads|tour)(.*?\.php["']\))#$1module/$2$3#gix; -$content =~ s#(include\(["'].*?plugins/)(auth_)(.*?\.php["']\))#$1auth/$2$3#gix; -# R1.01e1 -$content =~ s#(include\(["'].*?plugins/)aview/aedit_(.*?\.php["']\))#$1edit/$2#gix; - - -#-- write back -open FH, "> $file"; -print FH $content; -close FH; - diff --git a/mods/wiki/tools/whiptail b/mods/wiki/tools/whiptail deleted file mode 100755 index 49e7f526b33c9e9bfca47cf15d7fcfb9f0ae87d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21292 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 "/^-+(h|help)$/i", - "dirs" => "/^-+(d|dir.*|create.*)$/i", - "ext" => "/^-+(e|ext.*)$/i", - "keepref" => "/^-+(k|keep.*|ref.*)$/i", - )); - - #-- main - if ($config["help"]) { - echo "wiki2html converts your ewiki database into .html body part files. -These files miss the and markup and only contain the rendered -wiki content. -If you rather want a static version of your site please choose 'wget' or a -similar utility instead. - ---help prints this help screen ---dirs creates the bin/ and img/ subdirectories (auto) ---ext extension for the created pages (.htm is default) ---keep keep references to external (but cached) images (NYI) - -"; - } - else { - - #-- working vars - $dest = "wiki2html-".time(); - mkdir($dest); - ($ext = $config["ext"]) || ($ext = "htm"); - $ewiki_config["script"] = "%s." . trim($ext, "."); - $ewiki_config["script_binary"] = "bin/%s"; - - #-- page names - $result = ewiki_db::GETALL(array("flags")); - - #-- loop - while ($row = $result->get()) { - - $id = $row["id"]; - $row = ewiki_db::GET($id); - - #-- pages - if (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) { - - $html = ewiki_format($row["content"]); - - $f = fopen("$dest/" . ewiki_script("", $id), "wb"); - fwrite($f, $html); fclose($f); - } - - #-- images - elseif (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_BINARY) { - - if (!file_exists("$dest/bin")) { - mkdir("$dest/bin"); - } - - $f = fopen("$dest/bin/" . ewiki_script("", $id), "wb"); - fwrite($f, $row["content"]); fclose($f); - } - - } - } - - - #------------------------------------------------------------------------ - - function regex_getopts($regexopts) { - if (empty($_SERVER)) { - $_SERVER = $GLOBALS["HTTP_SERVER_VARS"]; - } - if (!empty($GLOBALS["argc"])) { - $_SERVER["argc"] = $GLOBALS["argc"]; - $_SERVER["argv"] = $GLOBALS["argv"]; - } - $opts = array(); - for ($n = 1; $n < $_SERVER["argc"]; $n++) { - foreach ($regexopts as $opts_id => $optsregex) { - if (preg_match($optsregex, $_SERVER["argv"][$n])) { - $value = 1; - if (($next = @$_SERVER['argv'][$n+1]) && ($next[0] != "-")) { - $value = $next; - $n++; - } - $opts[$opts_id] = $value; - continue 2; - } - } - $opts[] = $_SERVER["argv"][$n]; - } - return($opts); - } - #------------------------------------------------------------------------- - - -?> \ No newline at end of file diff --git a/mods/wiki/tools/xt_searchcache_staticf.php b/mods/wiki/tools/xt_searchcache_staticf.php deleted file mode 100644 index db39ac9d9..000000000 --- a/mods/wiki/tools/xt_searchcache_staticf.php +++ /dev/null @@ -1,100 +0,0 @@ - - - - XT: cache static files' text into database - - - -

          cache static files

          - - This tool is useful if 'yoursite.php' loads from static files and from the Wiki - database concurrently and the URLs are therefore similar enough to warrant - caching of static .html files into the database to use the unified search - feature.
          - This is the case if you use mod_rewrite and have URLs like - http://example.org/WikiPage and http://example.org/otherpage.html - and both get displayed by your index.php script depending on if such a static page - exists. In this case EWIKI_SCRIPT is most always set to "/". -
          -
          - Else don't use this tool, it would generate silly database entries then - for your setup. -
          -
          -
          - directory
          - (we're currently in "") -

          - maps to
          - (don't forget that EWIKI_SCRIPT is also prepended to this) -

          - file types
          - (unix filename globbing!) -

          - -
          - - - diff --git a/mods/wiki/tools/xt_sysinfo.php b/mods/wiki/tools/xt_sysinfo.php deleted file mode 100644 index c2edfe0f2..000000000 --- a/mods/wiki/tools/xt_sysinfo.php +++ /dev/null @@ -1,54 +0,0 @@ - - - PHP System Information - - - -

          compatibility check

          -

          - This page only provides compatibility informations about ewiki and your - PHP setup/version. Check it on new installations to be aware of problems - and workarounds beforehand. -

          - - - - - - - array( - PHP_VERSION, - PHP_VERSION<"4.3", - "ewiki requires version 4.3 or later, else a few features may not work due to lack of language functionality" - ), - "safe mode" => array( - ini_get("safe_mode"), - ini_get("safe_mode"), - "The so called 'Safe Mode' cripples the PHP language from a few features, and makes running it on a Unix/Linux server senseless. If your provider has Perl or Python enabled on the server, this setting is clearly dumb or only meant to squeeze additional cash from you (before you get full PHP support). 90% of ewiki plugins will run anyhow. Don't ask for support in the other cases.", - ), - ); - foreach ($tests as $title=>$dat) { - if ($dat[1]) { - $text = $dat[2]; - $class = "error"; - } - else { - $text = "-"; - $class = "ok"; - } - if (is_bool($dat[0]) || !strlen($dat[0])) { - $dat[0] = $dat[0] ? "ON" : "OFF"; - } - echo "\n" - . " \n" - . " \n" - . " \n" - . "\n"; - } -?> -
          infovaluehelp/workaround
          $title$dat[0]$text
          -

          - - diff --git a/mods/wiki/wiki.css b/mods/wiki/wiki.css deleted file mode 100644 index eaaa15bec..000000000 --- a/mods/wiki/wiki.css +++ /dev/null @@ -1,37 +0,0 @@ - -/* - This sample stylesheet lists all possible stylesheet sections, that - ewiki and its plugins may output. But don't forget to also have a look - into the README section about this. (This also obsoletes the 'core.css' - sample in the fragments/css/ directory.) -*/ - - - -/* a typical wiki page outout is separated into following classes: - - .wiki.. - .text-head - h2.text-title - .text-body - <...> - .wiki-plugins - .action-links - . -*/ -.wiki.edit.FrontPage { - background: transparent; -} - - - -/*-- links to non-existent pages*/ -.NotFound * { - text-decoration: none; - border-bottom: dashed 1px blue; -} -.NotFound a { - color: red; - border-bottom-style: none; -} - diff --git a/mods/wiki/z.php b/mods/wiki/z.php deleted file mode 100644 index d83b2a646..000000000 --- a/mods/wiki/z.php +++ /dev/null @@ -1,106 +0,0 @@ -ServeRequest(); - exit; -} - - -#-- what kind of request -$rt = strtolower(trim(strtok(@$_SERVER["CONTENT_TYPE"], ",;"))); -switch ($rt) { - - #-- WikiApi - case XMLRPC_MIME_OLD: - case XMLRPC_MIME_NEW: - xmlrpc_server(); - exit; - - #-- Atom - case "application/atom+xml": - // atom_server(); - header("501 Not Implemented"); - exit; - - #-- WikiSync or PHP-RPC - case "application/vnd.php.serialized": - phprpc_server(); - include("tools/t_sync.php"); - exit; - - default: -} - -#-- other detection mechanism? -//... - - -#-- else complain -header("Content-Type: text/html"); -header("Status: 401 Method Not Implemented"); -die('This is the interface for XML-RPC, OpenSearch, WikiSync, PHP-RPC,
          WebDAV and Atom requests. Go away already!'); - -?> \ No newline at end of file diff --git a/mods/wordpress/README b/mods/wordpress/README deleted file mode 100644 index 238d298f5..000000000 --- a/mods/wordpress/README +++ /dev/null @@ -1,28 +0,0 @@ -## WordPress Integration module for ATutor - -#################### - -**Wordpress needs to be installed and configured before installing this module. See the Wordpress documentation for instruction on installing and configuring Wordpress. - -http://codex.wordpress.org/Installing_WordPress - - -#################### -Installation the ATutor WordPress Module: -1. Unzip the atutor_wordpress.x.x.x.zip file into the ATutor mods/ directory to create a "wordpress directory. -2. Login to ATutor as the admin, click on the Modules tab then click Install Modules. Wordpress should be listed. Select it and press the Install button. -3. Follow the installer instructions. -4. Once the module is installed, select the WordPress module now listed in the available modules in the module manager, then press the Enable button. This inserts another main navigation tab above. -5. Click the WordPress tab then enter the URL to the base directory under which WordPress is installed, then press the Save button. WordPress should then appear below. -6. Next set the database access information for WordPress in the wp_config.php file in the module directory, then save the file. This information is required for the module detailed view to display recent posts on a course home page, or student tools page. - -##################### -Authenticate Wordpress Users from ATutor Members -To remove the need to setup separate accounts in WordPress and ATutor, you can install the WordPress External DB Authentication plugin. A copy of the plugin is available in the modules' wp_plugin directory. For details on how to install the plugin, see the link below. - -Plugin details can be found at: -http://wordpress.org/extend/plugins/external-database-authentication/ - -Note that this is not a single sign-on, but rather just a way to ensure anyone registered in ATutor, is automatically registered in Wordpress. When a user logs into Wordpress for the first time, the member information in ATutor is copied over to WordPress. If you find you are unable to login with an account you know exists in ATutor, review the cookies you have set in your browser, and remove any WordPress related ones. Then try to login again. This problem can occur when you are using more than one ATutor account to access Wordpress. - -Note also that you will probably want to install this ATutor Wordpress plugin before you start using Wordpress. Otherwise you will need to recreate any Wordpress accounts in ATutor. Once the module is installed, Wrodpress users are no longer able to modify their Wordpress account information. \ No newline at end of file diff --git a/mods/wordpress/index.php b/mods/wordpress/index.php deleted file mode 100644 index ab72ba4d6..000000000 --- a/mods/wordpress/index.php +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/mods/wordpress/index_admin.php b/mods/wordpress/index_admin.php deleted file mode 100644 index ccb4dea3a..000000000 --- a/mods/wordpress/index_admin.php +++ /dev/null @@ -1,46 +0,0 @@ -$wp_config) - if($key != "submit"){ - $sql="REPLACE INTO ".TABLE_PREFIX."config SET name='$key', value='".$wp_config."'"; - if($result= mysql_query($sql, $db)){ - $msg->addFeedback("WP_CONFIG_SAVED"); - $_config['wp-url'] = $_POST['wp-url']; - }else{ - $msg->addError("WP_CONFIG_FAIL"); - } - - } -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> - -
          - -
          - - -
          - -

          - - - - -

          - - - - \ No newline at end of file diff --git a/mods/wordpress/index_instructor.php b/mods/wordpress/index_instructor.php deleted file mode 100644 index cbdc7421c..000000000 --- a/mods/wordpress/index_instructor.php +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/mods/wordpress/index_mystart.php b/mods/wordpress/index_mystart.php deleted file mode 100644 index d66deed4f..000000000 --- a/mods/wordpress/index_mystart.php +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - diff --git a/mods/wordpress/index_public.php b/mods/wordpress/index_public.php deleted file mode 100644 index cf2ca9594..000000000 --- a/mods/wordpress/index_public.php +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/mods/wordpress/module.css b/mods/wordpress/module.css deleted file mode 100644 index c9fce7ac6..000000000 --- a/mods/wordpress/module.css +++ /dev/null @@ -1,15 +0,0 @@ -div#helloworld { - border: 1px solid #ccc; - padding: 10px; - width: 50%; - margin-right: auto; - margin-left: auto; - background-color: #efefef; - color: #444; - margin-top: 30px; - margin-bottom: 30px; -} - -#frame_set{ - border:none; -} \ No newline at end of file diff --git a/mods/wordpress/module.php b/mods/wordpress/module.php deleted file mode 100644 index a8134c086..000000000 --- a/mods/wordpress/module.php +++ /dev/null @@ -1,84 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_WORDPRESS', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -//$this->_stacks['wordpress'] = array('title_var'=>'wordpress', 'file'=>'mods/wordpress/side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('wordpress', array('title_var' => 'wordpress', 'file' => './side_menu.inc.php'); - -/******* - * create optional sublinks for module "detail view" on course home page - * when this line is uncommented, "mods/wordpress/sublinks.php" need to be created to return an array of content to be displayed - */ -$this->_list['wordpress'] = array('title_var'=>'wordpress','file'=>'mods/wordpress/sublinks.php'); - -// Uncomment for tiny list bullet icon for module sublinks "icon view" on course home page -$this->_pages['mods/wordpress/index.php']['icon'] = 'mods/wordpress/wordpress_icon_sm.png'; - -// Uncomment for big icon for module sublinks "detail view" on course home page -//$this->_pages['mods/wordpress/index.php']['img'] = 'mods/wordpress/wordpress.jpg'; - -// ** possible alternative: ** -// the text to display on module "detail view" when sublinks are not available -$this->_pages['mods/wordpress/index.php']['text'] = _AT('wordpress_text'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_group_tool = $_student_tool = 'mods/wordpress/index.php'; - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_WORDPRESS, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/wordpress/index_admin.php'); - $this->_pages['mods/wordpress/index_admin.php']['title_var'] = 'wordpress'; - $this->_pages['mods/wordpress/index_admin.php']['parent'] = AT_NAV_ADMIN; -} - -/******* - * instructor Manage section: - */ -$this->_pages['mods/wordpress/index_instructor.php']['title_var'] = 'wordpress'; -$this->_pages['mods/wordpress/index_instructor.php']['parent'] = 'tools/index.php'; -// ** possible alternative: ** -// $this->pages['./index_instructor.php']['title_var'] = 'wordpress'; -// $this->pages['./index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages['mods/wordpress/index.php']['title_var'] = 'wordpress'; -$this->_pages['mods/wordpress/index.php']['img'] = 'mods/wordpress/wordpress_logo.png'; - -/* public pages */ -//$this->_pages[AT_NAV_PUBLIC] = array('mods/wordpress/index_public.php'); -//$this->_pages['mods/wordpress/index_public.php']['title_var'] = 'wordpress'; -//$this->_pages['mods/wordpress/index_public.php']['parent'] = AT_NAV_PUBLIC; - -/* my start page pages */ -$this->_pages[AT_NAV_START] = array('mods/wordpress/index_mystart.php'); -$this->_pages['mods/wordpress/index_mystart.php']['title_var'] = 'wordpress'; -$this->_pages['mods/wordpress/index_mystart.php']['parent'] = AT_NAV_START; - -function wordpress_get_group_url($group_id) { - return 'mods/wordpress/index.php'; -} - -?> \ No newline at end of file diff --git a/mods/wordpress/module.sql b/mods/wordpress/module.sql deleted file mode 100644 index c9e2eac34..000000000 --- a/mods/wordpress/module.sql +++ /dev/null @@ -1,30 +0,0 @@ -# sql file for hello world module - -CREATE TABLE `wordpress` ( - `wordpress_id` mediumint(8) unsigned NOT NULL, - `course_id` mediumint(8) unsigned NOT NULL, - `value` VARCHAR( 30 ) NOT NULL , - PRIMARY KEY ( `wordpress_id` ) -) ENGINE = MyISAM; - -INSERT INTO `language_text` VALUES ('en', '_module','wordpress','WordPress',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_admin_login','Login to Administer WordPress',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_base_url','WordPress base URL',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_login','WordPress Login',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_host_url','WordPress Host URL',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_db_name','WordPress Database Name',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_db_port','WordPress Database Port',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_db_user','WordPress Database User',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_update','WordPress Update',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_db_pwd','WordPress Database Password',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_db_prefix','WordPress Database Table Prefix',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_save','Save',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_no_iframes','Your browser does not support iframes. Go to WordPress Login',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_do_setup','Enter the URL to the WordPress based directory in the form field above, including a trailing slash (/), to have WordPress appear here.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','wordpress_no_db_info','To access current information here, modify the wp_config.php file in the WordPress module.',NOW(),''); - - - - -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_WP_CONFIG_SAVED','Wordpress configuration successfully saved',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_WP_CONFIG_FAIL','Wordpress configuration failed to save. ',NOW(),''); \ No newline at end of file diff --git a/mods/wordpress/module.xml b/mods/wordpress/module.xml deleted file mode 100644 index ce996a6a0..000000000 --- a/mods/wordpress/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Wordpress Integration - This module integrate wordpress with ATutor, opening it in an iframe either as a course tool, or as My Start Page Blog. With the Wordpress external DB authentication plugin installed, available in the wp_plugins directory of the module, it synchronizes Wordpress users with ATutor members. See the README file for additional details. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 1.0 - 2011-06-21 - beta - Once installed, enable the module then under the new Wordpress tab, enter the URL to the base directory in which Wordpress is installed. - - diff --git a/mods/wordpress/module_delete.php b/mods/wordpress/module_delete.php deleted file mode 100644 index 322d3a611..000000000 --- a/mods/wordpress/module_delete.php +++ /dev/null @@ -1,21 +0,0 @@ - \ No newline at end of file diff --git a/mods/wordpress/module_install.php b/mods/wordpress/module_install.php deleted file mode 100644 index 9a828118f..000000000 --- a/mods/wordpress/module_install.php +++ /dev/null @@ -1,67 +0,0 @@ -addError(array('MODULE_INSTALL', '
        • '.$directory.' does not exist. Please create it.
        • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
        • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
        • ')); -} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/wordpress/module_news.php b/mods/wordpress/module_news.php deleted file mode 100644 index c6df5387a..000000000 --- a/mods/wordpress/module_news.php +++ /dev/null @@ -1,43 +0,0 @@ - 100){ - $row['post_content'] = substr($row['post_content'],0,100)."..."; - } - if(!in_array($row['post_title'], $post_title)){ - $post_title[] = $row['post_title']; - $news[] = array('time'=> $row['post_modified'], - 'alt'=>_AT('wordpress_update'), - 'thumb'=>'mods/wordpress/wordpress_icon_sm.png', - 'link'=>' SUBLINK_TEXT_LEN ? ' title="'.$row['post_title'].'"' : '') .'>'. - validate_length($row['post_title'], SUBLINK_TEXT_LEN, VALIDATE_LENGTH_FOR_DISPLAY) .'
          '.$row['post_content']); - } - } - } - - return $news; - -} -?> diff --git a/mods/wordpress/module_uninstall.php b/mods/wordpress/module_uninstall.php deleted file mode 100644 index 9ed6969e7..000000000 --- a/mods/wordpress/module_uninstall.php +++ /dev/null @@ -1,44 +0,0 @@ -addError(array('MODULE_UNINSTALL', '
        • '.$directory.' can not be removed. Please manually remove it.
        • ')); -} - -/****** - * the following code checks if there are any errors (generated previously) - * then uses the SqlUtility to run reverted database queries of module.sql, - * ie. "create table" statement in module.sql is run as drop according table. - */ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/wordpress/sublinks.php b/mods/wordpress/sublinks.php deleted file mode 100644 index 5a8e77554..000000000 --- a/mods/wordpress/sublinks.php +++ /dev/null @@ -1,36 +0,0 @@ -$value){ - $list[] = ' SUBLINK_TEXT_LEN ? ' title="'.$row['value'].'"' : '') .'>'. - validate_length($value['post_title'], SUBLINK_TEXT_LEN, VALIDATE_LENGTH_FOR_DISPLAY) .''; - } - return $list; -} else { - return 0; -} - -?> \ No newline at end of file diff --git a/mods/wordpress/wordpress_icon_sm.png b/mods/wordpress/wordpress_icon_sm.png deleted file mode 100644 index ea596008d263891f83ad7ff911f32369d8fe5035..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1089 zcmV-H1it%;P)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RW1_=)=2zt|4#{d8TL3Bk}bVF}# zZDnqB07FtmK~zstIv{6cEoyLOXCQVlE-)Y{b#rNMXCO&RM<7a2MMofZHZmzJAaQkJ zY-x0PAUz;CFbc3mSd#z%1BOXNK~y-)Ws_S>TXg`3fB$psX*q47v>mVuIwobnKqnWM zxl}Z0#*7+$(8R#>jrrn}G0xi(6B84SW{Ho}WF~ILWh~ZY%3R_gk>cjovUOXrK+8%C z^nN>sp3C0{eIW6B`z7DQ@8u)-kHFk*92@Szm79sSU+=AT_O;pHX>r@1Wk66YRKnSO z>06gezWBnBZw1>R+sEbL?KAhX+N)2rHb`a8igckuVFGShBF&2uVbTWNCarUz} z4~?^zf=g|o2Zb{)9o)r90z;yaI5f$DVl0NvCJV$`0jtX?sJtByb2U8PwVSjziS$ld z?Hd@IIL}PYt#pobG)eJ|5*g_5LM08zD<*Pe2fVC;r+W6_?+lA<#lWqU4#PANTFR1M zFM}2vdy+ZW?))H86L2GGfKtF?B`B2)Y%x48{E-9zcrA5=VrBdm7xDd-1yGj9x$9LF zYxObCYPI=qE@x>$6Nq6L*z003vrq=tAY!9phoY!>`amnDe=2~8B7VPL#Y&}!Xof=2 z>y1pltRk1+!d%=$D6)j1o;F19E@365VtqXgRaLOpYk^WKpst(P=jO1mZo(x(x1Cre0iOqA05}}o&tol9!*IKR)0e_%blB1Fs-ToF!0&TnF(F%_gZ)16453f9TM=4Zi@){qaDX}W z%~gDOd}KVGt<1mH&5q4fgzi}c>8rM00000NkvXX Hu0mjfUp?fV diff --git a/mods/wordpress/wordpress_logo.png b/mods/wordpress/wordpress_logo.png deleted file mode 100644 index 88e20b9d28a3a9a8d5f05b4bc9682d285730f942..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5886 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 Up^0CqlK=n!07*qoM6N<$f*TQ7EdT%j diff --git a/mods/wordpress/wp_config.php b/mods/wordpress/wp_config.php deleted file mode 100644 index 3e667c543..000000000 --- a/mods/wordpress/wp_config.php +++ /dev/null @@ -1,13 +0,0 @@ - diff --git a/mods/wordpress/wp_connect.php b/mods/wordpress/wp_connect.php deleted file mode 100644 index f220f37dc..000000000 --- a/mods/wordpress/wp_connect.php +++ /dev/null @@ -1,25 +0,0 @@ - \ No newline at end of file diff --git a/mods/wordpress/wp_plugin/external-database-authentication/ext_db_auth.php b/mods/wordpress/wp_plugin/external-database-authentication/ext_db_auth.php deleted file mode 100644 index abf690dd5..000000000 --- a/mods/wordpress/wp_plugin/external-database-authentication/ext_db_auth.php +++ /dev/null @@ -1,536 +0,0 @@ - -
          -

          External Database Authentication Settings

          -
          - -

          External Database Settings

          - Make sure your WP admin account exists in the external db prior to saving these settings. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          Database type - - required; If not MySQL, requires PEAR MDB2 package and relevant database driver package installation. -
          Only when using non-MySQL database and in case this isn't in some sort of include path in your PHP configuration. No trailing slash! e.g., /home/username/php
          required; (often localhost)
          Only set this if you have a non-standard port for connecting.
          required
          required; (recommend select privileges only)
          required
          required
          - -

          External Database Source Fields

          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          required
          required -
          Password encryption methodrequired; (using "Other" requires you to enter PHP code below!)
          Only will run if "Other" is selected and needs to be PHP code. Variable you need to set is $password2, and you have access to (original) $username and $password.
          -
          -
          -
          Use this if you have certain user role ids in your external database to further restrict allowed logins. If unused, leave fields blank.
          -

          Other

          - - - - - - -
          Custom login messageShows up in login box, e.g., to tell them where to get an account. You can use HTML in this text.
          - -

          - -

          -
          -
          -getMessage()); - return $resource; - break; - case "query": - $result = $resource->query($query); - if(PEAR::isError($result)) die('Failed to issue query, error message : ' . $result->getMessage()); - return $result; - break; - case "numrows": - return $resource->numRows(); - break; - case "fetch": - return $resource->fetchRow(MDB2_FETCHMODE_ASSOC); - break; - case "close": - $resource->disconnect(); - break; - } - } -} - -//actual meat of plugin - essentially, you're setting $username and $password to pass on to the system. -//You check from your external system and insert/update users into the WP system just before WP actually -//authenticates with its own database. -function ext_db_auth_check_login($username,$password) { - require_once('./wp-includes/registration.php'); - - //first figure out the DB type and connect... - $driver = get_option('ext_db_type'); - //if on same host have to use resource id to make sure you don't lose the wp db connection - - $mdbpath = get_option('ext_db_mdb2_path')."/MDB2.php"; - if ($mdbpath != "/MDB2.php") @require_once($mdbpath); - - $resource = db_functions($driver,"connect","",""); - //prepare the db for unicode queries - //to pick up umlauts, non-latin text, etc., without choking - $utfquery = "SET NAMES 'utf8'"; - $resultutf = db_functions($driver,"query",$resource,$utfquery); - - //do the password hash for comparing - switch(get_option('ext_db_enc')) { - case "SHA1" : - $password2 = sha1($password); - break; - case "MD5" : - $password2 = md5($password); - break; - case "Other" : //right now defaulting to plaintext. People can change code here for their own special hash - eval(get_option('ext_db_other_enc')); - break; - } - - - //first check to see if login exists in external db - $query = "SELECT count(*) AS numrows FROM " . get_option('ext_db_table') . " WHERE ".get_option('ext_db_namefield')." = '$username'"; - $result = db_functions($driver,"query",$resource,$query); - $numrows = db_functions($driver,"fetch",$result,""); - $numrows = $numrows["numrows"]; - - if ($numrows) { - //then check to see if pw matches and get other fields... - $sqlfields['first_name'] = get_option('ext_db_first_name'); - $sqlfields['last_name'] = get_option('ext_db_last_name'); - $sqlfields['user_url'] = get_option('ext_db_user_url'); - $sqlfields['user_email'] = get_option('ext_db_user_email'); - $sqlfields['description'] = get_option('ext_db_description'); - $sqlfields['aim'] = get_option('ext_db_aim'); - $sqlfields['yim'] = get_option('ext_db_yim'); - $sqlfields['jabber'] = get_option('ext_db_jabber'); - $sqlfields['ext_db_role'] = get_option('ext_db_role'); - - foreach($sqlfields as $key=>$value) { - if ($value == "") unset($sqlfields[$key]); - } - $sqlfields2 = implode(", ",$sqlfields); - - //just so queries won't error out if there are no relevant fields for extended data. - if (empty($sqlfields2)) $sqlfields2 = get_option('ext_db_namefield'); - - $query = "SELECT $sqlfields2 FROM " . get_option('ext_db_table') . " WHERE ".get_option('ext_db_namefield')." = '$username' AND ".get_option('ext_db_pwfield')." = '$password2'"; - $result = db_functions($driver,"query",$resource,$query); - $numrows = db_functions($driver,"numrows",$result,""); - - if ($numrows) { //create/update wp account from external database if login/pw exact match exists in that db - $extfields = db_functions($driver,"fetch",$result,""); - $process = TRUE; - - //check role, if present. - $role = get_option('ext_db_role'); - if (!empty($role)) { //build the role checker too - $rolevalue = $extfields[$sqlfields['ext_db_role']]; - $rolethresh = get_option('ext_db_role_value'); - $rolebool = get_option('ext_db_role_bool'); - global $ext_error; - if ($rolebool == 'is') { - if ($rolevalue == $rolethresh) {} - else { - $username = NULL; - $ext_error = "wrongrole"; - $process = FALSE; - } - } - if ($rolebool == 'greater than') { - if ($rolevalue > $rolethresh) {} - else { - $username = NULL; - $ext_error = "wrongrole"; - $process = FALSE; - } - } - if ($rolebool == 'less than') { - if ($rolevalue < $rolethresh) {} - else { - $username = NULL; - $ext_error = "wrongrole"; - $process = FALSE; - } - } - } - //only continue with user update/creation if login/pw is valid AND, if used, proper role perms - if ($process) { - $userarray['user_login'] = $username; - $userarray['user_pass'] = $password; - $userarray['first_name'] = $extfields[$sqlfields['first_name']]; - $userarray['last_name'] = $extfields[$sqlfields['last_name']]; - $userarray['user_url'] = $extfields[$sqlfields['user_url']]; - $userarray['user_email'] = $extfields[$sqlfields['user_email']]; - $userarray['description'] = $extfields[$sqlfields['description']]; - $userarray['aim'] = $extfields[$sqlfields['aim']]; - $userarray['yim'] = $extfields[$sqlfields['yim']]; - $userarray['jabber'] = $extfields[$sqlfields['jabber']]; - $userarray['display_name'] = $extfields[$sqlfields['first_name']]." ".$extfields[$sqlfields['last_name']]; - - //also if no extended data fields - if ($userarray['display_name'] == " ") $userarray['display_name'] = $username; - - db_functions($driver,"close",$resource,""); - - //looks like wp functions clean up data before entry, so I'm not going to try to clean out fields beforehand. - if ($id = username_exists($username)) { //just do an update - $userarray['ID'] = $id; - wp_update_user($userarray); - } - else wp_insert_user($userarray); //otherwise create - } - } - else { //username exists but wrong password... - global $ext_error; - $ext_error = "wrongpw"; - $username = NULL; - } - } - else { //don't let login even if it's in the WP db - it needs to come only from the external db. - global $ext_error; - $ext_error = "notindb"; - $username = NULL; - } -} - - -//gives warning for login - where to get "source" login -function ext_db_auth_warning() { - echo "

          ".get_option('ext_db_error_msg')."

          "; -} - -function ext_db_errors() { - global $error; - global $ext_error; - if ($ext_error == "notindb") - return "ERROR: Username not found."; - else if ($ext_error == "wrongrole") - return "ERROR: You don't have permissions to log in."; - else if ($ext_error == "wrongpw") - return "ERROR: Invalid password."; - else - return $error; -} - -//hopefully grays stuff out. -function ext_db_warning() { - echo 'Any changes made below WILL NOT be preserved when you login again. You have to change your personal information per instructions found in the login box.'; -} - -//disables the (useless) password reset option in WP when this plugin is enabled. -function ext_db_show_password_fields() { - return 0; -} - - -/* - * Disable functions. Idea taken from http auth plugin. - */ -function disable_function_register() { - $errors = new WP_Error(); - $errors->add('registerdisabled', __('User registration is not available from this site, so you can\'t create an account or retrieve your password from here. See the message above.')); - ?>
          User registration is not available from this site, so you can't create an account or retrieve your password from here. See the message above.
          -

          - add('registerdisabled', __('User registration is not available from this site, so you can\'t create an account or retrieve your password from here. See the message above.')); - login_header(__('Log In'), '', $errors); - ?> -

          - General, if desired, to whatever level of control you wish externally authenticated users to have. -1. Upload `ext_db_auth.php` to the `/wp-content/plugins/` directory -1. Activate the plugin through the 'Plugins' menu in WordPress -1. Enter your external database settings in Settings->External DB settings - - -== Frequently Asked Questions == - -= My admin account for WP doesn't work anymore! = - -We're authenticating externally, right? Take that admin account you initially created in your WP setup and make sure it's in your external database. Once it's in there you'll be able to log in as admin with no problems. If you can't do this, delete the plugin and it'll restore access using your WP admin account. - -= Can I still create accounts within WordPress? = - -You could, but they don't work properly as it's not checking against the WP database, just the external then making sure the WP user info is the same as what's currently on the external database. - -= Can I update user information within WordPress? = - -Nope. - -= My external database's passwords are hashed with a salt/datestamp/phases of the moon/etc = - -Choose "Other" as your encoding method, then enter the method you use in the "Other" textbox as PHP code. If it involves more than the username and password, though, you may need to modify the plugin source code. - -= I'm locked out! = - -Delete or rename the plugin; if it's a DB connection-related error most likely you have the wrong connection, etc. information for the external database. - -== Screenshots == - -1. Plugin config screen -2. Example login warning message upon access to wp-login.php -3. Example "Lost my password" retrieval attempt - -== Changelog == - -= 3.15 = -* Disables password reset on user profile screen and has warning concerning updating profile within Wordpress -* Changes to config screen form for improved usability. -* Made lost your password and register error messages less fugly. -* Updated readme.txt - -= 3.12 = -* Now correctly imports unicode text into user profile fields -* Checked with 2.8x WP, 2.8x WPMU, and 2.9 WP -* Added in line as noted in forum post http://wordpress.org/support/topic/277235?replies=4 \ No newline at end of file -- 2.17.1
    ';
    -//var_dump($wAll);
    -//var_dump($hAll);
    -//var_dump($zcAR);
    -							//if (($wAll > $borderThickness) && ($wAll > $borderThickness)) {
    -							//	$zcAR = ($wAll - (2 * $borderThickness)) / ($hAll - (2 * $borderThickness));
    -							//}
    -//echo ($wAll - (2 * $borderThickness))."\n";
    -//echo ($hAll - (2 * $borderThickness))."\n";
    -//var_dump($zcAR);
    -							$side  = phpthumb_functions::nonempty_min($this->source_width, $this->source_height, max($wAll, $hAll));
    -							$sideX = phpthumb_functions::nonempty_min($this->source_width,                       $wAll, round($hAll * $zcAR));
    -							$sideY = phpthumb_functions::nonempty_min(                     $this->source_height, $hAll, round($wAll / $zcAR));
    -
    -							//if ($zcAR > 1) {  // landscape
    -								$thumbnailH = round(max($sideY, ($sideY * $zcAR) / $imAR));
    -//echo '
    ';
    -//var_dump($sideY);
    -//var_dump($zcAR);
    -//var_dump($imAR);
    -//var_dump($thumbnailH);
    -
    -								$commandline .= ' -thumbnail x'.$thumbnailH;
    -							//} else {          // portrait or square
    -							//	$thumbnailH = max($sideY, ($sideY * $zcAR) / $imAR);
    -							//	$commandline .= ' -thumbnail '.$sideX.'x'.round($sideX / $zcAR);
    -							//}
    -//echo '
    ';
    -//var_dump($this->w);
    -//var_dump($this->wp);
    -//var_dump($this->wl);
    -//var_dump($this->ws);
    -//var_dump($wAll);
    -//var_dump($side);
    -//var_dump($sideX);
    -//var_dump($sideY);
    -//var_dump($zcAR);
    -//var_dump($thumbnailH);
    -//print_r($getimagesize);
    -//echo '
    '; - - $commandline .= ' -gravity center'; - - if (($wAll > 0) && ($hAll > 0)) { - $commandline .= ' -crop '.$wAll.'x'.$hAll.'+0+0'; - } else { - $commandline .= ' -crop '.$side.'x'.$side.'+0+0'; - } - $commandline .= ' +repage'; - - } elseif ($this->sw || $this->sh || $this->sx || $this->sy) { - - $commandline .= ' -crop '.($this->sw ? $this->sw : $this->source_width).'x'.($this->sh ? $this->sh : $this->source_height).'+'.$this->sx.'+'.$this->sy; - // this is broken for aoe=1, but unsure how to fix. Send advice to info@silisoftware.com - if ($this->w || $this->h) { - $commandline .= ' -repage'; - $commandline .= ' -thumbnail '.$this->w.'x'.$this->h; - } - - } else { - - if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) { - $commandline .= ' -thumbnail '.$this->w.'x'.$this->h.'!'; - } else { -//echo '
    ';
    -//print_r($getimagesize);
    -//echo '
    '; -//echo $this->w.'x'.$this->h.'
    '; - $this->w = ((($this->aoe || $this->far) && $this->w) ? $this->w : ($this->w ? phpthumb_functions::nonempty_min($this->w, $getimagesize[0]) : '')); - $this->h = ((($this->aoe || $this->far) && $this->h) ? $this->h : ($this->h ? phpthumb_functions::nonempty_min($this->h, $getimagesize[1]) : '')); -//echo $this->w.'x'.$this->h.'
    '; - if ($this->w || $this->h) { - $commandline .= ' -thumbnail '.$this->w.'x'.$this->h; - } - } - } - } - - } else { - - $this->DebugMessage('GetImageSize('.$this->sourceFilename.') failed', __FILE__, __LINE__); - if ($this->w || $this->h) { - $commandline .= ' -thumbnail '.$this->w.'x'.$this->h; - if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) { - $commandline .= '!'; - } - } - - } - foreach ($this->fltr as $filterkey => $filtercommand) { - @list($command, $parameter) = explode('|', $filtercommand, 2); - switch ($command) { - case 'brit': - if ($this->ImageMagickSwitchAvailable('modulate')) { - $commandline .= ' -modulate '.(100 + $parameter).',100,100'; - unset($this->fltr[$filterkey]); - } - break; - - case 'cont': - if ($this->ImageMagickSwitchAvailable('contrast')) { - $contDiv10 = round($parameter / 10); - if ($contDiv10 > 0) { - for ($i = 0; $i < $contDiv10; $i++) { - $commandline .= ' -contrast'; // increase contrast by 10% - } - } elseif ($contDiv10 < 0) { - for ($i = $contDiv10; $i < 0; $i++) { - $commandline .= ' +contrast'; // decrease contrast by 10% - } - } else { - // do nothing - } - unset($this->fltr[$filterkey]); - } - break; - - case 'ds': - if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) { - if ($parameter == 100) { - $commandline .= ' -colorspace GRAY -modulate 100,0,100'; - } else { - $commandline .= ' -modulate 100,'.(100 - $parameter).',100'; - } - unset($this->fltr[$filterkey]); - } - break; - - case 'sat': - if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) { - if ($parameter == -100) { - $commandline .= ' -colorspace GRAY -modulate 100,0,100'; - } else { - $commandline .= ' -modulate 100,'.(100 + $parameter).',100'; - } - unset($this->fltr[$filterkey]); - } - break; - - case 'gray': - if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) { - $commandline .= ' -colorspace GRAY -modulate 100,0,100'; - //$commandline .= ' -colorspace GRAY'; - unset($this->fltr[$filterkey]); - } - break; - - case 'clr': - if ($this->ImageMagickSwitchAvailable(array('fill', 'colorize'))) { - @list($amount, $color) = explode('|', $parameter); - $commandline .= ' -fill #'.$color.' -colorize '.$amount; - } - break; - - case 'sep': - if ($this->ImageMagickSwitchAvailable('sepia-tone')) { - @list($amount, $color) = explode('|', $parameter); - $amount = ($amount ? $amount : 80); - if (!$color) { - $commandline .= ' -sepia-tone '.$amount.'%'; - unset($this->fltr[$filterkey]); - } - } - break; - - case 'gam': - if ($this->ImageMagickSwitchAvailable('gamma')) { - $commandline .= ' -gamma '.$parameter; - unset($this->fltr[$filterkey]); - } - break; - - case 'neg': - if ($this->ImageMagickSwitchAvailable('negate')) { - $commandline .= ' -negate'; - unset($this->fltr[$filterkey]); - } - break; - - case 'th': - if ($this->ImageMagickSwitchAvailable(array('threshold', 'dither', 'monochrome'))) { - $commandline .= ' -threshold '.round($parameter / 2.55).'% -dither -monochrome'; - unset($this->fltr[$filterkey]); - } - break; - - case 'rcd': - if ($this->ImageMagickSwitchAvailable(array('colors', 'dither'))) { - @list($colors, $dither) = explode('|', $parameter); - $colors = ($colors ? (int) $colors : 256); - $dither = ((strlen($dither) > 0) ? (bool) $dither : true); - $commandline .= ' -colors '.max($colors, 8); // ImageMagick will otherwise fail with "cannot quantize to fewer than 8 colors" - $commandline .= ($dither ? ' -dither' : ' +dither'); - unset($this->fltr[$filterkey]); - } - break; - - case 'flip': - if ($this->ImageMagickSwitchAvailable(array('flip', 'flop'))) { - if (strpos(strtolower($parameter), 'x') !== false) { - $commandline .= ' -flop'; - } - if (strpos(strtolower($parameter), 'y') !== false) { - $commandline .= ' -flip'; - } - unset($this->fltr[$filterkey]); - } - break; - - case 'edge': - if ($this->ImageMagickSwitchAvailable('edge')) { - $parameter = ($parameter ? $parameter : 2); - $commandline .= ' -edge '.($parameter ? $parameter : 1); - unset($this->fltr[$filterkey]); - } - break; - - case 'emb': - if ($this->ImageMagickSwitchAvailable(array('emboss', 'negate'))) { - $parameter = ($parameter ? $parameter : 2); - $commandline .= ' -emboss '.$parameter; - if ($parameter < 2) { - $commandline .= ' -negate'; // ImageMagick negates the image for some reason with '-emboss 1'; - } - unset($this->fltr[$filterkey]); - } - break; - - case 'lvl': - if ($this->ImageMagickSwitchAvailable(array('normalize', 'level'))) { - @list($band, $min, $max) = explode('|', $parameter); - $band = ($band ? $band : '*'); - $min = ((strlen($min) > 0) ? $min : '-1'); - $max = ((strlen($max) > 0) ? $max : '-1'); - if ($band == '*') { - if (($min == -1) && ($max == -1)) { - $commandline .= ' -normalize'; - unset($this->fltr[$filterkey]); - } elseif (($min == -1) || ($max == -1)) { - // - } else { - $commandline .= ' -level '.$min.'%,'.$max.'%'; - unset($this->fltr[$filterkey]); - } - } - } - break; - - case 'blur': - if ($this->ImageMagickSwitchAvailable('blur')) { - @list($radius) = explode('|', $parameter); - $radius = ($radius ? $radius : 1); - $commandline .= ' -blur '.$radius; - unset($this->fltr[$filterkey]); - } - break; - - case 'gblr': - if ($this->ImageMagickSwitchAvailable('gaussian')) { - @list($radius) = explode('|', $parameter); - $radius = ($radius ? $radius : 1); - $commandline .= ' -gaussian '.$radius; - unset($this->fltr[$filterkey]); - } - break; - - case 'usm': - if ($this->ImageMagickSwitchAvailable('unsharp')) { - @list($amount, $radius, $threshold) = explode('|', $parameter); - $amount = ($amount ? $amount : 80); - $radius = ($radius ? $radius : 0.5); - $threshold = (strlen($threshold) ? $threshold : 3); - $commandline .= ' -unsharp '.number_format(($radius * 2) - 1, 2).'x1+'.number_format($amount / 100, 2).'+'.number_format($threshold / 100, 2); - unset($this->fltr[$filterkey]); - } - break; - - case 'bord': - if ($this->ImageMagickSwitchAvailable(array('border', 'bordercolor', 'thumbnail', 'crop'))) { - if (!$this->zc) { - @list($width, $rX, $rY, $color) = explode('|', $parameter); - if ($width && !$rX && !$rY) { - if (!phpthumb_functions::IsHexColor($color)) { - $color = ($this->bc ? $this->bc : '000000'); - } - $commandline .= ' -border '.$width.' -bordercolor "#'.$color.'"'; - if (ereg(' \-crop ([0-9]+)x([0-9]+)\+0\+0 ', $commandline, $matches)) { - $commandline = str_replace(' -crop '.$matches[1].'x'.$matches[2].'+0+0 ', ' -crop '.($matches[1] - (2 * $width)).'x'.($matches[2] - (2 * $width)).'+0+0 ', $commandline); - } elseif (ereg(' \-thumbnail ([0-9]+)x([0-9]+) ', $commandline, $matches)) { - $commandline = str_replace(' -thumbnail '.$matches[1].'x'.$matches[2].' ', ' -thumbnail '.($matches[1] - (2 * $width)).'x'.($matches[2] - (2 * $width)).' ', $commandline); - } - unset($this->fltr[$filterkey]); - } - } - } - break; - - case 'crop': - break; - - case 'sblr': - break; - - case 'mean': - break; - - case 'smth': - break; - - case 'bvl': - break; - - case 'wmi': - break; - - case 'wmt': - break; - - case 'over': - break; - - case 'wb': - break; - - case 'hist': - break; - - case 'fram': - break; - - case 'drop': - break; - - case 'mask': - break; - - case 'elip': - break; - - case 'ric': - break; - - } - if (!isset($this->fltr[$filterkey])) { - $this->DebugMessage('Processed $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__); - } else { - $this->DebugMessage('Skipping $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__); - } - } - $this->DebugMessage('Remaining $this->fltr after ImageMagick: ('.$this->phpThumbDebugVarDump($this->fltr).')', __FILE__, __LINE__); - - if (eregi('jpe?g', $outputFormat) && $this->q) { - if ($this->ImageMagickSwitchAvailable(array('quality', 'interlace'))) { - $commandline .= ' -quality '.$this->thumbnailQuality; - if ($this->config_output_interlace) { - // causes weird things with animated GIF... leave for JPEG only - $commandline .= ' -interlace line '; // Use Line or Plane to create an interlaced PNG or GIF or progressive JPEG image - } - } - } - $commandline .= ' "'.str_replace('/', DIRECTORY_SEPARATOR, $this->sourceFilename).(($outputFormat == 'gif') ? '' : '[0]').'"'; // [0] means first frame of (GIF) animation, can be ignored - $commandline .= ' '.$outputFormat.':"'.$IMtempfilename.'"'; - $commandline .= ' 2>&1'; - $this->DebugMessage('ImageMagick called as ('.$commandline.')', __FILE__, __LINE__); - $IMresult = phpthumb_functions::SafeExec($commandline); -//echo '
    ';
    -//var_dump($commandline);
    -////var_dump($ImageCreateFunction);
    -////var_dump($IMresult);
    -//echo '
    '; -//exit; - clearstatcache(); - if (!@file_exists($IMtempfilename) || !@filesize($IMtempfilename)) { - - $this->DebugMessage('ImageMagick failed with message ('.$IMresult.')', __FILE__, __LINE__); - if ($this->iswindows && !$IMresult) { - $this->DebugMessage('Check to make sure that PHP has read+write permissions to "'.dirname($IMtempfilename).'"', __FILE__, __LINE__); - } - - } else { - - $this->IMresizedData = file_get_contents($IMtempfilename); - if (function_exists(@$ImageCreateFunction) && ($this->gdimg_source = @$ImageCreateFunction($IMtempfilename))) { -//header('Content-Type: image/png'); -//ImageSaveAlpha($this->gdimg_source, true); -//ImagePNG($this->gdimg_source); -//exit; - $this->source_width = ImageSX($this->gdimg_source); - $this->source_height = ImageSY($this->gdimg_source); - $this->DebugMessage('ImageMagickThumbnailToGD::'.$ImageCreateFunction.'() succeeded, $this->gdimg_source is now ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__); - $this->DebugMessage('ImageMagickThumbnailToGD() returning $IMresizedData ('.strlen($this->IMresizedData).' bytes)', __FILE__, __LINE__); - } else { - $this->useRawIMoutput = true; - $this->DebugMessage('$this->useRawIMoutput set to TRUE because '.@$ImageCreateFunction.'('.$IMtempfilename.') failed', __FILE__, __LINE__); - } - @unlink($IMtempfilename); - return true; - - } - unlink($IMtempfilename); - - } else { - $this->DebugMessage('ImageMagickThumbnailToGD() aborting, phpThumb_tempnam() failed', __FILE__, __LINE__); - } - } else { - $this->DebugMessage('ImageMagickThumbnailToGD() aborting because ImageMagickCommandlineBase() failed', __FILE__, __LINE__); - } - $this->useRawIMoutput = false; - return false; - } - - - function Rotate() { - if ($this->ra || $this->ar) { - if (!function_exists('ImageRotate')) { - $this->DebugMessage('!function_exists(ImageRotate)', __FILE__, __LINE__); - return false; - } - if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) { - $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__); - return false; - } - - $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); - if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { - return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); - } - - $rotate_angle = 0; - if ($this->ra) { - - $rotate_angle = floatval($this->ra); - - } else { - - if ($this->ar == 'x') { - if (phpthumb_functions::version_compare_replacement(phpversion(), '4.2.0', '>=')) { - if ($this->sourceFilename) { - if (function_exists('exif_read_data')) { - if ($exif_data = @exif_read_data($this->sourceFilename, 'IFD0')) { - // http://sylvana.net/jpegcrop/exif_orientation.html - switch (@$exif_data['Orientation']) { - case 1: - $rotate_angle = 0; - break; - case 3: - $rotate_angle = 180; - break; - case 6: - $rotate_angle = 270; - break; - case 8: - $rotate_angle = 90; - break; - - default: - $this->DebugMessage('EXIF auto-rotate failed because unknown $exif_data[Orientation] "'.@$exif_data['Orientation'].'"', __FILE__, __LINE__); - return false; - break; - } - $this->DebugMessage('EXIF auto-rotate set to '.$rotate_angle.' degrees ($exif_data[Orientation] = "'.@$exif_data['Orientation'].'")', __FILE__, __LINE__); - } else { - $this->DebugMessage('failed: exif_read_data('.$this->sourceFilename.')', __FILE__, __LINE__); - return false; - } - } else { - $this->DebugMessage('!function_exists(exif_read_data)', __FILE__, __LINE__); - return false; - } - } else { - $this->DebugMessage('Cannot auto-rotate from EXIF data because $this->sourceFilename is empty', __FILE__, __LINE__); - return false; - } - } else { - $this->DebugMessage('Cannot auto-rotate from EXIF data because PHP is less than v4.2.0 ('.phpversion().')', __FILE__, __LINE__); - return false; - } - } elseif (($this->ar == 'l') && ($this->source_height > $this->source_width)) { - $rotate_angle = 270; - } elseif (($this->ar == 'L') && ($this->source_height > $this->source_width)) { - $rotate_angle = 90; - } elseif (($this->ar == 'p') && ($this->source_width > $this->source_height)) { - $rotate_angle = 90; - } elseif (($this->ar == 'P') && ($this->source_width > $this->source_height)) { - $rotate_angle = 270; - } - - } - while ($rotate_angle < 0) { - $rotate_angle += 360; - } - $rotate_angle = $rotate_angle % 360; - if ($rotate_angle != 0) { - - if ($rotate_angle % 90) { - $this->is_alpha = true; - } - - $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_source, $this->config_background_hexcolor); - - //if ((phpthumb_functions::gd_version() >= 2) && phpthumb_functions::CaseInsensitiveInArray($this->thumbnailFormat, $this->AlphaCapableFormats) && !$this->bg && ($rotate_angle % 90)) { - if ((phpthumb_functions::gd_version() >= 2) && !$this->bg && ($rotate_angle % 90)) { - - $this->DebugMessage('Using alpha rotate', __FILE__, __LINE__); - if ($gdimg_rotate_mask = phpthumb_functions::ImageCreateFunction(ImageSX($this->gdimg_source), ImageSY($this->gdimg_source))) { - - for ($i = 0; $i <= 255; $i++) { - $color_mask[$i] = ImageColorAllocate($gdimg_rotate_mask, $i, $i, $i); - } - ImageFilledRectangle($gdimg_rotate_mask, 0, 0, ImageSX($gdimg_rotate_mask), ImageSY($gdimg_rotate_mask), $color_mask[255]); - $imageX = ImageSX($this->gdimg_source); - $imageY = ImageSY($this->gdimg_source); - for ($x = 0; $x < $imageX; $x++) { - for ($y = 0; $y < $imageY; $y++) { - $pixelcolor = phpthumb_functions::GetPixelColor($this->gdimg_source, $x, $y); - ImageSetPixel($gdimg_rotate_mask, $x, $y, $color_mask[255 - round($pixelcolor['alpha'] * 255 / 127)]); - } - } - $gdimg_rotate_mask = ImageRotate($gdimg_rotate_mask, $rotate_angle, $color_mask[0]); - $this->gdimg_source = ImageRotate($this->gdimg_source, $rotate_angle, $background_color); - - ImageAlphaBlending($this->gdimg_source, false); - ImageSaveAlpha($this->gdimg_source, true); - $this->is_alpha = true; - $phpThumbFilters = new phpthumb_filters(); - $phpThumbFilters->phpThumbObject = $this; - $phpThumbFilters->ApplyMask($gdimg_rotate_mask, $this->gdimg_source); - - ImageDestroy($gdimg_rotate_mask); - $this->source_width = ImageSX($this->gdimg_source); - $this->source_height = ImageSY($this->gdimg_source); - - } else { - $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); - } - - } else { - - if (phpthumb_functions::gd_version() < 2) { - $this->DebugMessage('Using non-alpha rotate because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - } elseif ($this->bg) { - $this->DebugMessage('Using non-alpha rotate because $this->bg is "'.$this->bg.'"', __FILE__, __LINE__); - } elseif ($this->bg) { - $this->DebugMessage('Using non-alpha rotate because ($rotate_angle % 90) = "'.($rotate_angle % 90).'"', __FILE__, __LINE__); - } else { - $this->DebugMessage('Using non-alpha rotate because $this->thumbnailFormat is "'.$this->thumbnailFormat.'"', __FILE__, __LINE__); - } - - if (ImageColorTransparent($this->gdimg_source) >= 0) { - // ImageRotate() forgets all about an image's transparency and sets the transparent color to black - // To compensate, flood-fill the transparent color of the source image with the specified background color first - // then rotate and the colors should match - - if (!function_exists('ImageIsTrueColor') || !ImageIsTrueColor($this->gdimg_source)) { - // convert paletted image to true-color before rotating to prevent nasty aliasing artifacts - - $this->source_width = ImageSX($this->gdimg_source); - $this->source_height = ImageSY($this->gdimg_source); - $gdimg_newsrc = phpthumb_functions::ImageCreateFunction($this->source_width, $this->source_height); - $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $this->config_background_hexcolor); - ImageFilledRectangle($gdimg_newsrc, 0, 0, $this->source_width, $this->source_height, phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $this->config_background_hexcolor)); - ImageCopy($gdimg_newsrc, $this->gdimg_source, 0, 0, 0, 0, $this->source_width, $this->source_height); - ImageDestroy($this->gdimg_source); - unset($this->gdimg_source); - $this->gdimg_source = $gdimg_newsrc; - unset($gdimg_newsrc); - - } else { - - ImageColorSet( - $this->gdimg_source, - ImageColorTransparent($this->gdimg_source), - hexdec(substr($this->config_background_hexcolor, 0, 2)), - hexdec(substr($this->config_background_hexcolor, 2, 2)), - hexdec(substr($this->config_background_hexcolor, 4, 2))); - - ImageColorTransparent($this->gdimg_source, -1); - - } - } - - $this->gdimg_source = ImageRotate($this->gdimg_source, $rotate_angle, $background_color); - $this->source_width = ImageSX($this->gdimg_source); - $this->source_height = ImageSY($this->gdimg_source); - - } - } - } - return true; - } - - - function FixedAspectRatio() { - // optional fixed-dimension images (regardless of aspect ratio) - -//echo $this->thumbnail_width.'x'.$this->thumbnail_height.'['.__LINE__.']
    '; - if (!$this->far) { - // do nothing - return true; - } - - if (!$this->w || !$this->h) { - return false; - } - $this->thumbnail_width = $this->w; - $this->thumbnail_height = $this->h; - $this->is_alpha = true; - if ($this->thumbnail_image_width >= $this->thumbnail_width) { -//echo __LINE__.'
    '; - - if ($this->w) { - $aspectratio = $this->thumbnail_image_height / $this->thumbnail_image_width; - $this->thumbnail_image_height = round($this->thumbnail_image_width * $aspectratio); - $this->thumbnail_height = ($this->h ? $this->h : $this->thumbnail_image_height); - } elseif ($this->thumbnail_image_height < $this->thumbnail_height) { - $this->thumbnail_image_height = $this->thumbnail_height; - $this->thumbnail_image_width = round($this->thumbnail_image_height / $aspectratio); - } - - } else { -//echo __LINE__.'
    '; - - if ($this->h) { - $aspectratio = $this->thumbnail_image_width / $this->thumbnail_image_height; - $this->thumbnail_image_width = round($this->thumbnail_image_height * $aspectratio); - } elseif ($this->thumbnail_image_width < $this->thumbnail_width) { - $this->thumbnail_image_width = $this->thumbnail_width; - $this->thumbnail_image_height = round($this->thumbnail_image_width / $aspectratio); - } - - } -//echo $this->thumbnail_width.'x'.$this->thumbnail_height.'['.__LINE__.']
    '; -//exit; - return true; - } - - - function AntiOffsiteLinking() { - // Optional anti-offsite hijacking of the thumbnail script - $allow = true; - if ($allow && $this->config_nooffsitelink_enabled && (@$_SERVER['HTTP_REFERER'] || $this->config_nooffsitelink_require_refer)) { - $this->DebugMessage('AntiOffsiteLinking() checking $_SERVER[HTTP_REFERER] "'.@$_SERVER['HTTP_REFERER'].'"', __FILE__, __LINE__); - $parsed_url = parse_url(@$_SERVER['HTTP_REFERER']); - if (!phpthumb_functions::CaseInsensitiveInArray(@$parsed_url['host'], $this->config_nooffsitelink_valid_domains)) { - $allow = false; - $erase = $this->config_nooffsitelink_erase_image; - $message = $this->config_nooffsitelink_text_message; - $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is NOT in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); - } else { - $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); - } - } - - if ($allow && $this->config_nohotlink_enabled && eregi('^(f|ht)tps?\://', $this->src)) { - $parsed_url = parse_url($this->src); - if (!phpthumb_functions::CaseInsensitiveInArray(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) { - // This domain is not allowed - $allow = false; - $erase = $this->config_nohotlink_erase_image; - $message = $this->config_nohotlink_text_message; - $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is NOT in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__); - } else { - $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__); - } - } - - if ($allow) { - $this->DebugMessage('AntiOffsiteLinking() says this is allowed', __FILE__, __LINE__); - return true; - } - - if (!phpthumb_functions::IsHexColor($this->config_error_bgcolor)) { - return $this->ErrorImage('Invalid hex color string "'.$this->config_error_bgcolor.'" for $this->config_error_bgcolor'); - } - if (!phpthumb_functions::IsHexColor($this->config_error_textcolor)) { - return $this->ErrorImage('Invalid hex color string "'.$this->config_error_textcolor.'" for $this->config_error_textcolor'); - } - if ($erase) { - - return $this->ErrorImage($message, $this->thumbnail_width, $this->thumbnail_height, $this->config_error_bgcolor, $this->config_error_textcolor, $this->config_error_fontsize); - - } else { - - $nohotlink_text_array = explode("\n", wordwrap($message, floor($this->thumbnail_width / ImageFontWidth($this->config_error_fontsize)), "\n")); - $nohotlink_text_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_error_textcolor); - - $topoffset = round(($this->thumbnail_height - (count($nohotlink_text_array) * ImageFontHeight($this->config_error_fontsize))) / 2); - - $rowcounter = 0; - $this->DebugMessage('AntiOffsiteLinking() writing '.count($nohotlink_text_array).' lines of text "'.$message.'" (in #'.$this->config_error_textcolor.') on top of image', __FILE__, __LINE__); - foreach ($nohotlink_text_array as $dummy => $textline) { - $leftoffset = max(0, round(($this->thumbnail_width - (strlen($textline) * ImageFontWidth($this->config_error_fontsize))) / 2)); - ImageString($this->gdimg_output, $this->config_error_fontsize, $leftoffset, $topoffset + ($rowcounter++ * ImageFontHeight($this->config_error_fontsize)), $textline, $nohotlink_text_color); - } - - } - return true; - } - - - function AlphaChannelFlatten() { - if (!$this->is_alpha) { - // image doesn't have alpha transparency, no need to flatten - $this->DebugMessage('skipping AlphaChannelFlatten() because !$this->is_alpha', __FILE__, __LINE__); - return false; - } - switch ($this->thumbnailFormat) { - case 'png': - case 'ico': - // image has alpha transparency, but output as PNG or ICO which can handle it - $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'")', __FILE__, __LINE__); - return false; - break; - - case 'gif': - // image has alpha transparency, but output as GIF which can handle only single-color transparency - $CurrentImageColorTransparent = ImageColorTransparent($this->gdimg_output); - if ($CurrentImageColorTransparent == -1) { - // no transparent color defined - - if (phpthumb_functions::gd_version() < 2.0) { - $this->DebugMessage('AlphaChannelFlatten() failed because GD version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - return false; - } - - if ($img_alpha_mixdown_dither = @ImageCreateTrueColor(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output))) { - - for ($i = 0; $i <= 255; $i++) { - $dither_color[$i] = ImageColorAllocate($img_alpha_mixdown_dither, $i, $i, $i); - } - - // scan through current truecolor image copy alpha channel to temp image as grayscale - for ($x = 0; $x < $this->thumbnail_width; $x++) { - for ($y = 0; $y < $this->thumbnail_height; $y++) { - $PixelColor = phpthumb_functions::GetPixelColor($this->gdimg_output, $x, $y); - ImageSetPixel($img_alpha_mixdown_dither, $x, $y, $dither_color[($PixelColor['alpha'] * 2)]); - } - } - - // dither alpha channel grayscale version down to 2 colors - ImageTrueColorToPalette($img_alpha_mixdown_dither, true, 2); - - // reduce color palette to 256-1 colors (leave one palette position for transparent color) - ImageTrueColorToPalette($this->gdimg_output, true, 255); - - // allocate a new color for transparent color index - $TransparentColor = ImageColorAllocate($this->gdimg_output, 1, 254, 253); - ImageColorTransparent($this->gdimg_output, $TransparentColor); - - // scan through alpha channel image and note pixels with >50% transparency - $TransparentPixels = array(); - for ($x = 0; $x < $this->thumbnail_width; $x++) { - for ($y = 0; $y < $this->thumbnail_height; $y++) { - $AlphaChannelPixel = phpthumb_functions::GetPixelColor($img_alpha_mixdown_dither, $x, $y); - if ($AlphaChannelPixel['red'] > 127) { - ImageSetPixel($this->gdimg_output, $x, $y, $TransparentColor); - } - } - } - ImageDestroy($img_alpha_mixdown_dither); - - $this->DebugMessage('AlphaChannelFlatten() set image to 255+1 colors with transparency for GIF output', __FILE__, __LINE__); - return true; - - } else { - $this->DebugMessage('AlphaChannelFlatten() failed ImageCreate('.ImageSX($this->gdimg_output).', '.ImageSY($this->gdimg_output).')', __FILE__, __LINE__); - return false; - } - - } else { - // a single transparent color already defined, leave as-is - $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'") and ImageColorTransparent returned "'.$CurrentImageColorTransparent.'"', __FILE__, __LINE__); - return true; - } - break; - } - $this->DebugMessage('continuing AlphaChannelFlatten() for output format "'.$this->thumbnailFormat.'"', __FILE__, __LINE__); - - // image has alpha transparency, and is being output in a format that doesn't support it -- flatten - if ($gdimg_flatten_temp = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height)) { - - $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); - if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { - return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); - } - $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor); - ImageFilledRectangle($gdimg_flatten_temp, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color); - ImageCopy($gdimg_flatten_temp, $this->gdimg_output, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height); - - ImageAlphaBlending($this->gdimg_output, true); - ImageSaveAlpha($this->gdimg_output, false); - ImageColorTransparent($this->gdimg_output, -1); - ImageCopy($this->gdimg_output, $gdimg_flatten_temp, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height); - - ImageDestroy($gdimg_flatten_temp); - return true; - - } else { - $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); - } - return false; - } - - - function ApplyFilters() { - if ($this->fltr && is_array($this->fltr)) { - if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) { - $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__); - return false; - } - $phpthumbFilters = new phpthumb_filters(); - $phpthumbFilters->phpThumbObject = $this; - foreach ($this->fltr as $dummy => $filtercommand) { - @list($command, $parameter) = explode('|', $filtercommand, 2); - $this->DebugMessage('Attempting to process filter command "'.$command.'('.$parameter.')"', __FILE__, __LINE__); - switch ($command) { - case 'brit': - $phpthumbFilters->Brightness($this->gdimg_output, $parameter); - break; - - case 'cont': - $phpthumbFilters->Contrast($this->gdimg_output, $parameter); - break; - - case 'ds': - $phpthumbFilters->Desaturate($this->gdimg_output, $parameter, ''); - break; - - case 'sat': - $phpthumbFilters->Saturation($this->gdimg_output, $parameter, ''); - break; - - case 'gray': - $phpthumbFilters->Grayscale($this->gdimg_output); - break; - - case 'clr': - if (phpthumb_functions::gd_version() < 2) { - $this->DebugMessage('Skipping Colorize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - break; - } - @list($amount, $color) = explode('|', $parameter); - $phpthumbFilters->Colorize($this->gdimg_output, $amount, $color); - break; - - case 'sep': - if (phpthumb_functions::gd_version() < 2) { - $this->DebugMessage('Skipping Sepia() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - break; - } - @list($amount, $color) = explode('|', $parameter); - $phpthumbFilters->Sepia($this->gdimg_output, $amount, $color); - break; - - case 'gam': - $phpthumbFilters->Gamma($this->gdimg_output, $parameter); - break; - - case 'neg': - $phpthumbFilters->Negative($this->gdimg_output); - break; - - case 'th': - $phpthumbFilters->Threshold($this->gdimg_output, $parameter); - break; - - case 'rcd': - if (phpthumb_functions::gd_version() < 2) { - $this->DebugMessage('Skipping ReduceColorDepth() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - break; - } - @list($colors, $dither) = explode('|', $parameter); - $colors = ($colors ? (int) $colors : 256); - $dither = ((strlen($dither) > 0) ? (bool) $dither : true); - $phpthumbFilters->ReduceColorDepth($this->gdimg_output, $colors, $dither); - break; - - case 'flip': - $phpthumbFilters->Flip($this->gdimg_output, (strpos(strtolower($parameter), 'x') !== false), (strpos(strtolower($parameter), 'y') !== false)); - break; - - case 'edge': - $phpthumbFilters->EdgeDetect($this->gdimg_output); - break; - - case 'emb': - $phpthumbFilters->Emboss($this->gdimg_output); - break; - - case 'bvl': - @list($width, $color1, $color2) = explode('|', $parameter); - $phpthumbFilters->Bevel($this->gdimg_output, $width, $color1, $color2); - break; - - case 'lvl': - @list($band, $min, $max) = explode('|', $parameter); - $band = ($band ? $band : '*'); - $min = ((strlen($min) > 0) ? $min : '-1'); - $max = ((strlen($max) > 0) ? $max : '-1'); - $phpthumbFilters->HistogramStretch($this->gdimg_output, $band, $min, $max); - break; - - case 'wb': - $phpthumbFilters->WhiteBalance($this->gdimg_output, $parameter); - break; - - case 'hist': - if (phpthumb_functions::gd_version() < 2) { - $this->DebugMessage('Skipping HistogramOverlay() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - break; - } - @list($bands, $colors, $width, $height, $alignment, $opacity, $margin) = explode('|', $parameter); - $bands = ($bands ? $bands : '*'); - $colors = ($colors ? $colors : ''); - $width = ($width ? $width : 0.25); - $height = ($height ? $height : 0.25); - $alignment = ($alignment ? $alignment : 'BR'); - $opacity = ($opacity ? $opacity : 50); - $margin = ($margin ? $margin : 5); - $phpthumbFilters->HistogramOverlay($this->gdimg_output, $bands, $colors, $width, $height, $alignment, $opacity, $margin); - break; - - case 'fram': - @list($frame_width, $edge_width, $color_frame, $color1, $color2) = explode('|', $parameter); - $phpthumbFilters->Frame($this->gdimg_output, $frame_width, $edge_width, $color_frame, $color1, $color2); - break; - - case 'drop': - if (phpthumb_functions::gd_version() < 2) { - $this->DebugMessage('Skipping DropShadow() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - return false; - } - $this->is_alpha = true; - @list($distance, $width, $color, $angle, $fade) = explode('|', $parameter); - $phpthumbFilters->DropShadow($this->gdimg_output, $distance, $width, $color, $angle, $fade); - break; - - case 'mask': - if (phpthumb_functions::gd_version() < 2) { - $this->DebugMessage('Skipping Mask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - return false; - } - $mask_filename = $this->ResolveFilenameToAbsolute($parameter); - if (@is_readable($mask_filename) && ($fp_mask = @fopen($mask_filename, 'rb'))) { - $MaskImageData = ''; - do { - $buffer = fread($fp_mask, 8192); - $MaskImageData .= $buffer; - } while (strlen($buffer) > 0); - fclose($fp_mask); - if ($gdimg_mask = $this->ImageCreateFromStringReplacement($MaskImageData)) { - $this->is_alpha = true; - $phpthumbFilters->ApplyMask($gdimg_mask, $this->gdimg_output); - ImageDestroy($gdimg_mask); - } else { - $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$mask_filename.'"', __FILE__, __LINE__); - } - } else { - $this->DebugMessage('Cannot open mask file "'.$mask_filename.'"', __FILE__, __LINE__); - } - break; - - case 'elip': - if (phpthumb_functions::gd_version() < 2) { - $this->DebugMessage('Skipping Elipse() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - return false; - } - $this->is_alpha = true; - $phpthumbFilters->Elipse($this->gdimg_output); - break; - - case 'ric': - if (phpthumb_functions::gd_version() < 2) { - $this->DebugMessage('Skipping RoundedImageCorners() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - return false; - } - @list($radius_x, $radius_y) = explode('|', $parameter); - if (($radius_x < 1) || ($radius_y < 1)) { - $this->DebugMessage('Skipping RoundedImageCorners('.$radius_x.', '.$radius_y.') because x/y radius is less than 1', __FILE__, __LINE__); - break; - } - $this->is_alpha = true; - $phpthumbFilters->RoundedImageCorners($this->gdimg_output, $radius_x, $radius_y); - break; - - case 'crop': - @list($left, $right, $top, $bottom) = explode('|', $parameter); - $phpthumbFilters->Crop($this->gdimg_output, $left, $right, $top, $bottom); - break; - - case 'bord': - @list($border_width, $radius_x, $radius_y, $hexcolor_border) = explode('|', $parameter); - $this->is_alpha = true; - $phpthumbFilters->ImageBorder($this->gdimg_output, $border_width, $radius_x, $radius_y, $hexcolor_border); - break; - - case 'over': - @list($filename, $underlay, $margin, $opacity) = explode('|', $parameter); - $underlay = (bool) ($underlay ? $underlay : false); - $margin = ((strlen($margin) > 0) ? $margin : ($underlay ? 0.1 : 0.0)); - $opacity = ((strlen($opacity) > 0) ? $opacity : 100); - if (($margin > 0) && ($margin < 1)) { - $margin = min(0.499, $margin); - } elseif (($margin > -1) && ($margin < 0)) { - $margin = max(-0.499, $margin); - } - - $filename = $this->ResolveFilenameToAbsolute($filename); - if (@is_readable($filename) && ($fp_watermark = @fopen($filename, 'rb'))) { - $WatermarkImageData = ''; - do { - $buffer = fread($fp_watermark, 8192); - $WatermarkImageData .= $buffer; - } while (strlen($buffer) > 0); - fclose($fp_watermark); - if ($img_watermark = $this->ImageCreateFromStringReplacement($WatermarkImageData)) { - if ($margin < 1) { - $resized_x = max(1, ImageSX($this->gdimg_output) - round(2 * (ImageSX($this->gdimg_output) * $margin))); - $resized_y = max(1, ImageSY($this->gdimg_output) - round(2 * (ImageSY($this->gdimg_output) * $margin))); - } else { - $resized_x = max(1, ImageSX($this->gdimg_output) - round(2 * $margin)); - $resized_y = max(1, ImageSY($this->gdimg_output) - round(2 * $margin)); - } - - if ($underlay) { - - if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output))) { - ImageAlphaBlending($img_watermark_resized, false); - ImageSaveAlpha($img_watermark_resized, true); - $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, ImageSX($img_watermark_resized), ImageSY($img_watermark_resized), ImageSX($img_watermark), ImageSY($img_watermark)); - if ($img_source_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) { - ImageAlphaBlending($img_source_resized, false); - ImageSaveAlpha($img_source_resized, true); - $this->ImageResizeFunction($img_source_resized, $this->gdimg_output, 0, 0, 0, 0, ImageSX($img_source_resized), ImageSY($img_source_resized), ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); - $phpthumbFilters->WatermarkOverlay($img_watermark_resized, $img_source_resized, 'C', $opacity, $margin); - ImageCopy($this->gdimg_output, $img_watermark_resized, 0, 0, 0, 0, ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); - } else { - $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__); - } - ImageDestroy($img_watermark_resized); - } else { - $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.ImageSX($this->gdimg_output).', '.ImageSY($this->gdimg_output).')', __FILE__, __LINE__); - } - - } else { // overlay - - if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) { - ImageAlphaBlending($img_watermark_resized, false); - ImageSaveAlpha($img_watermark_resized, true); - $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, ImageSX($img_watermark_resized), ImageSY($img_watermark_resized), ImageSX($img_watermark), ImageSY($img_watermark)); - $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark_resized, 'C', $opacity, $margin); - ImageDestroy($img_watermark_resized); - } else { - $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__); - } - - } - ImageDestroy($img_watermark); - - } else { - $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$filename.'"', __FILE__, __LINE__); - } - } else { - $this->DebugMessage('Cannot open overlay file "'.$filename.'"', __FILE__, __LINE__); - } - break; - - case 'wmi': - @list($filename, $alignment, $opacity, $margin) = explode('|', $parameter); - $alignment = ($alignment ? $alignment : 'BR'); - $opacity = (strlen($opacity) ? $opacity : 50); - $margin = (strlen($margin) ? $margin : 5); - - $filename = $this->ResolveFilenameToAbsolute($filename); - if (@is_readable($filename)) { - //if ($img_watermark = $this->ImageCreateFromFilename($filename, $rawImageData)) { - if ($img_watermark = $this->ImageCreateFromFilename($filename)) { - // great - $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark, $alignment, $opacity, $margin); - ImageDestroy($img_watermark); - } else { - $this->DebugMessage('ImageCreateFromFilename() failed for "'.$filename.'"', __FILE__, __LINE__); - } - } else { - $this->DebugMessage('!is_readable('.$filename.')', __FILE__, __LINE__); - } - break; - - case 'wmt': - @list($text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend) = explode('|', $parameter); - $text = ($text ? $text : ''); - $size = ($size ? $size : 3); - $alignment = ($alignment ? $alignment : 'BR'); - $hex_color = ($hex_color ? $hex_color : '000000'); - $ttffont = ($ttffont ? $ttffont : ''); - $opacity = (strlen($opacity) ? $opacity : 50); - $margin = (strlen($margin) ? $margin : 5); - $angle = (strlen($angle) ? $angle : 0); - $bg_color = ($bg_color ? $bg_color : false); - $bg_opacity = ($bg_opacity ? $bg_opacity : 0); - $fillextend = ($fillextend ? $fillextend : ''); - - if (basename($ttffont) == $ttffont) { - $ttffont = realpath($this->config_ttf_directory.DIRECTORY_SEPARATOR.$ttffont); - } else { - $ttffont = $this->ResolveFilenameToAbsolute($ttffont); - } - $phpthumbFilters->WatermarkText($this->gdimg_output, $text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend); - break; - - case 'blur': - @list($radius) = explode('|', $parameter); - $radius = ($radius ? $radius : 1); - if (phpthumb_functions::gd_version() < 2) { - $this->DebugMessage('Skipping Blur() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - return false; - } - $phpthumbFilters->Blur($this->gdimg_output, $radius); - break; - - case 'gblr': - $phpthumbFilters->BlurGaussian($this->gdimg_output); - break; - - case 'sblr': - $phpthumbFilters->BlurSelective($this->gdimg_output); - break; - - case 'mean': - $phpthumbFilters->MeanRemoval($this->gdimg_output); - break; - - case 'smth': - $phpthumbFilters->Smooth($this->gdimg_output, $parameter); - break; - - case 'usm': - @list($amount, $radius, $threshold) = explode('|', $parameter); - $amount = ($amount ? $amount : 80); - $radius = ($radius ? $radius : 0.5); - $threshold = (strlen($threshold) ? $threshold : 3); - if (phpthumb_functions::gd_version() >= 2.0) { - ob_start(); - if (!@include_once(dirname(__FILE__).'/phpthumb.unsharp.php')) { - $include_error = ob_get_contents(); - if ($include_error) { - $this->DebugMessage('include_once("'.dirname(__FILE__).'/phpthumb.unsharp.php") generated message: "'.$include_error.'"', __FILE__, __LINE__); - } - $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.unsharp.php" which is required for unsharp masking', __FILE__, __LINE__); - ob_end_clean(); - return false; - } - ob_end_clean(); - phpUnsharpMask::applyUnsharpMask($this->gdimg_output, $amount, $radius, $threshold); - } else { - $this->DebugMessage('Skipping unsharp mask because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - return false; - } - break; - } - } - } - return true; - } - - - function MaxFileSize() { - if (phpthumb_functions::gd_version() < 2) { - $this->DebugMessage('Skipping MaxFileSize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - return false; - } - if ($this->maxb > 0) { - switch ($this->thumbnailFormat) { - case 'png': - case 'gif': - $imgRenderFunction = 'image'.$this->thumbnailFormat; - - ob_start(); - $imgRenderFunction($this->gdimg_output); - $imgdata = ob_get_contents(); - ob_end_clean(); - - if (strlen($imgdata) > $this->maxb) { - for ($i = 8; $i >= 1; $i--) { - $tempIMG = ImageCreateTrueColor(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); - ImageCopy($tempIMG, $this->gdimg_output, 0, 0, 0, 0, ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); - ImageTrueColorToPalette($tempIMG, true, pow(2, $i)); - ob_start(); - $imgRenderFunction($tempIMG); - $imgdata = ob_get_contents(); - ob_end_clean(); - - if (strlen($imgdata) <= $this->maxb) { - ImageTrueColorToPalette($this->gdimg_output, true, pow(2, $i)); - break; - } - } - } - if (strlen($imgdata) > $this->maxb) { - ImageTrueColorToPalette($this->gdimg_output, true, pow(2, $i)); - return false; - } - break; - - case 'jpeg': - ob_start(); - ImageJPEG($this->gdimg_output); - $imgdata = ob_get_contents(); - ob_end_clean(); - - $OriginalJPEGquality = $this->thumbnailQuality; - if (strlen($imgdata) > $this->maxb) { - for ($i = 3; $i < 20; $i++) { - $q = round(100 * (1 - log10($i / 2))); - ob_start(); - ImageJPEG($this->gdimg_output, '', $q); - $imgdata = ob_get_contents(); - ob_end_clean(); - - $this->thumbnailQuality = $q; - if (strlen($imgdata) <= $this->maxb) { - break; - } - } - } - if (strlen($imgdata) > $this->maxb) { - return false; - } - break; - - default: - return false; - break; - } - } - return true; - } - - - function CalculateThumbnailDimensions() { -//echo $this->source_width.'x'.$this->source_height.'
    '; - $this->thumbnailCropX = ($this->sx ? (($this->sx >= 1) ? $this->sx : round($this->sx * $this->source_width)) : 0); -//echo $this->thumbnailCropX.'
    '; - $this->thumbnailCropY = ($this->sy ? (($this->sy >= 1) ? $this->sy : round($this->sy * $this->source_height)) : 0); -//echo $this->thumbnailCropY.'
    '; - $this->thumbnailCropW = ($this->sw ? (($this->sw >= 1) ? $this->sw : round($this->sw * $this->source_width)) : $this->source_width); -//echo $this->thumbnailCropW.'
    '; - $this->thumbnailCropH = ($this->sh ? (($this->sh >= 1) ? $this->sh : round($this->sh * $this->source_height)) : $this->source_height); -//echo $this->thumbnailCropH.'
    '; - - // limit source area to original image area - $this->thumbnailCropW = max(1, min($this->thumbnailCropW, $this->source_width - $this->thumbnailCropX)); - $this->thumbnailCropH = max(1, min($this->thumbnailCropH, $this->source_height - $this->thumbnailCropY)); - - $this->DebugMessage('CalculateThumbnailDimensions() [x,y,w,h] initially set to ['.$this->thumbnailCropX.','.$this->thumbnailCropY.','.$this->thumbnailCropW.','.$this->thumbnailCropH.']', __FILE__, __LINE__); - - - if ($this->zc && $this->w && $this->h) { - // Zoom Crop - // retain proportional resizing we did above, but crop off larger dimension so smaller - // dimension fully fits available space - - $scaling_X = $this->source_width / $this->w; - $scaling_Y = $this->source_height / $this->h; - if ($scaling_X > $scaling_Y) { - // some of the width will need to be cropped - $allowable_width = $this->source_width / $scaling_X * $scaling_Y; - $this->thumbnailCropW = round($allowable_width); - $this->thumbnailCropX = round(($this->source_width - $allowable_width) / 2); - - } elseif ($scaling_Y > $scaling_X) { - // some of the height will need to be cropped - $allowable_height = $this->source_height / $scaling_Y * $scaling_X; - $this->thumbnailCropH = round($allowable_height); - $this->thumbnailCropY = round(($this->source_height - $allowable_height) / 2); - - } else { - // image fits perfectly, no cropping needed - } - $this->thumbnail_width = $this->w; - $this->thumbnail_height = $this->h; - $this->thumbnail_image_width = $this->thumbnail_width; - $this->thumbnail_image_height = $this->thumbnail_height; - - } elseif ($this->iar && $this->w && $this->h) { - - // Ignore Aspect Ratio - // stretch image to fit exactly 'w' x 'h' - $this->thumbnail_width = $this->w; - $this->thumbnail_height = $this->h; - $this->thumbnail_image_width = $this->thumbnail_width; - $this->thumbnail_image_height = $this->thumbnail_height; - - } else { - - $original_aspect_ratio = $this->thumbnailCropW / $this->thumbnailCropH; -//var_dump($original_aspect_ratio); -//echo '
    '; - if ($this->aoe) { - if ($this->w && $this->h) { - $maxwidth = min($this->w, $this->h * $original_aspect_ratio); - $maxheight = min($this->h, $this->w / $original_aspect_ratio); - } elseif ($this->w) { - $maxwidth = $this->w; - $maxheight = $this->w / $original_aspect_ratio; - } elseif ($this->h) { - $maxwidth = $this->h * $original_aspect_ratio; - $maxheight = $this->h; - } else { - $maxwidth = $this->thumbnailCropW; - $maxheight = $this->thumbnailCropH; - } - } else { - $maxwidth = phpthumb_functions::nonempty_min($this->w, $this->thumbnailCropW, $this->config_output_maxwidth); - $maxheight = phpthumb_functions::nonempty_min($this->h, $this->thumbnailCropH, $this->config_output_maxheight); -//echo $maxwidth.'x'.$maxheight.'
    '; - $maxwidth = min($maxwidth, $maxheight * $original_aspect_ratio); - $maxheight = min($maxheight, $maxwidth / $original_aspect_ratio); -//echo $maxwidth.'x'.$maxheight.'
    '; - } - - $this->thumbnail_image_width = $maxwidth; - $this->thumbnail_image_height = $maxheight; - $this->thumbnail_width = $maxwidth; - $this->thumbnail_height = $maxheight; - - $this->FixedAspectRatio(); - } - - $this->thumbnail_width = max(1, floor($this->thumbnail_width)); - $this->thumbnail_height = max(1, floor($this->thumbnail_height)); - return true; - } - - - function CreateGDoutput() { - $this->CalculateThumbnailDimensions(); - - // Create the GD image (either true-color or 256-color, depending on GD version) - $this->gdimg_output = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height); - - // Images that have transparency must have the background filled with the configured 'bg' color - // otherwise the transparent color will appear as black - ImageSaveAlpha($this->gdimg_output, true); - if ($this->is_alpha && phpthumb_functions::gd_version() >= 2) { - - ImageAlphaBlending($this->gdimg_output, false); - $output_full_alpha = phpthumb_functions::ImageColorAllocateAlphaSafe($this->gdimg_output, 255, 255, 255, 127); - ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $output_full_alpha); - - } else { - - $current_transparent_color = ImageColorTransparent($this->gdimg_source); - if ($this->bg || (@$current_transparent_color >= 0)) { - - $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); - if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { - return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); - } - $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor); - ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color); - - } - - } - $this->DebugMessage('CreateGDoutput() returning canvas "'.$this->thumbnail_width.'x'.$this->thumbnail_height.'"', __FILE__, __LINE__); - return true; - } - - function SetOrientationDependantWidthHeight() { - $this->DebugMessage('SetOrientationDependantWidthHeight() starting with "'.$this->source_width.'"x"'.$this->source_height.'"', __FILE__, __LINE__); - if ($this->source_height > $this->source_width) { - // portrait - $this->w = phpthumb_functions::OneOfThese($this->wp, $this->w, $this->ws, $this->wl); - $this->h = phpthumb_functions::OneOfThese($this->hp, $this->h, $this->hs, $this->hl); - } elseif ($this->source_height < $this->source_width) { - // landscape - $this->w = phpthumb_functions::OneOfThese($this->wl, $this->w, $this->ws, $this->wp); - $this->h = phpthumb_functions::OneOfThese($this->hl, $this->h, $this->hs, $this->hp); - } else { - // square - $this->w = phpthumb_functions::OneOfThese($this->ws, $this->w, $this->wl, $this->wp); - $this->h = phpthumb_functions::OneOfThese($this->hs, $this->h, $this->hl, $this->hp); - } - //$this->w = round($this->w ? $this->w : (($this->h && $this->source_height) ? $this->h * $this->source_width / $this->source_height : $this->w)); - //$this->h = round($this->h ? $this->h : (($this->w && $this->source_width) ? $this->w * $this->source_height / $this->source_width : $this->h)); - $this->DebugMessage('SetOrientationDependantWidthHeight() setting w="'.intval($this->w).'", h="'.intval($this->h).'"', __FILE__, __LINE__); - return true; - } - - function ExtractEXIFgetImageSize() { - $this->DebugMessage('starting ExtractEXIFgetImageSize()', __FILE__, __LINE__); - - if (is_resource($this->gdimg_source)) { - - $this->source_width = ImageSX($this->gdimg_source); - $this->source_height = ImageSY($this->gdimg_source); - - $this->SetOrientationDependantWidthHeight(); - - } elseif ($this->rawImageData && !$this->sourceFilename) { - - $this->DebugMessage('bypassing EXIF and GetImageSize sections because $this->rawImageData is set and $this->sourceFilename is not set', __FILE__, __LINE__); - - } - - if (is_null($this->getimagesizeinfo)) { - $this->getimagesizeinfo = @GetImageSize($this->sourceFilename); - } - - if (!empty($this->getimagesizeinfo)) { - // great - $this->getimagesizeinfo['filesize'] = @filesize($this->sourceFilename); - } elseif (!$this->rawImageData) { - $this->DebugMessage('GetImageSize("'.$this->sourceFilename.'") failed', __FILE__, __LINE__); - } - - if ($this->config_prefer_imagemagick) { - if ($this->ImageMagickThumbnailToGD()) { - return true; - } - $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); - } - - $this->source_width = $this->getimagesizeinfo[0]; - $this->source_height = $this->getimagesizeinfo[1]; - - $this->SetOrientationDependantWidthHeight(); - - if (phpthumb_functions::version_compare_replacement(phpversion(), '4.2.0', '>=') && function_exists('exif_read_data')) { - $this->exif_raw_data = @exif_read_data($this->sourceFilename, 0, true); - } - if (function_exists('exif_thumbnail') && ($this->getimagesizeinfo[2] == 2)) { - // Extract EXIF info from JPEGs - - $this->exif_thumbnail_width = ''; - $this->exif_thumbnail_height = ''; - $this->exif_thumbnail_type = ''; - - // The parameters width, height and imagetype are available since PHP v4.3.0 - if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { - - $this->exif_thumbnail_data = @exif_thumbnail($this->sourceFilename, $this->exif_thumbnail_width, $this->exif_thumbnail_height, $this->exif_thumbnail_type); - - } else { - - // older versions of exif_thumbnail output an error message but NOT return false on failure - ob_start(); - $this->exif_thumbnail_data = exif_thumbnail($this->sourceFilename); - $exit_thumbnail_error = ob_get_contents(); - ob_end_clean(); - if (!$exit_thumbnail_error && $this->exif_thumbnail_data) { - - if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { - $this->exif_thumbnail_width = ImageSX($gdimg_exif_temp); - $this->exif_thumbnail_height = ImageSY($gdimg_exif_temp); - $this->exif_thumbnail_type = 2; // (2 == JPEG) before PHP v4.3.0 only JPEG format EXIF thumbnails are returned - unset($gdimg_exif_temp); - } else { - return $this->ErrorImage('Failed - $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data) in '.__FILE__.' on line '.__LINE__); - } - - } - - } - - } elseif (!function_exists('exif_thumbnail')) { - - $this->DebugMessage('exif_thumbnail() does not exist, cannot extract EXIF thumbnail', __FILE__, __LINE__); - return false; - - } - - $this->DebugMessage('EXIF thumbnail extraction: (size='.strlen($this->exif_thumbnail_data).'; type="'.$this->exif_thumbnail_type.'"; '.intval($this->exif_thumbnail_width).'x'.intval($this->exif_thumbnail_height).')', __FILE__, __LINE__); - - // see if EXIF thumbnail can be used directly with no processing - if ($this->config_use_exif_thumbnail_for_speed && $this->exif_thumbnail_data) { - while (true) { - if (!$this->xto) { - $source_ar = $this->source_width / $this->source_height; - $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height; - if (number_format($source_ar, 2) != number_format($exif_ar, 2)) { - $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__); - break; - } - if ($this->w && ($this->w != $this->exif_thumbnail_width)) { - $this->DebugMessage('not using EXIF thumbnail because $this->w != $this->exif_thumbnail_width ('.$this->w.' != '.$this->exif_thumbnail_width.')', __FILE__, __LINE__); - break; - } - if ($this->h && ($this->h != $this->exif_thumbnail_height)) { - $this->DebugMessage('not using EXIF thumbnail because $this->h != $this->exif_thumbnail_height ('.$this->h.' != '.$this->exif_thumbnail_height.')', __FILE__, __LINE__); - break; - } - $CannotBeSetParameters = array('sx', 'sy', 'sh', 'sw', 'far', 'bg', 'bc', 'fltr', 'phpThumbDebug'); - foreach ($CannotBeSetParameters as $dummy => $parameter) { - if ($this->$parameter) { - break 2; - } - } - } - - $this->DebugMessage('setting $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data)', __FILE__, __LINE__); - $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data); - $this->source_width = ImageSX($this->gdimg_source); - $this->source_height = ImageSY($this->gdimg_source); - return true; - } - } - - if (($this->config_max_source_pixels > 0) && (($this->source_width * $this->source_height) > $this->config_max_source_pixels)) { - - // Source image is larger than would fit in available PHP memory. - // If ImageMagick is installed, use it to generate the thumbnail. - // Else, if an EXIF thumbnail is available, use that as the source image. - // Otherwise, no choice but to fail with an error message - $this->DebugMessage('image is '.$this->source_width.'x'.$this->source_height.' and therefore contains more pixels ('.($this->source_width * $this->source_height).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__); - if (!$this->config_prefer_imagemagick && $this->ImageMagickThumbnailToGD()) { - // excellent, we have a thumbnailed source image - return true; - } - - } - return true; - } - - - function SetCacheFilename() { - if (!is_null($this->cache_filename)) { - $this->DebugMessage('$this->cache_filename already set, skipping SetCacheFilename()', __FILE__, __LINE__); - return true; - } - $this->setOutputFormat(); - $this->setCacheDirectory(); - if (!$this->config_cache_directory) { - $this->DebugMessage('SetCacheFilename() failed because $this->config_cache_directory is empty', __FILE__, __LINE__); - return false; - } - - if (!$this->sourceFilename && !$this->rawImageData && $this->src) { - $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src); - } - - if ($this->config_cache_default_only_suffix && $this->sourceFilename) { - // simplified cache filenames: - // only use default parameters in phpThumb.config.php - // substitute source filename into * in $this->config_cache_default_only_suffix - // (eg: '*_thumb' becomes 'picture_thumb.jpg') - if (strpos($this->config_cache_default_only_suffix, '*') === false) { - $this->DebugMessage('aborting simplified caching filename because no * in "'.$this->config_cache_default_only_suffix.'"', __FILE__, __LINE__); - } else { - eregi('(.+)(\.[a-z0-9]+)?$', basename($this->sourceFilename), $matches); - $this->cache_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.rawurlencode(str_replace('*', @$matches[1], $this->config_cache_default_only_suffix)).'.'.strtolower($this->thumbnailFormat); - return true; - } - } - - $this->cache_filename = ''; - if ($this->new) { - $this->cache_filename .= '_new'.strtolower(md5($this->new)); - } elseif ($this->md5s) { - // source image MD5 hash provided - $this->DebugMessage('SetCacheFilename() _raw set from $this->md5s = "'.$this->md5s.'"', __FILE__, __LINE__); - $this->cache_filename .= '_raw'.$this->md5s; - } elseif (!$this->src && $this->rawImageData) { - $this->DebugMessage('SetCacheFilename() _raw set from md5($this->rawImageData) = "'.md5($this->rawImageData).'"', __FILE__, __LINE__); - $this->cache_filename .= '_raw'.strtolower(md5($this->rawImageData)); - } else { - $this->DebugMessage('SetCacheFilename() _src set from md5($this->sourceFilename) "'.$this->sourceFilename.'" = "'.md5($this->sourceFilename).'"', __FILE__, __LINE__); - $this->cache_filename .= '_src'.strtolower(md5($this->sourceFilename)); - } - if (@$_SERVER['HTTP_REFERER'] && $this->config_nooffsitelink_enabled) { - $parsed_url1 = @parse_url(@$_SERVER['HTTP_REFERER']); - $parsed_url2 = @parse_url('http://'.@$_SERVER['HTTP_HOST']); - if (@$parsed_url1['host'] && @$parsed_url2['host'] && ($parsed_url1['host'] != $parsed_url2['host'])) { - // include "_offsite" only if nooffsitelink_enabled and if referrer doesn't match the domain of the current server - $this->cache_filename .= '_offsite'; - } - } - - $ParametersString = ''; - if ($this->fltr && is_array($this->fltr)) { - $ParametersString .= '_fltr'.implode('_fltr', $this->fltr); - } - $FilenameParameters1 = array('ar', 'bg', 'bc', 'far', 'sx', 'sy', 'sw', 'sh', 'zc'); - foreach ($FilenameParameters1 as $dummy => $key) { - if ($this->$key) { - $ParametersString .= '_'.$key.$this->$key; - } - } - $FilenameParameters2 = array('h', 'w', 'wl', 'wp', 'ws', 'hp', 'hs', 'xto', 'ra', 'iar', 'aoe', 'maxb'); - foreach ($FilenameParameters2 as $dummy => $key) { - if ($this->$key) { - $ParametersString .= '_'.$key.intval($this->$key); - } - } - if ($this->thumbnailFormat == 'jpeg') { - // only JPEG output has variable quality option - $ParametersString .= '_q'.intval($this->thumbnailQuality); - } - $this->DebugMessage('SetCacheFilename() _par set from md5('.$ParametersString.')', __FILE__, __LINE__); - $this->cache_filename .= '_par'.strtolower(md5($ParametersString)); - - if ($this->md5s) { - // source image MD5 hash provided - // do not source image modification date -- - // cached image will be used even if file was modified or removed - } elseif (!$this->config_cache_source_filemtime_ignore_remote && eregi('^(f|ht)tps?\://', $this->src)) { - $this->cache_filename .= '_dat'.intval(phpthumb_functions::filedate_remote($this->src)); - } elseif (!$this->config_cache_source_filemtime_ignore_local && $this->src && !$this->rawImageData) { - $this->cache_filename .= '_dat'.intval(@filemtime($this->sourceFilename)); - } - - $this->cache_filename .= '.'.strtolower($this->thumbnailFormat); - - $this->cache_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.$this->config_cache_prefix.rawurlencode($this->cache_filename); - return true; - } - - - function ImageCreateFromFilename($filename) { - // try to create GD image source directly via GD, if possible, - // rather than buffering to memory and creating with ImageCreateFromString - $ImageCreateWasAttempted = false; - $gd_image = false; - - $this->DebugMessage('starting ImageCreateFromFilename('.$filename.')', __FILE__, __LINE__); - - if ($filename && ($getimagesizeinfo = @GetImageSize($filename))) { - if ($this->config_max_source_pixels > 0) { - if (($getimagesizeinfo[0] * $getimagesizeinfo[1]) < $this->config_max_source_pixels) { - $ImageCreateFromFunction = array( - 1 => 'ImageCreateFromGIF', - 2 => 'ImageCreateFromJPEG', - 3 => 'ImageCreateFromPNG', - 15 => 'ImageCreateFromWBMP', - ); - $this->DebugMessage('ImageCreateFromFilename found ($getimagesizeinfo[2]=='.@$getimagesizeinfo[2].')', __FILE__, __LINE__); - switch (@$getimagesizeinfo[2]) { - case 1: // GIF - case 2: // JPEG - case 3: // PNG - case 15: // WBMP - $ImageCreateFromFunctionName = $ImageCreateFromFunction[$getimagesizeinfo[2]]; - if (function_exists($ImageCreateFromFunctionName)) { - $this->DebugMessage('Calling '.$ImageCreateFromFunctionName.'('.$filename.')', __FILE__, __LINE__); - $ImageCreateWasAttempted = true; - $gd_image = @$ImageCreateFromFunctionName($filename); - } else { - $this->DebugMessage('NOT calling '.$ImageCreateFromFunctionName.'('.$filename.') because !function_exists('.$ImageCreateFromFunctionName.')', __FILE__, __LINE__); - } - break; - - case 4: // SWF - case 5: // PSD - case 6: // BMP - case 7: // TIFF (LE) - case 8: // TIFF (BE) - case 9: // JPC - case 10: // JP2 - case 11: // JPX - case 12: // JB2 - case 13: // SWC - case 14: // IFF - case 16: // XBM - $this->DebugMessage('No built-in image creation function for image type "'.@$getimagesizeinfo[2].'" ($getimagesizeinfo[2])', __FILE__, __LINE__); - break; - - default: - $this->DebugMessage('Unknown value for $getimagesizeinfo[2]: "'.@$getimagesizeinfo[2].'"', __FILE__, __LINE__); - break; - } - } else { - $this->DebugMessage('image is '.$getimagesizeinfo[0].'x'.$getimagesizeinfo[1].' and therefore contains more pixels ('.($getimagesizeinfo[0] * $getimagesizeinfo[1]).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__); - } - } - } else { - $this->DebugMessage('empty $filename or GetImageSize('.$filename.') failed', __FILE__, __LINE__); - } - - if (!$gd_image) { - // cannot create from filename, attempt to create source image with ImageCreateFromString, if possible - if ($ImageCreateWasAttempted) { - $this->DebugMessage(@$ImageCreateFromFunctionName.'() was attempted but FAILED', __FILE__, __LINE__); - } - $this->DebugMessage('Populating $rawimagedata', __FILE__, __LINE__); - $rawimagedata = ''; - if ($fp = @fopen($filename, 'rb')) { - $filesize = filesize($filename); - $blocksize = 8192; - $blockreads = ceil($filesize / $blocksize); - for ($i = 0; $i < $blockreads; $i++) { - $rawimagedata .= fread($fp, $blocksize); - } - fclose($fp); - } else { - $this->DebugMessage('cannot fopen('.$filename.')', __FILE__, __LINE__); - } - if ($rawimagedata) { - $this->DebugMessage('attempting ImageCreateFromStringReplacement($rawimagedata ('.strlen($rawimagedata).' bytes), true)', __FILE__, __LINE__); - $gd_image = $this->ImageCreateFromStringReplacement($rawimagedata, true); - } - } - return $gd_image; - } - - function SourceImageToGD() { - if (is_resource($this->gdimg_source)) { - $this->source_width = ImageSX($this->gdimg_source); - $this->source_height = ImageSY($this->gdimg_source); - $this->DebugMessage('skipping SourceImageToGD() because $this->gdimg_source is already a resource ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__); - return true; - } - $this->DebugMessage('starting SourceImageToGD()', __FILE__, __LINE__); - while (true) { - if (!$this->exif_thumbnail_data) { - $this->DebugMessage('Not using EXIF thumbnail data because $this->exif_thumbnail_data is empty', __FILE__, __LINE__); - break; - } - if (ini_get('safe_mode')) { - if (($this->config_max_source_pixels > 0) && (($this->source_width * $this->source_height) > $this->config_max_source_pixels)) { - $this->DebugMessage('Using EXIF thumbnail data because source image too large and safe_mode enabled', __FILE__, __LINE__); - $this->aoe = true; - } else { - break; - } - } else { - if (!$this->config_use_exif_thumbnail_for_speed) { - $this->DebugMessage('Not using EXIF thumbnail data because $this->config_use_exif_thumbnail_for_speed is FALSE', __FILE__, __LINE__); - break; - } - if (($this->thumbnailCropX != 0) || ($this->thumbnailCropY != 0)) { - $this->DebugMessage('Not using EXIF thumbnail data because source cropping is enabled ('.$this->thumbnailCropX.','.$this->thumbnailCropY.')', __FILE__, __LINE__); - break; - } - if (($this->w > $this->exif_thumbnail_width) || ($this->h > $this->exif_thumbnail_height)) { - $this->DebugMessage('Not using EXIF thumbnail data because EXIF thumbnail is too small ('.$this->exif_thumbnail_width.'x'.$this->exif_thumbnail_height.' vs '.$this->w.'x'.$this->h.')', __FILE__, __LINE__); - break; - } - $source_ar = $this->source_width / $this->source_height; - $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height; - if (number_format($source_ar, 2) != number_format($exif_ar, 2)) { - $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__); - break; - } - } - - // EXIF thumbnail exists, and is equal to or larger than destination thumbnail, and will be use as source image - $this->DebugMessage('Trying to use EXIF thumbnail as source image', __FILE__, __LINE__); - - if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { - - $this->DebugMessage('Successfully using EXIF thumbnail as source image', __FILE__, __LINE__); - $this->gdimg_source = $gdimg_exif_temp; - $this->source_width = $this->exif_thumbnail_width; - $this->source_height = $this->exif_thumbnail_height; - $this->thumbnailCropW = $this->source_width; - $this->thumbnailCropH = $this->source_height; - return true; - - } else { - $this->DebugMessage('$this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false) failed', __FILE__, __LINE__); - } - - break; - } - if (!$this->gdimg_source) { - - if ($this->md5s && ($this->md5s != phpthumb_functions::md5_file_safe($this->sourceFilename))) { - return $this->ErrorImage('$this->md5s != md5($rawimagedata)'."\n".'"'.$this->md5s.'" != '."\n".'"'.phpthumb_functions::md5_file_safe($this->sourceFilename).'"'); - } - switch (@$this->getimagesizeinfo[2]) { - case 1: - case 3: - // GIF or PNG input file may have transparency - $this->is_alpha = true; - break; - } - - //$this->gdimg_source = $this->ImageCreateFromFilename($this->sourceFilename, $this->rawImageData); - $this->gdimg_source = $this->ImageCreateFromFilename($this->sourceFilename); - - //if ($this->md5s && ($this->md5s != md5($this->rawImageData))) { - // return $this->ErrorImage('$this->md5s != md5($this->rawImageData)'."\n".'"'.$this->md5s.'" != '."\n".'"'.md5($this->rawImageData).'"'); - //} - - if (!$this->gdimg_source) { - $this->DebugMessage('$this->gdimg_source is still empty', __FILE__, __LINE__); - - if ($this->ImageMagickThumbnailToGD()) { - - // excellent, we have a thumbnailed source image - $this->DebugMessage('ImageMagickThumbnailToGD() succeeded', __FILE__, __LINE__); - - } else { - - $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); - - $imageHeader = ''; - $gd_info = gd_info(); - $GDreadSupport = false; - //switch (substr($this->rawImageData, 0, 3)) { - // case 'GIF': - // $imageHeader = 'Content-Type: image/gif'; - // $GDreadSupport = (bool) @$gd_info['GIF Read Support']; - // break; - // case "\xFF\xD8\xFF": - // $imageHeader = 'Content-Type: image/jpeg'; - // $GDreadSupport = (bool) @$gd_info['JPG Support']; - // break; - // case "\x89".'PN': - // $imageHeader = 'Content-Type: image/png'; - // $GDreadSupport = (bool) @$gd_info['PNG Support']; - // break; - //} - switch (@$this->getimagesizeinfo[2]) { - case 1: - $imageHeader = 'Content-Type: image/gif'; - $GDreadSupport = (bool) @$gd_info['GIF Read Support']; - break; - case 2: - $imageHeader = 'Content-Type: image/jpeg'; - $GDreadSupport = (bool) @$gd_info['JPG Support']; - break; - case 3: - $imageHeader = 'Content-Type: image/png'; - $GDreadSupport = (bool) @$gd_info['PNG Support']; - break; - } - if ($imageHeader) { - // cannot create image for whatever reason (maybe ImageCreateFromJPEG et al are not available?) - // and ImageMagick is not available either, no choice but to output original (not resized/modified) data and exit - if ($this->config_error_die_on_source_failure) { - $this->ErrorImage('All attempts to create GD image source failed ('.(ini_get('safe_mode') ? 'Safe Mode enabled, ImageMagick unavailable and source image probably too large for GD': ($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"')).'), cannot generate thumbnail'); - } else { - //$this->DebugMessage('All attempts to create GD image source failed ('.($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"').'), outputing raw image', __FILE__, __LINE__); - //if (!$this->phpThumbDebug) { - // header($imageHeader); - // echo $this->rawImageData; - // exit; - //} - return false; - } - } - - //switch (substr($this->rawImageData, 0, 2)) { - // case 'BM': - switch (@$this->getimagesizeinfo[2]) { - case 6: - ob_start(); - if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { - ob_end_clean(); - return $this->ErrorImage('include_once('.dirname(__FILE__).'/phpthumb.bmp.php) failed'); - } - ob_end_clean(); - if ($fp = @fopen($this->sourceFilename, 'rb')) { - $this->rawImageData = ''; - while (!feof($fp)) { - $this->rawImageData .= fread($fp, 32768); - } - fclose($fp); - } - $phpthumb_bmp = new phpthumb_bmp(); - if ($this->gdimg_source = $phpthumb_bmp->phpthumb_bmp2gd($this->rawImageData, (phpthumb_functions::gd_version() >= 2.0))) { - $this->DebugMessage('$phpthumb_bmp->phpthumb_bmp2gd() succeeded', __FILE__, __LINE__); - break; - } - return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on BMP source conversion' : 'phpthumb_bmp2gd() failed'); - break; - //} - //switch (substr($this->rawImageData, 0, 4)) { - // case 'II'."\x2A\x00": - // case 'MM'."\x00\x2A": - case 7: - case 8: - return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on TIFF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support TIFF source images without it'); - break; - - //case "\xD7\xCD\xC6\x9A": - // return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it'); - // break; - } - - if (!$this->gdimg_source) { - $HeaderFourBytes = ''; - if ($fp = @fopen($this->sourceFilename, 'rb')) { - $HeaderFourBytes = fread($fp, 4); - fclose($fp); - } - if ($HeaderFourBytes == "\xD7\xCD\xC6\x9A") { - return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it'); - } - return $this->ErrorImage('Unknown image type identified by "'.substr($HeaderFourBytes, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).') in SourceImageToGD()'); - } - - } - } - } - if (!$this->gdimg_source) { - if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { - $this->DebugMessage('All other attempts failed, but successfully using EXIF thumbnail as source image', __FILE__, __LINE__); - $this->gdimg_source = $gdimg_exif_temp; - // override allow-enlarging setting if EXIF thumbnail is the only source available - // otherwise thumbnails larger than the EXIF thumbnail will be created at EXIF size - $this->aoe = true; - return true; - } - return false; - } - $this->source_width = ImageSX($this->gdimg_source); - $this->source_height = ImageSY($this->gdimg_source); - return true; - } - - - function phpThumbDebugVarDump($var) { - if (is_null($var)) { - return 'NULL'; - } elseif (is_bool($var)) { - return ($var ? 'TRUE' : 'FALSE'); - } elseif (is_string($var)) { - return 'string('.strlen($var).')'.str_repeat(' ', max(0, 3 - strlen(strlen($var)))).' "'.$var.'"'; - } elseif (is_int($var)) { - return 'integer '.$var; - } elseif (is_float($var)) { - return 'float '.$var; - } elseif (is_array($var)) { - ob_start(); - var_dump($var); - $vardumpoutput = ob_get_contents(); - ob_end_clean(); - return strtr($vardumpoutput, "\n\r\t", ' '); - } - return gettype($var); - } - - function phpThumbDebug() { - if ($this->config_disable_debug) { - return $this->ErrorImage('phpThumbDebug disabled'); - } - - $FunctionsExistance = array('exif_thumbnail', 'gd_info', 'image_type_to_mime_type', 'ImageCopyResampled', 'ImageCopyResized', 'ImageCreate', 'ImageCreateFromString', 'ImageCreateTrueColor', 'ImageIsTrueColor', 'ImageRotate', 'ImageTypes', 'version_compare', 'ImageCreateFromGIF', 'ImageCreateFromJPEG', 'ImageCreateFromPNG', 'ImageCreateFromWBMP', 'ImageCreateFromXBM', 'ImageCreateFromXPM', 'ImageCreateFromString', 'ImageCreateFromGD', 'ImageCreateFromGD2', 'ImageCreateFromGD2Part', 'ImageJPEG', 'ImageGIF', 'ImagePNG', 'ImageWBMP'); - $ParameterNames = array('src', 'new', 'w', 'h', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'far', 'bg', 'bc', 'file', 'goto', 'err', 'xto', 'ra', 'ar', 'aoe', 'iar', 'maxb'); - $ConfigVariableNames = array('document_root', 'temp_directory', 'output_format', 'output_maxwidth', 'output_maxheight', 'error_message_image_default', 'error_bgcolor', 'error_textcolor', 'error_fontsize', 'error_die_on_error', 'error_silent_die_on_error', 'error_die_on_source_failure', 'nohotlink_enabled', 'nohotlink_valid_domains', 'nohotlink_erase_image', 'nohotlink_text_message', 'nooffsitelink_enabled', 'nooffsitelink_valid_domains', 'nooffsitelink_require_refer', 'nooffsitelink_erase_image', 'nooffsitelink_text_message', 'high_security_enabled', 'allow_src_above_docroot', 'allow_src_above_phpthumb', 'allow_parameter_file', 'allow_parameter_goto', 'max_source_pixels', 'use_exif_thumbnail_for_speed', 'border_hexcolor', 'background_hexcolor', 'ttf_directory', 'disable_pathinfo_parsing', 'disable_imagecopyresampled'); - $OtherVariableNames = array('phpThumbDebug', 'thumbnailQuality', 'thumbnailFormat', 'gdimg_output', 'gdimg_source', 'sourceFilename', 'source_width', 'source_height', 'thumbnailCropX', 'thumbnailCropY', 'thumbnailCropW', 'thumbnailCropH', 'exif_thumbnail_width', 'exif_thumbnail_height', 'exif_thumbnail_type', 'thumbnail_width', 'thumbnail_height', 'thumbnail_image_width', 'thumbnail_image_height'); - - $DebugOutput = array(); - $DebugOutput[] = 'phpThumb() version = '.$this->phpthumb_version; - $DebugOutput[] = 'phpversion() = '.@phpversion(); - $DebugOutput[] = 'PHP_OS = '.PHP_OS; - $DebugOutput[] = '__FILE__ = '.__FILE__; - $DebugOutput[] = 'realpath(.) = '.@realpath('.'); - $DebugOutput[] = '$_SERVER[PHP_SELF] = '.@$_SERVER['PHP_SELF']; - $DebugOutput[] = '$_SERVER[HOST_NAME] = '.@$_SERVER['HOST_NAME']; - $DebugOutput[] = '$_SERVER[HTTP_REFERER] = '.@$_SERVER['HTTP_REFERER']; - $DebugOutput[] = '$_SERVER[QUERY_STRING] = '.@$_SERVER['QUERY_STRING']; - $DebugOutput[] = '$_SERVER[PATH_INFO] = '.@$_SERVER['PATH_INFO']; - $DebugOutput[] = '$_SERVER[DOCUMENT_ROOT] = '.@$_SERVER['DOCUMENT_ROOT']; - $DebugOutput[] = 'getenv(DOCUMENT_ROOT) = '.@getenv('DOCUMENT_ROOT'); - $DebugOutput[] = ''; - - $DebugOutput[] = 'get_magic_quotes_gpc() = '.$this->phpThumbDebugVarDump(@get_magic_quotes_gpc()); - $DebugOutput[] = 'get_magic_quotes_runtime() = '.$this->phpThumbDebugVarDump(@get_magic_quotes_runtime()); - $DebugOutput[] = 'error_reporting() = '.$this->phpThumbDebugVarDump(error_reporting()); - $DebugOutput[] = 'ini_get(error_reporting) = '.$this->phpThumbDebugVarDump(@ini_get('error_reporting')); - $DebugOutput[] = 'ini_get(display_errors) = '.$this->phpThumbDebugVarDump(@ini_get('display_errors')); - $DebugOutput[] = 'ini_get(allow_url_fopen) = '.$this->phpThumbDebugVarDump(@ini_get('allow_url_fopen')); - $DebugOutput[] = 'ini_get(disable_functions) = '.$this->phpThumbDebugVarDump(@ini_get('disable_functions')); - $DebugOutput[] = 'ini_get(safe_mode) = '.$this->phpThumbDebugVarDump(@ini_get('safe_mode')); - $DebugOutput[] = 'ini_get(open_basedir) = '.$this->phpThumbDebugVarDump(@ini_get('open_basedir')); - $DebugOutput[] = 'ini_get(memory_limit) = '.$this->phpThumbDebugVarDump(@ini_get('memory_limit')); - $DebugOutput[] = 'ini_get(max_execution_time) = '.$this->phpThumbDebugVarDump(@ini_get('max_execution_time')); - $DebugOutput[] = 'get_cfg_var(memory_limit) = '.$this->phpThumbDebugVarDump(@get_cfg_var('memory_limit')); - $DebugOutput[] = 'memory_get_usage() = '.(function_exists('memory_get_usage') ? $this->phpThumbDebugVarDump(@memory_get_usage()) : 'n/a'); - $DebugOutput[] = ''; - - $DebugOutput[] = '$this->config_prefer_imagemagick = '.$this->phpThumbDebugVarDump($this->config_prefer_imagemagick); - $DebugOutput[] = '$this->config_imagemagick_path = '.$this->phpThumbDebugVarDump($this->config_imagemagick_path); - $DebugOutput[] = '$this->ImageMagickWhichConvert() = '.$this->ImageMagickWhichConvert(); - $IMpathUsed = ($this->config_imagemagick_path ? $this->config_imagemagick_path : $this->ImageMagickWhichConvert()); - $DebugOutput[] = '[actual ImageMagick path used] = '.$this->phpThumbDebugVarDump($IMpathUsed); - $DebugOutput[] = 'file_exists([actual ImageMagick path used]) = '.$this->phpThumbDebugVarDump(@file_exists($IMpathUsed)); - $DebugOutput[] = 'ImageMagickVersion(false) = '.$this->ImageMagickVersion(false); - $DebugOutput[] = 'ImageMagickVersion(true) = '.$this->ImageMagickVersion(true); - $DebugOutput[] = ''; - - $DebugOutput[] = '$this->config_cache_directory = '.$this->phpThumbDebugVarDump($this->config_cache_directory); - $DebugOutput[] = '$this->config_cache_disable_warning = '.$this->phpThumbDebugVarDump($this->config_cache_disable_warning); - $DebugOutput[] = '$this->config_cache_maxage = '.$this->phpThumbDebugVarDump($this->config_cache_maxage); - $DebugOutput[] = '$this->config_cache_maxsize = '.$this->phpThumbDebugVarDump($this->config_cache_maxsize); - $DebugOutput[] = '$this->config_cache_maxfiles = '.$this->phpThumbDebugVarDump($this->config_cache_maxfiles); - $DebugOutput[] = '$this->config_cache_force_passthru = '.$this->phpThumbDebugVarDump($this->config_cache_force_passthru); - $DebugOutput[] = '$this->cache_filename = '.$this->phpThumbDebugVarDump($this->cache_filename); - $DebugOutput[] = 'is_readable($this->config_cache_directory) = '.$this->phpThumbDebugVarDump(@is_readable($this->config_cache_directory)); - $DebugOutput[] = 'is_writable($this->config_cache_directory) = '.$this->phpThumbDebugVarDump(@is_writable($this->config_cache_directory)); - $DebugOutput[] = 'is_readable($this->cache_filename) = '.$this->phpThumbDebugVarDump(@is_readable($this->cache_filename)); - $DebugOutput[] = 'is_writable($this->cache_filename) = '.(@file_exists($this->cache_filename) ? $this->phpThumbDebugVarDump(@is_writable($this->cache_filename)) : 'n/a'); - $DebugOutput[] = ''; - - foreach ($ConfigVariableNames as $dummy => $varname) { - $varname = 'config_'.$varname; - $value = $this->$varname; - $DebugOutput[] = '$this->'.str_pad($varname, 37, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); - } - $DebugOutput[] = ''; - foreach ($OtherVariableNames as $dummy => $varname) { - $value = $this->$varname; - $DebugOutput[] = '$this->'.str_pad($varname, 27, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); - } - $DebugOutput[] = 'strlen($this->rawImageData) = '.strlen(@$this->rawImageData); - $DebugOutput[] = 'strlen($this->exif_thumbnail_data) = '.strlen(@$this->exif_thumbnail_data); - $DebugOutput[] = ''; - - foreach ($ParameterNames as $dummy => $varname) { - $value = $this->$varname; - $DebugOutput[] = '$this->'.str_pad($varname, 4, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); - } - $DebugOutput[] = ''; - - foreach ($FunctionsExistance as $dummy => $functionname) { - $DebugOutput[] = 'builtin_function_exists('.$functionname.')'.str_repeat(' ', 23 - strlen($functionname)).' = '.$this->phpThumbDebugVarDump(phpthumb_functions::builtin_function_exists($functionname)); - } - $DebugOutput[] = ''; - - $gd_info = gd_info(); - foreach ($gd_info as $key => $value) { - $DebugOutput[] = 'gd_info.'.str_pad($key, 34, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); - } - $DebugOutput[] = ''; - - $exif_info = phpthumb_functions::exif_info(); - foreach ($exif_info as $key => $value) { - $DebugOutput[] = 'exif_info.'.str_pad($key, 26, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); - } - $DebugOutput[] = ''; - - if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) { - foreach ($ApacheLookupURIarray as $key => $value) { - $DebugOutput[] = 'ApacheLookupURIarray.'.str_pad($key, 15, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); - } - } else { - $DebugOutput[] = 'ApacheLookupURIarray() -- FAILED'; - } - $DebugOutput[] = ''; - - if (isset($_GET) && is_array($_GET)) { - foreach ($_GET as $key => $value) { - $DebugOutput[] = '$_GET['.$key.']'.str_repeat(' ', 30 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value); - } - } - if (isset($_POST) && is_array($_POST)) { - foreach ($_POST as $key => $value) { - $DebugOutput[] = '$_POST['.$key.']'.str_repeat(' ', 29 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value); - } - } - $DebugOutput[] = ''; - - $DebugOutput[] = '$this->debugmessages:'; - foreach ($this->debugmessages as $dummy => $errorstring) { - $DebugOutput[] = ' * '.$errorstring; - } - $DebugOutput[] = ''; - - $DebugOutput[] = '$this->debugtiming:'; - foreach ($this->debugtiming as $timestamp => $timingstring) { - $DebugOutput[] = ' * '.$timestamp.' '.$timingstring; - } - $DebugOutput[] = ' * Total processing time: '.number_format(max(array_keys($this->debugtiming)) - min(array_keys($this->debugtiming)), 6); - - return $this->ErrorImage(implode("\n", $DebugOutput), 700, 500, true); - } - - function ErrorImage($text, $width=0, $height=0, $forcedisplay=false) { - $width = ($width ? $width : $this->config_error_image_width); - $height = ($height ? $height : $this->config_error_image_height); - - $text = 'phpThumb() v'.$this->phpthumb_version."\n\n".$text; - if ($this->config_disable_debug) { - $text = 'Error messages disabled'; - } - - $this->DebugMessage($text, __FILE__, __LINE__); - if ($this->phpThumbDebug && !$forcedisplay) { - return false; - } - if (!$this->config_error_die_on_error && !$forcedisplay) { - $this->fatalerror = $text; - return false; - } - if ($this->config_error_silent_die_on_error) { - exit; - } - if ($this->err || $this->config_error_message_image_default) { - // Show generic custom error image instead of error message - // for use on production sites where you don't want debug messages - if ($this->err == 'showerror') { - // fall through and actually show error message even if default error image is set - } else { - header('Location: '.($this->err ? $this->err : $this->config_error_message_image_default)); - exit; - } - } - $this->setOutputFormat(); - if (!$this->thumbnailFormat || (phpthumb_functions::gd_version() < 1)) { - $this->thumbnailFormat = 'text'; - } - if (@$this->thumbnailFormat == 'text') { - // bypass all GD functions and output text error message - die('
    '.$text.'
    '); - } - - $FontWidth = ImageFontWidth($this->config_error_fontsize); - $FontHeight = ImageFontHeight($this->config_error_fontsize); - - $LinesOfText = explode("\n", @wordwrap($text, floor($width / $FontWidth), "\n", true)); - $height = max($height, count($LinesOfText) * $FontHeight); - - $headers_file = ''; - $headers_line = ''; - if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=') && headers_sent($headers_file, $headers_line)) { - - echo "\n".'**Headers already sent in file "'.$headers_file.'" on line "'.$headers_line.'", dumping error message as text:**
    '."\n\n".$text."\n".'
    '; - - } elseif (headers_sent()) { - - echo "\n".'**Headers already sent, dumping error message as text:**
    '."\n\n".$text."\n".'
    '; - - } elseif ($gdimg_error = ImageCreate($width, $height)) { - - $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_bgcolor, true); - $text_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_textcolor, true); - ImageFilledRectangle($gdimg_error, 0, 0, $width, $height, $background_color); - $lineYoffset = 0; - foreach ($LinesOfText as $dummy => $line) { - ImageString($gdimg_error, $this->config_error_fontsize, 2, $lineYoffset, $line, $text_color); - $lineYoffset += $FontHeight; - } - if (function_exists('ImageTypes')) { - $imagetypes = ImageTypes(); - if ($imagetypes & IMG_PNG) { - header('Content-Type: image/png'); - ImagePNG($gdimg_error); - } elseif ($imagetypes & IMG_GIF) { - header('Content-Type: image/gif'); - ImageGIF($gdimg_error); - } elseif ($imagetypes & IMG_JPG) { - header('Content-Type: image/jpeg'); - ImageJPEG($gdimg_error); - } elseif ($imagetypes & IMG_WBMP) { - header('Content-Type: image/wbmp'); - ImageWBMP($gdimg_error); - } - } - ImageDestroy($gdimg_error); - - } - if (!headers_sent()) { - echo "\n".'**Failed to send graphical error image, dumping error message as text:**
    '."\n\n".$text; - } - exit; - return true; - } - - function ImageCreateFromStringReplacement(&$RawImageData, $DieOnErrors=false) { - // there are serious bugs in the non-bundled versions of GD which may cause - // PHP to segfault when calling ImageCreateFromString() - avoid if at all possible - // when not using a bundled version of GD2 - if (phpthumb_functions::gd_is_bundled()) { - return @ImageCreateFromString($RawImageData); - } - if (ini_get('safe_mode')) { - $this->DebugMessage('ImageCreateFromStringReplacement() failed: cannot create temp file in SAFE_MODE', __FILE__, __LINE__); - return false; - } - - switch (substr($RawImageData, 0, 3)) { - case 'GIF': - $ICFSreplacementFunctionName = 'ImageCreateFromGIF'; - break; - case "\xFF\xD8\xFF": - $ICFSreplacementFunctionName = 'ImageCreateFromJPEG'; - break; - case "\x89".'PN': - $ICFSreplacementFunctionName = 'ImageCreateFromPNG'; - break; - default: - $this->DebugMessage('ImageCreateFromStringReplacement() failed: unknown fileformat signature "'.phpthumb_functions::HexCharDisplay(substr($RawImageData, 0, 3)).'"', __FILE__, __LINE__); - return false; - break; - } - if ($tempnam = $this->phpThumb_tempnam()) { - if ($fp_tempnam = @fopen($tempnam, 'wb')) { - fwrite($fp_tempnam, $RawImageData); - fclose($fp_tempnam); - if (($ICFSreplacementFunctionName == 'ImageCreateFromGIF') && !function_exists($ICFSreplacementFunctionName)) { - - // Need to create from GIF file, but ImageCreateFromGIF does not exist - ob_start(); - if (!@include_once(dirname(__FILE__).'/phpthumb.gif.php')) { - $ErrorMessage = 'Failed to include required file "'.dirname(__FILE__).'/phpthumb.gif.php" in '.__FILE__.' on line '.__LINE__; - $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); - } - ob_end_clean(); - // gif_loadFileToGDimageResource() cannot read from raw data, write to file first - if ($tempfilename = $this->phpThumb_tempnam()) { - if ($fp_tempfile = @fopen($tempfilename, 'wb')) { - fwrite($fp_tempfile, $RawImageData); - fclose($fp_tempfile); - $gdimg_source = gif_loadFileToGDimageResource($tempfilename); - unlink($tempfilename); - return $gdimg_source; - break; - } else { - $ErrorMessage = 'Failed to open tempfile in '.__FILE__.' on line '.__LINE__; - $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); - } - } else { - $ErrorMessage = 'Failed to open generate tempfile name in '.__FILE__.' on line '.__LINE__; - $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); - } - - } elseif (function_exists($ICFSreplacementFunctionName) && ($gdimg_source = @$ICFSreplacementFunctionName($tempnam))) { - - // great - unlink($tempnam); - return $gdimg_source; - - } else { // GD functions not available - - if (isset($_GET['phpThumbDebug'])) { - $this->phpThumbDebug(); - } elseif (!headers_sent()) { - // base64-encoded error image in GIF format - $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7'; - header('Content-Type: image/gif'); - echo base64_decode($ERROR_NOGD); - } else { - echo '*** ERROR: No PHP-GD support available ***'; - } - exit; - - } - } else { - $ErrorMessage = 'Failed to fopen('.$tempnam.', "wb") in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; - $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); - } - @unlink($tempnam); - } else { - $ErrorMessage = 'Failed to generate phpThumb_tempnam() in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; - } - if ($DieOnErrors && $ErrorMessage) { - return $this->ErrorImage($ErrorMessage); - } - return false; - } - - function ImageResizeFunction(&$dst_im, &$src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH) { - $this->DebugMessage('ImageResizeFunction($o, $s, '.$dstX.', '.$dstY.', '.$srcX.', '.$srcY.', '.$dstW.', '.$dstH.', '.$srcW.', '.$srcH.')', __FILE__, __LINE__); - if (phpthumb_functions::gd_version() >= 2.0) { - if ($this->config_disable_imagecopyresampled) { - return phpthumb_functions::ImageCopyResampleBicubic($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); - } - return ImageCopyResampled($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); - } - return ImageCopyResized($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); - } - - function phpThumb_tempnam() { - $tempnam = realpath(tempnam($this->config_temp_directory, 'pThumb')); - $this->DebugMessage('phpThumb_tempnam() returning "'.$tempnam.'"', __FILE__, __LINE__); - return $tempnam; - } - - function DebugMessage($message, $file='', $line='') { - $this->debugmessages[] = $message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : ''); - return true; - } - - function DebugTimingMessage($message, $file='', $line='', $timestamp=0) { - if (!$timestamp) { - $timestamp = array_sum(explode(' ', microtime())); - } - $this->debugtiming[number_format($timestamp, 6, '.', '')] = ': '.$message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : ''); - return true; - } - -} - -?> \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.filters.php b/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.filters.php deleted file mode 100644 index 5bd9fb779..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.filters.php +++ /dev/null @@ -1,1266 +0,0 @@ - // -// available at http://phpthumb.sourceforge.net /// -////////////////////////////////////////////////////////////// -/// // -// phpthumb.filters.php - image processing filter functions // -// /// -////////////////////////////////////////////////////////////// - -class phpthumb_filters { - - var $phpThumbObject = null; - - function phpthumb_filters() { - return true; - } - - function ApplyMask(&$gdimg_mask, &$gdimg_image) { - if (phpthumb_functions::gd_version() < 2) { - $this->DebugMessage('Skipping ApplyMask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); - return false; - } - if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=')) { - - $this->DebugMessage('Using alpha ApplyMask() technique', __FILE__, __LINE__); - if ($gdimg_mask_resized = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_image), ImageSY($gdimg_image))) { - - ImageCopyResampled($gdimg_mask_resized, $gdimg_mask, 0, 0, 0, 0, ImageSX($gdimg_image), ImageSY($gdimg_image), ImageSX($gdimg_mask), ImageSY($gdimg_mask)); - if ($gdimg_mask_blendtemp = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_image), ImageSY($gdimg_image))) { - - $color_background = ImageColorAllocate($gdimg_mask_blendtemp, 0, 0, 0); - ImageFilledRectangle($gdimg_mask_blendtemp, 0, 0, ImageSX($gdimg_mask_blendtemp), ImageSY($gdimg_mask_blendtemp), $color_background); - ImageAlphaBlending($gdimg_mask_blendtemp, false); - ImageSaveAlpha($gdimg_mask_blendtemp, true); - for ($x = 0; $x < ImageSX($gdimg_image); $x++) { - for ($y = 0; $y < ImageSY($gdimg_image); $y++) { - //$RealPixel = phpthumb_functions::GetPixelColor($gdimg_mask_blendtemp, $x, $y); - $RealPixel = phpthumb_functions::GetPixelColor($gdimg_image, $x, $y); - $MaskPixel = phpthumb_functions::GrayscalePixel(phpthumb_functions::GetPixelColor($gdimg_mask_resized, $x, $y)); - $MaskAlpha = 127 - (floor($MaskPixel['red'] / 2) * (1 - ($RealPixel['alpha'] / 127))); - $newcolor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_mask_blendtemp, $RealPixel['red'], $RealPixel['green'], $RealPixel['blue'], $MaskAlpha); - ImageSetPixel($gdimg_mask_blendtemp, $x, $y, $newcolor); - } - } - ImageAlphaBlending($gdimg_image, false); - ImageSaveAlpha($gdimg_image, true); - ImageCopy($gdimg_image, $gdimg_mask_blendtemp, 0, 0, 0, 0, ImageSX($gdimg_mask_blendtemp), ImageSY($gdimg_mask_blendtemp)); - ImageDestroy($gdimg_mask_blendtemp); - - } else { - $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); - } - ImageDestroy($gdimg_mask_resized); - - } else { - $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); - } - - } else { - // alpha merging requires PHP v4.3.2+ - $this->DebugMessage('Skipping ApplyMask() technique because PHP is v"'.phpversion().'"', __FILE__, __LINE__); - } - return true; - } - - - function Bevel(&$gdimg, $width, $hexcolor1, $hexcolor2) { - $width = ($width ? $width : 5); - $hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF'); - $hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000'); - - ImageAlphaBlending($gdimg, true); - for ($i = 0; $i < $width; $i++) { - $alpha = round(($i / $width) * 127); - $color1[$i] = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1, false, $alpha); - $color2[$i] = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2, false, $alpha); - - ImageLine($gdimg, $i, $i, $i, ImageSY($gdimg) - $i, $color1[$i]); // left - ImageLine($gdimg, $i, $i, ImageSX($gdimg) - $i, $i, $color1[$i]); // top - ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, ImageSX($gdimg) - $i, $i, $color2[$i]); // right - ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, $i, ImageSY($gdimg) - $i, $color2[$i]); // bottom - } - return true; - } - - - function Blur(&$gdimg, $radius=0.5) { - // Taken from Torstein Hønsi's phpUnsharpMask (see phpthumb.unsharp.php) - - $radius = round(max(0, min($radius, 50)) * 2); - if (!$radius) { - return false; - } - - $w = ImageSX($gdimg); - $h = ImageSY($gdimg); - if ($imgBlur = ImageCreateTrueColor($w, $h)) { - // Gaussian blur matrix: - // 1 2 1 - // 2 4 2 - // 1 2 1 - - // Move copies of the image around one pixel at the time and merge them with weight - // according to the matrix. The same matrix is simply repeated for higher radii. - for ($i = 0; $i < $radius; $i++) { - ImageCopy ($imgBlur, $gdimg, 0, 0, 1, 1, $w - 1, $h - 1); // up left - ImageCopyMerge($imgBlur, $gdimg, 1, 1, 0, 0, $w, $h, 50.00000); // down right - ImageCopyMerge($imgBlur, $gdimg, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left - ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 1, $w, $h - 1, 25.00000); // up right - ImageCopyMerge($imgBlur, $gdimg, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left - ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 0, $w, $h, 25.00000); // right - ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 1, $w, $h - 1, 20.00000); // up - ImageCopyMerge($imgBlur, $gdimg, 0, 1, 0, 0, $w, $h, 16.666667); // down - ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 0, $w, $h, 50.000000); // center - ImageCopy ($gdimg, $imgBlur, 0, 0, 0, 0, $w, $h); - } - return true; - } - return false; - } - - - function BlurGaussian(&$gdimg) { - if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { - if (ImageFilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)) { - return true; - } - $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)', __FILE__, __LINE__); - // fall through and try it the hard way - } - $this->DebugMessage('FAILED: phpthumb_filters::BlurGaussian($gdimg) [using phpthumb_filters::Blur() instead]', __FILE__, __LINE__); - return phpthumb_filters::Blur($gdimg, 0.5); - } - - - function BlurSelective(&$gdimg) { - if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { - if (ImageFilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)) { - return true; - } - $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)', __FILE__, __LINE__); - // fall through and try it the hard way - } - // currently not implemented "the hard way" - $this->DebugMessage('FAILED: phpthumb_filters::BlurSelective($gdimg) [function not implemented]', __FILE__, __LINE__); - return false; - } - - - function Brightness(&$gdimg, $amount=0) { - if ($amount == 0) { - return true; - } - $amount = max(-255, min(255, $amount)); - - if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { - if (ImageFilter($gdimg, IMG_FILTER_BRIGHTNESS, $amount)) { - return true; - } - $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_BRIGHTNESS, '.$amount.')', __FILE__, __LINE__); - // fall through and try it the hard way - } - - $scaling = (255 - abs($amount)) / 255; - $baseamount = (($amount > 0) ? $amount : 0); - for ($x = 0; $x < ImageSX($gdimg); $x++) { - for ($y = 0; $y < ImageSY($gdimg); $y++) { - $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); - foreach ($OriginalPixel as $key => $value) { - $NewPixel[$key] = round($baseamount + ($OriginalPixel[$key] * $scaling)); - } - $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); - ImageSetPixel($gdimg, $x, $y, $newColor); - } - } - return true; - } - - - function Contrast(&$gdimg, $amount=0) { - if ($amount == 0) { - return true; - } - $amount = max(-255, min(255, $amount)); - - if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { - if (ImageFilter($gdimg, IMG_FILTER_CONTRAST, $amount)) { - return true; - } - $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_CONTRAST, '.$amount.')', __FILE__, __LINE__); - // fall through and try it the hard way - } - - if ($amount > 0) { - $scaling = 1 + ($amount / 255); - } else { - $scaling = (255 - abs($amount)) / 255; - } - for ($x = 0; $x < ImageSX($gdimg); $x++) { - for ($y = 0; $y < ImageSY($gdimg); $y++) { - $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); - foreach ($OriginalPixel as $key => $value) { - $NewPixel[$key] = min(255, max(0, round($OriginalPixel[$key] * $scaling))); - } - $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); - ImageSetPixel($gdimg, $x, $y, $newColor); - } - } - } - - - function Colorize(&$gdimg, $amount, $targetColor) { - $amount = (is_numeric($amount) ? $amount : 25); - $targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'gray'); - - if ($amount == 0) { - return true; - } - - if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { - if ($targetColor == 'gray') { - $targetColor = '808080'; - } - $r = substr($targetColor, 0, 2); - $g = substr($targetColor, 2, 2); - $b = substr($targetColor, 4, 2); - if (ImageFilter($gdimg, IMG_FILTER_COLORIZE, $r, $g, $b)) { - return true; - } - $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_COLORIZE)', __FILE__, __LINE__); - // fall through and try it the hard way - } - - // overridden below for grayscale - if ($targetColor != 'gray') { - $TargetPixel['red'] = hexdec(substr($targetColor, 0, 2)); - $TargetPixel['green'] = hexdec(substr($targetColor, 2, 2)); - $TargetPixel['blue'] = hexdec(substr($targetColor, 4, 2)); - } - - for ($x = 0; $x < ImageSX($gdimg); $x++) { - for ($y = 0; $y < ImageSY($gdimg); $y++) { - $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); - if ($targetColor == 'gray') { - $TargetPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); - } - foreach ($TargetPixel as $key => $value) { - $NewPixel[$key] = round(max(0, min(255, ($OriginalPixel[$key] * ((100 - $amount) / 100)) + ($TargetPixel[$key] * ($amount / 100))))); - } - //$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']); - $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); - ImageSetPixel($gdimg, $x, $y, $newColor); - } - } - return true; - } - - - function Crop(&$gdimg, $left=0, $right=0, $top=0, $bottom=0) { - if (!$left && !$right && !$top && !$bottom) { - return true; - } - $oldW = ImageSX($gdimg); - $oldH = ImageSY($gdimg); - if (($left > 0) && ($left < 1)) { $left = round($left * $oldW); } - if (($right > 0) && ($right < 1)) { $right = round($right * $oldW); } - if (($top > 0) && ($top < 1)) { $top = round($top * $oldH); } - if (($bottom > 0) && ($bottom < 1)) { $bottom = round($bottom * $oldH); } - $right = min($oldW - $left - 1, $right); - $bottom = min($oldH - $top - 1, $bottom); - $newW = $oldW - $left - $right; - $newH = $oldH - $top - $bottom; - - if ($imgCropped = ImageCreateTrueColor($newW, $newH)) { - ImageCopy($imgCropped, $gdimg, 0, 0, $left, $top, $newW, $newH); - if ($gdimg = ImageCreateTrueColor($newW, $newH)) { - ImageCopy($gdimg, $imgCropped, 0, 0, 0, 0, $newW, $newH); - ImageDestroy($imgCropped); - return true; - } - ImageDestroy($imgCropped); - } - return false; - } - - - function Desaturate(&$gdimg, $amount, $color='') { - if ($amount == 0) { - return true; - } - return phpthumb_filters::Colorize($gdimg, $amount, (phpthumb_functions::IsHexColor($color) ? $color : 'gray')); - } - - - function DropShadow(&$gdimg, $distance, $width, $hexcolor, $angle, $fade) { - if (phpthumb_functions::gd_version() < 2) { - return false; - } - $distance = ($distance ? $distance : 10); - $width = ($width ? $width : 10); - $hexcolor = ($hexcolor ? $hexcolor : '000000'); - $angle = ($angle ? $angle : 225); - $fade = ($fade ? $fade : 1); - - $width_shadow = cos(deg2rad($angle)) * ($distance + $width); - $height_shadow = sin(deg2rad($angle)) * ($distance + $width); - - $scaling = min(ImageSX($gdimg) / (ImageSX($gdimg) + abs($width_shadow)), ImageSY($gdimg) / (ImageSY($gdimg) + abs($height_shadow))); - - for ($i = 0; $i < $width; $i++) { - $WidthAlpha[$i] = (abs(($width / 2) - $i) / $width) * $fade; - $Offset['x'] = cos(deg2rad($angle)) * ($distance + $i); - $Offset['y'] = sin(deg2rad($angle)) * ($distance + $i); - } - - $tempImageWidth = ImageSX($gdimg) + abs($Offset['x']); - $tempImageHeight = ImageSY($gdimg) + abs($Offset['y']); - - if ($gdimg_dropshadow_temp = phpthumb_functions::ImageCreateFunction($tempImageWidth, $tempImageHeight)) { - - ImageAlphaBlending($gdimg_dropshadow_temp, false); - ImageSaveAlpha($gdimg_dropshadow_temp, true); - $transparent1 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, 0, 0, 0, 127); - ImageFill($gdimg_dropshadow_temp, 0, 0, $transparent1); - - for ($x = 0; $x < ImageSX($gdimg); $x++) { - for ($y = 0; $y < ImageSY($gdimg); $y++) { - $PixelMap[$x][$y] = phpthumb_functions::GetPixelColor($gdimg, $x, $y); - } - } - for ($x = 0; $x < $tempImageWidth; $x++) { - for ($y = 0; $y < $tempImageHeight; $y++) { - //for ($i = 0; $i < $width; $i++) { - for ($i = 0; $i < 1; $i++) { - if (!isset($PixelMap[$x][$y]['alpha']) || ($PixelMap[$x][$y]['alpha'] > 0)) { - if (isset($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']) && ($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha'] < 127)) { - $thisColor = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor, false, $PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']); - ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor); - } - } - } - } - } - - ImageAlphaBlending($gdimg_dropshadow_temp, true); - for ($x = 0; $x < ImageSX($gdimg); $x++) { - for ($y = 0; $y < ImageSY($gdimg); $y++) { - if ($PixelMap[$x][$y]['alpha'] < 127) { - $thisColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, $PixelMap[$x][$y]['red'], $PixelMap[$x][$y]['green'], $PixelMap[$x][$y]['blue'], $PixelMap[$x][$y]['alpha']); - ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor); - } - } - } - - ImageSaveAlpha($gdimg, true); - ImageAlphaBlending($gdimg, false); - //$this->is_alpha = true; - $transparent2 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0, 0, 0, 127); - ImageFilledRectangle($gdimg, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $transparent2); - ImageCopyResampled($gdimg, $gdimg_dropshadow_temp, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg_dropshadow_temp), ImageSY($gdimg_dropshadow_temp)); - - ImageDestroy($gdimg_dropshadow_temp); - } - return true; - } - - - function EdgeDetect(&$gdimg) { - if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { - if (ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)) { - return true; - } - $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)', __FILE__, __LINE__); - // fall through and try it the hard way - } - // currently not implemented "the hard way" - $this->DebugMessage('FAILED: phpthumb_filters::EdgeDetect($gdimg) [function not implemented]', __FILE__, __LINE__); - return false; - } - - - function Elipse($gdimg) { - if (phpthumb_functions::gd_version() < 2) { - return false; - } - // generate mask at twice desired resolution and downsample afterwards for easy antialiasing - if ($gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg) * 2, ImageSY($gdimg) * 2)) { - if ($gdimg_elipsemask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { - - $color_transparent = ImageColorAllocate($gdimg_elipsemask_double, 255, 255, 255); - ImageFilledEllipse($gdimg_elipsemask_double, ImageSX($gdimg), ImageSY($gdimg), (ImageSX($gdimg) - 1) * 2, (ImageSY($gdimg) - 1) * 2, $color_transparent); - ImageCopyResampled($gdimg_elipsemask, $gdimg_elipsemask_double, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg) * 2, ImageSY($gdimg) * 2); - - phpthumb_filters::ApplyMask($gdimg_elipsemask, $gdimg); - ImageDestroy($gdimg_elipsemask); - return true; - - } else { - $this->DebugMessage('$gdimg_elipsemask = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__); - } - ImageDestroy($gdimg_elipsemask_double); - } else { - $this->DebugMessage('$gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__); - } - return false; - } - - - function Emboss(&$gdimg) { - if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { - if (ImageFilter($gdimg, IMG_FILTER_EMBOSS)) { - return true; - } - $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EMBOSS)', __FILE__, __LINE__); - // fall through and try it the hard way - } - // currently not implemented "the hard way" - $this->DebugMessage('FAILED: phpthumb_filters::Emboss($gdimg) [function not implemented]', __FILE__, __LINE__); - return false; - } - - - function Flip(&$gdimg, $x=false, $y=false) { - if (!$x && !$y) { - return false; - } - if ($tempImage = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { - if ($x) { - ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg)); - for ($x = 0; $x < ImageSX($gdimg); $x++) { - ImageCopy($gdimg, $tempImage, ImageSX($gdimg) - 1 - $x, 0, $x, 0, 1, ImageSY($gdimg)); - } - } - if ($y) { - ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg)); - for ($y = 0; $y < ImageSY($gdimg); $y++) { - ImageCopy($gdimg, $tempImage, 0, ImageSY($gdimg) - 1 - $y, 0, $y, ImageSX($gdimg), 1); - } - } - ImageDestroy($tempImage); - } - return true; - } - - - function Frame(&$gdimg, $frame_width, $edge_width, $hexcolor_frame, $hexcolor1, $hexcolor2) { - $frame_width = ($frame_width ? $frame_width : 5); - $edge_width = ($edge_width ? $edge_width : 1); - $hexcolor_frame = ($hexcolor_frame ? $hexcolor_frame : 'CCCCCC'); - $hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF'); - $hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000'); - - $color_frame = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor_frame); - $color1 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1); - $color2 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2); - for ($i = 0; $i < $edge_width; $i++) { - // outer bevel - ImageLine($gdimg, $i, $i, $i, ImageSY($gdimg) - $i, $color1); // left - ImageLine($gdimg, $i, $i, ImageSX($gdimg) - $i, $i, $color1); // top - ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, ImageSX($gdimg) - $i, $i, $color2); // right - ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, $i, ImageSY($gdimg) - $i, $color2); // bottom - } - for ($i = 0; $i < $frame_width; $i++) { - // actual frame - ImageRectangle($gdimg, $edge_width + $i, $edge_width + $i, ImageSX($gdimg) - $edge_width - $i, ImageSY($gdimg) - $edge_width - $i, $color_frame); - } - for ($i = 0; $i < $edge_width; $i++) { - // inner bevel - ImageLine($gdimg, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $color2); // left - ImageLine($gdimg, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, ImageSX($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, $color2); // top - ImageLine($gdimg, ImageSX($gdimg) - $frame_width - $edge_width - $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, ImageSX($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, $color1); // right - ImageLine($gdimg, ImageSX($gdimg) - $frame_width - $edge_width - $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $color1); // bottom - } - return true; - } - - - function Gamma(&$gdimg, $amount) { - if (number_format($amount, 4) == '1.0000') { - return true; - } - return ImageGammaCorrect($gdimg, 1.0, $amount); - } - - - function Grayscale(&$gdimg) { - if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { - if (ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)) { - return true; - } - $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)', __FILE__, __LINE__); - // fall through and try it the hard way - } - return phpthumb_filters::Colorize($gdimg, 100, 'gray'); - } - - - function HistogramAnalysis(&$gdimg, $calculateGray=false) { - $ImageSX = ImageSX($gdimg); - $ImageSY = ImageSY($gdimg); - for ($x = 0; $x < $ImageSX; $x++) { - for ($y = 0; $y < $ImageSY; $y++) { - $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); - @$Analysis['red'][$OriginalPixel['red']]++; - @$Analysis['green'][$OriginalPixel['green']]++; - @$Analysis['blue'][$OriginalPixel['blue']]++; - @$Analysis['alpha'][$OriginalPixel['alpha']]++; - if ($calculateGray) { - $GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); - @$Analysis['gray'][$GrayPixel['red']]++; - } - } - } - $keys = array('red', 'green', 'blue', 'alpha'); - if ($calculateGray) { - $keys[] = 'gray'; - } - foreach ($keys as $dummy => $key) { - ksort($Analysis[$key]); - } - return $Analysis; - } - - - function HistogramStretch(&$gdimg, $band='*', $min=-1, $max=-1) { - // equivalent of "Auto Contrast" in Adobe Photoshop - - $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true); - $keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>'gray'); - if (!isset($keys[$band])) { - return false; - } - $key = $keys[$band]; - - // If the absolute brightest and darkest pixels are used then one random - // pixel in the image could throw off the whole system. Instead, count up/down - // from the limit and allow 0.1% of brightest/darkest pixels to be clipped to min/max - $clip_threshold = ImageSX($gdimg) * ImageSX($gdimg) * 0.001; - if ($min >= 0) { - $range_min = min($min, 255); - } else { - $countsum = 0; - for ($i = 0; $i <= 255; $i++) { - $countsum += @$Analysis[$key][$i]; - if ($countsum >= $clip_threshold) { - $range_min = $i - 1; - break; - } - } - $range_min = max($range_min, 0); - } - if ($max >= 0) { - $range_max = max($max, 255); - } else { - $countsum = 0; - $threshold = ImageSX($gdimg) * ImageSX($gdimg) * 0.001; // 0.1% of brightest and darkest pixels can be clipped - for ($i = 255; $i >= 0; $i--) { - $countsum += @$Analysis[$key][$i]; - if ($countsum >= $clip_threshold) { - $range_max = $i + 1; - break; - } - } - $range_max = min($range_max, 255); - } - $range_scale = (($range_max == $range_min) ? 1 : (255 / ($range_max - $range_min))); - if (($range_min == 0) && ($range_max == 255)) { - // no adjustment neccesary - don't waste CPU time! - return true; - } - - $ImageSX = ImageSX($gdimg); - $ImageSY = ImageSY($gdimg); - for ($x = 0; $x < $ImageSX; $x++) { - for ($y = 0; $y < $ImageSY; $y++) { - $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); - if ($band == '*') { - $new['red'] = min(255, max(0, ($OriginalPixel['red'] - $range_min) * $range_scale)); - $new['green'] = min(255, max(0, ($OriginalPixel['green'] - $range_min) * $range_scale)); - $new['blue'] = min(255, max(0, ($OriginalPixel['blue'] - $range_min) * $range_scale)); - $new['alpha'] = min(255, max(0, ($OriginalPixel['alpha'] - $range_min) * $range_scale)); - } else { - $new = $OriginalPixel; - $new[$key] = min(255, max(0, ($OriginalPixel[$key] - $range_min) * $range_scale)); - } - $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $new['red'], $new['green'], $new['blue'], $new['alpha']); - ImageSetPixel($gdimg, $x, $y, $newColor); - } - } - - return true; - } - - - function HistogramOverlay(&$gdimg, $bands='*', $colors='', $width=0.25, $height=0.25, $alignment='BR', $opacity=50, $margin=5) { - $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true); - - $histW = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width); - $histH = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width); - if ($gdHist = ImageCreateTrueColor($histW, $histH)) { - $color_back = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHist, 0, 0, 0, 127); - ImageFilledRectangle($gdHist, 0, 0, $histW, $histH, $color_back); - ImageAlphaBlending($gdHist, false); - ImageSaveAlpha($gdHist, true); - - if ($gdHistTemp = ImageCreateTrueColor(256, 100)) { - $color_back_temp = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHistTemp, 255, 0, 255, 127); - ImageAlphaBlending($gdHistTemp, false); - ImageSaveAlpha($gdHistTemp, true); - ImageFilledRectangle($gdHistTemp, 0, 0, ImageSX($gdHistTemp), ImageSY($gdHistTemp), $color_back_temp); - - $DefaultColors = array('r'=>'FF0000', 'g'=>'00FF00', 'b'=>'0000FF', 'a'=>'999999', '*'=>'FFFFFF'); - $Colors = explode(';', $colors); - $BandsToGraph = array_unique(preg_split('//', $bands)); - $keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>'gray'); - foreach ($BandsToGraph as $key => $band) { - if (!isset($keys[$band])) { - continue; - } - $PeakValue = max($Analysis[$keys[$band]]); - $thisColor = phpthumb_functions::ImageHexColorAllocate($gdHistTemp, phpthumb_functions::IsHexColor(@$Colors[$key]) ? $Colors[$key] : $DefaultColors[$band]); - $tempHeight = ImageSY($gdHistTemp); - for ($x = 0; $x <= 255; $x++) { - ImageLine($gdHistTemp, $x, $tempHeight - 1, $x, $tempHeight - 1 - round(@$Analysis[$keys[$band]][$x] / $PeakValue * $tempHeight), $thisColor); - } - ImageLine($gdHistTemp, 0, $tempHeight - 1, 255, $tempHeight - 1, $thisColor); - ImageLine($gdHistTemp, 0, $tempHeight - 2, 255, $tempHeight - 2, $thisColor); - } - ImageCopyResampled($gdHist, $gdHistTemp, 0, 0, 0, 0, ImageSX($gdHist), ImageSY($gdHist), ImageSX($gdHistTemp), ImageSY($gdHistTemp)); - ImageDestroy($gdHistTemp); - } else { - return false; - } - - phpthumb_filters::WatermarkOverlay($gdimg, $gdHist, $alignment, $opacity, $margin); - ImageDestroy($gdHist); - return true; - } - return false; - } - - - function ImageBorder(&$gdimg, $border_width, $radius_x, $radius_y, $hexcolor_border) { - $border_width = ($border_width ? $border_width : 1); - $radius_x = ($radius_x ? $radius_x : 0); - $radius_y = ($radius_y ? $radius_y : 0); - - $output_width = ImageSX($gdimg); - $output_height = ImageSY($gdimg); - - list($new_width, $new_height) = phpthumb_functions::ProportionalResize($output_width, $output_height, $output_width - max($border_width * 2, $radius_x), $output_height - max($border_width * 2, $radius_y)); - $offset_x = ($radius_x ? $output_width - $new_width - $radius_x : 0); - $offset_y = ($radius_y ? $output_height - $new_height - $radius_y : 0); - -//header('Content-Type: image/png'); -//ImagePNG($gdimg); -//exit; - if ($gd_border_canvas = phpthumb_functions::ImageCreateFunction($output_width, $output_height)) { - - ImageSaveAlpha($gd_border_canvas, true); - ImageAlphaBlending($gd_border_canvas, false); - $color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gd_border_canvas, 255, 255, 255, 127); - ImageFilledRectangle($gd_border_canvas, 0, 0, $output_width, $output_height, $color_background); - - $color_border = phpthumb_functions::ImageHexColorAllocate($gd_border_canvas, (phpthumb_functions::IsHexColor($hexcolor_border) ? $hexcolor_border : '000000')); - - for ($i = 0; $i < $border_width; $i++) { - ImageLine($gd_border_canvas, floor($offset_x / 2) + $radius_x, $i, $output_width - $radius_x - ceil($offset_x / 2), $i, $color_border); // top - ImageLine($gd_border_canvas, floor($offset_x / 2) + $radius_x, $output_height - 1 - $i, $output_width - $radius_x - ceil($offset_x / 2), $output_height - 1 - $i, $color_border); // bottom - ImageLine($gd_border_canvas, floor($offset_x / 2) + $i, $radius_y, floor($offset_x / 2) + $i, $output_height - $radius_y, $color_border); // left - ImageLine($gd_border_canvas, $output_width - 1 - $i - ceil($offset_x / 2), $radius_y, $output_width - 1 - $i - ceil($offset_x / 2), $output_height - $radius_y, $color_border); // right - } - - if ($radius_x && $radius_y) { - - // PHP bug: ImageArc() with thicknesses > 1 give bad/undesirable/unpredicatable results - // Solution: Draw multiple 1px arcs side-by-side. - - // Problem: parallel arcs give strange/ugly antialiasing problems - // Solution: draw non-parallel arcs, from one side of the line thickness at the start angle - // to the opposite edge of the line thickness at the terminating angle - for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) { - ImageArc($gd_border_canvas, floor($offset_x / 2) + 1 + $radius_x, $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left - ImageArc($gd_border_canvas, $output_width - $radius_x - 1 - ceil($offset_x / 2), $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right - ImageArc($gd_border_canvas, $output_width - $radius_x - 1 - ceil($offset_x / 2), $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2, 0, 90, $color_border); // bottom-right - ImageArc($gd_border_canvas, floor($offset_x / 2) + 1 + $radius_x, $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2, 90, 180, $color_border); // bottom-left - } - if ($border_width > 1) { - for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) { - ImageArc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x, $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left - ImageArc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2), $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right - ImageArc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2), $output_height - $radius_y, $radius_x * 2, $radius_y * 2, 0, 90, $color_border); // bottom-right - ImageArc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x, $output_height - $radius_y, $radius_x * 2, $radius_y * 2, 90, 180, $color_border); // bottom-left - } - } - - } - $this->phpThumbObject->ImageResizeFunction($gd_border_canvas, $gdimg, floor(($output_width - $new_width) / 2), round(($output_height - $new_height) / 2), 0, 0, $new_width, $new_height, $output_width, $output_height); - - ImageDestroy($gdimg); - $gdimg = phpthumb_functions::ImageCreateFunction($output_width, $output_height); - ImageSaveAlpha($gdimg, true); - ImageAlphaBlending($gdimg, false); - $gdimg_color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 255, 255, 255, 127); - ImageFilledRectangle($gdimg, 0, 0, $output_width, $output_height, $gdimg_color_background); - - ImageCopy($gdimg, $gd_border_canvas, 0, 0, 0, 0, $output_width, $output_height); - //$gdimg = $gd_border_canvas; - ImageDestroy($gd_border_canvas); - return true; - - - } else { - $this->DebugMessage('FAILED: $gd_border_canvas = phpthumb_functions::ImageCreateFunction('.$output_width.', '.$output_height.')', __FILE__, __LINE__); - } - return false; - } - - - function MeanRemoval(&$gdimg) { - if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { - if (ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)) { - return true; - } - $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)', __FILE__, __LINE__); - // fall through and try it the hard way - } - // currently not implemented "the hard way" - $this->DebugMessage('FAILED: phpthumb_filters::MeanRemoval($gdimg) [function not implemented]', __FILE__, __LINE__); - return false; - } - - - function Negative(&$gdimg) { - if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { - if (ImageFilter($gdimg, IMG_FILTER_NEGATE)) { - return true; - } - $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_NEGATE)', __FILE__, __LINE__); - // fall through and try it the hard way - } - $ImageSX = ImageSX($gdimg); - $ImageSY = ImageSY($gdimg); - for ($x = 0; $x < $ImageSX; $x++) { - for ($y = 0; $y < $ImageSY; $y++) { - $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); - $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, (~$currentPixel['red'] & 0xFF), (~$currentPixel['green'] & 0xFF), (~$currentPixel['blue'] & 0xFF), $currentPixel['alpha']); - ImageSetPixel($gdimg, $x, $y, $newColor); - } - } - return true; - } - - - function RoundedImageCorners(&$gdimg, $radius_x, $radius_y) { - // generate mask at twice desired resolution and downsample afterwards for easy antialiasing - // mask is generated as a white double-size elipse on a triple-size black background and copy-paste-resampled - // onto a correct-size mask image as 4 corners due to errors when the entire mask is resampled at once (gray edges) - if ($gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction($radius_x * 6, $radius_y * 6)) { - if ($gdimg_cornermask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { - - $color_transparent = ImageColorAllocate($gdimg_cornermask_triple, 255, 255, 255); - ImageFilledEllipse($gdimg_cornermask_triple, $radius_x * 3, $radius_y * 3, $radius_x * 4, $radius_y * 4, $color_transparent); - - ImageFilledRectangle($gdimg_cornermask, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $color_transparent); - - ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, 0, 0, $radius_x, $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); - ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, 0, ImageSY($gdimg) - $radius_y, $radius_x, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); - ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, ImageSX($gdimg) - $radius_x, ImageSY($gdimg) - $radius_y, $radius_x * 3, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); - ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, ImageSX($gdimg) - $radius_x, 0, $radius_x * 3, $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); - - phpthumb_filters::ApplyMask($gdimg_cornermask, $gdimg); - ImageDestroy($gdimg_cornermask); - $this->DebugMessage('RoundedImageCorners('.$radius_x.', '.$radius_y.') succeeded', __FILE__, __LINE__); - return true; - - } else { - $this->DebugMessage('FAILED: $gdimg_cornermask = phpthumb_functions::ImageCreateFunction('.ImageSX($gdimg).', '.ImageSY($gdimg).')', __FILE__, __LINE__); - } - ImageDestroy($gdimg_cornermask_triple); - - } else { - $this->DebugMessage('FAILED: $gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction('.($radius_x * 6).', '.($radius_y * 6).')', __FILE__, __LINE__); - } - return false; - } - - - function Saturation(&$gdimg, $amount, $color='') { - if ($amount == 0) { - return true; - } elseif ($amount > 0) { - $amount = 0 - $amount; - } else { - $amount = abs($amount); - } - return phpthumb_filters::Desaturate($gdimg, $amount, $color); - } - - - function Sepia(&$gdimg, $amount, $targetColor) { - $amount = (is_numeric($amount) ? max(0, min(100, $amount)) : 50); - $targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'A28065'); - - if ($amount == 0) { - return true; - } - - $TargetPixel['red'] = hexdec(substr($targetColor, 0, 2)); - $TargetPixel['green'] = hexdec(substr($targetColor, 2, 2)); - $TargetPixel['blue'] = hexdec(substr($targetColor, 4, 2)); - - $ImageSX = ImageSX($gdimg); - $ImageSY = ImageSY($gdimg); - for ($x = 0; $x < $ImageSX; $x++) { - for ($y = 0; $y < $ImageSY; $y++) { - $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); - $GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); - - // http://www.gimpguru.org/Tutorials/SepiaToning/ - // "In the traditional sepia toning process, the tinting occurs most in - // the mid-tones: the lighter and darker areas appear to be closer to B&W." - $SepiaAmount = ((128 - abs($GrayPixel['red'] - 128)) / 128) * ($amount / 100); - - foreach ($TargetPixel as $key => $value) { - $NewPixel[$key] = round(max(0, min(255, $GrayPixel[$key] * (1 - $SepiaAmount) + ($TargetPixel[$key] * $SepiaAmount)))); - } - $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']); - ImageSetPixel($gdimg, $x, $y, $newColor); - } - } - return true; - } - - - function Smooth(&$gdimg, $amount=6) { - $amount = min(25, max(0, $amount)); - if ($amount == 0) { - return true; - } - if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { - if (ImageFilter($gdimg, IMG_FILTER_SMOOTH, $amount)) { - return true; - } - $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SMOOTH, '.$amount.')', __FILE__, __LINE__); - // fall through and try it the hard way - } - // currently not implemented "the hard way" - $this->DebugMessage('FAILED: phpthumb_filters::Smooth($gdimg, '.$amount.') [function not implemented]', __FILE__, __LINE__); - return false; - } - - - function Threshold(&$gdimg, $cutoff) { - $cutoff = min(255, max(0, ($cutoff ? $cutoff : 128))); - for ($x = 0; $x < ImageSX($gdimg); $x++) { - for ($y = 0; $y < ImageSY($gdimg); $y++) { - $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); - $grayPixel = phpthumb_functions::GrayscalePixel($currentPixel); - if ($grayPixel['red'] < $cutoff) { - $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0x00, 0x00, 0x00, $currentPixel['alpha']); - } else { - $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0xFF, 0xFF, 0xFF, $currentPixel['alpha']); - } - ImageSetPixel($gdimg, $x, $y, $newColor); - } - } - return true; - } - - - function ImageTrueColorToPalette2(&$image, $dither, $ncolors) { - // http://www.php.net/manual/en/function.imagetruecolortopalette.php - // zmorris at zsculpt dot com (17-Aug-2004 06:58) - $width = ImageSX($image); - $height = ImageSY($image); - $image_copy = ImageCreateTrueColor($width, $height); - //ImageCopyMerge($image_copy, $image, 0, 0, 0, 0, $width, $height, 100); - ImageCopy($image_copy, $image, 0, 0, 0, 0, $width, $height); - ImageTrueColorToPalette($image, $dither, $ncolors); - ImageColorMatch($image_copy, $image); - ImageDestroy($image_copy); - return true; - } - - function ReduceColorDepth(&$gdimg, $colors=256, $dither=true) { - $colors = max(min($colors, 256), 2); - // ImageTrueColorToPalette usually makes ugly colors, the replacement is a bit better - //ImageTrueColorToPalette($gdimg, $dither, $colors); - phpthumb_filters::ImageTrueColorToPalette2($gdimg, $dither, $colors); - return true; - } - - - function WhiteBalance(&$gdimg, $targetColor='') { - if (phpthumb_functions::IsHexColor($targetColor)) { - $targetPixel = array( - 'red' => hexdec(substr($targetColor, 0, 2)), - 'green' => hexdec(substr($targetColor, 2, 2)), - 'blue' => hexdec(substr($targetColor, 4, 2)) - ); - } else { - $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, false); - $targetPixel = array( - 'red' => max(array_keys($Analysis['red'])), - 'green' => max(array_keys($Analysis['green'])), - 'blue' => max(array_keys($Analysis['blue'])) - ); - } - $grayValue = phpthumb_functions::GrayscaleValue($targetPixel['red'], $targetPixel['green'], $targetPixel['blue']); - $scaleR = $grayValue / $targetPixel['red']; - $scaleG = $grayValue / $targetPixel['green']; - $scaleB = $grayValue / $targetPixel['blue']; - - for ($x = 0; $x < ImageSX($gdimg); $x++) { - for ($y = 0; $y < ImageSY($gdimg); $y++) { - $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); - $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe( - $gdimg, - max(0, min(255, round($currentPixel['red'] * $scaleR))), - max(0, min(255, round($currentPixel['green'] * $scaleG))), - max(0, min(255, round($currentPixel['blue'] * $scaleB))), - $currentPixel['alpha'] - ); - ImageSetPixel($gdimg, $x, $y, $newColor); - } - } - return true; - } - - - function WatermarkText(&$gdimg, $text, $size, $alignment, $hex_color='000000', $ttffont='', $opacity=100, $margin=5, $angle=0, $bg_color=false, $bg_opacity=0, $fillextend='') { - // text watermark requested - if (!$text) { - return false; - } - ImageAlphaBlending($gdimg, true); - - $metaTextArray = array( - '^Fb' => $this->phpThumbObject->getimagesizeinfo['filesize'], - '^Fk' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1024), - '^Fm' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1048576), - '^X' => $this->phpThumbObject->getimagesizeinfo[0], - '^Y' => $this->phpThumbObject->getimagesizeinfo[1], - '^x' => ImageSX($gdimg), - '^y' => ImageSY($gdimg), - '^^' => '^', - ); - $text = strtr($text, $metaTextArray); - - $text = str_replace("\r\n", "\n", $text); - $text = str_replace("\r", "\n", $text); - $textlines = explode("\n", $text); - - if (@is_readable($ttffont) && is_file($ttffont)) { - - $opacity = 100 - intval(max(min($opacity, 100), 0)); - - $this->DebugMessage('Using TTF font "'.$ttffont.'"', __FILE__, __LINE__); - - $TTFbox = ImageTTFbBox($size, $angle, $ttffont, $text); - - $min_x = min($TTFbox[0], $TTFbox[2], $TTFbox[4], $TTFbox[6]); - $max_x = max($TTFbox[0], $TTFbox[2], $TTFbox[4], $TTFbox[6]); - //$text_width = round($max_x - $min_x + ($size * 0.5)); - $text_width = round($max_x - $min_x); - - $min_y = min($TTFbox[1], $TTFbox[3], $TTFbox[5], $TTFbox[7]); - $max_y = max($TTFbox[1], $TTFbox[3], $TTFbox[5], $TTFbox[7]); - //$text_height = round($max_y - $min_y + ($size * 0.5)); - $text_height = round($max_y - $min_y); - - $TTFboxChar = ImageTTFbBox($size, $angle, $ttffont, 'jH'); - $char_min_y = min($TTFboxChar[1], $TTFboxChar[3], $TTFboxChar[5], $TTFboxChar[7]); - $char_max_y = max($TTFboxChar[1], $TTFboxChar[3], $TTFboxChar[5], $TTFboxChar[7]); - $char_height = round($char_max_y - $char_min_y); - - switch ($alignment) { - case 'T': - $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); - $text_origin_y = $char_height + $margin; - break; - - case 'B': - $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); - $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; - break; - - case 'L': - $text_origin_x = $margin; - $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; - break; - - case 'R': - $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; - $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; - break; - - case 'C': - $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); - $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; - break; - - case 'TL': - $text_origin_x = $margin; - $text_origin_y = $char_height + $margin; - break; - - case 'TR': - $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; - $text_origin_y = $char_height + $margin; - break; - - case 'BL': - $text_origin_x = $margin; - $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; - break; - - case 'BR': - default: - $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; - $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; - break; - } - $letter_color_text = phpthumb_functions::ImageHexColorAllocate($gdimg, $hex_color, false, $opacity * 1.27); - - if ($alignment == '*') { - - $text_origin_y = $char_height + $margin; - while (($text_origin_y - $text_height) < ImageSY($gdimg)) { - $text_origin_x = $margin; - while ($text_origin_x < ImageSX($gdimg)) { - ImageTTFtext($gdimg, $size, $angle, $text_origin_x, $text_origin_y, $letter_color_text, $ttffont, $text); - $text_origin_x += ($text_width + $margin); - } - $text_origin_y += ($text_height + $margin); - } - - } else { - - //ImageRectangle($gdimg, $text_origin_x + $min_x, $text_origin_y + $TTFbox[1], $text_origin_x + $min_x + $text_width, $text_origin_y + $TTFbox[1] - $text_height, $letter_color_text); - if (phpthumb_functions::IsHexColor($bg_color)) { - $text_background_alpha = round(127 * ((100 - min(max(0, $bg_opacity), 100)) / 100)); - $text_color_background = phpthumb_functions::ImageHexColorAllocate($gdimg, $bg_color, false, $text_background_alpha); - } else { - $text_color_background = phpthumb_functions::ImageHexColorAllocate($gdimg, 'FFFFFF', false, 127); - } - $x1 = $text_origin_x + $min_x; - $y1 = $text_origin_y + $TTFbox[1]; - $x2 = $text_origin_x + $min_x + $text_width; - $y2 = $text_origin_y + $TTFbox[1] - $text_height; - $x_TL = eregi('x', $fillextend) ? 0 : min($x1, $x2); - $y_TL = eregi('y', $fillextend) ? 0 : min($y1, $y2); - $x_BR = eregi('x', $fillextend) ? ImageSX($gdimg) : max($x1, $x2); - $y_BR = eregi('y', $fillextend) ? ImageSY($gdimg) : max($y1, $y2); - //while ($y_BR > ImageSY($gdimg)) { - // $y_TL--; - // $y_BR--; - // $text_origin_y--; - //} - ImageFilledRectangle($gdimg, $x_TL, $y_TL, $x_BR, $y_BR, $text_color_background); - ImageTTFtext($gdimg, $size, $angle, $text_origin_x, $text_origin_y, $letter_color_text, $ttffont, $text); - - } - return true; - - } else { - - $size = min(5, max(1, $size)); - $this->DebugMessage('Using built-in font (size='.$size.') for text watermark'.($ttffont ? ' because $ttffont !is_readable('.$ttffont.')' : ''), __FILE__, __LINE__); - - $text_width = 0; - $text_height = 0; - foreach ($textlines as $dummy => $line) { - $text_width = max($text_width, ImageFontWidth($size) * strlen($line)); - $text_height += ImageFontHeight($size); - } - if ($img_watermark = phpthumb_functions::ImageCreateFunction($text_width, $text_height)) { - ImageAlphaBlending($img_watermark, false); - if (phpthumb_functions::IsHexColor($bg_color)) { - $text_background_alpha = round(127 * ((100 - min(max(0, $bg_opacity), 100)) / 100)); - $text_color_background = phpthumb_functions::ImageHexColorAllocate($img_watermark, $bg_color, false, $text_background_alpha); - } else { - $text_color_background = phpthumb_functions::ImageHexColorAllocate($img_watermark, 'FFFFFF', false, 127); - } - ImageFilledRectangle($img_watermark, 0, 0, ImageSX($img_watermark), ImageSY($img_watermark), $text_color_background); - - if ($angle && function_exists('ImageRotate')) { - // using $img_watermark_mask is pointless if ImageRotate function isn't available - if ($img_watermark_mask = phpthumb_functions::ImageCreateFunction($text_width, $text_height)) { - $mask_color_background = ImageColorAllocate($img_watermark_mask, 0, 0, 0); - ImageAlphaBlending($img_watermark_mask, false); - ImageFilledRectangle($img_watermark_mask, 0, 0, ImageSX($img_watermark_mask), ImageSY($img_watermark_mask), $mask_color_background); - $mask_color_watermark = ImageColorAllocate($img_watermark_mask, 255, 255, 255); - } - } - - $text_color_watermark = phpthumb_functions::ImageHexColorAllocate($img_watermark, $hex_color); - foreach ($textlines as $key => $line) { - switch ($alignment) { - case 'C': - case 'T': - case 'B': - $x_offset = round(($text_width - (ImageFontWidth($size) * strlen($line))) / 2); - break; - - case 'L': - case 'TL': - case 'BL': - $x_offset = 0; - break; - - case 'R': - case 'TR': - case 'BR': - default: - $x_offset = $text_width - (ImageFontWidth($size) * strlen($line)); - break; - } - ImageString($img_watermark, $size, $x_offset, $key * ImageFontHeight($size), $line, $text_color_watermark); - if ($angle && $img_watermark_mask) { - ImageString($img_watermark_mask, $size, $x_offset, $key * ImageFontHeight($size), $text, $mask_color_watermark); - } - } - if ($angle && $img_watermark_mask) { - $img_watermark = ImageRotate($img_watermark, $angle, $text_color_background); - $img_watermark_mask = ImageRotate($img_watermark_mask, $angle, $mask_color_background); - phpthumb_filters::ApplyMask($img_watermark_mask, $img_watermark); - } - phpthumb_filters::WatermarkOverlay($gdimg, $img_watermark, $alignment, $opacity, $margin); - ImageDestroy($img_watermark); - return true; - } - - } - return false; - } - - - function WatermarkOverlay(&$gdimg_dest, &$img_watermark, $alignment='*', $opacity=50, $margin=5) { - if (is_resource($gdimg_dest) && is_resource($img_watermark)) { - $watermark_source_x = 0; - $watermark_source_y = 0; - $img_source_width = ImageSX($gdimg_dest); - $img_source_height = ImageSY($gdimg_dest); - $watermark_source_width = ImageSX($img_watermark); - $watermark_source_height = ImageSY($img_watermark); - $watermark_opacity_percent = max(0, min(100, $opacity)); - if ($margin < 1) { - $watermark_margin_percent = 1 - $margin; - } else { - $watermark_margin_percent = (100 - max(0, min(100, $margin))) / 100; - } - $watermark_margin_x = round((1 - $watermark_margin_percent) * $img_source_width); - $watermark_margin_y = round((1 - $watermark_margin_percent) * $img_source_height); - switch ($alignment) { - case '*': - if ($gdimg_tiledwatermark = phpthumb_functions::ImageCreateFunction($img_source_width, $img_source_height)) { - - ImageAlphaBlending($gdimg_tiledwatermark, false); - ImageSaveAlpha($gdimg_tiledwatermark, true); - $text_color_transparent = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_tiledwatermark, 255, 0, 255, 127); - ImageFill($gdimg_tiledwatermark, 0, 0, $text_color_transparent); - - // set the tiled image transparent color to whatever the untiled image transparency index is -// ImageColorTransparent($gdimg_tiledwatermark, ImageColorTransparent($img_watermark)); - - // a "cleaner" way of doing it, but can't handle the margin feature :( -// ImageSetTile($gdimg_tiledwatermark, $img_watermark); -// ImageFill($gdimg_tiledwatermark, 0, 0, IMG_COLOR_TILED); -// break; - -// ImageFill($gdimg_tiledwatermark, 0, 0, ImageColorTransparent($gdimg_tiledwatermark)); - // tile the image as many times as can fit - for ($x = $watermark_margin_x; $x < ($img_source_width + $watermark_source_width); $x += round($watermark_source_width + ((1 - $watermark_margin_percent) * $img_source_width))) { - for ($y = $watermark_margin_y; $y < ($img_source_height + $watermark_source_height); $y += round($watermark_source_height + ((1 - $watermark_margin_percent) * $img_source_height))) { - ImageCopy( - $gdimg_tiledwatermark, - $img_watermark, - $x, - $y, - 0, - 0, - min($watermark_source_width, $img_source_width - $x - ((1 - $watermark_margin_percent) * $img_source_width)), - min($watermark_source_height, $img_source_height - $y - ((1 - $watermark_margin_percent) * $img_source_height)) - ); - } - } - - $watermark_source_width = ImageSX($gdimg_tiledwatermark); - $watermark_source_height = ImageSY($gdimg_tiledwatermark); - $watermark_destination_x = 0; - $watermark_destination_y = 0; - - ImageDestroy($img_watermark); - $img_watermark = $gdimg_tiledwatermark; - } - break; - - case 'T': - $watermark_destination_x = round((($img_source_width / 2) - ($watermark_source_width / 2)) + $watermark_margin_x); - $watermark_destination_y = $watermark_margin_y; - break; - - case 'B': - $watermark_destination_x = round((($img_source_width / 2) - ($watermark_source_width / 2)) + $watermark_margin_x); - $watermark_destination_y = round(($img_source_height - $watermark_source_height) * $watermark_margin_percent); - break; - - case 'L': - $watermark_destination_x = $watermark_margin_x; - $watermark_destination_y = round((($img_source_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_y); - break; - - case 'R': - $watermark_destination_x = round(($img_source_width - $watermark_source_width) * $watermark_margin_percent); - $watermark_destination_y = round((($img_source_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_y); - break; - - case 'C': - $watermark_destination_x = round(($img_source_width / 2) - ($watermark_source_width / 2)); - $watermark_destination_y = round(($img_source_height / 2) - ($watermark_source_height / 2)); - break; - - case 'TL': - $watermark_destination_x = $watermark_margin_x; - $watermark_destination_y = $watermark_margin_y; - break; - - case 'TR': - $watermark_destination_x = round(($img_source_width - $watermark_source_width) * $watermark_margin_percent); - $watermark_destination_y = $watermark_margin_y; - break; - - case 'BL': - $watermark_destination_x = $watermark_margin_x; - $watermark_destination_y = round(($img_source_height - $watermark_source_height) * $watermark_margin_percent); - break; - - case 'BR': - default: - $watermark_destination_x = round(($img_source_width - $watermark_source_width) * $watermark_margin_percent); - $watermark_destination_y = round(($img_source_height - $watermark_source_height) * $watermark_margin_percent); - break; - } - ImageAlphaBlending($gdimg_dest, false); - ImageSaveAlpha($gdimg_dest, true); - ImageSaveAlpha($img_watermark, true); - phpthumb_functions::ImageCopyRespectAlpha($gdimg_dest, $img_watermark, $watermark_destination_x, $watermark_destination_y, 0, 0, $watermark_source_width, $watermark_source_height, $watermark_opacity_percent); - - return true; - } - return false; - } - - - function DebugMessage($message, $file='', $line='') { - if (is_object($this->phpThumbObject)) { - return $this->phpThumbObject->DebugMessage($message, $file, $line); - } - return false; - } -} - -?> \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.functions.php b/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.functions.php deleted file mode 100644 index d4e8252d7..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.functions.php +++ /dev/null @@ -1,757 +0,0 @@ - // -// available at http://phpthumb.sourceforge.net /// -////////////////////////////////////////////////////////////// -/// // -// phpthumb.functions.php - general support functions // -// /// -////////////////////////////////////////////////////////////// - -class phpthumb_functions { - - function user_function_exists($functionname) { - if (function_exists('get_defined_functions')) { - static $get_defined_functions = array(); - if (empty($get_defined_functions)) { - $get_defined_functions = get_defined_functions(); - } - return in_array(strtolower($functionname), $get_defined_functions['user']); - } - return function_exists($functionname); - } - - - function builtin_function_exists($functionname) { - if (function_exists('get_defined_functions')) { - static $get_defined_functions = array(); - if (empty($get_defined_functions)) { - $get_defined_functions = get_defined_functions(); - } - return in_array(strtolower($functionname), $get_defined_functions['internal']); - } - return function_exists($functionname); - } - - - function version_compare_replacement_sub($version1, $version2, $operator='') { - // If you specify the third optional operator argument, you can test for a particular relationship. - // The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively. - // Using this argument, the function will return 1 if the relationship is the one specified by the operator, 0 otherwise. - - // If a part contains special version strings these are handled in the following order: dev < (alpha = a) < (beta = b) < RC < pl - static $versiontype_lookup = array(); - if (empty($versiontype_lookup)) { - $versiontype_lookup['dev'] = 10001; - $versiontype_lookup['a'] = 10002; - $versiontype_lookup['alpha'] = 10002; - $versiontype_lookup['b'] = 10003; - $versiontype_lookup['beta'] = 10003; - $versiontype_lookup['RC'] = 10004; - $versiontype_lookup['pl'] = 10005; - } - if (isset($versiontype_lookup[$version1])) { - $version1 = $versiontype_lookup[$version1]; - } - if (isset($versiontype_lookup[$version2])) { - $version2 = $versiontype_lookup[$version2]; - } - - switch ($operator) { - case '<': - case 'lt': - return intval($version1 < $version2); - break; - case '<=': - case 'le': - return intval($version1 <= $version2); - break; - case '>': - case 'gt': - return intval($version1 > $version2); - break; - case '>=': - case 'ge': - return intval($version1 >= $version2); - break; - case '==': - case '=': - case 'eq': - return intval($version1 == $version2); - break; - case '!=': - case '<>': - case 'ne': - return intval($version1 != $version2); - break; - } - if ($version1 == $version2) { - return 0; - } elseif ($version1 < $version2) { - return -1; - } - return 1; - } - - - function version_compare_replacement($version1, $version2, $operator='') { - if (function_exists('version_compare')) { - // built into PHP v4.1.0+ - return version_compare($version1, $version2, $operator); - } - - // The function first replaces _, - and + with a dot . in the version strings - $version1 = strtr($version1, '_-+', '...'); - $version2 = strtr($version2, '_-+', '...'); - - // and also inserts dots . before and after any non number so that for example '4.3.2RC1' becomes '4.3.2.RC.1'. - // Then it splits the results like if you were using explode('.',$ver). Then it compares the parts starting from left to right. - $version1 = eregi_replace('([0-9]+)([A-Z]+)([0-9]+)', '\\1.\\2.\\3', $version1); - $version2 = eregi_replace('([0-9]+)([A-Z]+)([0-9]+)', '\\1.\\2.\\3', $version2); - - $parts1 = explode('.', $version1); - $parts2 = explode('.', $version1); - $parts_count = max(count($parts1), count($parts2)); - for ($i = 0; $i < $parts_count; $i++) { - $comparison = phpthumb_functions::version_compare_replacement_sub($version1, $version2, $operator); - if ($comparison != 0) { - return $comparison; - } - } - return 0; - } - - - function phpinfo_array() { - static $phpinfo_array = array(); - if (empty($phpinfo_array)) { - ob_start(); - phpinfo(); - $phpinfo = ob_get_contents(); - ob_end_clean(); - $phpinfo_array = explode("\n", $phpinfo); - } - return $phpinfo_array; - } - - - function exif_info() { - static $exif_info = array(); - if (empty($exif_info)) { - // based on code by johnschaefer at gmx dot de - // from PHP help on gd_info() - $exif_info = array( - 'EXIF Support' => '', - 'EXIF Version' => '', - 'Supported EXIF Version' => '', - 'Supported filetypes' => '' - ); - $phpinfo_array = phpthumb_functions::phpinfo_array(); - foreach ($phpinfo_array as $dummy => $line) { - $line = trim(strip_tags($line)); - foreach ($exif_info as $key => $value) { - if (strpos($line, $key) === 0) { - $newvalue = trim(str_replace($key, '', $line)); - $exif_info[$key] = $newvalue; - } - } - } - } - return $exif_info; - } - - - function ImageTypeToMIMEtype($imagetype) { - if (function_exists('image_type_to_mime_type') && ($imagetype >= 1) && ($imagetype <= 16)) { - // PHP v4.3.0+ - return image_type_to_mime_type($imagetype); - } - static $image_type_to_mime_type = array( - 1 => 'image/gif', // IMAGETYPE_GIF - 2 => 'image/jpeg', // IMAGETYPE_JPEG - 3 => 'image/png', // IMAGETYPE_PNG - 4 => 'application/x-shockwave-flash', // IMAGETYPE_SWF - 5 => 'image/psd', // IMAGETYPE_PSD - 6 => 'image/bmp', // IMAGETYPE_BMP - 7 => 'image/tiff', // IMAGETYPE_TIFF_II (intel byte order) - 8 => 'image/tiff', // IMAGETYPE_TIFF_MM (motorola byte order) - 9 => 'application/octet-stream', // IMAGETYPE_JPC - 10 => 'image/jp2', // IMAGETYPE_JP2 - 11 => 'application/octet-stream', // IMAGETYPE_JPX - 12 => 'application/octet-stream', // IMAGETYPE_JB2 - 13 => 'application/x-shockwave-flash', // IMAGETYPE_SWC - 14 => 'image/iff', // IMAGETYPE_IFF - 15 => 'image/vnd.wap.wbmp', // IMAGETYPE_WBMP - 16 => 'image/xbm', // IMAGETYPE_XBM - - 'gif' => 'image/gif', // IMAGETYPE_GIF - 'jpg' => 'image/jpeg', // IMAGETYPE_JPEG - 'jpeg' => 'image/jpeg', // IMAGETYPE_JPEG - 'png' => 'image/png', // IMAGETYPE_PNG - 'bmp' => 'image/bmp', // IMAGETYPE_BMP - 'ico' => 'image/x-icon', - ); - - return (isset($image_type_to_mime_type[$imagetype]) ? $image_type_to_mime_type[$imagetype] : false); - } - - - function HexCharDisplay($string) { - $len = strlen($string); - $output = ''; - for ($i = 0; $i < $len; $i++) { - $output .= ' 0x'.str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT); - } - return $output; - } - - - function IsHexColor($HexColorString) { - return eregi('^[0-9A-F]{6}$', $HexColorString); - } - - - function ImageColorAllocateAlphaSafe(&$gdimg_hexcolorallocate, $R, $G, $B, $alpha=false) { - if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=') && ($alpha !== false)) { - return ImageColorAllocateAlpha($gdimg_hexcolorallocate, $R, $G, $B, intval($alpha)); - } else { - return ImageColorAllocate($gdimg_hexcolorallocate, $R, $G, $B); - } - } - - function ImageHexColorAllocate(&$gdimg_hexcolorallocate, $HexColorString, $dieOnInvalid=false, $alpha=false) { - if (!is_resource($gdimg_hexcolorallocate)) { - die('$gdimg_hexcolorallocate is not a GD resource in ImageHexColorAllocate()'); - } - if (phpthumb_functions::IsHexColor($HexColorString)) { - $R = hexdec(substr($HexColorString, 0, 2)); - $G = hexdec(substr($HexColorString, 2, 2)); - $B = hexdec(substr($HexColorString, 4, 2)); - return phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_hexcolorallocate, $R, $G, $B, $alpha); - } - if ($dieOnInvalid) { - die('Invalid hex color string: "'.$HexColorString.'"'); - } - return ImageColorAllocate($gdimg_hexcolorallocate, 0x00, 0x00, 0x00); - } - - - function HexColorXOR($hexcolor) { - return strtoupper(str_pad(dechex(~hexdec($hexcolor) & 0xFFFFFF), 6, '0', STR_PAD_LEFT)); - } - - - function GetPixelColor(&$img, $x, $y) { - if (!is_resource($img)) { - return false; - } - return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y)); - } - - - function GrayscaleValue($r, $g, $b) { - return round(($r * 0.30) + ($g * 0.59) + ($b * 0.11)); - } - - - function GrayscalePixel($OriginalPixel) { - $gray = phpthumb_functions::GrayscaleValue($OriginalPixel['red'], $OriginalPixel['green'], $OriginalPixel['blue']); - return array('red'=>$gray, 'green'=>$gray, 'blue'=>$gray); - } - - - function GrayscalePixelRGB($rgb) { - $r = ($rgb >> 16) & 0xFF; - $g = ($rgb >> 8) & 0xFF; - $b = $rgb & 0xFF; - return ($r * 0.299) + ($g * 0.587) + ($b * 0.114); - } - - - function ImageCopyResampleBicubic($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) { - // ron at korving dot demon dot nl - // http://www.php.net/imagecopyresampled - - $scaleX = ($src_w - 1) / $dst_w; - $scaleY = ($src_h - 1) / $dst_h; - - $scaleX2 = $scaleX / 2.0; - $scaleY2 = $scaleY / 2.0; - - $isTrueColor = ImageIsTrueColor($src_img); - - for ($y = $src_y; $y < $src_y + $dst_h; $y++) { - $sY = $y * $scaleY; - $siY = (int) $sY; - $siY2 = (int) $sY + $scaleY2; - - for ($x = $src_x; $x < $src_x + $dst_w; $x++) { - $sX = $x * $scaleX; - $siX = (int) $sX; - $siX2 = (int) $sX + $scaleX2; - - if ($isTrueColor) { - - $c1 = ImageColorAt($src_img, $siX, $siY2); - $c2 = ImageColorAt($src_img, $siX, $siY); - $c3 = ImageColorAt($src_img, $siX2, $siY2); - $c4 = ImageColorAt($src_img, $siX2, $siY); - - $r = (( $c1 + $c2 + $c3 + $c4 ) >> 2) & 0xFF0000; - $g = ((($c1 & 0x00FF00) + ($c2 & 0x00FF00) + ($c3 & 0x00FF00) + ($c4 & 0x00FF00)) >> 2) & 0x00FF00; - $b = ((($c1 & 0x0000FF) + ($c2 & 0x0000FF) + ($c3 & 0x0000FF) + ($c4 & 0x0000FF)) >> 2); - - } else { - - $c1 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX, $siY2)); - $c2 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX, $siY)); - $c3 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX2, $siY2)); - $c4 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX2, $siY)); - - $r = ($c1['red'] + $c2['red'] + $c3['red'] + $c4['red'] ) << 14; - $g = ($c1['green'] + $c2['green'] + $c3['green'] + $c4['green']) << 6; - $b = ($c1['blue'] + $c2['blue'] + $c3['blue'] + $c4['blue'] ) >> 2; - - } - ImageSetPixel($dst_img, $dst_x + $x - $src_x, $dst_y + $y - $src_y, $r+$g+$b); - } - } - return true; - } - - - function ImageCreateFunction($x_size, $y_size) { - $ImageCreateFunction = 'ImageCreate'; - if (phpthumb_functions::gd_version() >= 2.0) { - $ImageCreateFunction = 'ImageCreateTrueColor'; - } - if (!function_exists($ImageCreateFunction)) { - return phpthumb::ErrorImage($ImageCreateFunction.'() does not exist - no GD support?'); - } - if (($x_size <= 0) || ($y_size <= 0)) { - return phpthumb::ErrorImage('Invalid image dimensions: '.$ImageCreateFunction.'('.$x_size.', '.$y_size.')'); - } - return $ImageCreateFunction($x_size, $y_size); - } - - - function ImageCopyRespectAlpha(&$dst_im, &$src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct=100) { - for ($x = $src_x; $x < $src_w; $x++) { - for ($y = $src_y; $y < $src_h; $y++) { - $RealPixel = phpthumb_functions::GetPixelColor($dst_im, $dst_x + $x, $dst_y + $y); - $OverlayPixel = phpthumb_functions::GetPixelColor($src_im, $x, $y); - $alphapct = $OverlayPixel['alpha'] / 127; - $opacipct = $pct / 100; - $overlaypct = (1 - $alphapct) * $opacipct; - - $newcolor = phpthumb_functions::ImageColorAllocateAlphaSafe( - $dst_im, - round($RealPixel['red'] * (1 - $overlaypct)) + ($OverlayPixel['red'] * $overlaypct), - round($RealPixel['green'] * (1 - $overlaypct)) + ($OverlayPixel['green'] * $overlaypct), - round($RealPixel['blue'] * (1 - $overlaypct)) + ($OverlayPixel['blue'] * $overlaypct), - //$RealPixel['alpha']); - 0); - - ImageSetPixel($dst_im, $dst_x + $x, $dst_y + $y, $newcolor); - } - } - return true; - } - - - function ProportionalResize($old_width, $old_height, $new_width=false, $new_height=false) { - $old_aspect_ratio = $old_width / $old_height; - if (($new_width === false) && ($new_height === false)) { - return false; - } elseif ($new_width === false) { - $new_width = $new_height * $old_aspect_ratio; - } elseif ($new_height === false) { - $new_height = $new_width / $old_aspect_ratio; - } - $new_aspect_ratio = $new_width / $new_height; - if ($new_aspect_ratio == $old_aspect_ratio) { - // great, done - } elseif ($new_aspect_ratio < $old_aspect_ratio) { - // limited by width - $new_height = $new_width / $old_aspect_ratio; - } elseif ($new_aspect_ratio > $old_aspect_ratio) { - // limited by height - $new_width = $new_height * $old_aspect_ratio; - } - return array(round($new_width), round($new_height)); - } - - - function SafeExec($command) { - static $AllowedExecFunctions = array(); - if (empty($AllowedExecFunctions)) { - $AllowedExecFunctions = array('shell_exec'=>true, 'passthru'=>true, 'system'=>true, 'exec'=>true); - if (@ini_get('safe_mode')) { - $AllowedExecFunctions['shell_exec'] = false; - } - $disable_functions = explode(',', @ini_get('disable_functions')); - foreach ($AllowedExecFunctions as $key => $value) { - if (in_array($key, $disable_functions)) { - $AllowedExecFunctions[$key] = false; - } - } - } - foreach ($AllowedExecFunctions as $execfunction => $is_allowed) { - if (!$is_allowed) { - continue; - } - switch ($execfunction) { - case 'passthru': - ob_start(); - $execfunction($command); - $returnvalue = ob_get_contents(); - ob_end_clean(); - break; - - case 'shell_exec': - case 'system': - case 'exec': - default: - $returnvalue = @$execfunction($command); - break; - } - return $returnvalue; - } - return false; - } - - - function ApacheLookupURIarray($filename) { - // apache_lookup_uri() only works when PHP is installed as an Apache module. - if (php_sapi_name() == 'apache') { - $keys = array('status', 'the_request', 'status_line', 'method', 'content_type', 'handler', 'uri', 'filename', 'path_info', 'args', 'boundary', 'no_cache', 'no_local_copy', 'allowed', 'send_bodyct', 'bytes_sent', 'byterange', 'clength', 'unparsed_uri', 'mtime', 'request_time'); - if ($apacheLookupURIobject = @apache_lookup_uri($filename)) { - $apacheLookupURIarray = array(); - foreach ($keys as $dummy => $key) { - $apacheLookupURIarray[$key] = @$apacheLookupURIobject->$key; - } - return $apacheLookupURIarray; - } - } - return false; - } - - - function gd_is_bundled() { - static $isbundled = null; - if (is_null($isbundled)) { - $gd_info = gd_info(); - $isbundled = (strpos($gd_info['GD Version'], 'bundled') !== false); - } - return $isbundled; - } - - - function gd_version($fullstring=false) { - static $cache_gd_version = array(); - if (empty($cache_gd_version)) { - $gd_info = gd_info(); - if (eregi('bundled \((.+)\)$', $gd_info['GD Version'], $matches)) { - $cache_gd_version[1] = $gd_info['GD Version']; // e.g. "bundled (2.0.15 compatible)" - $cache_gd_version[0] = (float) $matches[1]; // e.g. "2.0" (not "bundled (2.0.15 compatible)") - } else { - $cache_gd_version[1] = $gd_info['GD Version']; // e.g. "1.6.2 or higher" - $cache_gd_version[0] = (float) substr($gd_info['GD Version'], 0, 3); // e.g. "1.6" (not "1.6.2 or higher") - } - } - return $cache_gd_version[intval($fullstring)]; - } - - - function filesize_remote($remotefile, $timeout=10) { - $size = false; - $url = parse_url($remotefile); - if ($fp = @fsockopen($url['host'], ($url['port'] ? $url['port'] : 80), $errno, $errstr, $timeout)) { - fwrite($fp, 'HEAD '.@$url['path'].@$url['query'].' HTTP/1.0'."\r\n".'Host: '.@$url['host']."\r\n\r\n"); - if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { - stream_set_timeout($fp, $timeout); - } - while (!feof($fp)) { - $headerline = fgets($fp, 4096); - if (eregi('^Content-Length: (.*)', $headerline, $matches)) { - $size = intval($matches[1]); - break; - } - } - fclose ($fp); - } - return $size; - } - - - function filedate_remote($remotefile, $timeout=10) { - $date = false; - $url = parse_url($remotefile); - if ($fp = @fsockopen($url['host'], ($url['port'] ? $url['port'] : 80), $errno, $errstr, $timeout)) { - fwrite($fp, 'HEAD '.@$url['path'].@$url['query'].' HTTP/1.0'."\r\n".'Host: '.@$url['host']."\r\n\r\n"); - if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { - stream_set_timeout($fp, $timeout); - } - while (!feof($fp)) { - $headerline = fgets($fp, 4096); - if (eregi('^Last-Modified: (.*)', $headerline, $matches)) { - $date = strtotime($matches[1]) - date('Z'); - break; - } - } - fclose ($fp); - } - return $date; - } - - - function md5_file_safe($filename) { - // md5_file() doesn't exist in PHP < 4.2.0 - if (function_exists('md5_file')) { - return md5_file($filename); - } - if ($fp = @fopen($filename, 'rb')) { - $rawData = ''; - do { - $buffer = fread($fp, 8192); - $rawData .= $buffer; - } while (strlen($buffer) > 0); - fclose($fp); - return md5($rawData); - } - return false; - } - - - function nonempty_min() { - $arg_list = func_get_args(); - $acceptable = array(); - foreach ($arg_list as $dummy => $arg) { - if ($arg) { - $acceptable[] = $arg; - } - } - return min($acceptable); - } - - - function LittleEndian2String($number, $minbytes=1) { - $intstring = ''; - while ($number > 0) { - $intstring = $intstring.chr($number & 255); - $number >>= 8; - } - return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT); - } - - function OneOfThese() { - // return the first useful (non-empty/non-zero/non-false) value from those passed - $arg_list = func_get_args(); - foreach ($arg_list as $key => $value) { - if ($value) { - return $value; - } - } - return false; - } - - function CaseInsensitiveInArray($needle, $haystack) { - $needle = strtolower($needle); - foreach ($haystack as $key => $value) { - if (is_array($value)) { - // skip? - } elseif ($needle == strtolower($value)) { - return true; - } - } - return false; - } - - function SafeURLread($url, &$error) { - if (function_exists('curl_version')) { - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_HEADER, false); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); - $rawData = curl_exec($ch); - curl_close($ch); - if (strlen($rawData) > 0) { - return $rawData; - } - $error .= 'CURL available but returned no data; '; - } else { - $error .= 'CURL unavailable; '; - } - if (@ini_get('allow_url_fopen')) { - $rawData = ''; - ob_start(); - if ($fp = fopen($url, 'rb')) { - do { - $buffer = fread($fp, 8192); - $rawData .= $buffer; - } while (strlen($buffer) > 0); - fclose($fp); - } else { - $error = trim(strip_tags(ob_get_contents())); - } - ob_end_clean(); - if (!$error) { - return $rawData; - } - $error .= '; "allow_url_fopen" enabled but returned no data; '; - } else { - $error .= '"allow_url_fopen" disabled; '; - } - return false; - } - -} - - -if (!function_exists('gd_info')) { - // built into PHP v4.3.0+ (with bundled GD2 library) - function gd_info() { - static $gd_info = array(); - if (empty($gd_info)) { - // based on code by johnschaefer at gmx dot de - // from PHP help on gd_info() - $gd_info = array( - 'GD Version' => '', - 'FreeType Support' => false, - 'FreeType Linkage' => '', - 'T1Lib Support' => false, - 'GIF Read Support' => false, - 'GIF Create Support' => false, - 'JPG Support' => false, - 'PNG Support' => false, - 'WBMP Support' => false, - 'XBM Support' => false - ); - $phpinfo_array = phpthumb_functions::phpinfo_array(); - foreach ($phpinfo_array as $dummy => $line) { - $line = trim(strip_tags($line)); - foreach ($gd_info as $key => $value) { - //if (strpos($line, $key) !== false) { - if (strpos($line, $key) === 0) { - $newvalue = trim(str_replace($key, '', $line)); - $gd_info[$key] = $newvalue; - } - } - } - if (empty($gd_info['GD Version'])) { - // probable cause: "phpinfo() disabled for security reasons" - if (function_exists('ImageTypes')) { - $imagetypes = ImageTypes(); - if ($imagetypes & IMG_PNG) { - $gd_info['PNG Support'] = true; - } - if ($imagetypes & IMG_GIF) { - $gd_info['GIF Create Support'] = true; - } - if ($imagetypes & IMG_JPG) { - $gd_info['JPG Support'] = true; - } - if ($imagetypes & IMG_WBMP) { - $gd_info['WBMP Support'] = true; - } - } - // to determine capability of GIF creation, try to use ImageCreateFromGIF on a 1px GIF - if (function_exists('ImageCreateFromGIF')) { - if ($tempfilename = phpthumb::phpThumb_tempnam()) { - if ($fp_tempfile = @fopen($tempfilename, 'wb')) { - fwrite($fp_tempfile, base64_decode('R0lGODlhAQABAIAAAH//AP///ywAAAAAAQABAAACAUQAOw==')); // very simple 1px GIF file base64-encoded as string - fclose($fp_tempfile); - - // if we can convert the GIF file to a GD image then GIF create support must be enabled, otherwise it's not - $gd_info['GIF Read Support'] = (bool) @ImageCreateFromGIF($tempfilename); - } - unlink($tempfilename); - } - } - if (function_exists('ImageCreateTrueColor') && @ImageCreateTrueColor(1, 1)) { - $gd_info['GD Version'] = '2.0.1 or higher (assumed)'; - } elseif (function_exists('ImageCreate') && @ImageCreate(1, 1)) { - $gd_info['GD Version'] = '1.6.0 or higher (assumed)'; - } - } - } - return $gd_info; - } -} - - -if (!function_exists('is_executable')) { - // in PHP v3+, but v5.0+ for Windows - function is_executable($filename) { - // poor substitute, but better than nothing - return file_exists($filename); - } -} - - -if (!function_exists('preg_quote')) { - // included in PHP v3.0.9+, but may be unavailable if not compiled in - function preg_quote($string, $delimiter='\\') { - static $preg_quote_array = array(); - if (empty($preg_quote_array)) { - $escapeables = '.\\+*?[^]$(){}=!<>|:'; - for ($i = 0; $i < strlen($escapeables); $i++) { - $strtr_preg_quote[$escapeables{$i}] = $delimiter.$escapeables{$i}; - } - } - return strtr($string, $strtr_preg_quote); - } -} - -if (!function_exists('file_get_contents')) { - // included in PHP v4.3.0+ - function file_get_contents($filename) { - if (eregi('^(f|ht)tp\://', $filename)) { - return SafeURLread($filename); - } - if ($fp = @fopen($filename, 'rb')) { - $rawData = ''; - do { - $buffer = fread($fp, 8192); - $rawData .= $buffer; - } while (strlen($buffer) > 0); - fclose($fp); - return $rawData; - } - return false; - } -} - - -if (!function_exists('file_put_contents')) { - // included in PHP v5.0.0+ - function file_put_contents($filename, $filedata) { - if ($fp = @fopen($filename, 'wb')) { - fwrite($fp, $filedata); - fclose($fp); - return true; - } - return false; - } -} - -if (!function_exists('imagealphablending')) { - // built-in function requires PHP v4.0.6+ *and* GD v2.0.1+ - function imagealphablending(&$img, $blendmode=true) { - // do nothing, this function is declared here just to - // prevent runtime errors if GD2 is not available - return true; - } -} - -if (!function_exists('imagesavealpha')) { - // built-in function requires PHP v4.3.2+ *and* GD v2.0.1+ - function imagesavealpha(&$img, $blendmode=true) { - // do nothing, this function is declared here just to - // prevent runtime errors if GD2 is not available - return true; - } -} - -?> \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.gif.php b/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.gif.php deleted file mode 100644 index e9285942c..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.gif.php +++ /dev/null @@ -1,1168 +0,0 @@ - = gif_loadFile(filename, [index]) -// = gif_getSize( or filename, &width, &height) -// = gif_outputAsPng(, filename, [bgColor]) -// = gif_outputAsBmp(, filename, [bgcolor]) -// = gif_outputAsJpeg(, filename, [bgcolor]) - use cjpeg if available otherwise uses GD -/////////////////////////////////////////////////////////////////////////////////////////////////// -// Original code by Fabien Ezber -// Modified by James Heinrich for use in phpThumb() - December 10, 2003 -// * Added function gif_loadFileToGDimageResource() - this returns a GD image resource -// * Modified gif_outputAsJpeg() to check if it's running under Windows, or if cjpeg is not -// available, in which case it will attempt to output JPEG using GD functions -// * added @ error-suppression to two lines where it checks: if ($this->m_img->m_bTrans) -// otherwise warnings are generated if error_reporting == E_ALL -/////////////////////////////////////////////////////////////////////////////////////////////////// - -function gif_loadFile($lpszFileName, $iIndex = 0) -{ - $gif = new CGIF(); - if ($gif->loadFile($lpszFileName, $iIndex)) { - return $gif; - } - return false; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// Added by James Heinrich - December 10, 2003 -function gif_loadFileToGDimageResource($gifFilename, $bgColor = -1) -{ - if ($gif = gif_loadFile($gifFilename)) { - - @set_time_limit(300); - // general strategy: convert raw data to PNG then convert PNG data to GD image resource - $PNGdata = $gif->getPng($bgColor); - if ($img = @ImageCreateFromString($PNGdata)) { - - // excellent - PNG image data successfully converted to GD image - return $img; - - } elseif ($img = $gif->getGD_PixelPlotterVersion()) { - - // problem: ImageCreateFromString() didn't like the PNG image data. - // This has been known to happen in PHP v4.0.6 - // solution: take the raw image data and create a new GD image and plot - // pixel-by-pixel on the GD image. This is extremely slow, but it does - // work and a slow solution is better than no solution, right? :) - return $img; - - } - } - return false; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -function gif_outputAsBmp($gif, $lpszFileName, $bgColor = -1) -{ - if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) { - return false; - } - - $fd = $gif->getBmp($bgColor); - if (strlen($fd) <= 0) { - return false; - } - - if (!($fh = @fopen($lpszFileName, 'wb'))) { - return false; - } - @fwrite($fh, $fd, strlen($fd)); - @fflush($fh); - @fclose($fh); - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -function gif_outputAsPng($gif, $lpszFileName, $bgColor = -1) -{ - if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) { - return false; - } - - $fd = $gif->getPng($bgColor); - if (strlen($fd) <= 0) { - return false; - } - - if (!($fh = @fopen($lpszFileName, 'wb'))) { - return false; - } - @fwrite($fh, $fd, strlen($fd)); - @fflush($fh); - @fclose($fh); - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -function gif_outputAsJpeg($gif, $lpszFileName, $bgColor = -1) -{ - // JPEG output that does not require cjpeg added by James Heinrich - December 10, 2003 - if ((strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') && (file_exists('/usr/local/bin/cjpeg') || `which cjpeg`)) { - - if (gif_outputAsBmp($gif, $lpszFileName.'.bmp', $bgColor)) { - exec('cjpeg '.$lpszFileName.'.bmp >'.$lpszFileName.' 2>/dev/null'); - @unLink($lpszFileName.'.bmp'); - - if (@file_exists($lpszFileName)) { - if (@fileSize($lpszFileName) > 0) { - return true; - } - - @unLink($lpszFileName); - } - } - - } else { - - // either Windows, or cjpeg not found in path - if ($img = @ImageCreateFromString($gif->getPng($bgColor))) { - if (@ImageJPEG($img, $lpszFileName)) { - return true; - } - } - - } - - return false; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -function gif_getSize($gif, &$width, &$height) -{ - if (isSet($gif) && (@get_class($gif) == 'cgif') && $gif->loaded()) { - $width = $gif->width(); - $height = $gif->height(); - } elseif (@file_exists($gif)) { - $myGIF = new CGIF(); - if (!$myGIF->getSize($gif, $width, $height)) { - return false; - } - } else { - return false; - } - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -class CGIFLZW -{ - var $MAX_LZW_BITS; - var $Fresh, $CodeSize, $SetCodeSize, $MaxCode, $MaxCodeSize, $FirstCode, $OldCode; - var $ClearCode, $EndCode, $Next, $Vals, $Stack, $sp, $Buf, $CurBit, $LastBit, $Done, $LastByte; - - /////////////////////////////////////////////////////////////////////////// - - // CONSTRUCTOR - function CGIFLZW() - { - $this->MAX_LZW_BITS = 12; - unSet($this->Next); - unSet($this->Vals); - unSet($this->Stack); - unSet($this->Buf); - - $this->Next = range(0, (1 << $this->MAX_LZW_BITS) - 1); - $this->Vals = range(0, (1 << $this->MAX_LZW_BITS) - 1); - $this->Stack = range(0, (1 << ($this->MAX_LZW_BITS + 1)) - 1); - $this->Buf = range(0, 279); - } - - /////////////////////////////////////////////////////////////////////////// - - function deCompress($data, &$datLen) - { - $stLen = strlen($data); - $datLen = 0; - $ret = ''; - - // INITIALIZATION - $this->LZWCommand($data, true); - - while (($iIndex = $this->LZWCommand($data, false)) >= 0) { - $ret .= chr($iIndex); - } - - $datLen = $stLen - strlen($data); - - if ($iIndex != -2) { - return false; - } - - return $ret; - } - - /////////////////////////////////////////////////////////////////////////// - - function LZWCommand(&$data, $bInit) - { - if ($bInit) { - $this->SetCodeSize = ord($data{0}); - $data = substr($data, 1); - - $this->CodeSize = $this->SetCodeSize + 1; - $this->ClearCode = 1 << $this->SetCodeSize; - $this->EndCode = $this->ClearCode + 1; - $this->MaxCode = $this->ClearCode + 2; - $this->MaxCodeSize = $this->ClearCode << 1; - - $this->GetCode($data, $bInit); - - $this->Fresh = 1; - for ($i = 0; $i < $this->ClearCode; $i++) { - $this->Next[$i] = 0; - $this->Vals[$i] = $i; - } - - for (; $i < (1 << $this->MAX_LZW_BITS); $i++) { - $this->Next[$i] = 0; - $this->Vals[$i] = 0; - } - - $this->sp = 0; - return 1; - } - - if ($this->Fresh) { - $this->Fresh = 0; - do { - $this->FirstCode = $this->GetCode($data, $bInit); - $this->OldCode = $this->FirstCode; - } - while ($this->FirstCode == $this->ClearCode); - - return $this->FirstCode; - } - - if ($this->sp > 0) { - $this->sp--; - return $this->Stack[$this->sp]; - } - - while (($Code = $this->GetCode($data, $bInit)) >= 0) { - if ($Code == $this->ClearCode) { - for ($i = 0; $i < $this->ClearCode; $i++) { - $this->Next[$i] = 0; - $this->Vals[$i] = $i; - } - - for (; $i < (1 << $this->MAX_LZW_BITS); $i++) { - $this->Next[$i] = 0; - $this->Vals[$i] = 0; - } - - $this->CodeSize = $this->SetCodeSize + 1; - $this->MaxCodeSize = $this->ClearCode << 1; - $this->MaxCode = $this->ClearCode + 2; - $this->sp = 0; - $this->FirstCode = $this->GetCode($data, $bInit); - $this->OldCode = $this->FirstCode; - - return $this->FirstCode; - } - - if ($Code == $this->EndCode) { - return -2; - } - - $InCode = $Code; - if ($Code >= $this->MaxCode) { - $this->Stack[$this->sp] = $this->FirstCode; - $this->sp++; - $Code = $this->OldCode; - } - - while ($Code >= $this->ClearCode) { - $this->Stack[$this->sp] = $this->Vals[$Code]; - $this->sp++; - - if ($Code == $this->Next[$Code]) // Circular table entry, big GIF Error! - return -1; - - $Code = $this->Next[$Code]; - } - - $this->FirstCode = $this->Vals[$Code]; - $this->Stack[$this->sp] = $this->FirstCode; - $this->sp++; - - if (($Code = $this->MaxCode) < (1 << $this->MAX_LZW_BITS)) { - $this->Next[$Code] = $this->OldCode; - $this->Vals[$Code] = $this->FirstCode; - $this->MaxCode++; - - if (($this->MaxCode >= $this->MaxCodeSize) && ($this->MaxCodeSize < (1 << $this->MAX_LZW_BITS))) { - $this->MaxCodeSize *= 2; - $this->CodeSize++; - } - } - - $this->OldCode = $InCode; - if ($this->sp > 0) { - $this->sp--; - return $this->Stack[$this->sp]; - } - } - - return $Code; - } - - /////////////////////////////////////////////////////////////////////////// - - function GetCode(&$data, $bInit) - { - if ($bInit) { - $this->CurBit = 0; - $this->LastBit = 0; - $this->Done = 0; - $this->LastByte = 2; - return 1; - } - - if (($this->CurBit + $this->CodeSize) >= $this->LastBit) { - if ($this->Done) { - if ($this->CurBit >= $this->LastBit) { - // Ran off the end of my bits - return 0; - } - return -1; - } - - $this->Buf[0] = $this->Buf[$this->LastByte - 2]; - $this->Buf[1] = $this->Buf[$this->LastByte - 1]; - - $Count = ord($data{0}); - $data = substr($data, 1); - - if ($Count) { - for ($i = 0; $i < $Count; $i++) { - $this->Buf[2 + $i] = ord($data{$i}); - } - $data = substr($data, $Count); - } else { - $this->Done = 1; - } - - $this->LastByte = 2 + $Count; - $this->CurBit = ($this->CurBit - $this->LastBit) + 16; - $this->LastBit = (2 + $Count) << 3; - } - - $iRet = 0; - for ($i = $this->CurBit, $j = 0; $j < $this->CodeSize; $i++, $j++) { - $iRet |= (($this->Buf[intval($i / 8)] & (1 << ($i % 8))) != 0) << $j; - } - - $this->CurBit += $this->CodeSize; - return $iRet; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -class CGIFCOLORTABLE -{ - var $m_nColors; - var $m_arColors; - - /////////////////////////////////////////////////////////////////////////// - - // CONSTRUCTOR - function CGIFCOLORTABLE() - { - unSet($this->m_nColors); - unSet($this->m_arColors); - } - - /////////////////////////////////////////////////////////////////////////// - - function load($lpData, $num) - { - $this->m_nColors = 0; - $this->m_arColors = array(); - - for ($i = 0; $i < $num; $i++) { - $rgb = substr($lpData, $i * 3, 3); - if (strlen($rgb) < 3) { - return false; - } - - $this->m_arColors[] = (ord($rgb{2}) << 16) + (ord($rgb{1}) << 8) + ord($rgb{0}); - $this->m_nColors++; - } - - return true; - } - - /////////////////////////////////////////////////////////////////////////// - - function toString() - { - $ret = ''; - - for ($i = 0; $i < $this->m_nColors; $i++) { - $ret .= - chr(($this->m_arColors[$i] & 0x000000FF)) . // R - chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G - chr(($this->m_arColors[$i] & 0x00FF0000) >> 16); // B - } - - return $ret; - } - - /////////////////////////////////////////////////////////////////////////// - - function toRGBQuad() - { - $ret = ''; - - for ($i = 0; $i < $this->m_nColors; $i++) { - $ret .= - chr(($this->m_arColors[$i] & 0x00FF0000) >> 16) . // B - chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G - chr(($this->m_arColors[$i] & 0x000000FF)) . // R - "\x00"; - } - - return $ret; - } - - /////////////////////////////////////////////////////////////////////////// - - function colorIndex($rgb) - { - $rgb = intval($rgb) & 0xFFFFFF; - $r1 = ($rgb & 0x0000FF); - $g1 = ($rgb & 0x00FF00) >> 8; - $b1 = ($rgb & 0xFF0000) >> 16; - $idx = -1; - - for ($i = 0; $i < $this->m_nColors; $i++) { - $r2 = ($this->m_arColors[$i] & 0x000000FF); - $g2 = ($this->m_arColors[$i] & 0x0000FF00) >> 8; - $b2 = ($this->m_arColors[$i] & 0x00FF0000) >> 16; - $d = abs($r2 - $r1) + abs($g2 - $g1) + abs($b2 - $b1); - - if (($idx == -1) || ($d < $dif)) { - $idx = $i; - $dif = $d; - } - } - - return $idx; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -class CGIFFILEHEADER -{ - var $m_lpVer; - var $m_nWidth; - var $m_nHeight; - var $m_bGlobalClr; - var $m_nColorRes; - var $m_bSorted; - var $m_nTableSize; - var $m_nBgColor; - var $m_nPixelRatio; - var $m_colorTable; - - /////////////////////////////////////////////////////////////////////////// - - // CONSTRUCTOR - function CGIFFILEHEADER() - { - unSet($this->m_lpVer); - unSet($this->m_nWidth); - unSet($this->m_nHeight); - unSet($this->m_bGlobalClr); - unSet($this->m_nColorRes); - unSet($this->m_bSorted); - unSet($this->m_nTableSize); - unSet($this->m_nBgColor); - unSet($this->m_nPixelRatio); - unSet($this->m_colorTable); - } - - /////////////////////////////////////////////////////////////////////////// - - function load($lpData, &$hdrLen) - { - $hdrLen = 0; - - $this->m_lpVer = substr($lpData, 0, 6); - if (($this->m_lpVer <> 'GIF87a') && ($this->m_lpVer <> 'GIF89a')) { - return false; - } - - $this->m_nWidth = $this->w2i(substr($lpData, 6, 2)); - $this->m_nHeight = $this->w2i(substr($lpData, 8, 2)); - if (!$this->m_nWidth || !$this->m_nHeight) { - return false; - } - - $b = ord(substr($lpData, 10, 1)); - $this->m_bGlobalClr = ($b & 0x80) ? true : false; - $this->m_nColorRes = ($b & 0x70) >> 4; - $this->m_bSorted = ($b & 0x08) ? true : false; - $this->m_nTableSize = 2 << ($b & 0x07); - $this->m_nBgColor = ord(substr($lpData, 11, 1)); - $this->m_nPixelRatio = ord(substr($lpData, 12, 1)); - $hdrLen = 13; - - if ($this->m_bGlobalClr) { - $this->m_colorTable = new CGIFCOLORTABLE(); - if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) { - return false; - } - $hdrLen += 3 * $this->m_nTableSize; - } - - return true; - } - - /////////////////////////////////////////////////////////////////////////// - - function w2i($str) - { - return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -class CGIFIMAGEHEADER -{ - var $m_nLeft; - var $m_nTop; - var $m_nWidth; - var $m_nHeight; - var $m_bLocalClr; - var $m_bInterlace; - var $m_bSorted; - var $m_nTableSize; - var $m_colorTable; - - /////////////////////////////////////////////////////////////////////////// - - // CONSTRUCTOR - function CGIFIMAGEHEADER() - { - unSet($this->m_nLeft); - unSet($this->m_nTop); - unSet($this->m_nWidth); - unSet($this->m_nHeight); - unSet($this->m_bLocalClr); - unSet($this->m_bInterlace); - unSet($this->m_bSorted); - unSet($this->m_nTableSize); - unSet($this->m_colorTable); - } - - /////////////////////////////////////////////////////////////////////////// - - function load($lpData, &$hdrLen) - { - $hdrLen = 0; - - $this->m_nLeft = $this->w2i(substr($lpData, 0, 2)); - $this->m_nTop = $this->w2i(substr($lpData, 2, 2)); - $this->m_nWidth = $this->w2i(substr($lpData, 4, 2)); - $this->m_nHeight = $this->w2i(substr($lpData, 6, 2)); - - if (!$this->m_nWidth || !$this->m_nHeight) { - return false; - } - - $b = ord($lpData{8}); - $this->m_bLocalClr = ($b & 0x80) ? true : false; - $this->m_bInterlace = ($b & 0x40) ? true : false; - $this->m_bSorted = ($b & 0x20) ? true : false; - $this->m_nTableSize = 2 << ($b & 0x07); - $hdrLen = 9; - - if ($this->m_bLocalClr) { - $this->m_colorTable = new CGIFCOLORTABLE(); - if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) { - return false; - } - $hdrLen += 3 * $this->m_nTableSize; - } - - return true; - } - - /////////////////////////////////////////////////////////////////////////// - - function w2i($str) - { - return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -class CGIFIMAGE -{ - var $m_disp; - var $m_bUser; - var $m_bTrans; - var $m_nDelay; - var $m_nTrans; - var $m_lpComm; - var $m_gih; - var $m_data; - var $m_lzw; - - /////////////////////////////////////////////////////////////////////////// - - function CGIFIMAGE() - { - unSet($this->m_disp); - unSet($this->m_bUser); - unSet($this->m_bTrans); - unSet($this->m_nDelay); - unSet($this->m_nTrans); - unSet($this->m_lpComm); - unSet($this->m_data); - $this->m_gih = new CGIFIMAGEHEADER(); - $this->m_lzw = new CGIFLZW(); - } - - /////////////////////////////////////////////////////////////////////////// - - function load($data, &$datLen) - { - $datLen = 0; - - while (true) { - $b = ord($data{0}); - $data = substr($data, 1); - $datLen++; - - switch($b) { - case 0x21: // Extension - if (!$this->skipExt($data, $len = 0)) { - return false; - } - $datLen += $len; - break; - - case 0x2C: // Image - // LOAD HEADER & COLOR TABLE - if (!$this->m_gih->load($data, $len = 0)) { - return false; - } - $data = substr($data, $len); - $datLen += $len; - - // ALLOC BUFFER - if (!($this->m_data = $this->m_lzw->deCompress($data, $len = 0))) { - return false; - } - $data = substr($data, $len); - $datLen += $len; - - if ($this->m_gih->m_bInterlace) { - $this->deInterlace(); - } - return true; - - case 0x3B: // EOF - default: - return false; - } - } - return false; - } - - /////////////////////////////////////////////////////////////////////////// - - function skipExt(&$data, &$extLen) - { - $extLen = 0; - - $b = ord($data{0}); - $data = substr($data, 1); - $extLen++; - - switch($b) { - case 0xF9: // Graphic Control - $b = ord($data{1}); - $this->m_disp = ($b & 0x1C) >> 2; - $this->m_bUser = ($b & 0x02) ? true : false; - $this->m_bTrans = ($b & 0x01) ? true : false; - $this->m_nDelay = $this->w2i(substr($data, 2, 2)); - $this->m_nTrans = ord($data{4}); - break; - - case 0xFE: // Comment - $this->m_lpComm = substr($data, 1, ord($data{0})); - break; - - case 0x01: // Plain text - break; - - case 0xFF: // Application - break; - } - - // SKIP DEFAULT AS DEFS MAY CHANGE - $b = ord($data{0}); - $data = substr($data, 1); - $extLen++; - while ($b > 0) { - $data = substr($data, $b); - $extLen += $b; - $b = ord($data{0}); - $data = substr($data, 1); - $extLen++; - } - return true; - } - - /////////////////////////////////////////////////////////////////////////// - - function w2i($str) - { - return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8); - } - - /////////////////////////////////////////////////////////////////////////// - - function deInterlace() - { - $data = $this->m_data; - - for ($i = 0; $i < 4; $i++) { - switch($i) { - case 0: - $s = 8; - $y = 0; - break; - - case 1: - $s = 8; - $y = 4; - break; - - case 2: - $s = 4; - $y = 2; - break; - - case 3: - $s = 2; - $y = 1; - break; - } - - for (; $y < $this->m_gih->m_nHeight; $y += $s) { - $lne = substr($this->m_data, 0, $this->m_gih->m_nWidth); - $this->m_data = substr($this->m_data, $this->m_gih->m_nWidth); - - $data = - substr($data, 0, $y * $this->m_gih->m_nWidth) . - $lne . - substr($data, ($y + 1) * $this->m_gih->m_nWidth); - } - } - - $this->m_data = $data; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -class CGIF -{ - var $m_gfh; - var $m_lpData; - var $m_img; - var $m_bLoaded; - - /////////////////////////////////////////////////////////////////////////// - - // CONSTRUCTOR - function CGIF() - { - $this->m_gfh = new CGIFFILEHEADER(); - $this->m_img = new CGIFIMAGE(); - $this->m_lpData = ''; - $this->m_bLoaded = false; - } - - /////////////////////////////////////////////////////////////////////////// - - function loadFile($lpszFileName, $iIndex) - { - if ($iIndex < 0) { - return false; - } - - // READ FILE - if (!($fh = @fopen($lpszFileName, 'rb'))) { - return false; - } - $this->m_lpData = @fRead($fh, @fileSize($lpszFileName)); - fclose($fh); - - // GET FILE HEADER - if (!$this->m_gfh->load($this->m_lpData, $len = 0)) { - return false; - } - $this->m_lpData = substr($this->m_lpData, $len); - - do { - if (!$this->m_img->load($this->m_lpData, $imgLen = 0)) { - return false; - } - $this->m_lpData = substr($this->m_lpData, $imgLen); - } - while ($iIndex-- > 0); - - $this->m_bLoaded = true; - return true; - } - - /////////////////////////////////////////////////////////////////////////// - - function getSize($lpszFileName, &$width, &$height) - { - if (!($fh = @fopen($lpszFileName, 'rb'))) { - return false; - } - $data = @fRead($fh, @fileSize($lpszFileName)); - @fclose($fh); - - $gfh = new CGIFFILEHEADER(); - if (!$gfh->load($data, $len = 0)) { - return false; - } - - $width = $gfh->m_nWidth; - $height = $gfh->m_nHeight; - return true; - } - - /////////////////////////////////////////////////////////////////////////// - - function getBmp($bgColor) - { - $out = ''; - - if (!$this->m_bLoaded) { - return false; - } - - // PREPARE COLOR TABLE (RGBQUADs) - if ($this->m_img->m_gih->m_bLocalClr) { - $nColors = $this->m_img->m_gih->m_nTableSize; - $rgbq = $this->m_img->m_gih->m_colorTable->toRGBQuad(); - if ($bgColor != -1) { - $bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor); - } - } elseif ($this->m_gfh->m_bGlobalClr) { - $nColors = $this->m_gfh->m_nTableSize; - $rgbq = $this->m_gfh->m_colorTable->toRGBQuad(); - if ($bgColor != -1) { - $bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor); - } - } else { - $nColors = 0; - $bgColor = -1; - } - - // PREPARE BITMAP BITS - $data = $this->m_img->m_data; - $nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth; - $bmp = ''; - $nPad = ($this->m_gfh->m_nWidth % 4) ? 4 - ($this->m_gfh->m_nWidth % 4) : 0; - for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) { - for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) { - if ( - ($x >= $this->m_img->m_gih->m_nLeft) && - ($y >= $this->m_img->m_gih->m_nTop) && - ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) && - ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) { - // PART OF IMAGE - if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) { - // TRANSPARENT -> BACKGROUND - if ($bgColor == -1) { - $bmp .= chr($this->m_gfh->m_nBgColor); - } else { - $bmp .= chr($bgColor); - } - } else { - $bmp .= $data{$nPxl}; - } - } else { - // BACKGROUND - if ($bgColor == -1) { - $bmp .= chr($this->m_gfh->m_nBgColor); - } else { - $bmp .= chr($bgColor); - } - } - } - $nPxl -= $this->m_gfh->m_nWidth << 1; - - // ADD PADDING - for ($x = 0; $x < $nPad; $x++) { - $bmp .= "\x00"; - } - } - - // BITMAPFILEHEADER - $out .= 'BM'; - $out .= $this->dword(14 + 40 + ($nColors << 2) + strlen($bmp)); - $out .= "\x00\x00"; - $out .= "\x00\x00"; - $out .= $this->dword(14 + 40 + ($nColors << 2)); - - // BITMAPINFOHEADER - $out .= $this->dword(40); - $out .= $this->dword($this->m_gfh->m_nWidth); - $out .= $this->dword($this->m_gfh->m_nHeight); - $out .= "\x01\x00"; - $out .= "\x08\x00"; - $out .= "\x00\x00\x00\x00"; - $out .= "\x00\x00\x00\x00"; - $out .= "\x12\x0B\x00\x00"; - $out .= "\x12\x0B\x00\x00"; - $out .= $this->dword($nColors % 256); - $out .= "\x00\x00\x00\x00"; - - // COLOR TABLE - if ($nColors > 0) { - $out .= $rgbq; - } - - // DATA - $out .= $bmp; - - return $out; - } - - /////////////////////////////////////////////////////////////////////////// - - function getPng($bgColor) - { - $out = ''; - - if (!$this->m_bLoaded) { - return false; - } - - // PREPARE COLOR TABLE (RGBQUADs) - if ($this->m_img->m_gih->m_bLocalClr) { - $nColors = $this->m_img->m_gih->m_nTableSize; - $pal = $this->m_img->m_gih->m_colorTable->toString(); - if ($bgColor != -1) { - $bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor); - } - } elseif ($this->m_gfh->m_bGlobalClr) { - $nColors = $this->m_gfh->m_nTableSize; - $pal = $this->m_gfh->m_colorTable->toString(); - if ($bgColor != -1) { - $bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor); - } - } else { - $nColors = 0; - $bgColor = -1; - } - - // PREPARE BITMAP BITS - $data = $this->m_img->m_data; - $nPxl = 0; - $bmp = ''; - for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) { - $bmp .= "\x00"; - for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) { - if ( - ($x >= $this->m_img->m_gih->m_nLeft) && - ($y >= $this->m_img->m_gih->m_nTop) && - ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) && - ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) { - // PART OF IMAGE - $bmp .= $data{$nPxl}; - } else { - // BACKGROUND - if ($bgColor == -1) { - $bmp .= chr($this->m_gfh->m_nBgColor); - } else { - $bmp .= chr($bgColor); - } - } - } - } - $bmp = gzcompress($bmp, 9); - - /////////////////////////////////////////////////////////////////////// - // SIGNATURE - $out .= "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"; - /////////////////////////////////////////////////////////////////////// - // HEADER - $out .= "\x00\x00\x00\x0D"; - $tmp = 'IHDR'; - $tmp .= $this->ndword($this->m_gfh->m_nWidth); - $tmp .= $this->ndword($this->m_gfh->m_nHeight); - $tmp .= "\x08\x03\x00\x00\x00"; - $out .= $tmp; - $out .= $this->ndword(crc32($tmp)); - /////////////////////////////////////////////////////////////////////// - // PALETTE - if ($nColors > 0) { - $out .= $this->ndword($nColors * 3); - $tmp = 'PLTE'; - $tmp .= $pal; - $out .= $tmp; - $out .= $this->ndword(crc32($tmp)); - } - /////////////////////////////////////////////////////////////////////// - // TRANSPARENCY - if (@$this->m_img->m_bTrans && ($nColors > 0)) { - $out .= $this->ndword($nColors); - $tmp = 'tRNS'; - for ($i = 0; $i < $nColors; $i++) { - $tmp .= ($i == $this->m_img->m_nTrans) ? "\x00" : "\xFF"; - } - $out .= $tmp; - $out .= $this->ndword(crc32($tmp)); - } - /////////////////////////////////////////////////////////////////////// - // DATA BITS - $out .= $this->ndword(strlen($bmp)); - $tmp = 'IDAT'; - $tmp .= $bmp; - $out .= $tmp; - $out .= $this->ndword(crc32($tmp)); - /////////////////////////////////////////////////////////////////////// - // END OF FILE - $out .= "\x00\x00\x00\x00IEND\xAE\x42\x60\x82"; - - return $out; - } - - /////////////////////////////////////////////////////////////////////////// - - // Added by James Heinrich - January 5, 2003 - - // Takes raw image data and plots it pixel-by-pixel on a new GD image and returns that - // It's extremely slow, but the only solution when ImageCreateFromString() fails - function getGD_PixelPlotterVersion() - { - if (!$this->m_bLoaded) { - return false; - } - - // PREPARE COLOR TABLE (RGBQUADs) - if ($this->m_img->m_gih->m_bLocalClr) { - $pal = $this->m_img->m_gih->m_colorTable->toString(); - } elseif ($this->m_gfh->m_bGlobalClr) { - $pal = $this->m_gfh->m_colorTable->toString(); - } else { - die('No color table available in getGD_PixelPlotterVersion()'); - } - - $PlottingIMG = ImageCreate($this->m_gfh->m_nWidth, $this->m_gfh->m_nHeight); - $NumColorsInPal = floor(strlen($pal) / 3); - for ($i = 0; $i < $NumColorsInPal; $i++) { - $ThisImageColor[$i] = ImageColorAllocate( - $PlottingIMG, - ord($pal{(($i * 3) + 0)}), - ord($pal{(($i * 3) + 1)}), - ord($pal{(($i * 3) + 2)})); - } - - // PREPARE BITMAP BITS - $data = $this->m_img->m_data; - $nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth; - for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) { - set_time_limit(30); - for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) { - if ( - ($x >= $this->m_img->m_gih->m_nLeft) && - ($y >= $this->m_img->m_gih->m_nTop) && - ($x < ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) && - ($y < ($this->m_img->m_gih->m_nTop + $this->m_img->m_gih->m_nHeight))) { - // PART OF IMAGE - if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) { - ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]); - } else { - ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[ord($data{$nPxl})]); - } - } else { - // BACKGROUND - ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]); - } - } - $nPxl -= $this->m_gfh->m_nWidth << 1; - - } - - return $PlottingIMG; - } - - /////////////////////////////////////////////////////////////////////////// - - function dword($val) - { - $val = intval($val); - return chr($val & 0xFF).chr(($val & 0xFF00) >> 8).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF000000) >> 24); - } - - /////////////////////////////////////////////////////////////////////////// - - function ndword($val) - { - $val = intval($val); - return chr(($val & 0xFF000000) >> 24).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF00) >> 8).chr($val & 0xFF); - } - - /////////////////////////////////////////////////////////////////////////// - - function width() - { - return $this->m_gfh->m_nWidth; - } - - /////////////////////////////////////////////////////////////////////////// - - function height() - { - return $this->m_gfh->m_nHeight; - } - - /////////////////////////////////////////////////////////////////////////// - - function comment() - { - return $this->m_img->m_lpComm; - } - - /////////////////////////////////////////////////////////////////////////// - - function loaded() - { - return $this->m_bLoaded; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -?> \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.ico.php b/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.ico.php deleted file mode 100644 index aed7214c7..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.ico.php +++ /dev/null @@ -1,119 +0,0 @@ - // -// available at http://phpthumb.sourceforge.net /// -////////////////////////////////////////////////////////////// -/// // -// phpthumb.ico.php - .ICO output format functions // -// /// -////////////////////////////////////////////////////////////// - - -class phpthumb_ico { - - function phpthumb_ico() { - return true; - } - - - function GD2ICOstring(&$gd_image_array) { - foreach ($gd_image_array as $key => $gd_image) { - - $ImageWidths[$key] = ImageSX($gd_image); - $ImageHeights[$key] = ImageSY($gd_image); - $bpp[$key] = ImageIsTrueColor($gd_image) ? 32 : 24; - $totalcolors[$key] = ImageColorsTotal($gd_image); - - $icXOR[$key] = ''; - for ($y = $ImageHeights[$key] - 1; $y >= 0; $y--) { - for ($x = 0; $x < $ImageWidths[$key]; $x++) { - $argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y); - $a = round(255 * ((127 - $argb['alpha']) / 127)); - $r = $argb['red']; - $g = $argb['green']; - $b = $argb['blue']; - - if ($bpp[$key] == 32) { - $icXOR[$key] .= chr($b).chr($g).chr($r).chr($a); - } elseif ($bpp[$key] == 24) { - $icXOR[$key] .= chr($b).chr($g).chr($r); - } - - if ($a < 128) { - @$icANDmask[$key][$y] .= '1'; - } else { - @$icANDmask[$key][$y] .= '0'; - } - } - // mask bits are 32-bit aligned per scanline - while (strlen($icANDmask[$key][$y]) % 32) { - $icANDmask[$key][$y] .= '0'; - } - } - $icAND[$key] = ''; - foreach ($icANDmask[$key] as $y => $scanlinemaskbits) { - for ($i = 0; $i < strlen($scanlinemaskbits); $i += 8) { - $icAND[$key] .= chr(bindec(str_pad(substr($scanlinemaskbits, $i, 8), 8, '0', STR_PAD_LEFT))); - } - } - - } - - foreach ($gd_image_array as $key => $gd_image) { - $biSizeImage = $ImageWidths[$key] * $ImageHeights[$key] * ($bpp[$key] / 8); - - // BITMAPINFOHEADER - 40 bytes - $BitmapInfoHeader[$key] = ''; - $BitmapInfoHeader[$key] .= "\x28\x00\x00\x00"; // DWORD biSize; - $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageWidths[$key], 4); // LONG biWidth; - // The biHeight member specifies the combined - // height of the XOR and AND masks. - $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageHeights[$key] * 2, 4); // LONG biHeight; - $BitmapInfoHeader[$key] .= "\x01\x00"; // WORD biPlanes; - $BitmapInfoHeader[$key] .= chr($bpp[$key])."\x00"; // wBitCount; - $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biCompression; - $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($biSizeImage, 4); // DWORD biSizeImage; - $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // LONG biXPelsPerMeter; - $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // LONG biYPelsPerMeter; - $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biClrUsed; - $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biClrImportant; - } - - - $icondata = "\x00\x00"; // idReserved; // Reserved (must be 0) - $icondata .= "\x01\x00"; // idType; // Resource Type (1 for icons) - $icondata .= phpthumb_functions::LittleEndian2String(count($gd_image_array), 2); // idCount; // How many images? - - $dwImageOffset = 6 + (count($gd_image_array) * 16); - foreach ($gd_image_array as $key => $gd_image) { - // ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) - - $icondata .= chr($ImageWidths[$key]); // bWidth; // Width, in pixels, of the image - $icondata .= chr($ImageHeights[$key]); // bHeight; // Height, in pixels, of the image - $icondata .= chr($totalcolors[$key]); // bColorCount; // Number of colors in image (0 if >=8bpp) - $icondata .= "\x00"; // bReserved; // Reserved ( must be 0) - - $icondata .= "\x01\x00"; // wPlanes; // Color Planes - $icondata .= chr($bpp[$key])."\x00"; // wBitCount; // Bits per pixel - - $dwBytesInRes = 40 + strlen($icXOR[$key]) + strlen($icAND[$key]); - $icondata .= phpthumb_functions::LittleEndian2String($dwBytesInRes, 4); // dwBytesInRes; // How many bytes in this resource? - - $icondata .= phpthumb_functions::LittleEndian2String($dwImageOffset, 4); // dwImageOffset; // Where in the file is this image? - $dwImageOffset += strlen($BitmapInfoHeader[$key]); - $dwImageOffset += strlen($icXOR[$key]); - $dwImageOffset += strlen($icAND[$key]); - } - - foreach ($gd_image_array as $key => $gd_image) { - $icondata .= $BitmapInfoHeader[$key]; - $icondata .= $icXOR[$key]; - $icondata .= $icAND[$key]; - } - - return $icondata; - } - -} - -?> \ No newline at end of file diff --git a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.unsharp.php b/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.unsharp.php deleted file mode 100644 index 799b5cdf2..000000000 --- a/mods/photo_album/classes/phpThumb_1.7.2/phpthumb.unsharp.php +++ /dev/null @@ -1,162 +0,0 @@ - // -// for use in phpThumb() on 3 February 2003. // -// // -// phpThumb() is found at http://phpthumb.sourceforge.net /// -////////////////////////////////////////////////////////////// - -/* -WARNING! Due to a known bug in PHP 4.3.2 this script is not working well in this version. -The sharpened images get too dark. The bug is fixed in version 4.3.3. - -Unsharp masking is a traditional darkroom technique that has proven very suitable for -digital imaging. The principle of unsharp masking is to create a blurred copy of the image -and compare it to the underlying original. The difference in colour values -between the two images is greatest for the pixels near sharp edges. When this -difference is subtracted from the original image, the edges will be -accentuated. - -The Amount parameter simply says how much of the effect you want. 100 is 'normal'. -Radius is the radius of the blurring circle of the mask. 'Threshold' is the least -difference in colour values that is allowed between the original and the mask. In practice -this means that low-contrast areas of the picture are left unrendered whereas edges -are treated normally. This is good for pictures of e.g. skin or blue skies. - -Any suggenstions for improvement of the algorithm, expecially regarding the speed -and the roundoff errors in the Gaussian blur process, are welcome. -*/ - -class phpUnsharpMask { - - function applyUnsharpMask(&$img, $amount, $radius, $threshold) { - - // $img is an image that is already created within php using - // imgcreatetruecolor. No url! $img must be a truecolor image. - - // Attempt to calibrate the parameters to Photoshop: - $amount = min($amount, 500); - $amount = $amount * 0.016; - if ($amount == 0) { - return true; - } - - $radius = min($radius, 50); - $radius = $radius * 2; - - $threshold = min($threshold, 255); - - $radius = abs(round($radius)); // Only integers make sense. - if ($radius == 0) { - return true; - } - - $w = ImageSX($img); - $h = ImageSY($img); - $imgCanvas = ImageCreateTrueColor($w, $h); - $imgCanvas2 = ImageCreateTrueColor($w, $h); - ImageCopy($imgCanvas, $img, 0, 0, 0, 0, $w, $h); - ImageCopy($imgCanvas2, $img, 0, 0, 0, 0, $w, $h); - - - $builtinFilterSucceeded = false; - if ($radius == 1) { - if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { - if (ImageFilter($imgCanvas, IMG_FILTER_GAUSSIAN_BLUR) && ImageFilter($imgCanvas2, IMG_FILTER_GAUSSIAN_BLUR)) { - $builtinFilterSucceeded = true; - } - } - } - - if (!$builtinFilterSucceeded) { - $imgBlur = ImageCreateTrueColor($w, $h); - $imgBlur2 = ImageCreateTrueColor($w, $h); - - /////////////////////////// - // - // Gaussian blur matrix: - // 1 2 1 - // 2 4 2 - // 1 2 1 - // - /////////////////////////// - - // Move copies of the image around one pixel at the time and merge them with weight - // according to the matrix. The same matrix is simply repeated for higher radii. - for ($i = 0; $i < $radius; $i++) { - ImageCopy ($imgBlur, $imgCanvas, 0, 0, 1, 1, $w - 1, $h - 1); // up left - ImageCopyMerge($imgBlur, $imgCanvas, 1, 1, 0, 0, $w, $h, 50); // down right - ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left - ImageCopyMerge($imgBlur, $imgCanvas, 1, 0, 0, 1, $w, $h - 1, 25); // up right - ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left - ImageCopyMerge($imgBlur, $imgCanvas, 1, 0, 0, 0, $w, $h, 25); // right - ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 20 ); // up - ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 16.666667); // down - ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 0, $w, $h, 50); // center - ImageCopy ($imgCanvas, $imgBlur, 0, 0, 0, 0, $w, $h); - - // During the loop above the blurred copy darkens, possibly due to a roundoff - // error. Therefore the sharp picture has to go through the same loop to - // produce a similar image for comparison. This is not a good thing, as processing - // time increases heavily. - ImageCopy ($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h); - ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 50); - ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 33.33333); - ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 25); - ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 33.33333); - ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 25); - ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 20 ); - ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 16.666667); - ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 50); - ImageCopy ($imgCanvas2, $imgBlur2, 0, 0, 0, 0, $w, $h); - } - ImageDestroy($imgBlur); - ImageDestroy($imgBlur2); - } - - // Calculate the difference between the blurred pixels and the original - // and set the pixels - for ($x = 0; $x < $w; $x++) { // each row - for ($y = 0; $y < $h; $y++) { // each pixel - - $rgbOrig = ImageColorAt($imgCanvas2, $x, $y); - $rOrig = (($rgbOrig >> 16) & 0xFF); - $gOrig = (($rgbOrig >> 8) & 0xFF); - $bOrig = ($rgbOrig & 0xFF); - - $rgbBlur = ImageColorAt($imgCanvas, $x, $y); - $rBlur = (($rgbBlur >> 16) & 0xFF); - $gBlur = (($rgbBlur >> 8) & 0xFF); - $bBlur = ($rgbBlur & 0xFF); - - // When the masked pixels differ less from the original - // than the threshold specifies, they are set to their original value. - $rNew = (abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig; - $gNew = (abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig; - $bNew = (abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig; - - if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) { - $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew); - ImageSetPixel($img, $x, $y, $pixCol); - } - } - } - ImageDestroy($imgCanvas); - ImageDestroy($imgCanvas2); - - return true; - } - -} - -?> \ No newline at end of file diff --git a/mods/photo_album/define.php b/mods/photo_album/define.php deleted file mode 100644 index 0625b7416..000000000 --- a/mods/photo_album/define.php +++ /dev/null @@ -1,105 +0,0 @@ - diff --git a/mods/photo_album/fluid/component-templates/css/Lightbox.css b/mods/photo_album/fluid/component-templates/css/Lightbox.css deleted file mode 100644 index c071dbb8e..000000000 --- a/mods/photo_album/fluid/component-templates/css/Lightbox.css +++ /dev/null @@ -1,111 +0,0 @@ -body{ - font-family: verdana, helvetica, sans-serif; - font-size: 12px; -} - -.image-container{ - overflow: hidden; width: 100%; -} - -.image-inner-container{ - height: 100px; - width: 140px; - background-color: #eee; - overflow: hidden; - margin: 0 auto 3px auto; -} - -.image-inner-container img{ - width: 150px; -} - -.orderable-default{ - height: 150px !important; - width: 150px; - border: 2px solid #ddd; - float: left; - margin: 5px !important; - text-align: center; - padding-top: 10px; -} - -.orderable-hover{ - height: 150px !important; - width: 150px; - border: 2px solid #666; - float: left; - margin: 5px !important; - text-align: center; - padding-top: 10px; -} - -.orderable-selected{ - height: 150px !important; - width: 150px; - border: 2px solid #666; - background-color: #ddd; - float: left; - margin: 5px !important; - text-align: center; - padding-top: 10px; -} - -.orderable-selected img{ - border: 1px solid #eee; -} - -.orderable-dragging{ - height: 150px !important; - width: 150px; - border: 2px solid #666; - background-color: #eee; - float: left; - margin: 5px !important; - text-align: center; - opacity: .2; - filter: alpha(opacity=20); - padding-top: 10px; -} - -.image-title{ - margin-top:5px; - height: 40px; - overflow: hidden; -} - -.image-title a{ - text-decoration: none; -} - -.image-title a:hover{ - text-decoration: underline; -} - -div .orderable-drop-marker{ - height: 160px !important; - width: 4px; - background-color: red; - float: left; -} - -.lightbox-instructions{ - color: #666; - background-color: lightyellow; - padding: 3px; - border: 2px solid #ddd; - font-size: .9em; - position: absolute; - top: 0; - right: 0; - width: 300px; -} - -.lightbox-downarrow{ - font-size: 0px; line-height: 0%; width: 0px; - margin: 5px 8px 10px 0; - float: left; - border-top: 10px solid red; - border-left: 10px solid lightyellow; - border-right: 10px solid lightyellow; -} - diff --git a/mods/photo_album/fluid/component-templates/html/Lightbox.html b/mods/photo_album/fluid/component-templates/html/Lightbox.html deleted file mode 100644 index 5569cd919..000000000 --- a/mods/photo_album/fluid/component-templates/html/Lightbox.html +++ /dev/null @@ -1,383 +0,0 @@ - - - - - - - - - Fluid Lightbox - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    This is the Lightbox demo page.

    - - -
    - - - - - - -
    - - diff --git a/mods/photo_album/fluid/component-templates/images/Banana.jpg b/mods/photo_album/fluid/component-templates/images/Banana.jpg deleted file mode 100644 index 7967d44db4d95b2834ff3a768426b2bdd62da5fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1708 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 diff --git a/mods/photo_album/fluid/component-templates/images/Cherry.jpg b/mods/photo_album/fluid/component-templates/images/Cherry.jpg deleted file mode 100644 index d89e4ddf301f1340c40bfe1bd6f3ce6403f66888..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3359 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 diff --git a/mods/photo_album/fluid/component-templates/images/Fig.jpg b/mods/photo_album/fluid/component-templates/images/Fig.jpg deleted file mode 100644 index a6f6366c2e5e8d891d36fb2c42fda665f43320c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4568 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 T^zREk5&ToF(CBIDY5^cH0JvNa;OaL(dp8j7 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 diff --git a/mods/photo_album/fluid/component-templates/images/Kiwano.jpg b/mods/photo_album/fluid/component-templates/images/Kiwano.jpg deleted file mode 100644 index a45b18771c9a40420e7b87d1a1119d30f503246f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2611 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 OSl#*0SN8|GJM=Gp#}8Hj diff --git a/mods/photo_album/fluid/component-templates/images/Mangosteen.jpg b/mods/photo_album/fluid/component-templates/images/Mangosteen.jpg deleted file mode 100644 index e416ac970ff60b6faa0237b67396456317dc1eee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3637 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 XF;$Fbist!Yq(j0uv|1C&el_zSLFLOE diff --git a/mods/photo_album/fluid/component-templates/images/Orange.jpg b/mods/photo_album/fluid/component-templates/images/Orange.jpg deleted file mode 100644 index 35ce31a9e43f496298bc2c0bed4528678dc31397..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4029 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 JG(i}f^)IFSX1D+V diff --git a/mods/photo_album/fluid/component-templates/js/fluid/Fluid.js b/mods/photo_album/fluid/component-templates/js/fluid/Fluid.js deleted file mode 100644 index ce6e7f991..000000000 --- a/mods/photo_album/fluid/component-templates/js/fluid/Fluid.js +++ /dev/null @@ -1,136 +0,0 @@ -/* -Copyright 2007 University of Cambridge -Copyright 2007 University of Toronto - -Licensed under the Educational Community License (ECL), Version 2.0 or the New -BSD license. You may not use this file except in compliance with one these -Licenses. - -You may obtain a copy of the ECL 2.0 License and BSD License at -https://source.fluidproject.org/svn/LICENSE.txt -*/ - -var fluid = fluid || {}; - -fluid.keys = { - UP: 38, - DOWN: 40, - LEFT: 37, - RIGHT: 39, - SPACE: 32, - ENTER: 13, - TAB: 9, - CTRL: 17 -}; - -fluid.orientation = { - HORIZONTAL: 0, - VERTICAL: 1 -}; - -fluid.position = { - BEFORE: 0, - AFTER: 1 -}; - -fluid.mixin = function (target, args) { - for (var arg in args) { - if (args.hasOwnProperty (arg)) { - target[arg] = args[arg]; - } - } -}; - -fluid.deriveLightboxCellBase = function (namebase, index) { - return namebase + "lightbox-cell:" + index + ":"; -}; - -// Client-level initialisation for the lightbox, allowing parameterisation for -// different templates. -fluid.initLightbox = function (namebase, messageNamebase) { - var reorderform = fluid.Utilities.findForm (document.getElementById (namebase)); - - // Remove the anchors from the taborder - camel case 'tabIndex' needed for IE7 support - jQuery ("a", reorderform).attr ("tabIndex", "-1"); - - // An tag nested within our root namebase tag, which has an id which - // begins with the namebase:lightbox-cell:: prefix, and ends with "reorder-index" trail. - // Very hard to imagine any perversity which may lead to this picking any stray stuff :P - - // An approach based on the "sourceIndex" DOM property would be much more efficient, - // but this is only supported in IE. - var orderChangedCallback = function() { - var inputs = fluid.Utilities.seekNodesById( - reorderform, - "input", - "^" + fluid.deriveLightboxCellBase (namebase, "[^:]*") + "reorder-index$"); - - for (var i = 0; i < inputs.length; ++ i) { - inputs[i].value = i; - } - - if (reorderform && reorderform.action) { - jQuery.post(reorderform.action, - jQuery(reorderform).serialize(), - function (type, data, evt) { /* No-op response */ }); - } - }; - - // This orderable finder knows that the lightbox thumbnails are 'div' elements - var lightboxCellNamePattern = "^" + fluid.deriveLightboxCellBase (namebase, "[0-9]+") +"$"; - var lightboxOrderableFinder = function (containerEl) { - return fluid.Utilities.seekNodesById (containerEl, "div", lightboxCellNamePattern); - }; - - var lightboxContainer = jQuery ("[id=" + namebase + "]"); - var layoutHandlerParams = { - orderableFinder: lightboxOrderableFinder, - container: lightboxContainer, - orderChangedCallback: orderChangedCallback - }; - var lightbox = new fluid.Reorderer (lightboxContainer, { - messageNamebase : messageNamebase, - layoutHandler: new fluid.GridLayoutHandler (layoutHandlerParams), - orderableFinder: lightboxOrderableFinder - } - ); - - fluid.Lightbox.addThumbnailActivateHandler (lightbox); -}; - - - -/* - * Utilities object for providing various general convenience functions - */ -fluid.Utilities = {}; - -// Custom query method seeks all tags descended from a given root with a -// particular tag name, whose id matches a regex. The Dojo query parser -// is broken http://trac.dojotoolkit.org/ticket/3520#preview, this is all -// it might do anyway, and this will be plenty fast. -fluid.Utilities.seekNodesById = function (rootnode, tagname, idmatch) { - var inputs = rootnode.getElementsByTagName (tagname); - var togo = []; - for (var i = 0; i < inputs.length; ++ i) { - var input = inputs[i]; - var id = input.id; - if (id && id.match (idmatch)) { - togo.push (input); - } - } - return togo; -}; - -fluid.Utilities.escapeSelector = function(id) { - return id.replace (/\:/g,"\\:"); -}; - -fluid.Utilities.findForm = function (element) { - while(element) { - if (element.nodeName.toLowerCase() === "form") { - return element; - } - element = element.parentNode; - } -}; diff --git a/mods/photo_album/fluid/component-templates/js/fluid/Lightbox.js b/mods/photo_album/fluid/component-templates/js/fluid/Lightbox.js deleted file mode 100755 index bfc387c4e..000000000 --- a/mods/photo_album/fluid/component-templates/js/fluid/Lightbox.js +++ /dev/null @@ -1,15 +0,0 @@ -var fluid = fluid || {}; - -fluid.Lightbox = { - addThumbnailActivateHandler: function (lightbox) { - var lightboxContainerElement = lightbox.domNode; - var enterKeyHandler = function (evt) { - if (evt.which == fluid.keys.ENTER) { - var thumbnailAnchors = jQuery ("a", lightbox.activeItem); - document.location = thumbnailAnchors.attr ('href'); - } - }; - - jQuery (lightboxContainerElement).keypress (enterKeyHandler); - } -}; \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/fluid/Reorderer.js b/mods/photo_album/fluid/component-templates/js/fluid/Reorderer.js deleted file mode 100644 index f5c89a364..000000000 --- a/mods/photo_album/fluid/component-templates/js/fluid/Reorderer.js +++ /dev/null @@ -1,945 +0,0 @@ -/* -Copyright 2007 - 2008 University of Toronto -Copyright 2007 University of Cambridge - -Licensed under the Educational Community License (ECL), Version 2.0 or the New -BSD license. You may not use this file except in compliance with one these -Licenses. - -You may obtain a copy of the ECL 2.0 License and BSD License at -https://source.fluidproject.org/svn/LICENSE.txt -*/ - -// Declare dependencies. -var fluid = fluid || {}; - -fluid.Reorderer = function (container, params) { - // Reliable 'this'. - // - var thisReorderer = this; - var theAvatar = null; - - this.domNode = jQuery (container); - - // the reorderable DOM element that is currently active - this.activeItem = null; - - this.layoutHandler = null; - - this.messageNamebase = "message-bundle:"; - - this.orderableFinder = null; - - this.cssClasses = { - defaultStyle: "orderable-default", - selected: "orderable-selected", - dragging: "orderable-dragging", - hover: "orderable-hover", - focusTarget: "orderable-focus-target", - dropMarker: "orderable-drop-marker", - avatar: "orderable-avatar" - }; - - if (params) { - fluid.mixin (this, params); - } - - /** - * Return the element within the item that should receive focus. This is determined by - * cssClasses.focusTarget. If it is not specified, the item itself is returned. - * - * @param {Object} item - * @return {Object} The element that should receive focus in the specified item. - */ - this.findElementToFocus = function (item) { - var elementToFocus = jQuery ("." + this.cssClasses.focusTarget, item).get (0); - if (elementToFocus) { - return elementToFocus; - } - return item; - }; - - function setupDomNode (domNode) { - domNode.focus(thisReorderer.handleFocus); - domNode.blur (thisReorderer.handleBlur); - domNode.keydown (thisReorderer.handleKeyDown); - domNode.keyup (thisReorderer.handleKeyUp); - domNode.removeAttr ("aaa:activedescendent"); - } - - /** - * Changes the current focus to the specified item. - * @param {Object} anItem - */ - this.focusItem = function(anItem) { - if (this.activeItem !== anItem) { - this.changeActiveItemToDefaultState(); - this._setActiveItem (anItem); - } - - var jActiveItem = jQuery (this.activeItem); - jActiveItem.removeClass (this.cssClasses.defaultStyle); - jActiveItem.addClass (this.cssClasses.selected); - - this.addFocusToElement (this.findElementToFocus (this.activeItem)); - }; - - this.addFocusToElement = function (anElement) { - var jElement = jQuery (anElement); - if (!jElement.hasTabIndex ()) { - jElement.tabIndex (-1); - } - jElement.focus (); - }; - - this.removeFocusFromElement = function (anElement) { - jQuery (anElement).blur (); - }; - - /** - * Changes focus to the active item. - */ - this.selectActiveItem = function() { - if (!this.activeItem) { - var orderables = this.orderableFinder (this.domNode.get(0)); - if (orderables.length > 0) { - this._setActiveItem (orderables[0]); - } - else { - return; - } - } - this.focusItem (this.activeItem); - }; - - this.handleFocus = function (evt) { - thisReorderer.selectActiveItem(); - return false; - }; - - this.handleBlur = function (evt) { - // Temporarily disabled blur handling in IE. See FLUID-7 for details. - if (!jQuery.browser.msie) { - thisReorderer.changeActiveItemToDefaultState(); - } - }; - - this.changeActiveItemToDefaultState = function() { - if (this.activeItem) { - var jActiveItem = jQuery (this.activeItem); - jActiveItem.removeClass (this.cssClasses.selected); - jActiveItem.addClass (this.cssClasses.defaultStyle); - this.removeFocusFromElement (jActiveItem); - } - }; - - this.handleKeyDown = function (evt) { - if (thisReorderer.activeItem && evt.keyCode === fluid.keys.CTRL) { - jQuery (thisReorderer.activeItem).removeClass (thisReorderer.cssClasses.selected); - jQuery (thisReorderer.activeItem).addClass (thisReorderer.cssClasses.dragging); - thisReorderer.activeItem.setAttribute ("aaa:grab", "true"); - return false; - } - - return thisReorderer.handleArrowKeyPress(evt); - }; - - this.handleKeyUp = function (evt) { - if (thisReorderer.activeItem && evt.keyCode === fluid.keys.CTRL) { - jQuery (thisReorderer.activeItem).removeClass (thisReorderer.cssClasses.dragging); - jQuery (thisReorderer.activeItem).addClass (thisReorderer.cssClasses.selected); - thisReorderer.activeItem.setAttribute ("aaa:grab", "supported"); - return false; - } - }; - - this.handleArrowKeyPress = function (evt) { - if (thisReorderer.activeItem) { - switch (evt.keyCode) { - case fluid.keys.DOWN: - evt.preventDefault(); - thisReorderer.handleDownArrow (evt.ctrlKey); - return false; - case fluid.keys.UP: - evt.preventDefault(); - thisReorderer.handleUpArrow (evt.ctrlKey); - return false; - case fluid.keys.LEFT: - evt.preventDefault(); - thisReorderer.handleLeftArrow (evt.ctrlKey); - return false; - case fluid.keys.RIGHT: - evt.preventDefault(); - thisReorderer.handleRightArrow (evt.ctrlKey); - return false; - default: - return true; - } - } - }; - - this.handleUpArrow = function (isCtrl) { - if (isCtrl) { - this.layoutHandler.moveItemUp (this.activeItem); - this.findElementToFocus (this.activeItem).focus(); - } else { - this.focusItem (this.layoutHandler.getItemAbove(this.activeItem)); - } - }; - - this.handleDownArrow = function (isCtrl) { - if (isCtrl) { - this.layoutHandler.moveItemDown (this.activeItem); - this.findElementToFocus (this.activeItem).focus(); - } else { - this.focusItem (this.layoutHandler.getItemBelow (this.activeItem)); - } - }; - - this.handleRightArrow = function (isCtrl) { - if (isCtrl) { - this.layoutHandler.moveItemRight (this.activeItem); - jQuery(this.findElementToFocus (this.activeItem)).focus(); - } else { - this.focusItem (this.layoutHandler.getRightSibling (this.activeItem)); - } - }; - - this.handleLeftArrow = function (isCtrl) { - if (isCtrl) { - this.layoutHandler.moveItemLeft (this.activeItem); - this.findElementToFocus (this.activeItem).focus(); - } else { - this.focusItem (this.layoutHandler.getLeftSibling (this.activeItem)); - } - }; - - this._fetchMessage = function (messagekey) { - var messageID = this.messageNamebase + messagekey; - var node = document.getElementById (messageID); - - return node? node.innerHTML: "[Message not found at id " + messageID + "]"; - }; - - this._setActiveItem = function (anItem) { - this.activeItem = anItem; - this._updateActiveDescendent(); - }; - - this._updateActiveDescendent = function() { - if (this.activeItem) { - this.domNode.attr ("aaa:activedescendent", this.activeItem.id); - } else { - this.domNode.removeAttr ("aaa:activedescendent"); - } - }; - - var dropMarker; // private scratch variable - - /** - * evt.data - the droppable DOM element. - */ - function trackMouseMovement (evt) { - if (thisReorderer.layoutHandler.isMouseBefore (evt, evt.data)) { - jQuery (evt.data).before (dropMarker); - } - else { - jQuery (evt.data).after (dropMarker); - } - } - - /** - * Given an item, make it draggable. - */ - function setUpDraggable (anItem) { - anItem.draggable ({ - helper: function() { - theAvatar = jQuery (this).clone(); - jQuery (theAvatar).removeAttr ("id"); - jQuery ("[id]", theAvatar).removeAttr ("id"); - jQuery (":hidden", theAvatar).remove(); - jQuery ("input", theAvatar).attr ("disabled", "true"); - theAvatar.addClass (thisReorderer.cssClasses.avatar); - return theAvatar; - }, - start: function (e, ui) { - thisReorderer.focusItem (ui.draggable.element); - jQuery (ui.draggable.element).addClass (thisReorderer.cssClasses.dragging); - ui.draggable.element.setAttribute ("aaa:grab", "true"); - - // In order to create valid html, the drop marker is the same type as the node being dragged. - // This creates a confusing UI in cases such as an ordered list. - // drop marker functionality should be made pluggable. - dropMarker = document.createElement (ui.draggable.element.tagName); - jQuery (dropMarker).addClass (thisReorderer.cssClasses.dropMarker); - dropMarker.style.visibility = "hidden"; - }, - stop: function(e, ui) { - jQuery (ui.draggable.element).removeClass (thisReorderer.cssClasses.dragging); - thisReorderer.activeItem.setAttribute ("aaa:grab", "supported"); - thisReorderer.domNode.focus(); - if (dropMarker.parentNode) { - dropMarker.parentNode.removeChild (dropMarker); - } - theAvatar = null; - } - }); - - } // end setUpDraggable() - - /** - * Make item a drop target. - */ - function setUpDroppable (anItem, selector) { - anItem.droppable ({ - accept: selector, - tolerance: "pointer", - over: function (e, ui) { - // the second parameter to bind() can be accessed through the event as event.data - jQuery (ui.droppable.element).bind ("mousemove", ui.droppable.element, trackMouseMovement); - jQuery (theAvatar).bind ("mousemove", ui.droppable.element, trackMouseMovement); - dropMarker.style.visibility = "visible"; - }, - out: function (e, ui) { - dropMarker.style.visibility = "hidden"; - jQuery (ui.droppable.element).unbind ("mousemove", trackMouseMovement); - jQuery (theAvatar).unbind ("mousemove", trackMouseMovement); - }, - drop: function (e, ui) { - thisReorderer.layoutHandler.mouseMoveItem(e, ui.draggable.element, ui.droppable.element); - jQuery (ui.droppable.element).unbind ("mousemove", trackMouseMovement); - jQuery (theAvatar).unbind ("mousemove", trackMouseMovement); - } - }); - - } // end setUpDroppable(). - - /** - * Given an item, make it a draggable and a droppable with the relevant properties and functions. - * @param anItem The element to make draggable and droppable. - * @param selector The jQuery selector(s) that select all the orderables. - */ - function setUpDnDItem (anItem, selector) { - anItem.mouseover ( - function () { - jQuery (this).addClass (thisReorderer.cssClasses.hover); - } - ); - - anItem.mouseout ( - function () { - jQuery (this).removeClass (thisReorderer.cssClasses.hover); - } - ); - - // Make anItem draggable and a drop target (in the jQuery UI sense). - setUpDraggable (anItem); - setUpDroppable (anItem, selector); - - } // end setUpDnDItem() - - function initOrderables() { - var items = thisReorderer.orderableFinder (thisReorderer.domNode.get(0)); - if (items.length === 0) { - return; - } - - // Create a selector based on the ids of the nodes for use with drag and drop. - // This should be replaced with using the actual nodes rather then a selector - // but will require a patch to jquery's DnD. - // See: FLUID-71, FLUID-112 - var selector = ""; - for (var i = 0; i < items.length; i++) { - var item = items[i]; - selector += "[id=" + item.id + "]"; - if (i !== items.length - 1) { - selector += ", "; - } - } - - // Setup orderable item including drag and drop. - for (i = 0; i < items.length; i++) { - jQuery (items[i]).addClass (thisReorderer.cssClasses.defaultStyle); - setUpDnDItem (jQuery (items[i]), selector); - } - - // Add any other drop targets (e.g., any unmoveable ones). - if ((thisReorderer.droppableFinder) && (thisReorderer.droppableFinder.constructor === Function)) { - var extraDropTargets = thisReorderer.droppableFinder (thisReorderer.domNode); - for (i = 0; i < extraDropTargets.length; i++) { - var jExtraDropTarget = jQuery (extraDropTargets[i]); - if (!jExtraDropTarget.droppableInstance()) { - setUpDroppable (jExtraDropTarget, selector); - } - } - } - } // end initOrderables(). - - /** - * Finds the "orderable" parent element given a child element. - */ - this._findReorderableParent = function (childElement, items) { - if (!childElement) { - return null; - } - else { - for (var i=0; i orderables.length) { - index = 0; - } - - return {item: orderables[index], hasWrapped: hasWrapped}; - }, - - /* - * Returns an object containing the item that is to the right of the given item - * and a flag indicating whether or not the process has 'wrapped' around the end of - * the row that the given item is in - */ - getRightSiblingInfo: function (item, orderables) { - return this.getSiblingInfo (item, orderables, 1); - }, - - /* - * Returns an object containing the item that is to the left of the given item - * and a flag indicating whether or not the process has 'wrapped' around the end of - * the row that the given item is in - */ - getLeftSiblingInfo: function (item, orderables) { - return this.getSiblingInfo (item, orderables, -1); - }, - - /* - * Returns an object containing the item that is below the given item in the current grid - * and a flag indicating whether or not the process has 'wrapped' around the end of - * the column that the given item is in. The flag is necessary because when an image is being - * moved to the resulting item location, the decision of whether or not to insert before or - * after the item changes if the process wrapped around the column. - */ - getItemInfoBelow: function (inItem, orderables) { - var curCoords = jQuery (inItem).offset(); - var i, iCoords; - var firstItemInColumn, currentItem; - - for (i = 0; i < orderables.length; i++) { - currentItem = orderables [i]; - iCoords = jQuery (orderables[i]).offset(); - if (iCoords.left === curCoords.left) { - firstItemInColumn = firstItemInColumn || currentItem; - if (iCoords.top > curCoords.top) { - return {item: currentItem, hasWrapped: false}; - } - } - } - - firstItemInColumn = firstItemInColumn || orderables [0]; - return {item: firstItemInColumn, hasWrapped: true}; - }, - - /* - * Returns an object containing the item that is above the given item in the current grid - * and a flag indicating whether or not the process has 'wrapped' around the end of - * the column that the given item is in. The flag is necessary because when an image is being - * moved to the resulting item location, the decision of whether or not to insert before or - * after the item changes if the process wrapped around the column. - */ - getItemInfoAbove: function (inItem, orderables) { - var curCoords = jQuery (inItem).offset(); - var i, iCoords; - var lastItemInColumn, currentItem; - - for (i = orderables.length - 1; i > -1; i--) { - currentItem = orderables [i]; - iCoords = jQuery (orderables[i]).offset(); - if (iCoords.left === curCoords.left) { - lastItemInColumn = lastItemInColumn || currentItem; - if (curCoords.top > iCoords.top) { - return {item: currentItem, hasWrapped: false}; - } - } - } - - lastItemInColumn = lastItemInColumn || orderables [0]; - return {item: lastItemInColumn, hasWrapped: true}; - } - - }; - - // Public layout handlers. - fluid.ListLayoutHandler = function (params) { - var orderableFinder = params.orderableFinder; - var container = params.container; - var orderChangedCallback = params.orderChangedCallback; - var orientation = params.orientation; - - // Unwrap the container if it's a jQuery. - container = (container.jquery) ? container.get(0) : container; - - orderChangedCallback = orderChangedCallback || function () {}; - - orientation = orientation || fluid.orientation.VERTICAL; // default - - this.getRightSibling = function (item) { - return itemInfoFinders.getRightSiblingInfo(item, orderableFinder(container)).item; - }; - - this.moveItemRight = function (item) { - moveItem (item, itemInfoFinders.getRightSiblingInfo(item, orderableFinder(container)), "after", "before"); - orderChangedCallback(); - }; - - this.getLeftSibling = function (item) { - return itemInfoFinders.getLeftSiblingInfo(item, orderableFinder(container)).item; - }; - - this.moveItemLeft = function (item) { - moveItem (item, itemInfoFinders.getLeftSiblingInfo(item, orderableFinder(container)), "before", "after"); - orderChangedCallback(); - }; - - this.getItemBelow = this.getRightSibling; - - this.getItemAbove = this.getLeftSibling; - - this.moveItemUp = this.moveItemLeft; - - this.moveItemDown = this.moveItemRight; - - this.isMouseBefore = function(evt, droppableEl) { - return isMouseBefore(evt, droppableEl, orientation); - }; - - this.mouseMoveItem = function (e, item, relatedItem) { - if (this.isMouseBefore (e, relatedItem)) { - jQuery (relatedItem).before (item); - } else { - jQuery (relatedItem).after (item); - } - orderChangedCallback(); - }; - }; // End ListLayoutHandler - - /* - * Items in the Lightbox are stored in a list, but they are visually presented as a grid that - * changes dimensions when the window changes size. As a result, when the user presses the up or - * down arrow key, what lies above or below depends on the current window size. - * - * The GridLayoutHandler is responsible for handling changes to this virtual 'grid' of items - * in the window, and of informing the Lightbox of which items surround a given item. - */ - fluid.GridLayoutHandler = function (params) { - fluid.ListLayoutHandler.call (this, params); - - var orderableFinder = params.orderableFinder; - var container = params.container; - var orderChangedCallback = params.orderChangedCallback; - var orientation = fluid.orientation.HORIZONTAL; - - // Unwrap the container if it's a jQuery. - container = (container.jquery) ? container.get(0) : container; - - orderChangedCallback = orderChangedCallback || function () {}; - - this.getItemBelow = function(item) { - return itemInfoFinders.getItemInfoBelow (item, orderableFinder(container)).item; - }; - - this.moveItemDown = function (item) { - moveItem (item, itemInfoFinders.getItemInfoBelow (item, orderableFinder(container)), "after", "before"); - orderChangedCallback(); - }; - - this.getItemAbove = function (item) { - return itemInfoFinders.getItemInfoAbove (item, orderableFinder(container)).item; - }; - - this.moveItemUp = function (item) { - moveItem (item, itemInfoFinders.getItemInfoAbove (item, orderableFinder(container)), "before", "after"); - orderChangedCallback(); - }; - - // We need to override ListLayoutHandler.isMouseBefore to ensure that the local private - // orientation is used. - this.isMouseBefore = function(evt, droppableEl) { - return isMouseBefore(evt, droppableEl, orientation); - }; - - }; // End of GridLayoutHandler - - fluid.portletPerms = fluid.portletPerms || {}; - fluid.portletPerms.canDrop = function (perms, indexOfItem, indexOfTarget, position) { - return (!!perms[indexOfItem][indexOfTarget][position]); - }; - - /* - * PortletLayout helper object. - */ - fluid.PortletLayout = function() { - - /** - * Calculate the location of the item and the column in which it resides. - * @return An object with column index and item index (within that column) properties. - * These indices are -1 if the item does not exist in the grid. - */ - this.calcColumnAndItemIndex = function (item, portletLayoutJSON) { - var indices = { columnIndex: -1, itemIndex: -1 }; - for (var col = 0; col < portletLayoutJSON.columns.length; col++) { - var itemIndex = jQuery (portletLayoutJSON.columns[col].children).index (item.id); - if (itemIndex !== -1) { - indices.columnIndex = col; - indices.itemIndex = itemIndex; - break; - } - } - return indices; - }; - - /** - * Return the first orderable item in the given column. - */ - this.findFirstOrderableSiblingInColumn = function (columnIndex, orderableItems, portletLayoutJSON) { - // Pull out the portlet id of the top-most sibling in the column. - var topMostOrderableSibling = null; - var itemIndex = 0; - var column = portletLayoutJSON.columns[columnIndex]; - if (column) { - var id = column.children[itemIndex]; - topMostOrderableSibling = jQuery ("#" + id)[0]; - // loop down the column looking for first orderable portlet (i.e. skip over non-movable portlets) - while (orderableItems.index (topMostOrderableSibling) === -1) { - itemIndex += 1; - id = column.children[itemIndex]; - topMostOrderableSibling = jQuery ("#" + id).get (0); - } - } - return topMostOrderableSibling; - }; - - /** - * Return the number of items in the given column. If the column index - * is out of bounds, this returns -1. - */ - this.numItemsInColumn = function (columnIndex, portletLayoutJSON) { - if ((columnIndex < 0) || (columnIndex > portletLayoutJSON.columns.length)) { - return -1; - } - else { - return portletLayoutJSON.columns[columnIndex].children.length; - } - }; - - this.numColumns = function (layout) { - return layout.columns.length; - }; - - this.findLinearIndex = function (itemId, layout) { - var columns = layout.columns; - var linearIndex = 0; - - for (var i = 0; i < columns.length; i++) { - var idsInCol = columns[i].children; - for (var j = 0; j < idsInCol.length; j++) { - if (idsInCol[j] === itemId) { - return linearIndex; - } - linearIndex++; - } - } - - return -1; - }; - - /** - * Move an item within the portletLayoutJSON object. - */ - this.updateLayout = function (item, relativeItem, placement, portletLayoutJSON) { - if (!item || !relativeItem) { return; } - var itemIndices = this.calcColumnAndItemIndex (item, portletLayoutJSON); - - var itemId = portletLayoutJSON.columns[itemIndices.columnIndex].children[itemIndices.itemIndex]; - portletLayoutJSON.columns[itemIndices.columnIndex].children.splice (itemIndices.itemIndex, 1); - - var relativeItemIndices = this.calcColumnAndItemIndex (relativeItem, portletLayoutJSON); - var targetCol = portletLayoutJSON.columns[relativeItemIndices.columnIndex].children; - targetCol.splice (relativeItemIndices.itemIndex + (placement === "before"? 0 : 1), 0, itemId); - }; - }; // End of PortletLayout. - - /* - * Portlet Layout Handler for reordering portlet-type markup. - * - * General movement guidelines: - * - * - Arrowing sideways will always go to the top (moveable) portlet in the column - * - Moving sideways will always move to the top available drop target in the column - * - Wrapping is not necessary at this first pass, but is ok - */ - fluid.PortletLayoutHandler = function (params) { - var orderableFinder = params.orderableFinder; - var container = params.container; - var orderChangedCallback = params.orderChangedCallback; - var portletLayoutJSON = params.portletLayout; - var targetPerms = params.dropTargetPermissions; - var orientation = fluid.orientation.VERTICAL; - - var portletLayout = new fluid.PortletLayout(); - - // Unwrap the container if it's a jQuery. - container = (container.jquery) ? container.get(0) : container; - - orderChangedCallback = orderChangedCallback || function () {}; - - // Private Methods. - /* - * A general get{Above|Below}Sibling() given an item and a direction. - * The direction is encoded by either a +1 to move down, or a -1 to - * move up, and that value is used internally as an increment or - * decrement, respectively, of the index of the given item. - * This implementation does not wrap around. - */ - var getVerticalSibling = function (item, /* +1, -1 */ incDecrement) { - var orderables = orderableFinder (container); - var index = jQuery(orderables).index(item) + incDecrement; - - // If we wrap, backup - if ((index === -1) || (index === orderables.length)) { - return null; - } - // Handle case where the passed-in item is *not* an "orderable" - // (or other undefined error). - // - else if (index < -1 || index > orderables.length) { - index = 0; - } - - return orderables[index]; - }; - - /* - * A general get{Beside}SiblingInfo() given an item and a direction. - * The direction is encoded by either a +1 to move right, or a -1 to - * move left. - * Currently, the horizontal sibling defaults to the top orderable item in the - * neighboring column. - */ - var getHorizontalSibling = function (item, /* +1, -1 */ incDecrement) { - var orderables = orderableFinder (container); - - // go through all the children and find which column the passed in item is located in. - // Save that column if found. - var colIndex = portletLayout.calcColumnAndItemIndex (item, portletLayoutJSON).columnIndex; - if (colIndex === -1) { - return null; - } - var sibling = portletLayout.findFirstOrderableSiblingInColumn (colIndex + incDecrement, orderables, portletLayoutJSON); - return sibling; - - }; - - // These methods are public only for our unit tests. They need to be refactored into a portletlayout object. - var isFirstInColumn = function (item) { - var position = portletLayout.calcColumnAndItemIndex (item, portletLayoutJSON); - return (position.itemIndex === 0) ? true : false; - }; - - var isLastInColumn = function (item) { - var position = portletLayout.calcColumnAndItemIndex (item, portletLayoutJSON); - return (position.itemIndex === portletLayout.numItemsInColumn (position.columnIndex, portletLayoutJSON)-1) ? true : false; - }; - - var isInLeftmostColumn = function (item) { - if (portletLayout.calcColumnAndItemIndex (item, portletLayoutJSON).columnIndex === 0) { - return true; - } else { - return false; - } - }; - - var isInRightmostColumn = function (item) { - if (portletLayout.calcColumnAndItemIndex (item, portletLayoutJSON).columnIndex === portletLayout.numColumns (portletLayoutJSON) - 1) { - return true; - } else { - return false; - } - }; - - var canDrop = function (itemId, relatedItemId, position) { - return fluid.portletPerms.canDrop( - targetPerms, - portletLayout.findLinearIndex(itemId, portletLayoutJSON), - portletLayout.findLinearIndex(relatedItemId, portletLayoutJSON), - position); - }; - - var moveBefore = function (item, relatedItem) { - if (!canDrop (item.id, relatedItem.id, fluid.position.BEFORE)) { - return; - } - - jQuery (relatedItem).before (item); - portletLayout.updateLayout (item, relatedItem, "before", portletLayoutJSON); - portletLayoutJSON = orderChangedCallback() || portletLayoutJSON; - }; - - var moveAfter = function (item, relatedItem) { - if (!canDrop (item.id, relatedItem.id, fluid.position.AFTER)) { - return; - } - - jQuery (relatedItem).after (item); - portletLayout.updateLayout (item, relatedItem, "after", portletLayoutJSON); - portletLayoutJSON = orderChangedCallback() || portletLayoutJSON; - }; - - // Public Methods - - this.getRightSibling = function (item) { - if (isInRightmostColumn(item)) { - return item; - } else { - return getHorizontalSibling(item, 1); - } - }; - - this.moveItemRight = function (item) { - var rightSibling = this.getRightSibling (item); - jQuery (rightSibling).before (item); - portletLayout.updateLayout (item, rightSibling, "before", portletLayoutJSON); - // first, stringify the json before sending it - portletLayoutJSON = orderChangedCallback() || portletLayoutJSON; - // the return value will actually be a big json object with two parts - // we'll have to parse it, and separate the two parts - }; - - this.getLeftSibling = function (item) { - if (isInLeftmostColumn(item)) { - return item; - } else { - return getHorizontalSibling(item, -1); - } - }; - - this.moveItemLeft = function (item) { - var leftSibling = this.getLeftSibling(item); - jQuery (leftSibling).before (item); - portletLayout.updateLayout (item, leftSibling, "before", portletLayoutJSON); - portletLayoutJSON = orderChangedCallback() || portletLayoutJSON; - }; - - this.getItemAbove = function (item) { - if (isFirstInColumn(item)) { - return item; - } else { - return getVerticalSibling (item, -1); - } - }; - - this.moveItemUp = function (item) { - var siblingAbove = this.getItemAbove(item); - moveBefore (item, siblingAbove); - }; - - this.getItemBelow = function (item) { - if (isLastInColumn(item)) { - return item; - } else { - return getVerticalSibling (item, 1); - } - }; - - this.moveItemDown = function (item) { - var siblingBelow = this.getItemBelow(item); - moveAfter (item, siblingBelow); - }; - - this.isMouseBefore = function(evt, droppableEl) { - return isMouseBefore(evt, droppableEl, orientation); - }; - - this.mouseMoveItem = function (e, item, relatedItem) { - if (this.isMouseBefore (e, relatedItem)) { - moveBefore (item, relatedItem); - } else { - moveAfter (item, relatedItem); - } - }; - - }; // End PortalLayoutHandler -}) (); - diff --git a/mods/photo_album/fluid/component-templates/js/jquery.tabindex/LICENSE.txt b/mods/photo_album/fluid/component-templates/js/jquery.tabindex/LICENSE.txt deleted file mode 100755 index 452f77ad1..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.tabindex/LICENSE.txt +++ /dev/null @@ -1,307 +0,0 @@ -GNU General Public License, Version 2.0 -*************************************** - -Copyright 2007 University of Toronto - - 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. - -MIT License -*********** - -Copyright 2007 University of Toronto, http://fluidproject.org - -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. \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/jquery.tabindex/jquery.tabindex.js b/mods/photo_album/fluid/component-templates/js/jquery.tabindex/jquery.tabindex.js deleted file mode 100644 index 4c8ee5ac6..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.tabindex/jquery.tabindex.js +++ /dev/null @@ -1,52 +0,0 @@ -/* -Copyright 2007 University of Toronto - -Licensed under the GNU Public License or the MIT license. -You may not use this file except in compliance with one these -Licenses. - -You may obtain a copy of the GPL and MIT License at -https://source.fluidproject.org/svn/sandbox/tabindex/trunk/LICENSE.txt -*/ -(function ($) { - // Private functions. - var normalizeTabIndexName = function () { - return $.browser.msie ? "tabIndex" : "tabindex"; - } - - var getValue = function (elements) { - if (!elements.hasTabIndex ()) { - return undefined; - } - - // Get the attribute (.attr () doesn't work for tabIndex in IE) and return it as a number value. - var value = elements[0].getAttribute (normalizeTabIndexName ()); - return Number (value); - }; - - var setValue = function (elements, toIndex) { - return elements.each (function (i, item) { - $ (item).attr (normalizeTabIndexName (), toIndex); - }); - }; - - // Public methods. - $.fn.tabIndex = function (toIndex) { - if (toIndex !== null && toIndex !== undefined) { - return setValue (this, toIndex); - } else { - return getValue (this); - } - }; - - $.fn.removeTabIndex = function () { - return this.each(function (i, item) { - $ (item).removeAttr (normalizeTabIndexName ()); - }); - }; - - $.fn.hasTabIndex = function () { - var attributeNode = this[0].getAttributeNode (normalizeTabIndexName ()); - return attributeNode ? attributeNode.specified : false; - }; -}) (jQuery); diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/GPL-LICENSE.txt b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/GPL-LICENSE.txt deleted file mode 100644 index 11dddd00e..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/GPL-LICENSE.txt +++ /dev/null @@ -1,278 +0,0 @@ - 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/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/MIT-LICENSE.txt b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/MIT-LICENSE.txt deleted file mode 100644 index 965a83130..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/MIT-LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -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/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/jquery.dimensions.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/jquery.dimensions.js deleted file mode 100644 index b7e6f7ec4..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/jquery.dimensions.js +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net) - * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) - * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. - * - * $LastChangedDate: 2007-09-11 02:38:31 +0000 (Tue, 11 Sep 2007) $ - * $Rev: 3238 $ - * - * Version: @VERSION - * - * Requires: jQuery 1.2+ - */ - -(function($){ - -$.dimensions = { - version: '@VERSION' -}; - -// Create innerHeight, innerWidth, outerHeight and outerWidth methods -$.each( [ 'Height', 'Width' ], function(i, name){ - - // innerHeight and innerWidth - $.fn[ 'inner' + name ] = function() { - if (!this[0]) return; - - var torl = name == 'Height' ? 'Top' : 'Left', // top or left - borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right - - return this[ name.toLowerCase() ]() + num(this, 'padding' + torl) + num(this, 'padding' + borr); - }; - - // outerHeight and outerWidth - $.fn[ 'outer' + name ] = function(options) { - if (!this[0]) return; - - var torl = name == 'Height' ? 'Top' : 'Left', // top or left - borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right - - options = $.extend({ margin: false }, options || {}); - - return this[ name.toLowerCase() ]() - + num(this, 'border' + torl + 'Width') + num(this, 'border' + borr + 'Width') - + num(this, 'padding' + torl) + num(this, 'padding' + borr) - + (options.margin ? (num(this, 'margin' + torl) + num(this, 'margin' + borr)) : 0); - }; -}); - -// Create scrollLeft and scrollTop methods -$.each( ['Left', 'Top'], function(i, name) { - $.fn[ 'scroll' + name ] = function(val) { - if (!this[0]) return; - - return val != undefined ? - - // Set the scroll offset - this.each(function() { - this == window || this == document ? - window.scrollTo( - name == 'Left' ? val : $(window)[ 'scrollLeft' ](), - name == 'Top' ? val : $(window)[ 'scrollTop' ]() - ) : - this[ 'scroll' + name ] = val; - }) : - - // Return the scroll offset - this[0] == window || this[0] == document ? - self[ (name == 'Left' ? 'pageXOffset' : 'pageYOffset') ] || - $.boxModel && document.documentElement[ 'scroll' + name ] || - document.body[ 'scroll' + name ] : - this[0][ 'scroll' + name ]; - }; -}); - -$.fn.extend({ - position: function() { - var left = 0, top = 0, elem = this[0], offset, parentOffset, offsetParent, results; - - if (elem) { - // Get *real* offsetParent - offsetParent = this.offsetParent(); - - // Get correct offsets - offset = this.offset(); - parentOffset = offsetParent.offset(); - - // Subtract element margins - offset.top -= num(elem, 'marginTop'); - offset.left -= num(elem, 'marginLeft'); - - // Add offsetParent borders - parentOffset.top += num(offsetParent, 'borderTopWidth'); - parentOffset.left += num(offsetParent, 'borderLeftWidth'); - - // Subtract the two offsets - results = { - top: offset.top - parentOffset.top, - left: offset.left - parentOffset.left - }; - } - - return results; - }, - - offsetParent: function() { - var offsetParent = this[0].offsetParent; - while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static') ) - offsetParent = offsetParent.offsetParent; - return $(offsetParent); - } -}); - -var num = function(el, prop) { - return parseInt($.css(el.jquery?el[0]:el,prop))||0; -}; - -})(jQuery); \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.css deleted file mode 100644 index a5ae5596a..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.css +++ /dev/null @@ -1,11 +0,0 @@ -.dark { background:#111; color:snow; font:10pt Calibri, Arial, sans-serif; } -.dark a, a.dark { color:#68D; outline:none; } -.dark a:visited, a.dark:visited { color:#D66; } -.dark a:hover, a.dark:hover { color:#FFF; } -.dark fieldset { border:1px solid #282828; } -.dark legend { color:#CCC; font:.8em Verdana, san-serif; } -.dark button, button.dark, .dark input, input.dark { padding:2px 4px; font:.9em Consolas, Verdana, san-serif; } -.dark textarea, textarea.dark { padding:2px 4px; font:.9em Consolas, Courier New, san-serif; width:20em; height:5em; overflow:auto; } -.dark select, select.dark { padding:3px 0 3px 4px; font:.9em Verdana, san-serif; } -.dark label { font-weight:bold; } - diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.form.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.form.css deleted file mode 100644 index 9be8c9ae0..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.form.css +++ /dev/null @@ -1,192 +0,0 @@ -.dark .ui-form-hide { position:absolute; left:-2000em; } - - -/*( fieldset )*/ -.dark .ui-form-fieldset, -.dark.ui-form-fieldset { - display:block; - border:1px solid #333; - padding:0; -} -.dark .ui-form-fieldset, -.dark.ui-form-fieldset { - margin-top:1.6em; -} -.dark fieldset.ui-form { - margin:0; - border:1px solid #111; - color:snow; -} -.dark fieldset.ui-form { background:#181818; } -.dark .ui-form-legend, -.dark.ui-form-legend { - display:block; - text-align:left; - border:1px solid #333; - background:#222; - margin:-1.05em 0 0 0; -} -.dark legend.ui-form { - display:block; - color:snow; - font-weight:bold; - background:#222; - border-top:1px dotted #282828; - border-bottom:1px dotted #282828; - margin:-1px 2px; - padding:0 2px 2px; -} - - -/*( inputs )*/ -.dark .ui-form-text, -.dark .ui-form-password, -.dark.ui-form-text, -.dark.ui-form-password { - border:1px solid #333; - padding:2px 0 3px; -} - -.dark .ui-form-textarea, -.dark.ui-form-textarea { - display:block; - border:1px solid #333; - padding:0; -} -.dark .ui-form-textarea .ui-form-inner, -.dark.ui-form-textarea .ui-form-inner { - display:block; - border:1px solid #111; - overflow:hidden; -} -.dark .ui-form-text.focus, -.dark .ui-form-password.focus, -.dark .ui-form-textarea.focus, -.dark.ui-form-text.focus, -.dark.ui-form-password.focus, -.dark.ui-form-textarea.focus { - border:1px solid #444; -} - -.dark .ui-form-text input, -.dark .ui-form-password input, -.dark textarea.ui-form { - margin:0; - border:1px solid #111; - background:#222; color:snow; -} -.dark textarea.ui-form { border:none; } -.dark .ui-form-text input:focus, -.dark .ui-form-password input:focus, -.dark textarea.ui-form:focus { background:#1D1D1D; } - - -/*( buttons )*/ -.dark .ui-form-buttons, -.dark.ui-form-buttons { - display:block; float:left; - height:40px; - background:url(dark.form.png) left -40px; - border:none; - color:#CCC; - padding-left:25px; - margin:0 4px; -} -.dark .ui-form-buttons .ui-form-inner, -.dark.ui-form-buttons .ui-form-inner { - display:block; float:left; - height:40px; - background:url(dark.form.png) right -40px; - margin-right:-5px; - padding-right:5px; -} -.dark .ui-form-buttons .ui-form, -.dark.ui-form-buttons .ui-form { - background:transparent; - border:none; - color:#DDD; - padding:9px 25px 10px 25px; - *padding:9px 15px 10px 15px; - margin-left:-25px; -} -.dark .ui-form-buttons.hover, -.dark.ui-form-buttons.hover { - background-position:left -80px; -} -.dark .ui-form-buttons.hover .ui-form-inner, -.dark.ui-form-buttons.hover .ui-form-inner { - background-position:right -80px; -} -.dark .ui-form-buttons.hover .ui-form, -.dark.ui-form-buttons.hover .ui-form { - color:#FFF; -} -.dark .ui-form-buttons.focus, -.dark.ui-form-buttons.focus { - background-position:left -80px; -} -.dark .ui-form-buttons.focus .ui-form-inner, -.dark.ui-form-buttons.focus .ui-form-inner { - background-position:right -80px; -} -.dark .ui-form-buttons.focus .ui-form, -.dark.ui-form-buttons.focus .ui-form { - color:#FFF; -} -.dark .ui-form-buttons.active, -.dark.ui-form-buttons.active { - background-position:left -120px; -} -.dark .ui-form-buttons.active .ui-form-inner, -.dark.ui-form-buttons.active .ui-form-inner { - background-position:right -120px; -} -.dark .ui-form-buttons.active .ui-form, -.dark.ui-form-buttons.active .ui-form { - background-position:right -120px; -} - - -/*( checkbox )*/ -.dark .ui-form-checkbox { - background:url(dark.form.png) -221px 0; - padding:2px 0 1px 0; -} -.dark .ui-form-checkbox .ui-form-content { - padding:0 7px 1px 7px; - color:#222; - cursor:default; -} -.dark .ui-form-checkbox.hover, -.dark .ui-form-checkbox.focus, -.dark .ui-form-checkbox.active { - background-position: -221px -20px; -} -.dark .ui-form-checkbox.selected .ui-form-inner { - background:url(dark.form.png) -201px -2px; -} - - -/*( radio )*/ -.dark .ui-form-radio { - padding:2px 1px; - background:url(dark.form.png) -1px -1px; -} -.dark .ui-form-radio .ui-form-content { - padding:1px 6px 1px 7px; - *padding:0 6px 0 7px; - color:#222; - cursor:default; -} -.dark .ui-form-radio.hover, -.dark .ui-form-radio.focus, -.dark .ui-form-radio.active { - background-position: -1px -21px; -} -.dark .ui-form-radio.selected .ui-form-inner { - background:url(dark.form.png) -22px -3px; -} -.dark .ui-form-radio.selected .ui-form-content { - color:#CDD6E7; -} - diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.form.png b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/dark/dark.form.png deleted file mode 100644 index ec28222fbb177bd98ffc86be964b2b682f0e4992..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12308 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 .ui-tree-node-text { - background: #448; -} - -.dark .ui-tree-node-button { - border: 1px solid #222; - padding-left:1px; - color: #666; - font:7pt Courier New,monospace; - margin-top: 0.5em; - position: absolute; - left: 0.2em; - width: 0.7em; - height: 0.8em; - line-height: 0.8em; - text-decoration: none; - display:none; -} - -.dark .ui-tree-node-expanded > .ui-tree-node-button { - background: #181818; - display:block; -} - -.dark .ui-tree-node-collapsed > .ui-tree-node-button { - background: #222; - display:block; -} - -.dark .ui-tree-node-moving > .ui-tree-node-button { - background: #282828; -} - -.dark .ui-tree-node-moving > .ui-tree-node-text { - background: #474; color:#FFF; -} - diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.accordion.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.accordion.css deleted file mode 100644 index 4bee95175..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.accordion.css +++ /dev/null @@ -1,12 +0,0 @@ -ul.ui-accordion-container { margin: 0; padding: 0; list-style-type: none; } -ul.ui-accordion-container li { position: relative; margin: 0; margin-bottom: 2px; padding: 0; background-image: url(i/accordion-left.png); background-repeat: no-repeat; } -ul.ui-accordion-container li a.ui-accordion-link { display: block; padding-left: 5px; margin-right: 3px; height: 28px; background-image: url(i/accordion-middle.png); color: #000; text-decoration: none; line-height: 28px; } -ul.ui-accordion-container li div.ui-accordion-right { background-image: url(i/accordion-right.png); position: absolute; top: 0px; right: 0px; height: 28px; width: 3px; } - -ul.ui-accordion-container li:hover { background-image: url(i/accordion-left-over.png); } -ul.ui-accordion-container li:hover a.ui-accordion-link { background-image: url(i/accordion-middle-over.png); } -ul.ui-accordion-container li:hover div.ui-accordion-right { background-image: url(i/accordion-right-over.png); } - -ul.ui-accordion-container li.active { background-image: url(i/accordion-left-act.png); } -ul.ui-accordion-container li.active a.ui-accordion-link { background-image: url(i/accordion-middle-act.png); } -ul.ui-accordion-container li.active div.ui-accordion-right { background-image: url(i/accordion-right-act.png); } \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.all.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.all.css deleted file mode 100644 index fed27deb7..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.all.css +++ /dev/null @@ -1,9 +0,0 @@ -@import "flora.css"; -@import "flora.shadow.css"; -@import "flora.resizable.css"; -@import "flora.slider.css"; -@import "flora.accordion.css"; -@import "flora.tabs.css"; -@import "flora.dialog.css"; -@import "flora.tablesorter.css"; -@import "flora.calendar.css"; diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.calendar.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.calendar.css deleted file mode 100644 index dedcf0ca6..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.calendar.css +++ /dev/null @@ -1,167 +0,0 @@ -/* Main Style Sheet for jQuery Calendar */ -#calendar_div, .calendar_inline { - font-family: Arial, Helvetica, sans-serif; - font-size: 14px; - padding: 0; - margin: 0; - background: #ddd; -} -#calendar_div { - display: none; - border: 1px solid #FF9900; - z-index: 10; /*must have*/ -} -#calendar_div, .calendar_control, .calendar_links, .calendar_header, .calendar { - width: 185px; -} -.calendar_inline { - float: left; - display: block; - border: 0; -} -.calendar_dialog { - padding: 5px !important; - border: 4px ridge #ddd !important; -} -button.calendar_trigger { - width: 25px; -} -img.calendar_trigger { - margin: 2px; - vertical-align: middle; -} -.calendar_prompt { - float: left; - width: 181px; - padding: 2px; - background: #ddd; - color: #000; -} -* html .calendar_prompt { - width: 185px; -} -.calendar_control, .calendar_links, .calendar_header, .calendar { - clear: both; - float: left; - color: #fff; -} -.calendar_control { - background: #FF9900; -} -.calendar_links { - background: #E0F4D7; -} -.calendar_control, .calendar_links { - font-weight: bold; - font-size: 80%; - letter-spacing: 1px; -} -.calendar_links label { /* disabled links */ - padding: 2px 5px; - color: #888; -} -.calendar_clear, .calendar_prev { - float: left; -} -.calendar_current { - float: left; - width: 35%; - text-align: center; -} -.calendar_close, .calendar_next { - float: right; -} -.calendar_header { - background: #83C948; - text-align: center; - font-weight: bold; -} -.calendar_header select { - background: #83C948; - color: #000; - border: 0px; - font-weight: bold; -} -.calendar { - background: #ccc; - text-align: center; - font-size: 100%; -} -.calendar a { - display: block; - width: 100%; -} -.calendar .calendar_titleRow { - background: #B1DB87; - color: #000 !important; -} -.calendar .calendar_daysRow { - background: #FFF; - color: #666; -} -.calendar .calendar_daysCell { - color: #000; - border: 1px solid #ddd; -} -#calendar .calendar_daysCell a{ - display: block; -} -.calendar .calendar_weekEndCell { - background: #E0F4D7; -} -.calendar .calendar_daysCellOver { - background: #fff; - border: 1px solid #777; -} -.calendar .calendar_unselectable { - color: #888; -} -.calendar_today { - background: #ccc !important; -} -.calendar_currentDay { - background: #999 !important; -} - -/* ________ CALENDAR LINKS _______ - -** Reset link properties and then override them with !important */ -#calendar_div a, .calendar_inline a { - cursor: pointer; - margin: 0; - padding: 0; - background: none; - color: #000; -} -.calendar_inline .calendar_links a { - padding: 0 5px !important; -} -.calendar_control a, .calendar_links a { - padding: 2px 5px !important; - color: #000 !important; -} -.calendar_titleRow a { - color: #000 !important; -} -.calendar_control a:hover { - /*background: #fdd !important;*/ - color: #333 !important; -} -.calendar_links a:hover, .calendar_titleRow a:hover { - background: #FFF !important; - color: #333 !important; -} - -/* ___________ IE6 IFRAME FIX ________ */ - -.calendar_cover { - display: none; /*sorry for IE5*/ - display/**/: block; /*sorry for IE5*/ - position: absolute; /*must have*/ - z-index: -1; /*must have*/ - filter: mask(); /*must have*/ - top: -4px; /*must have*/ - left: -4px; /*must have*/ - width: 193px; /*must have to match width and borders*/ - height: 200px; /*must have to match maximum height*/ -} diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.css deleted file mode 100644 index b38529688..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.css +++ /dev/null @@ -1,2 +0,0 @@ -.ui-wrapper { border: 1px solid #50A029; } -.ui-wrapper input,textarea { border: 0; } \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.dialog.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.dialog.css deleted file mode 100644 index 43dcec6e9..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.dialog.css +++ /dev/null @@ -1,86 +0,0 @@ -/* This file skins dialog */ - -.flora .ui-dialog, -.flora.ui-dialog { - background-color: #e6f7d4; -} - -.flora .ui-dialog .ui-dialog-titlebar, -.flora.ui-dialog .ui-dialog-titlebar { - border-bottom: 1px solid #d8d2aa; - background: #ff9900 url(i/dialog-title.gif) repeat-x; - padding: 0px; - cursor: move; - height: 28px; - _height: 29px; -} - -.flora .ui-dialog .ui-dialog-titlebar-close, -.flora.ui-dialog .ui-dialog-titlebar-close { - width: 16px; - height: 16px; - background: url(i/dialog-titlebar-close.png) no-repeat; - position:absolute; - top: 6px; - right: 7px; - cursor: default; -} - -.flora .ui-dialog .ui-dialog-titlebar-close-hover, -.flora.ui-dialog .ui-dialog-titlebar-close-hover { - background: url(i/dialog-titlebar-close-hover.png) no-repeat; -} - -.flora .ui-dialog .ui-dialog-title, -.flora.ui-dialog .ui-dialog-title { - margin-left: 5px; - color: white; - font-weight: bold; - position: relative; - top: 7px; - left: 4px; -} - -.flora .ui-dialog .ui-dialog-content, -.flora.ui-dialog .ui-dialog-content { - margin: 1.2em; -} - -.flora .ui-dialog .ui-dialog-buttonpane, -.flora.ui-dialog .ui-dialog-buttonpane { - position: absolute; - bottom: 8px; - right: 12px; - width: 100%; - text-align: right; -} - -.flora .ui-dialog .ui-dialog-buttonpane button, -.flora.ui-dialog .ui-dialog-buttonpane button { - margin: 6px; -} - -/* Dialog handle styles */ -.flora .ui-dialog .ui-resizable-n, -.flora.ui-dialog .ui-resizable-n { cursor: n-resize; height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/dialog-n.gif) repeat scroll center top; } - -.flora .ui-dialog .ui-resizable-s, -.flora.ui-dialog .ui-resizable-s { cursor: s-resize; height: 8px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/dialog-s.gif) repeat scroll center top; } - -.flora .ui-dialog .ui-resizable-e, -.flora.ui-dialog .ui-resizable-e { cursor: e-resize; width: 7px; right: 0px; top: 0px; height: 100%; background: transparent url(i/dialog-e.gif) repeat scroll right center; } - -.flora .ui-dialog .ui-resizable-w, -.flora.ui-dialog .ui-resizable-w { cursor: w-resize; width: 7px; left: 0px; top: 0px; height: 100%; background: transparent url(i/dialog-w.gif) repeat scroll right center; } - -.flora .ui-dialog .ui-resizable-se, -.flora.ui-dialog .ui-resizable-se { cursor: se-resize; width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/dialog-se.gif); } - -.flora .ui-dialog .ui-resizable-sw, -.flora.ui-dialog .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/dialog-sw.gif); } - -.flora .ui-dialog .ui-resizable-nw, -.flora.ui-dialog .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 29px; left: 0px; top: 0px; background: transparent url(i/dialog-nw.gif); } - -.flora .ui-dialog .ui-resizable-ne, -.flora.ui-dialog .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 29px; right: 0px; top: 0px; background: transparent url(i/dialog-ne.gif); } diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.menu.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.menu.css deleted file mode 100644 index 6d2dd213c..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.menu.css +++ /dev/null @@ -1,8 +0,0 @@ -.ui-menu-toolbar {z-index:500; list-style:none;} -.ui-menu-toolbar-button {float:left; padding:4px 20px; cursor:pointer;} -.ui-menu-toolbar-button:hover {} -.ui-menu-toolbar-button a {text-decoration:none;} -.ui-menu-items {display:none; padding:0; z-index:500; list-style:none; padding:1px 4px; min-width:80px; *width:80px;} -.ui-menu-item a { text-decoration:none;} -.ui-menu-item-parent { background: url('i/menu-submenu.gif') no-repeat center right; } -.ui-menu-item-disabled {} \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.resizable.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.resizable.css deleted file mode 100644 index 5e30c0c2c..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.resizable.css +++ /dev/null @@ -1,20 +0,0 @@ -/* This file skins resizables */ - -.ui-resizable { position: relative; } - -/* Global handle styles */ -.ui-resizable-handle { position: absolute; display: none; font-size: 0.1px; } -.ui-resizable .ui-resizable-handle { display: block; } -body .ui-resizable-disabled .ui-resizable-handle { display: none; } /* use 'body' to make it more specific (css order) */ -body .ui-resizable-autohide .ui-resizable-handle { display: none; } /* use 'body' to make it more specific (css order) */ - -.ui-resizable-n { cursor: n-resize; height: 6px; width: 100%; top: 0px; left: 0px; background: transparent url(i/resizable-n.gif) repeat scroll center top; } -.ui-resizable-s { cursor: s-resize; height: 6px; width: 100%; bottom: 0px; left: 0px; background: transparent url(i/resizable-s.gif) repeat scroll center top; } - -.ui-resizable-e { cursor: e-resize; width: 6px; right: 0px; top: 0px; height: 100%; background: transparent url(i/resizable-e.gif) repeat scroll right center; } -.ui-resizable-w { cursor: w-resize; width: 6px; left: 0px; top: 0px; height: 100%; background: transparent url(i/resizable-w.gif) repeat scroll right center; } - -.ui-resizable-se { cursor: se-resize; width: 9px; height: 9px; right: 0px; bottom: 0px; background: transparent url(i/resizable-se.gif); } -.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: 0px; bottom: 0px; background: transparent url(i/resizable-sw.gif); } -.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: 0px; top: 0px; background: transparent url(i/resizable-nw.gif); } -.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: 0px; top: 0px; background: transparent url(i/resizable-ne.gif); } \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.shadow.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.shadow.css deleted file mode 100644 index 6c08d44fb..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.shadow.css +++ /dev/null @@ -1,33 +0,0 @@ -/* -.ui-shadow { -background:transparent url(i/shadow.png) no-repeat scroll right bottom; -height: 100px; -margin: 10px; -position: relative; -} - -.ui-shadow-ne { -background:transparent url(i/shadow.png) no-repeat scroll right top; -width: 6px; -height: 6px; -position: absolute; -top: -6px; -right: 0px; -} - -.ui-shadow-sw { -background:transparent url(i/shadow.png) no-repeat scroll left bottom; -width: 6px; -height: 6px; -position: absolute; -bottom: 0px; -left: -6px; -} -*/ - - - - -.ui-shadow { position:relative; } -.ui-shadow-color { background:#030; position:absolute; } /* Can be overidden via js */ - diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.slider.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.slider.css deleted file mode 100644 index b04ace982..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.slider.css +++ /dev/null @@ -1,8 +0,0 @@ -/* This file skins sliders */ - -.ui-slider-handle { position: absolute; height: 23px; width: 12px; top: 0px; left: 0px; background-image: url(i/slider-handle.gif); } -.ui-slider-disabled .ui-slider-handle { opacity: 0.5; filter: alpha(opacity=50); } - -/* Default slider backgrounds */ -.ui-slider-1 { width: 200px; height: 23px; position: relative; background-image: url(i/slider-bg-1.png); background-repeat: no-repeat; background-position: center center; } -.ui-slider-2 { width: 200px; height: 23px; position: relative; background-image: url(i/slider-bg-2.png); background-repeat: no-repeat; background-position: center center; } \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.tablesorter.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.tablesorter.css deleted file mode 100644 index 7d805a766..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.tablesorter.css +++ /dev/null @@ -1,40 +0,0 @@ -/* This file skins tableSorter */ - -table.tablesorter { - font-family:arial; - background-color: #CDCDCD; - margin:10px 0pt 15px; - font-size: 8pt; - width: 100%; - text-align: left; -} -table.tablesorter thead tr th, table.tablesorter tfoot tr th { - background-color: #B1DB87; - border: 1px solid #FFF; - font-size: 8pt; - padding: 4px; -} -table.tablesorter thead tr .header { - background-image: url(i/bg.gif); - background-repeat: no-repeat; - background-position: center right; - cursor: pointer; -} -table.tablesorter tbody td { - color: #3D3D3D; - padding: 4px; - background-color: #FFF; - vertical-align: top; -} -table.tablesorter tbody tr.odd td { - background-color:#E0F4D7; -} -table.tablesorter thead tr .headerSortUp { - background-image: url(i/asc.gif); -} -table.tablesorter thead tr .headerSortDown { - background-image: url(i/desc.gif); -} -table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp { -background-color: #83C948; -} diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.tabs.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.tabs.css deleted file mode 100644 index 4c9227c45..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/flora.tabs.css +++ /dev/null @@ -1,80 +0,0 @@ -@media projection, screen { .ui-tabs-hide { display:none; } } -@media print { .ui-tabs-nav { display: none; } } - -.ui-tabs-nav { - padding-left:10px; - float:left; - width:98%; - border-bottom:1px solid #FFF; - margin:0; -} -.ui-tabs-nav li { - list-style:none; - float:left; - } -.ui-tabs-nav a { - background:url(i/tabs.gif) no-repeat left 4px; - display:block; - height:27px; - padding:0 0 0 4px; - text-decoration:none!important; - margin:1px 5px -2px 0; - font:9pt Verdana; - outline:none; -} -.ui-tabs-nav span { - background:url(i/tabs.gif) no-repeat right 4px; - display:block; - height:27px; - line-height:29px; - padding:0px 13px 0 10px; - margin-right:-3px; - color:#FFF; -} -.ui-tabs-nav .ui-tabs-selected a { - background-position:left -23px; -} -.ui-tabs-nav .ui-tabs-selected a span { - background-position:right -23px; - margin-bottom:0; - cursor:default; - } -.ui-tabs-nav .ui-tabs-disabled a, -.ui-tabs-nav .ui-tabs-disabled a span { - color:#000; - opacity:0.4; - filter:alpha(opacity=40); - cursor:default; -} -.ui-tabs-container { - background:#FFF; - border:1px solid #519E2D; - clear:left; - padding:10px 10px 8px 10px; - *padding-top:3px; - *margin-top:-24px; -} - -/* hacks to get it working in IE */ -.ui-tabs-nav li { - display: inline !important; - position: relative; - _top: -3px; -} -.ui-tabs-nav li a { - display: inline !important; - float: left; - _padding-left: 2px; -} -.ui-tabs-nav li a span { - display: inline !important; - padding-top: 6px; - padding-bottom: 6px; - _padding-bottom: 0px; - position: relative; - top: -2px; - _top: 0px; - _left: 3px; - _padding-bottom: 2px; - _padding-right: 13px; -} diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-left-act.png b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-left-act.png deleted file mode 100644 index bf6ee995ba0c6059a0754a3d2b41ee8b92909600..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 249 zcmV!HWpZ|Z5{qqOAf0+LK{qx}u z)MBO|Uw&=?I~ItUc}2Mn7?|ryurRYK00bBSEl!`(vaoFE00000NkvXXu0mjfwohlT diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-left-over.png b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-left-over.png deleted file mode 100644 index 66378e0e6dc3bd1d4b277a6ef41d429bcda0687b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^%s?!|!3HFktYG~Jq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~-c6$N;@IEGZ*O8WEb`Qigl`;V*t`ThU){HLdm3;&I;ukT4` zU|P2Se?7Z_1EVnW;d(|DKBk_c12V_>3;2wcU$aTHN5%zyW6-wVd}O_Ry$Ayn55vxE VDO(Xw$x@)%44$rjF6*2UngGV+I*|YX diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-left.png b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-left.png deleted file mode 100644 index 13344fc9fdd7492a1d4e347362a01c4d62bea6cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^%s?!|!3HFktYG~Jq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~-c6$N;@IEGZ*O8WER_0|K8*R$3C{QQ1-{?iAqOaIE(?d?iu zU|M$ne;u2F1EVnW;d(|DKBk_c12V_>3;48!f3r!n|NOkYpZ$hqq-tHw-=z!!2@K+T WGA6~srw;(lX7F_Nb6Mw<&;$S+Ks|~8 diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-middle-act.png b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-middle-act.png deleted file mode 100644 index cecf4f1504bbb68bfd2730cc4ff4b82e9103cd62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{I!2~4r?VV-=DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_d9MP{BZjv*Ddl4k5)Jm1wRZpzE|`|W+||NUi4lK3m_`bK}# uop_xj0lU-k2LBE>t&?}*F6?Atkzkmm=QG!up>s3P1O`u6KbLh*2~7ax4KE1* diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-middle-over.png b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-middle-over.png deleted file mode 100644 index 251ad11f9b896517cc66601cabe331f91cbcd557..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{I!2~4r?VV-=DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_c!9iA?ZAr-fhEPkaKU+%ZRKSM%7BBSsA{y!`N2@JmXIsE-u SDSr z1<%~X^wgl##FWaylc_c!9iA?ZAr-fhBK}q=UA}HFKT|?NBBO8q{aR*$1O}bG>@V66 SJ5B?tWAJqKb6Mw<&;$Ss$|C>( diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-right-act.png b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-right-act.png deleted file mode 100644 index 1fa479280b9444f6016062e1afe1a1acd8f8ee4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 245 zcmV5=nq00000NkvXXu0mjfyeMdN diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-right-over.png b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-right-over.png deleted file mode 100644 index d676dad801c8f2dd1bba4cff27d3b067ee48e2db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^%s?!|!3HFktYG~Jq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~-c6$N{`IEGZ*O0xNu_PJWk?ON~eYx0^2KmR?S&A`m;yl2m} zC-rJ<8VQe+cpHjmNJz3iklAoRgZ<#o@Bja^TRgwM{l0X>J=_039$x<*FI}c@5y&8r Zz>v)-+b**AP6g0-22WQ%mvv4FO#qQ$K&1cx diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-right.png b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/accordion-right.png deleted file mode 100644 index 543991a2bbd8293ba26ea2b6af1dd2c2566266ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^%s?!|!3HFktYG~Jq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~-c6$N{`IEGZ*N{ahj@#y!8NepM@|L>Da`1$GiVg_br=RJLE zPt~ijX*_uJn4_V1#taG82QnKDXs{pr`ThNWc8lk?m&;2>%)49n_u=j3@1>tjS*Opy aVZczkK(6eDo4^X7@eH1>elF{r5}E)eqC+wO diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/asc.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/asc.gif deleted file mode 100644 index 74157867f25acbc146704d43399d6c3605ba7724..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54 zcmZ?wbhEHb6lGvxXkcJa);0M5|G(l-7DfgJMg|=QAOOiQF!A=tFW`Q0{?_dDi`go= G4AuZ#-wosd diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/bg.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/bg.gif deleted file mode 100644 index fac668fcf42af844a3af0a239fa638ddbc08443c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64 zcmZ?wbhEHb6lLIKXkcJa);0M5|G(l-7DfgJMg|=QAOOiQFp2l{H=O3Yl~fU8)V1~= QTew|n!uOuePzDBT00piR0RR91 diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/desc.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/desc.gif deleted file mode 100644 index 3b30b3c58eabdb47a1c420ad03c8e30b966cc858..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54 zcmZ?wbhEHb6lGvxXkcJa);0M5|G(l-7DfgJMg|=QAOOiQF!A>EGoD<#VNP?1QCB1* GgEatI(+xQQ diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-e.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-e.gif deleted file mode 100644 index 3b8b52189e1de83c8bc194972e981a202990084f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 440 zcmV;p0Z0BvNk%w1VFv){1G4}C00030|Nl^+DO$Av=J(X(_0r+;(BAIN*yzXr00000 z00000000000000000000EC2ui00#i*0{{g7kQ8%J7?N5%>&+ggecc9{B{_=WskSML zuCDyfFdf(Y?(4vu5J$WjZOC4*nEVZo%4c&4buyz@Yn3{cVz*vxH_QEw!Q^mRY;LpP z>$rNJuA}egyjyP9!|8Z?fPQ>|e|>_8hlYiOgNclfi;jwokd%>?l9rQ~o}HkaqMM|e zrkSXis-L5$tD&W-tg)}HvaqhRxwyBswY0juz`Vb^zQM)9#>2*xb_A+TG$w8Q;(6ALNuq9l!E12)hk)7 iWv^;Y+g0t^wP@qQo%^<~*}HD>w%yCNuUw%K002Aw%jQb} diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-n.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-n.gif deleted file mode 100644 index c00727df88bfa3d5b73ce6487a0680424fa0c83a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 569 zcmZ?wbhEHbe8J4daFqcB{sX~mmj81&{?Fz9KcD~qBC-FACI2s#|G!-2{|eRrE7kw6 z)cC(z=l@#c|LaWtZ*~8_!}r%#-}?()?k)f#*L#aR?l1Pf14PS0Z!Zn~f2Q&DqV!XX z(*B=q`hT|h|GC!x=i2^X=)8S$-G$}3U<;{9=zt6Z`GtY){{cbw;*B91CzceQ%(0q( zVMU48+Nkw6)|8!oTeUyol!}ku?DH?SRGrP+egDIb8oBimdXhovOoEMea?(xBEv;?s z9i3g>J-vPX6DCfYJZ0*%=`&`|nmuRky!i_jE?T@~>9XZ3R<2sTQchk$NkB+aK#`x9 zn~QVzp1u3_A2@jE@R6g(j-NPr>hzhj=gwcacLCpIiR+%BN(HOFJ) zqNCjs##whxOnl79!XwkMfngCN6EiEvikOp|mY$w&kbG*6=jLT+XIm7%x^r^#^7C=? z9h$jhy|%2lxY%Q|R_v)QD=#k(SnM^|YHI@{3$H`Sj|~qT8X1`mb;){fTXS=B#^qJ9 zr?;)Wy}jV^skz?U*WKM+@%h!=)7#hI-`~K@E$6di!^6WJ!rEar3l220$~Q4ESOWl` CT?4HE diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-ne.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-ne.gif deleted file mode 100644 index ab9c38e57817aff546ed4eab9eb1ef3d2e7d1a9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 353 zcmZ?wbhEHbz{Qnn;{a-Bkf2sWc(COcNe(aUEq3ek;mOd9`_e}-&^c`XIbctC839A z#r;3i`2TFv|Fg~i&$a$P*Y^KH=lu&iFD%amTS!ep2V@w?FAQvL4qY3P4rW*^_B;NW zu~S9(9FSw9q}a)J&{so7AaI$3oq`Degwz9SGD5xnt`71N0zCY!dJ-Z6+_KfB^^MK7 ztxYv`4P7n0?LBSXofD@{nJ{B=|Ll&LbNc4ZEvu-?Va_WkN?}dQ$co{JOGpY14Hrxj a+`U^!NJ+(6R8mq(*+co{DMk@T25SJZhk1Jd diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-nw.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-nw.gif deleted file mode 100644 index e93407333948f77ebf22f9a6c6377c469a9ca803..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 353 zcmZ?wbhEHbz{Qnn;{a-Bkf2sWcuA!=} zxwEOGwY{ZlVsCf<VOG!wGx_dAxpE|AV$Y2cs{j7S= diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-s.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-s.gif deleted file mode 100644 index d5f6b99b075eae4deb7aae93dbdb47146aaec4fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 434 zcmV;j0Zsl#Nk%w1Vdw)00J8u900030|Nl^+DO$Av=J(X(_0r+;(BAIN*yzXr00000 z00000000000000000000EC2ui0O$h<000F4kjP1^y*TU5yZ>M)j$~<`XsWJk>$Us;jK6uCK7L0S2?Rw70Xdy1Tr+zQ4f1!o$SHoCnCs%FE2n&d<=%($mz{*4NnC z+S}aS-rwNi;^XAy=I7|?>g(+7?(gvN^3VwN_V@Vt`uqI-{{H|23LHqVpuvL(6DnND zu%W|;5F<*QNU@^Dix@L%+{m$`$B+GI0*D+*vZTqAC{wCj$+D%(moQ_>oJq5$&6_xL z>fFh*r_Y~2g9;r=w5ZXeNRujE%2efmr%vSDJL^5V-+ diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-title.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-title.gif deleted file mode 100644 index 156c59b99f093255d9a9a713c807153dee2f83cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 238 zcmZ?wbhEHbWMq(KxXJ(m|AAm8!~fYV|L1W0pUeG!9?$>z{Qnn;{a-Bkf2sWcDbkb>5$NVf J6=7kp1_1C&OY{H$ diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-titlebar-close-hover.png b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/dialog-titlebar-close-hover.png deleted file mode 100644 index 67c1303e9a8e7089185d7ced8d817c26cc44370e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2927 zcmV-#3y}1QP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=00004XF*Lt006O$eEU(80000WV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}0001rNklTM~dE2n2^4c_**Yc#OJ}XR;qFmZ+TI zOPBWo+*j%pkVHWd_~nY)w!GsIAXiX;qlXVnZZ(xb$;RlY@hJ{U_uro+>I|i$v&oJD z+H&>m7@nBnDm=#IPQmN>z;vZ<1-56)$@C^_M~@SC6Rojcq=z63$Mj>BIeLvkNkU`X Z2LJ}KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=00004XF*Lt006O$eEU(80000WV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}00016Nkl&+ggecc9{B{_=WskSML zuCDyfFdf(Y?(4vu5J$WjZOC4*nEVZo%4c&4buyz@Yn3{cVz*vxH_QEw!Q^mRY;LpP z>$rNJuA}egyjyP9!|8Z?fPQ>|e|>_8hlYiOgNclfi;jwokd%>?l9rQ~o}HkaqMM|e zrkSXis-L5$tD&W-tg)}HvaqhRxwyBswY0juz`Vb^zQM)9#>2*xb_A+TG$)8{pID8R`@4-s5oY@)siW1oZ+00vQ1X0r>j(`2)CbLcf3O@)bmI zkf1<>?G!$AXmH>RrnhWCQ>^c>Ltp diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/menu-submenu.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/menu-submenu.gif deleted file mode 100644 index 77647d836805ff4070c14c8a6dd419c01f8ef336..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93 zcmZ?wbhEHb6krfwXkcUjg8%>jEB+I8E=o--Nlj5G&n(GM2+2rQaQE~LU{L(Y!pOzI s$e;sK2-3p9B;C`$^7L7TMq|TWQSxn7pPxi7xSsel-0#&XHC6^|0Oa8vPyhe` diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-e.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-e.gif deleted file mode 100644 index 7acf248362bf1c680a1489ca36fef65ee9ac175a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 338 zcmV-Y0j>T=Nk%w1VFm!`1EK%`P@pNz=di@#q~7w#)$F`x%mDxY{{R30A^8LV00000 zEC2ui00sc)0{{d6ST+=*%)#~+ozmu5IqsJRZlNcB=&71)>5}j$r)^BX^NQcL-q$%G zFSzp&e?_5j$Xq&=(4-VeJzAU5Dt3B(a<^J~ioHnb^@VDGeZ`;}UwLV_Y z^Y43efPa31g?)jDgo%TOjE9Yij*FC&mXer}nvk52o|T!MpqrnUq@$vysiCE;sI8}} zu&c4Ivah(ey0*NvzO=xzr2qr~9R>jg3dF_`$jS!H$H~jZ)6mk+)X~=3*xd`yxxK;T zzryC_yXWcX>+0n0@$K~Q^6d8Y^ZESy{`mjk0URi>;5~!-2p(LR5Me)s4H-Uk7*Jxx kh!`hYgs3qW}*y*TU5yZ>M)j$~<`XsWJk>%MR-&$J}mc&_h!@BhG{ za7Zi~kI1BQ$!t2G(5Q6EBnYh7tJX^GdcWYXcuX#v&uHUd&2GEj@VIs;jK6uCK7M zva__cwzs&sy1TRl0KUM#!oIx4#>dFX%FE2n&d<=U0n^mg*4NnC+S}aS-rwNi;^XAy z=I7|?>g(+7?(gXZ0rK?o_VV!g`uqI-{{H|23LHo<9D#!f6DnNDu%W|;5F<*QNU@^D nix@L%+{m#SqsNaRLy8#j0_CC3_2hl$P5M+%?T$h`}dZuJR2ItDb#i^$%r-CV1A?mTaZ%g W2B9~X4lpX#_sTLFoN#4eum%7Mt~NdZ diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-nw.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-nw.gif deleted file mode 100644 index 665f31890c6755dc8f1eeffe92aad9aeb9b8c5d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91 zcmZ?wbhEHbo_# rfq_{eVwcaqbrT$4Pf%u9YpB7r!lyBS>*1GHwX#`l>}+il85pbqkIW*2 diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-s.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-s.gif deleted file mode 100644 index da2fb35126a27cf38cd2fb7b25f1926e0b1923ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 341 zcmV-b0jmB-Nk%w1Vdw(}0HOc@P@pNz=di@#q~7w#)$F`x%mDxY{{R30A^8LV00000 zEC2ui0O$h-000C3Si0Q)Fv>}*y*TU5yZ>M)j$~<`XsWJk>%MR-&$MLRc&_h!@BhG{ za7Zi~kI1BQ$!t2G(5Q4uty-_xtai)odcWZCZ$K`a&*-#z&2GEj@VI00V=CgolHHii?bmj*pO$l9QB`a|D=~nwy-Ro}ZwhqNAjxrl+W>s;jK6uCK7M zva__V1_ZacxVyKtzQ4f1!o$SH#>dFXrUA^&&d<=%($mz{*4NnC+S}aS-rwNi;^XAy z=I7|)00Ham?CBRs4{~53W#h)yU zAaNZK0WyPuMOA>I@r2~EGhR%3B8qYz$5`*GcX7;=W#p+p+;F2T?aiOKKL-+67_0$1 C<0bU~ diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-sw.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-sw.gif deleted file mode 100644 index 2fd8de4dc206a307dc3a48e048751f46f2641548..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 175 zcmZ?wbhEHbMk5WsWG=b0ic@2@vUCebjknjlsMN%QL-r85yhrN_0Jq diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-w.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/resizable-w.gif deleted file mode 100644 index 34b875b955e10eb1de3fe279875c1159002389b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 339 zcmV-Z0j&N5}j$r)^BX^NQcL-q$%G zFSzp&e?_5j$Xq&=(4-VeJzAU5Dt3B(a<^J~ioHnb^@VDGeZ`;}UwLV_Y z^Y43efPa31g?)jDgo%TOjE9Yij*FC&mXer}nvk52o|T!MpqrnUq@$vysiCE;sI8}} zu&c4Ivah(ey0*NvzO=xzp9BL083h0Z55&e5$jZva$H~jm&eYM(3eVNr0^Hft(7V6F zxxK;X+<#a`1|zy_x%9>34Axu9>IeK6Y2|yaA84*4gE!As8C`> liV!b8w3x9NBgc;zL2e95a-_+LCpDs6sj{WVk_Zz306UGYvm^ij diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/shadow.png b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/shadow.png deleted file mode 100644 index 4c58c7fd9f67fbce64196d1945514161a34a105b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3977 zcmeAS@N?(olHy`uVBq!ia0y~yU{(NO4mP03?Eo%;1(@tNH-3F9b!28IhS zZPPj{dv|Va?*Dd!qTVml)fka?d|0I0nI7z9i}D=--XK-0leD2xUM zpff=ts0lQL0EPTFi37VYaZnVmPQ-oVQpb>;wbqnWCaxLj#@1ZYz!yZ!$OXB zwIcR#!qFTYu=0$W4Rh>y6ML3~C*4630e_?w-W#5NW*N;3?Bnr%o_;Lj{6k>Jko~Rq zb(`vK#=wr@?n5%x8(>u9-=0*1)c+Rj$6pyd=Gga@$QEZi&A$ zvh$OacLz(X-M?wqvpuz2j;lG$Dibc6|M4NXW4iU|6H_V+Po~-c73F!lIEGZ*dUO3C=K%$t)`v4Z_w4lB-8uJ2;H|vH+w+oy z1*$IOeW({WVfn#BsOtTtsM{_}B3v0iM969`)xHvCE2D1AsJ6TBEMr30l+9c}L`&~P zGl=c)U{^6_PtaUl`)a$X^lX+NX6@;RHh<(YV91^-+OzI^=L?|C44$rjF6*2UngCuv BOOpTq diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/slider-bg-2.png b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/slider-bg-2.png deleted file mode 100644 index 8b24cf0910fc24c075e44d324ab05ef2fb739ddc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 326 zcmV-M0lEH(P)2N3a1T2XOG^5J3rxRD->U5tO2~nPZ0nB diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/tabs.gif b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/flora/i/tabs.gif deleted file mode 100644 index d96489435915e8079ee19f968c20a0520629bd8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 377 zcmV-<0fzoZNk%w1VJrbM0FeR!px=T}peg_V{{R30A^8LW00062EC2ui04xDA00092 zlz^$r?GK}zwAzca-n?sbc;ZNw=82}NWUTHB$MP(<^o{5G{@VNx3<`z5q49`Jii*mn z^Z8^#r_?G=YRzi5BP{m|4nMr&vUy8BtJlpm`wjoO(-HLF%}1poj$R3Em8 diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.css deleted file mode 100644 index 14482cbdb..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.css +++ /dev/null @@ -1,11 +0,0 @@ -.light { background:#FFF; color:#111; font:10pt Verdana, Arial, sans-serif; } -.light a, a.light { color:#46C; outline:none; } -.light a:visited, a.light:visited { color:#C44; } -.light a:hover, a.light:hover { color:#000; } -.light fieldset { border:1px solid #CCC; } -.light legend { color:#555; font:.8em Verdana, san-serif; } -.light button, button.light, .light input, input.light { padding:2px 4px; font:.9em Consolas, Verdana, san-serif; } -.light textarea, textarea.light { padding:2px 4px; font:.9em Consolas, Courier New, san-serif; width:20em; height:5em; overflow:auto; } -.light select, select.light { padding:3px 0 3px 4px; font:.9em Verdana, san-serif; } -.light label { font-weight:bold; } - diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.form.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.form.css deleted file mode 100644 index da1014255..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.form.css +++ /dev/null @@ -1,45 +0,0 @@ -.light .ui-form-textarea, -.light.ui-form-textarea, -.light .ui-form-fieldset, -.light.ui-form-fieldset { - display:block; - border:1px solid #CCC; - padding:0; -} -.light .ui-form-fieldset, -.light.ui-form-fieldset { - margin-top:1.6em; -} -.light textarea.ui-form, -.light fieldset.ui-form { - margin:0; - border:1px solid #FFF; -} -.light textarea.ui-form { background:#F3F3F3; } -.light fieldset.ui-form { background:#F6F6F6; } -.light .ui-form-textarea.focus, -.light.ui-form-textarea.focus { - border:1px solid #AAA; -} -.light textarea.ui-form:focus { - background:#F5F5F5; -} -.light .ui-form-legend, -.light.ui-form-legend { - display:block; - text-align:left; - border:1px solid #CCC; - background:#F4F4F4; - margin:-1.05em 0 0 0; -} -.light legend.ui-form { - display:block; - font-weight:bold; - background:#F4F4F4; - border-top:1px dotted #EEE; - border-bottom:1px dotted #EEE; - margin:-1px 2px; - padding:0 2px 2px; -} - - diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.menu.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.menu.css deleted file mode 100644 index dab7af0e1..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.menu.css +++ /dev/null @@ -1,8 +0,0 @@ -.ui-menu-toolbar {background:#222; font:10pt Verdana;} -.ui-menu-toolbar-button {border:1px solid #DDD; background:#FFF;} -.ui-menu-toolbar-button:hover {border:1px solid #CCC; background:#EEE; } -.ui-menu-toolbar-button a {color:#000;} -.ui-menu-items {background:#FFF; border:1px solid #CCC; opacity:0.95; font:10pt Verdana; min-width:80px; *width:80px;} -.ui-menu-item a { color:#000; } -.ui-menu-item-parent { } -.ui-menu-item-disabled {color: #aaa; background: transparent;} \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.modal.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.modal.css deleted file mode 100644 index 246b800fd..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.modal.css +++ /dev/null @@ -1,91 +0,0 @@ -.light .ui-modal .top.pane, -.light.ui-modal .top.pane { - position: relative; - cursor:move; -} - -.light .ui-modal .top.pane .ui-modal-title-bar, -.light.ui-modal .top.pane .ui-modal-title-bar { - background:#333; - color:snow; - padding:2px 4px; - border-bottom:1px solid #000; - font-weight:bold; -} - -.light .ui-modal .top.pane .ui-modal-buttons-right, -.light.ui-modal .top.pane .ui-modal-buttons-right { - position: absolute; - right: 5px; -} - -.light .ui-modal .top.pane .ui-modal-button-close, -.light.ui-modal .top.pane .ui-modal-button-close { - font:10pt Verdana; - font-weight:bold; - color:snow; - cursor:pointer; -} - -.light .ui-modal .middle.pane, -.light.ui-modal .middle.pane { - position:relative; - height: 100%; - background:#F3F3F3; - padding-top:4px; -} -.light .ui-modal .middle.pane .center.pane, -.light.ui-modal .middle.pane .center.pane{ - position:relative; - overflow: auto; - height: 100%; - margin:0 4px; - background:#FFF; -} -.light .ui-modal.noOverflow .middle.pane .center.pane, -.light.ui-modal.noOverflow .middle.pane .center.pane{ - overflow: visible; -} - -.light .ui-modal .middle.pane .left.pane, -.light.ui-modal .middle.pane .left.pane { - position: absolute; - top: 0px; - left: 0px; - border-left:1px solid #DDD; - height:100%; - width: 2px; -} - -.light .ui-modal .middle.pane .right.pane, -.light.ui-modal .middle.pane .right.pane { - position: absolute; - top: 0px; - right: 0px; - border-right:1px solid #DDD; - height:100%; - width: 2px; - cursor:e-resize; -} - -.light .ui-modal .bottom.pane, -.light.ui-modal .bottom.pane { - position: relative; - height:3px; - background:#F3F3F3; - border:1px solid #DDD; - border-top:none; - cursor:s-resize; -} - - -.light .ui-modal .bottom.pane .ui-modal-resize-se, -.light.ui-modal .bottom.pane .ui-modal-resize-se { - position: absolute; - bottom:-1px; - right:-1px; - height:4px; - width:4px; - cursor:se-resize; -} - diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.tabs.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.tabs.css deleted file mode 100644 index 8d55b2298..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.tabs.css +++ /dev/null @@ -1,71 +0,0 @@ -@media projection, screen { .ui-tabs-hide { display:none; } } -@media print { .ui-tabs-nav { display: none; } } - -.light .ui-tabs-nav, -.light.ui-tabs-nav { - padding-left:6px; - border-bottom:1px solid #444; - float:left; - width:99%; - margin:0; -} -.light .ui-tabs-nav li, -.light.ui-tabs-nav li { - list-style:none; - float:left; -} -.light .ui-tabs-nav a, -.light.ui-tabs-nav a { - display:block; - padding:2px 0 1px; - text-decoration:none!important; - border:1px solid #444; - margin:1px 1px 0 0; - font:9pt Verdana; - color:#FFF; - background:#444; -} -.light .ui-tabs-nav span, -.light.ui-tabs-nav span { - padding:2px 13px 2px; - color:#FFF; - background:#444; -} -.light .ui-tabs-nav a:hover, -.light .ui-tabs-nav a:hover span, -.light.ui-tabs-nav a:hover, -.light.ui-tabs-nav a:hover span { - border-color:#222; - color:#FFF; - background:#222; - } -.light .ui-tabs-nav .ui-tabs-selected a, -.light.ui-tabs-nav .ui-tabs-selected a { - background:#AAA; - border-color:#666; -} -.light .ui-tabs-nav .ui-tabs-selected a span, -.light.ui-tabs-nav .ui-tabs-selected a span { - margin-bottom:0; - color:#000; - background:snow; - border-bottom:1px solid #FFF; - cursor:default; - } -.light .ui-tabs-nav .ui-tabs-disabled a, -.light .ui-tabs-nav .ui-tabs-disabled a span, -.light.ui-tabs-nav .ui-tabs-disabled a, -.light.ui-tabs-nav .ui-tabs-disabled a span { - background:#EEE; - color:#BBB; - border-color:#DDD; - cursor:default; -} -.light .ui-tabs-container { - clear:both; - padding:10px 10px 8px 10px; - *padding-top:3px; - *margin-top:-24px; - clear:left; -} - diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.tree.css b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.tree.css deleted file mode 100644 index c8fd0a9aa..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/themes/light/light.tree.css +++ /dev/null @@ -1,61 +0,0 @@ -body.light { font:10pt Verdana; background:#FFF; color:#111; } - -.light .ui-tree-nodes * { outline:none; } -.light .ui-tree-nodes { - position:relative; - list-style: none; - margin:0; - padding:0; - margin-left:0; - padding-left:0.8em; -} - -.light .ui-tree-node { - margin:0; - padding:0; - cursor: default; -} - -.light .ui-tree-node-text { - text-decoration:none; - color:#222; - padding:0 .3em; -} - -.light .ui-tree-node-selected > .ui-tree-node-text { - background: #EEE; -} - -.light .ui-tree-node-button { - border: 1px solid #CCC; - padding-left:1px; - color: #666; - font:7pt Courier New,monospace; - margin-top: 0.4em; - position: absolute; - left: 0.2em; - width: 0.7em; - height: 0.8em; - line-height: 0.8em; - text-decoration: none; - display:none; -} - -.light .ui-tree-node-expanded > .ui-tree-node-button { - background: #EEE; - display:block; -} - -.light .ui-tree-node-collapsed > .ui-tree-node-button { - background: #DDD; - display:block; -} - -.light .ui-tree-node-moving > .ui-tree-node-button { - background: #DDD; -} - -.light .ui-tree-node-moving > .ui-tree-node-text { - background: #DDD; -} - diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.accordion.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.accordion.js deleted file mode 100644 index 5689e8324..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.accordion.js +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Accordion 1.5 - jQuery menu widget - * - * Copyright (c) 2007 Jörn Zaefferer, Frank Marcia - * - * http://bassistance.de/jquery-plugins/jquery-plugin-accordion/ - * - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - * Revision: $Id: jquery.accordion.js 2951 2007-08-28 07:21:13Z joern.zaefferer $ - * - */ - -(function($) { - -$.ui = $.ui || {} - -$.ui.accordion = {}; -$.extend($.ui.accordion, { - defaults: { - selectedClass: "selected", - alwaysOpen: true, - animated: 'slide', - event: "click", - header: "a" - }, - animations: { - slide: function(settings, additions) { - settings = $.extend({ - easing: "swing", - duration: 300 - }, settings, additions); - if ( !settings.toHide.size() ) { - settings.toShow.animate({height: "show"}, { - duration: settings.duration, - easing: settings.easing, - complete: settings.finished - }); - return; - } - var hideHeight = settings.toHide.height(), - showHeight = settings.toShow.height(), - difference = showHeight / hideHeight; - settings.toShow.css({ height: 0, overflow: 'hidden' }).show(); - settings.toHide.filter(":hidden").each(settings.finished).end().filter(":visible").animate({height:"hide"},{ - step: function(n){ - settings.toShow.height(Math.ceil( (hideHeight - (n)) * difference )); - }, - duration: settings.duration, - easing: settings.easing, - complete: settings.finished - }); - }, - bounceslide: function(settings) { - this.slide(settings, { - easing: settings.down ? "bounceout" : "swing", - duration: settings.down ? 1000 : 200 - }); - }, - easeslide: function(settings) { - this.slide(settings, { - easing: "easeinout", - duration: 700 - }) - } - } -}); - -$.fn.extend({ - nextUntil: function(expr) { - var match = []; - - // We need to figure out which elements to push onto the array - this.each(function(){ - // Traverse through the sibling nodes - for( var i = this.nextSibling; i; i = i.nextSibling ) { - // Make sure that we're only dealing with elements - if ( i.nodeType != 1 ) continue; - - // If we find a match then we need to stop - if ( $.filter( expr, [i] ).r.length ) break; - - // Otherwise, add it on to the stack - match.push( i ); - } - }); - - return this.pushStack( match ); - }, - // the plugin method itself - accordion: function(settings) { - if ( !this.length ) - return this; - - // setup configuration - settings = $.extend({}, $.ui.accordion.defaults, settings); - - if ( settings.navigation ) { - var current = this.find("a").filter(function() { return this.href == location.href; }); - if ( current.length ) { - if ( current.filter(settings.header).length ) { - settings.active = current; - } else { - settings.active = current.parent().parent().prev(); - current.addClass("current"); - } - } - } - - // calculate active if not specified, using the first header - var container = this, - headers = container.find(settings.header), - active = findActive(settings.active), - running = 0; - - if ( settings.fillSpace ) { - var maxHeight = this.parent().height(); - headers.each(function() { - maxHeight -= $(this).outerHeight(); - }); - var maxPadding = 0; - headers.nextUntil(settings.header).each(function() { - maxPadding = Math.max(maxPadding, $(this).innerHeight() - $(this).height()); - }).height(maxHeight - maxPadding); - } else if ( settings.autoheight ) { - var maxHeight = 0; - headers.nextUntil(settings.header).each(function() { - maxHeight = Math.max(maxHeight, $(this).height()); - }).height(maxHeight); - } - - headers - .not(active || "") - .nextUntil(settings.header) - .hide(); - active.parent().andSelf().addClass(settings.selectedClass); - - - function findActive(selector) { - return selector != undefined - ? typeof selector == "number" - ? headers.filter(":eq(" + selector + ")") - : headers.not(headers.not(selector)) - : selector === false - ? $("").css("width", $(o.iframeFix[i])[0].offsetWidth+"px").css("height", $(o.iframeFix[i])[0].offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body"); - } - } else { - $("iframe").each(function() { - var co = $(this).offset({ border: false }); - $("
    ").css("width", this.offsetWidth+"px").css("height", this.offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body"); - }); - } - } - - }); - - $.ui.plugin.add("draggable","stop", "iframeFix", function(e,ui) { - if(ui.options.iframeFix) $("div.DragDropIframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers - }); - -//---------------------------------------------------------------- - - $.ui.plugin.add("draggable", "start", "containment", function(e,ui) { - - var o = ui.options; - - if(!o.cursorAtIgnore || o.containment.left != undefined || o.containment.constructor == Array) return; - if(o.containment == 'parent') o.containment = this.parentNode; - - - if(o.containment == 'document') { - o.containment = [ - 0-o.margins.left, - 0-o.margins.top, - $(document).width()-o.margins.right, - ($(document).height() || document.body.parentNode.scrollHeight)-o.margins.bottom - ]; - } else { //I'm a node, so compute top/left/right/bottom - var ce = $(o.containment)[0]; - var co = $(o.containment).offset({ border: false }); - - o.containment = [ - co.left-o.margins.left, - co.top-o.margins.top, - co.left+(ce.offsetWidth || ce.scrollWidth)-o.margins.right, - co.top+(ce.offsetHeight || ce.scrollHeight)-o.margins.bottom - ]; - } - - }); - - $.ui.plugin.add("draggable", "drag", "containment", function(e,ui) { - - var o = ui.options; - if(!o.cursorAtIgnore) return; - - var h = $(ui.helper); - var c = o.containment; - if(c.constructor == Array) { - - if((ui.draggable.pos[0] < c[0]-o.po.left)) ui.draggable.pos[0] = c[0]-o.po.left; - if((ui.draggable.pos[1] < c[1]-o.po.top)) ui.draggable.pos[1] = c[1]-o.po.top; - if(ui.draggable.pos[0]+h[0].offsetWidth > c[2]-o.po.left) ui.draggable.pos[0] = c[2]-o.po.left-h[0].offsetWidth; - if(ui.draggable.pos[1]+h[0].offsetHeight > c[3]-o.po.top) ui.draggable.pos[1] = c[3]-o.po.top-h[0].offsetHeight; - - } else { - - if(c.left && (ui.draggable.pos[0] < c.left)) ui.draggable.pos[0] = c.left; - if(c.top && (ui.draggable.pos[1] < c.top)) ui.draggable.pos[1] = c.top; - - var p = $(o.pp); - if(c.right && ui.draggable.pos[0]+h[0].offsetWidth > p[0].offsetWidth-c.right) ui.draggable.pos[0] = (p[0].offsetWidth-c.right)-h[0].offsetWidth; - if(c.bottom && ui.draggable.pos[1]+h[0].offsetHeight > p[0].offsetHeight-c.bottom) ui.draggable.pos[1] = (p[0].offsetHeight-c.bottom)-h[0].offsetHeight; - - } - - - }); - -//---------------------------------------------------------------- - - $.ui.plugin.add("draggable", "drag", "grid", function(e,ui) { - var o = ui.options; - if(!o.cursorAtIgnore) return; - ui.draggable.pos[0] = o.co.left + o.margins.left - o.po.left + Math.round((ui.draggable.pos[0] - o.co.left - o.margins.left + o.po.left) / o.grid[0]) * o.grid[0]; - ui.draggable.pos[1] = o.co.top + o.margins.top - o.po.top + Math.round((ui.draggable.pos[1] - o.co.top - o.margins.top + o.po.top) / o.grid[1]) * o.grid[1]; - }); - -//---------------------------------------------------------------- - - $.ui.plugin.add("draggable", "drag", "axis", function(e,ui) { - var o = ui.options; - if(!o.cursorAtIgnore) return; - if(o.constraint) o.axis = o.constraint; //Legacy check - o.axis ? ( o.axis == 'x' ? ui.draggable.pos[1] = o.co.top - o.margins.top - o.po.top : ui.draggable.pos[0] = o.co.left - o.margins.left - o.po.left ) : null; - }); - -//---------------------------------------------------------------- - - $.ui.plugin.add("draggable", "drag", "scroll", function(e,ui) { - - var o = ui.options; - o.scrollSensitivity = o.scrollSensitivity || 20; - o.scrollSpeed = o.scrollSpeed || 20; - - if(o.pp && o.ppOverflow) { // If we have a positioned parent, we only scroll in this one - // TODO: Extremely strange issues are waiting here..handle with care - } else { - if((ui.draggable.rpos[1] - $(window).height()) - $(document).scrollTop() > -o.scrollSensitivity) window.scrollBy(0,o.scrollSpeed); - if(ui.draggable.rpos[1] - $(document).scrollTop() < o.scrollSensitivity) window.scrollBy(0,-o.scrollSpeed); - if((ui.draggable.rpos[0] - $(window).width()) - $(document).scrollLeft() > -o.scrollSensitivity) window.scrollBy(o.scrollSpeed,0); - if(ui.draggable.rpos[0] - $(document).scrollLeft() < o.scrollSensitivity) window.scrollBy(-o.scrollSpeed,0); - } - - }); - -//---------------------------------------------------------------- - - $.ui.plugin.add("draggable", "drag", "wrapHelper", function(e,ui) { - - var o = ui.options; - if(o.cursorAtIgnore) return; - var t = ui.helper; - - if(!o.pp || !o.ppOverflow) { - var wx = $(window).width() - ($.browser.mozilla ? 20 : 0); - var sx = $(document).scrollLeft(); - - var wy = $(window).height(); - var sy = $(document).scrollTop(); - } else { - var wx = o.pp.offsetWidth + o.po.left - 20; - var sx = o.pp.scrollLeft; - - var wy = o.pp.offsetHeight + o.po.top - 20; - var sy = o.pp.scrollTop; - } - - ui.draggable.pos[0] -= ((ui.draggable.rpos[0]-o.cursorAt.left - wx + t.offsetWidth+o.margins.right) - sx > 0 || (ui.draggable.rpos[0]-o.cursorAt.left+o.margins.left) - sx < 0) ? (t.offsetWidth+o.margins.left+o.margins.right - o.cursorAt.left * 2) : 0; - - ui.draggable.pos[1] -= ((ui.draggable.rpos[1]-o.cursorAt.top - wy + t.offsetHeight+o.margins.bottom) - sy > 0 || (ui.draggable.rpos[1]-o.cursorAt.top+o.margins.top) - sy < 0) ? (t.offsetHeight+o.margins.top+o.margins.bottom - o.cursorAt.top * 2) : 0; - - }); - -})(jQuery); - diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.draggable.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.draggable.js deleted file mode 100644 index b3bcd008a..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.draggable.js +++ /dev/null @@ -1,182 +0,0 @@ -(function($) { - - //Make nodes selectable by expression - $.extend($.expr[':'], { draggable: "(' '+a.className+' ').indexOf(' ui-draggable ')" }); - - - //Macros for external methods that support chaining - var methods = "destroy,enable,disable".split(","); - for(var i=0;i *', el).each(function() { - var co = $(this).offset({ border: false }); - if(self.options.overlap) var cp = $(this).position(); - self.items.push([this, co, [$(this).width(),$(this).height()], (cp || null)]); - - if(o.opacity) - $(this).css('opacity', o.opacity.min); - }); - - if(o.overlap) { - for(var i=0;i this.pp.left-o.distance && p[0] < this.pp.left + this.element.offsetWidth + o.distance) && (p[1] > this.pp.top-o.distance && p[1] < this.pp.top + this.element.offsetHeight + o.distance)); - if(!overlap) return false; - - - for(var i=0;i 0 || o.cursorAt.bottom-o.margins.bottom > 0) && (o.cursorAt.left-o.margins.left > 0 || o.cursorAt.right-o.margins.right > 0)) ? true : false; //If cursorAt is within the helper, set slowMode to true - - if(!o.nonDestructive) $(this.helper).css('position', 'absolute'); - if(o.helper != 'original') $(this.helper).appendTo((o.appendTo == 'parent' ? a.parentNode : o.appendTo)).show(); - - // Remap right/bottom properties for cursorAt to left/top - if(o.cursorAt.right && !o.cursorAt.left) o.cursorAt.left = this.helper.offsetWidth+o.margins.right+o.margins.left - o.cursorAt.right; - if(o.cursorAt.bottom && !o.cursorAt.top) o.cursorAt.top = this.helper.offsetHeight+o.margins.top+o.margins.bottom - o.cursorAt.bottom; - - this.init = true; - - if(o._start) o._start.apply(a, [this.helper, this.pos, o.cursorAt, this, e]); // Trigger the start callback - this.helperSize = { width: outerWidth(this.helper), height: outerHeight(this.helper) }; //Set helper size property - return false; - - }, - stop: function(e) { - - var o = this.options; var a = this.element; var self = this; - - $(document).unbind('mouseup', self.mouseup); - $(document).unbind('mousemove', self.mousemove); - - if(this.init == false) return this.opos = this.pos = null; - if(o._beforeStop) o._beforeStop.apply(a, [this.helper, this.pos, o.cursorAt, this, e]); - - if(this.helper != a && !o.beQuietAtEnd) { // Remove helper, if it's not the original node - $(this.helper).remove(); this.helper = null; - } - - if(!o.beQuietAtEnd) { - //if(o.wasPositioned) $(a).css('position', o.wasPositioned); - if(o._stop) o._stop.apply(a, [this.helper, this.pos, o.cursorAt, this, e]); - } - - this.init = false; - this.opos = this.pos = null; - return false; - - }, - drag: function(e) { - - if (!this.opos || ($.browser.msie && !e.button)) return this.stop.apply(this, [e]); // check for IE mouseup when moving into the document again - var o = this.options; - - this.pos = [e.pageX,e.pageY]; //relative mouse position - if(this.rpos && this.rpos[0] == this.pos[0] && this.rpos[1] == this.pos[1]) return false; - this.rpos = [this.pos[0],this.pos[1]]; //absolute mouse position - - if(o.pp) { //If we have a positioned parent, use a relative position - this.pos[0] -= o.po.left; - this.pos[1] -= o.po.top; - } - - if( (Math.abs(this.rpos[0]-this.opos[0]) > o.preventionDistance || Math.abs(this.rpos[1]-this.opos[1]) > o.preventionDistance) && this.init == false) //If position is more than x pixels from original position, start dragging - this.start.apply(this,[e]); - else { - if(this.init == false) return false; - } - - if(o._drag) o._drag.apply(this.element, [this.helper, this.pos, o.cursorAt, this, e]); - return false; - - } - }); - - var num = function(el, prop) { - return parseInt($.css(el.jquery?el[0]:el,prop))||0; - }; - function outerWidth(el) { - var $el = $(el), ow = $el.width(); - for (var i = 0, props = ['borderLeftWidth', 'paddingLeft', 'paddingRight', 'borderRightWidth']; i < props.length; i++) - ow += num($el, props[i]); - return ow; - } - function outerHeight(el) { - var $el = $(el), oh = $el.width(); - for (var i = 0, props = ['borderTopWidth', 'paddingTop', 'paddingBottom', 'borderBottomWidth']; i < props.length; i++) - oh += num($el, props[i]); - return oh; - } - - })($); diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.resizable.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.resizable.js deleted file mode 100644 index 169c2f0e8..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.resizable.js +++ /dev/null @@ -1,304 +0,0 @@ -(function($) { - - //Make nodes selectable by expression - $.extend($.expr[':'], { resizable: "(' '+a.className+' ').indexOf(' ui-resizable ')" }); - - - $.fn.resizable = function(o) { - return this.each(function() { - if(!$(this).is(".ui-resizable")) new $.ui.resizable(this,o); - }); - } - - //Macros for external methods that support chaining - var methods = "destroy,enable,disable".split(","); - for(var i=0;i').css({ - width: $(this).width(), - height: $(this).height(), - position: 'absolute', - left: that.options.co.left, - top: that.options.co.top - }).addClass(that.options.proxy); - return helper; - } - } else { - var helper = "original"; - } - - //Destructive mode wraps the original element - if(el.nodeName.match(/textarea|input|select|button|img/i)) options.destructive = true; - if(options.destructive) { - - $(el).wrap('
    '); - var oel = el; - el = el.parentNode; this.element = el; - - //Move margins to the wrapper - $(el).css({ marginLeft: $(oel).css("marginLeft"), marginTop: $(oel).css("marginTop"), marginRight: $(oel).css("marginRight"), marginBottom: $(oel).css("marginBottom")}); - $(oel).css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); - - o.proportionallyResize = o.proportionallyResize || []; - o.proportionallyResize.push(oel); - - var b = [parseInt($(oel).css('borderTopWidth')),parseInt($(oel).css('borderRightWidth')),parseInt($(oel).css('borderBottomWidth')),parseInt($(oel).css('borderLeftWidth'))]; - } else { - var b = [0,0,0,0]; - } - - if(options.destructive || !$(".ui-resizable-handle",el).length) { - //Adding handles (disabled not so common ones) - var t = function(a,b) { $(el).append("
    "); }; - //t('n','top: '+b[0]+'px;'); - t('e','right: '+b[1]+'px;'+(options.zIndex ? 'z-index: '+options.zIndex+';' : '')); - t('s','bottom: '+b[1]+'px;'+(options.zIndex ? 'z-index: '+options.zIndex+';' : '')); - //t('w','left: '+b[3]+'px;'); - t('se','bottom: '+b[2]+'px; right: '+b[1]+'px;'+(options.zIndex ? 'z-index: '+options.zIndex+';' : '')); - //t('sw','bottom: '+b[2]+'px; left: '+b[3]+'px;'); - //t('ne','top: '+b[0]+'px; right: '+b[1]+'px;'); - //t('nw','top: '+b[0]+'px; left: '+b[3]+'px;'); - } - - - - //If other elements should be modified, we have to copy that array - options.modifyThese = []; - if(o.proportionallyResize) { - options.proportionallyResize = o.proportionallyResize.slice(0); - var propRes = options.proportionallyResize; - - for(var i in propRes) { - - if(propRes[i].constructor == String) - propRes[i] = $(propRes[i], el); - - if(!$(propRes[i]).length) continue; - - - var x = $(propRes[i]).width() - $(el).width(); - var y = $(propRes[i]).height() - $(el).height(); - options.modifyThese.push([$(propRes[i]),x,y]); - } - - } - - options.handles = {}; - if(!o.handles) o.handles = { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' }; - - for(var i in o.handles) { options.handles[i] = o.handles[i]; } //Copying the object - - for(var i in options.handles) { - - if(options.handles[i].constructor == String) - options.handles[i] = $(options.handles[i], el); - - if(!$(options.handles[i]).length) continue; - - $(options.handles[i]).bind('mousedown', function(e) { - self.interaction.options.axis = this.resizeAxis; - })[0].resizeAxis = i; - - } - - //If we want to auto hide the elements - if(o.autohide) - $(this.element).addClass("ui-resizable-autohide").hover(function() { $(this).removeClass("ui-resizable-autohide"); }, function() { if(self.interaction.options.autohide && !self.interaction.init) $(this).addClass("ui-resizable-autohide"); }); - - - $.extend(options, { - helper: helper, - nonDestructive: true, - dragPrevention: 'input,button,select', - minHeight: options.minHeight || 50, - minWidth: options.minWidth || 100, - startCondition: function(e) { - if(self.disabled) return false; - for(var i in options.handles) { - if($(options.handles[i])[0] == e.target) return true; - } - return false; - }, - _start: function(h,p,c,t,e) { - self.start.apply(t, [self, e]); // Trigger the start callback - }, - _beforeStop: function(h,p,c,t,e) { - self.stop.apply(t, [self, e]); // Trigger the stop callback - }, - _drag: function(h,p,c,t,e) { - self.drag.apply(t, [self, e]); // Trigger the start callback - } - }); - - //Initialize mouse interaction - this.interaction = new $.ui.mouseInteraction(el,options); - - //Add the class for themeing - $(this.element).addClass("ui-resizable"); - - } - - $.extend($.ui.resizable.prototype, { - plugins: {}, - prepareCallbackObj: function(self) { - return { - helper: self.helper, - resizable: self, - axis: self.options.axis, - options: self.options - } - }, - destroy: function() { - $(this.element).removeClass("ui-resizable").removeClass("ui-resizable-disabled"); - this.interaction.destroy(); - }, - enable: function() { - $(this.element).removeClass("ui-resizable-disabled"); - this.disabled = false; - }, - disable: function() { - $(this.element).addClass("ui-resizable-disabled"); - this.disabled = true; - }, - start: function(that, e) { - this.options.originalSize = [$(this.element).width(),$(this.element).height()]; - this.options.originalPosition = $(this.element).css("position"); - this.options.originalPositionValues = $(this.element).position(); - - this.options.modifyThese.push([$(this.helper),0,0]); - - $(that.element).triggerHandler("resizestart", [e, that.prepareCallbackObj(this)], this.options.start); - return false; - }, - stop: function(that, e) { - - var o = this.options; - - $(that.element).triggerHandler("resizestop", [e, that.prepareCallbackObj(this)], this.options.stop); - - if(o.proxy) { - $(this.element).css({ - width: $(this.helper).width(), - height: $(this.helper).height() - }); - - if(o.originalPosition == "absolute" || o.originalPosition == "fixed") { - $(this.element).css({ - top: $(this.helper).css("top"), - left: $(this.helper).css("left") - }); - } - } - return false; - - }, - drag: function(that, e) { - - var o = this.options; - var rel = (o.originalPosition != "absolute" && o.originalPosition != "fixed"); - var co = rel ? o.co : this.options.originalPositionValues; - var p = o.originalSize; - - this.pos = rel ? [this.rpos[0]-o.cursorAt.left, this.rpos[1]-o.cursorAt.top] : [this.pos[0]-o.cursorAt.left, this.pos[1]-o.cursorAt.top]; - - var nw = p[0] + (this.pos[0] - co.left); - var nh = p[1] + (this.pos[1] - co.top); - - if(o.axis) { - switch(o.axis) { - case 'e': - nh = p[1]; - break; - case 's': - nw = p[0]; - break; - case 'n': - case 'ne': - - - if(!o.proxy && (o.originalPosition != "absolute" && o.originalPosition != "fixed")) - return false; - - if(o.axis == 'n') nw = p[0]; - var mod = (this.pos[1] - co.top); nh = nh - (mod*2); - mod = nh <= o.minHeight ? p[1] - o.minHeight : (nh >= o.maxHeight ? 0-(o.maxHeight-p[1]) : mod); - $(this.helper).css('top', co.top + mod); - break; - - case 'w': - case 'sw': - - if(!o.proxy && (o.originalPosition != "absolute" && o.originalPosition != "fixed")) - return false; - - if(o.axis == 'w') nh = p[1]; - var mod = (this.pos[0] - co.left); nw = nw - (mod*2); - mod = nw <= o.minWidth ? p[0] - o.minWidth : (nw >= o.maxWidth ? 0-(o.maxWidth-p[0]) : mod); - $(this.helper).css('left', co.left + mod); - break; - - case 'nw': - - if(!o.proxy && (o.originalPosition != "absolute" && o.originalPosition != "fixed")) - return false; - - var modx = (this.pos[0] - co.left); nw = nw - (modx*2); - modx = nw <= o.minWidth ? p[0] - o.minWidth : (nw >= o.maxWidth ? 0-(o.maxWidth-p[0]) : modx); - - var mody = (this.pos[1] - co.top); nh = nh - (mody*2); - mody = nh <= o.minHeight ? p[1] - o.minHeight : (nh >= o.maxHeight ? 0-(o.maxHeight-p[1]) : mody); - - $(this.helper).css({ - left: co.left + modx, - top: co.top + mody - }); - - break; - } - } - - if(e.shiftKey) nh = nw * (p[1]/p[0]); - - if(o.minWidth) nw = nw <= o.minWidth ? o.minWidth : nw; - if(o.minHeight) nh = nh <= o.minHeight ? o.minHeight : nh; - - if(o.maxWidth) nw = nw >= o.maxWidth ? o.maxWidth : nw; - if(o.maxHeight) nh = nh >= o.maxHeight ? o.maxHeight : nh; - - if(e.shiftKey) nh = nw * (p[1]/p[0]); - - var modifier = $(that.element).triggerHandler("resize", [e, that.prepareCallbackObj(this)], o.resize); - if(!modifier) modifier = {}; - - for(var i in this.options.modifyThese) { - var c = this.options.modifyThese[i]; - c[0].css({ - width: modifier.width ? modifier.width+c[1] : nw+c[1], - height: modifier.height ? modifier.height+c[2] : nh+c[2] - }); - } - return false; - - } - }); - -})($); diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.selectable.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.selectable.js deleted file mode 100644 index 90e7b6c21..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.selectable.js +++ /dev/null @@ -1,116 +0,0 @@ -(function($) -{ - - //Make nodes selectable by expression - $.extend($.expr[':'], { selectable: "(' '+a.className+' ').indexOf(' ui-selectable ')" }); - $.extend($.expr[':'], { selectee: "(' '+a.className+' ').indexOf(' ui-selectee ')" }); - - $.fn.selectable = function(o) { - return this.each(function() { - if (!$(this).is(".ui-selectable")) new $.ui.selectable(this, o); - }); - } - - $.ui.selectable = function(el, o) { - - var options = { - filter: '*' - }; - var o = o || {}; $.extend(options, o); //Extend and copy options - this.element = el; var self = this; //Do bindings - self.dragged = false; - - $.extend(options, { - helper: function() { return $(document.createElement('div')).css({border:'1px dotted black'}); }, - _start: function(h,p,c,t,e) { - self.start.apply(t, [self, e]); // Trigger the start callback - }, - _drag: function(h,p,c,t,e) { - self.dragged = true; - self.drag.apply(t, [self, e]); // Trigger the drag callback - }, - _stop: function(h,p,c,t,e) { - self.stop.apply(t, [self, e]); // Trigger the end callback - self.dragged = false; - } - }); - - //Initialize mouse interaction - this.mouse = new $.ui.mouseInteraction(el, options); - - //Add the class for themeing - $(this.element).addClass("ui-selectable"); - $(this.element).children(options.filter).addClass("ui-selectee"); - - } - - $.extend($.ui.selectable.prototype, { - plugins: {}, - start: function(self, ev) { - $(self.mouse.helper).css({'z-index': 100, position: 'absolute', left: ev.clientX, top: ev.clientY, width:0, height: 0}); - if (ev.ctrlKey) { - if ($(ev.target).is('.ui-selected')) { - $(ev.target).removeClass('ui-selected').addClass('ui-unselecting'); - $(self.element).triggerHandler("selectableunselecting", [ev, { - selectable: self.element, - unselecting: ev.target, - options: this.options - }], this.options.unselecting); - } - } else { - self.unselecting(self, ev, this.options); - self.selectingTarget(self, ev, this.options); - } - }, - drag: function(self, ev) { - var x1 = self.mouse.opos[0], y1 = self.mouse.opos[1], x2 = ev.pageX, y2 = ev.pageY; - if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } - if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } - $(self.mouse.helper).css({left: x1, top: y1, width: x2-x1, height: y2-y1}); - self.selectingTarget(self, ev, this.options); - }, - stop: function(self, ev) { - var options = this.options; - $('.ui-selecting', self.element).each(function() { - $(this).removeClass('ui-selecting').addClass('ui-selected'); - $(self.element).triggerHandler("selectableselected", [ev, { - selectable: self.element, - selected: this, - options: options - }], options.selected); - }); - $('.ui-unselecting', self.element).each(function() { - $(this).removeClass('ui-unselecting'); - $(self.element).triggerHandler("selectableunselected", [ev, { - selectable: self.element, - unselected: this, - options: options - }], options.unselected); - }); - }, - unselecting: function(self, ev, options) { - $('.ui-selected', self.element).each(function() { - if (this != ev.target) { - $(this).removeClass('ui-selected').addClass('ui-unselecting'); - $(self.element).triggerHandler("selectableunselecting", [ev, { - selectable: self.element, - unselecting: this, - options: options - }], options.unselecting); - } - }); - }, - selectingTarget: function(self, ev, options) { - var target = $(ev.target); - if (target.is('.ui-selectee:not(.ui-selecting)')) { - target.removeClass('ui-selected').removeClass('ui-unselecting').addClass('ui-selecting'); - $(self.element).triggerHandler("selectableselecting", [ev, { - selectable: self.element, - selecting: ev.target, - options: options - }], options.selecting); - } - } - }); - -})(jQuery); \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.shadow.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.shadow.js deleted file mode 100644 index 754a64137..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.shadow.js +++ /dev/null @@ -1,87 +0,0 @@ -(function($) { - - //If the UI scope is not available, add it - $.ui = $.ui || {}; - - //Make nodes selectable by expression - $.extend($.expr[':'], { shadowed: "(' '+a.className+' ').indexOf(' ui-shadowed ')" }); - - $.fn.shadowEnable = function() { if($(this[0]).next().is(".ui-shadow")) $(this[0]).next().show(); } - $.fn.shadowDisable = function() { if($(this[0]).next().is(".ui-shadow")) $(this[0]).next().hide(); } - - $.fn.shadow = function(options) { - - options = options || {}; - options.offset = options.offset ? options.offset : 0; - options.opacity = options.opacity ? options.opacity : 0.2; - - return this.each(function() { - - var cur = $(this); - - //Create a shadow element - var shadow = $("
    "); cur.after(shadow); - - //Figure the base height and width - var baseWidth = cur.outerWidth(); - var baseHeight = cur.outerHeight(); - - //get the offset - var position = cur.position(); - - //Append smooth corners - $('
    ').css({ opacity: options.opacity-0.05, left: 5+options.offset, top: 5+options.offset, width: baseWidth+1, height: baseHeight+1 }).appendTo(shadow); - $('
    ').css({ opacity: options.opacity-0.1, left: 7+options.offset, top: 7+options.offset, width: baseWidth, height: baseHeight-3 }).appendTo(shadow); - $('
    ').css({ opacity: options.opacity-0.1, left: 7+options.offset, top: 7+options.offset, width: baseWidth-3, height: baseHeight }).appendTo(shadow); - $('
    ').css({ opacity: options.opacity, left: 6+options.offset, top: 6+options.offset, width: baseWidth-1, height: baseHeight-1 }).appendTo(shadow); - - //If we have a color, use it - if(options.color) - $("div.ui-shadow-color", shadow).css("background-color", options.color); - - //Determine the stack order (attention: the zIndex will get one higher!) - if(!cur.css("zIndex") || cur.css("zIndex") == "auto") { - var stack = 0; - cur.css("position", (cur.css("position") == "static" ? "relative" : cur.css("position"))).css("z-index", "1"); - } else { - var stack = parseInt(cur.css("zIndex")); - cur.css("zIndex", stack+1); - } - - //Copy the original z-index and position to the clone - //alert(shadow); If you insert this alert, opera will time correctly!! - shadow.css({ - position: "absolute", - zIndex: stack, - left: position.left, - top: position.top, - width: baseWidth, - height: baseHeight, - marginLeft: cur.css("marginLeft"), - marginRight: cur.css("marginRight"), - marginBottom: cur.css("marginBottom"), - marginTop: cur.css("marginTop") - }); - - - function rearrangeShadow(el,sh) { - var $el = $(el); - $(sh).css($el.position()); - $(sh).children().css({ height: $el.outerHeight()+"px", width: $el.outerWidth()+"px" }); - } - - if($.browser.msie) { - //Add dynamic css expressions - shadow[0].style.setExpression("left","parseInt(jQuery(this.previousSibling).css('left'))+'px' || jQuery(this.previousSibling).position().left"); - shadow[0].style.setExpression("top","parseInt(jQuery(this.previousSibling).css('top'))+'px' || jQuery(this.previousSibling).position().top"); - } else { - //Bind events for good browsers - this.addEventListener("DOMAttrModified",function() { rearrangeShadow(this,shadow); },false); - } - - - }); - }; - - -})($); \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.slider.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.slider.js deleted file mode 100644 index d1c43729a..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.slider.js +++ /dev/null @@ -1,294 +0,0 @@ -(function($) { - - - //Web Forms 2.0 - window.webforms = 1; - if(window['webforms']) { - $(document).ready(function() { - - $("input").each(function() { - if(this.getAttribute("type") == "range") { - var cur = $(this); - var slider = $("
    ").css({ width: cur.innerWidth()+"px", height: cur.innerHeight()+"px" }).insertAfter(cur); - var handle = $("
    ").appendTo(slider); - - - slider.css({ - "position": cur.css("position") == "absolute" ? "absolute" : "relative", - "left": cur.css("left"), - "right": cur.css("right"), - "zIndex": cur.css("zIndex"), - "float": cur.css("float"), - "clear": cur.css("clear") - }); - cur.css({ position: "absolute", opacity: 0, top: "-1000px", left: "-1000px" }); - - slider.slider({ - maxValue: cur.attr("max"), - minValue: cur.attr("min"), - startValue: this.getAttribute("value"), - stepping: cur.attr("step"), - change: function(e, ui) { cur[0].value = ui.value; cur[0].setAttribute("value", ui.value); }, - }); - - slider = slider.sliderInstance(); - - cur.bind("keydown", function(e) { - var o = slider.interaction.options; - switch(e.keyCode) { - case 37: - slider.moveTo(slider.interaction.curValue+o.minValue-(o.stepping || 1)); - break; - case 39: - slider.moveTo(slider.interaction.curValue+o.minValue+(o.stepping || 1)); - break; - } - if(e.keyCode != 9) return false; - }); - - }; - }); - - }); - } - - //Make nodes selectable by expression - $.extend($.expr[':'], { slider: "(' '+a.className+' ').indexOf(' ui-slider ')" }); - - $.fn.slider = function(o) { - return this.each(function() { - new $.ui.slider(this, o); - }); - } - - //Macros for external methods that support chaining - var methods = "destroy,enable,disable,moveTo".split(","); - for(var i=0;i this.interactions[i].curValue) return this.interactions[i-1].curValue; - } - - if(this.interactions[i+1]) { - if(this.interactions[i+1].curValue < this.interactions[i].curValue) return this.interactions[i+1].curValue; - } - } - } - - return false; - - }, - prepareCallbackObj: function(self,m) { - - var cur = this; - var func = function() { - var retVal = []; - for(var i=0;i p) m = p; - - this.curValue = (Math.round((m/p)*o.realValue)); - if(o.stepping) { - this.curValue = Math.round(this.curValue/o.stepping)*o.stepping; - m = ((this.curValue)/o.realValue) * p; - } - - if(that.interactions) { - nonvalidRange = that.nonvalidRange(this); - if(nonvalidRange) { - this.curValue = nonvalidRange; - m = ((this.curValue)/o.realValue) * p; - } - } - - $(this.element).css(prop, m+'px'); - $(that.element).triggerHandler("slide", [e, that.prepareCallbackObj(this,m)], o.slide); - return false; - - }, - moveTo: function(value,scale,changeslide,p) { // renamed from goto to moveTo as goto is reserved javascript word - - if(this.multipleHandles) return false; //TODO: Multiple handle moveTo function - - var o = this.interaction.options; - var offset = $(this.interaction.element).offsetParent().offset({ border: false }); - this.interaction.pickValue = this.interaction.curValue; - value = value-o.minValue; - - var modifier = scale || o.realValue; - - var p = this.parentSize; - var prop = this.prop; - - m = Math.round(((value)/modifier) * p); - - if(m < 0) m = 0; - if(m > p) m = p; - - this.interaction.curValue = (Math.round((m/p)*o.realValue)); - if(o.stepping) { - this.interaction.curValue = Math.round(this.interaction.curValue/o.stepping)*o.stepping; - m = ((this.interaction.curValue)/o.realValue) * p; - } - - $(this.interaction.element).css(prop, m+'px'); - - if(!changeslide && this.interaction.pickValue != this.interaction.curValue && !p) - $(this.element).triggerHandler("slidechange", [e, this.prepareCallbackObj(this.interaction)], o.change); - - if(changeslide) - $(this.element).triggerHandler("slide", [e, this.prepareCallbackObj(this.interaction)], o.slide); - - } - }); - -})($); diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.sortable.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.sortable.js deleted file mode 100644 index e8fdd82e1..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.sortable.js +++ /dev/null @@ -1,263 +0,0 @@ -if (window.Node && Node.prototype && !Node.prototype.contains) { - Node.prototype.contains = function (arg) { - return !!(this.compareDocumentPosition(arg) & 16) - } -} - -(function($) { - - //Make nodes selectable by expression - $.extend($.expr[':'], { sortable: "(' '+a.className+' ').indexOf(' ui-sortable ')" }); - - $.fn.sortable = function(o) { - return this.each(function() { - new $.ui.sortable(this,o); - }); - } - - //Macros for external methods that support chaining - var methods = "destroy,enable,disable,refresh".split(","); - for(var i=0;i li', - smooth: options.smooth != undefined ? options.smooth : true, - helper: 'clone', - containment: options.containment ? (options.containment == 'sortable' ? el : options.containment) : null, - zIndex: options.zIndex || 1000, - _start: function(h,p,c,t,e) { - self.start.apply(t, [self, e]); // Trigger the onStart callback - }, - _beforeStop: function(h,p,c,t,e) { - self.stop.apply(t, [self, e]); // Trigger the onStart callback - }, - _drag: function(h,p,c,t,e) { - self.drag.apply(t, [self, e]); // Trigger the onStart callback - }, - startCondition: function() { - return !self.disabled; - } - }); - - //Get the items - var items = $(options.items, el); - - //Let's determine the floating mode - options.floating = /left|right/.test(items.css('float')); - - //Let's determine the parent's offset - if($(el).css('position') == 'static') $(el).css('position', 'relative'); - options.offset = $(el).offset({ border: false }); - - items.each(function() { - new $.ui.mouseInteraction(this,options); - }); - - //Add current items to the set - items.each(function() { - self.set.push([this,null]); - }); - - this.options = options; - } - - $.extend($.ui.sortable.prototype, { - plugins: {}, - currentTarget: null, - lastTarget: null, - prepareCallbackObj: function(self, that) { - return { - helper: self.helper, - position: { left: self.pos[0], top: self.pos[1] }, - offset: self.options.cursorAt, - draggable: self, - current: that, - options: self.options - } - }, - refresh: function() { - - //Get the items - var self = this; - var items = $(this.options.items, this.element); - - var unique = []; - items.each(function() { - old = false; - for(var i=0;i').appendTo('body').css({ - height: this.element.offsetHeight+'px', - width: this.element.offsetWidth+'px', - position: 'absolute' - }); - } - - if(o.zIndex) { - if($(this.helper).css("zIndex")) o.ozIndex = $(this.helper).css("zIndex"); - $(this.helper).css('zIndex', o.zIndex); - } - - that.firstSibling = $(this.element).prev()[0]; - - $(this.element).triggerHandler("sortstart", [e, that.prepareCallbackObj(this)], o.start); - $(this.element).css('visibility', 'hidden'); - - return false; - - }, - stop: function(that, e) { - - var o = this.options; - var self = this; - var pos = this.pos; // patch - - if(o.smooth) { - var os = $(this.element).offset(); - o.beQuietAtEnd = true; - $(this.helper).animate({ left: os.left - o.po.left, top: os.top - o.po.top }, 500, stopIt); - } else { - stopIt(); - } - - function stopIt() { - self.pos = pos; // patch - - $(self.element).css('visibility', 'visible'); - if(that.helper) that.helper.remove(); - if(self.helper != self.element) $(self.helper).remove(); - - if(o.ozIndex) - $(self.helper).css('zIndex', o.ozIndex); - - - //Let's see if the position in DOM has changed - if($(self.element).prev()[0] != that.firstSibling) { - $(self.element).triggerHandler("sortupdate", [e, that.prepareCallbackObj(self, that)], o.update); - } - $(self.element).triggerHandler("sortstop", [e, that.prepareCallbackObj(self, that)], o.stop); // patch - } - - - return false; - - }, - drag: function(that, e) { - - var o = this.options; - - this.pos = [this.pos[0]-(o.cursorAt.left ? o.cursorAt.left : 0), this.pos[1]-(o.cursorAt.top ? o.cursorAt.top : 0)]; - var nv = $(this.element).triggerHandler("sort", [e, that.prepareCallbackObj(this)], o.sort); - var nl = (nv && nv.left) ? nv.left : this.pos[0]; - var nt = (nv && nv.top) ? nv.top : this.pos[1]; - - - var m = that.set; - var p = this.pos[1]; - - for(var i=0;i this.pos[1]+(this.options.po ? this.options.po.top : 0) + cio.offsetHeight/2)) continue; - - } else { - - var overlap = ((cO.top - (this.pos[1]+(this.options.po ? this.options.po.top : 0)))/this.helper.offsetHeight); - - if(!(cO.left < this.pos[0]+(this.options.po ? this.options.po.left : 0) + cio.offsetWidth/2 && cO.left + cio.offsetWidth > this.pos[0]+(this.options.po ? this.options.po.left : 0) + cio.offsetWidth/2)) continue; - - } - - if(overlap >= 0 && overlap <= 0.5) { //Overlapping at top - ci.prev().length ? ma(this.element) : mb(this.element); - } - - if(overlap < 0 && overlap > -0.5) { //Overlapping at bottom - ci.next()[0] == this.element ? mb(this.element) : ma(this.element); - } - - } - - //Let's see if the position in DOM has changed - if($(this.element).prev()[0] != that.lastSibling) { - $(this.element).triggerHandler("sortchange", [e, that.prepareCallbackObj(this, that)], this.options.change); - that.lastSibling = $(this.element).prev()[0]; - } - - if(that.helper) { //reposition helper if available - var to = $(this.element).offset(); - that.helper.css({ - top: to.top+'px', - left: to.left+'px' - }); - } - - $(this.helper).css('left', nl+'px').css('top', nt+'px'); // Stick the helper to the cursor - return false; - - } - }); - - })($); diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.tablesorter.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.tablesorter.js deleted file mode 100644 index 5bd18718e..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.tablesorter.js +++ /dev/null @@ -1,808 +0,0 @@ -/* - * - * TableSorter 2.0 - Client-side table sorting with ease! - * Version 2.0 - * @requires jQuery v1.1.3 - * - * Copyright (c) 2007 Christian Bach - * Examples and docs at: http://tablesorter.com - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - */ -/** - * - * @description Create a sortable table with multi-column sorting capabilitys - * - * @example $('#table').tablesorter(); - * @desc Create a simple tablesorter interface. - * - * @example $('#table').tablesorter({ sortList:[[0,0],[1,0]] }); - * @desc Create a tablesorter interface and sort on the first and secound column in ascending order. - * - * @example $('#table').tablesorter({ headers: { 0: { sorter: false}, 1: {sorter: false} } }); - * @desc Create a tablesorter interface and disableing the first and secound column headers. - * - * @example $('#table').tablesorter({ 0: {sorter:"integer"}, 1: {sorter:"currency"} }); - * @desc Create a tablesorter interface and set a column parser for the first and secound column. - * - * - * @param Object settings An object literal containing key/value pairs to provide optional settings. - * - * @option String cssHeader (optional) A string of the class name to be appended to sortable tr elements in the thead of the table. - * Default value: "header" - * - * @option String cssAsc (optional) A string of the class name to be appended to sortable tr elements in the thead on a ascending sort. - * Default value: "headerSortUp" - * - * @option String cssDesc (optional) A string of the class name to be appended to sortable tr elements in the thead on a descending sort. - * Default value: "headerSortDown" - * - * @option String sortInitialOrder (optional) A string of the inital sorting order can be asc or desc. - * Default value: "asc" - * - * @option String sortMultisortKey (optional) A string of the multi-column sort key. - * Default value: "shiftKey" - * - * @option String textExtraction (optional) A string of the text-extraction method to use. - * For complex html structures inside td cell set this option to "complex", - * on large tables the complex option can be slow. - * Default value: "simple" - * - * @option Object headers (optional) An array containing the forces sorting rules. - * This option let's you specify a default sorting rule. - * Default value: null - * - * @option Array sortList (optional) An array containing the forces sorting rules. - * This option let's you specify a default sorting rule. - * Default value: null - * - * @option Array sortForce (optional) An array containing the forces sorting rules. - * This option let's you specify a default sorting rule. - * Default value: null - * - * - * @option Boolean widthFixed (optional) Boolean flag indicating if tablesorter should apply fixed widths to the table columns. - * This is usefull when using the pager companion plugin. - * This options requires the dimension jquery plugin. - * Default value: false - * - * @option Boolean cancelSelection (optional) Boolean flag indicating if tablesorter should cancel selection of the table headers text. - * Default value: true - * - * @type jQuery - * - * @name tablesorter - * - * @cat Plugins/Tablesorter - * - * @author Christian Bach/christian.bach@polyester.se - */ - -(function($) { - $.extend({ - tablesorter: new function() { - - var parsers = [], widgets = []; - - this.defaults = { - cssHeader: "header", - cssAsc: "headerSortUp", - cssDesc: "headerSortDown", - sortInitialOrder: "asc", - sortMultiSortKey: "shiftKey", - sortForce: null, - textExtraction: "simple", - parsers: {}, - widgets: [], - widgetZebra: {css: ["even","odd"]}, - headers: {}, - widthFixed: false, - cancelSelection: true, - sortList: [], - headerList: [], - dateFormat: "us", - debug: false - }; - - /* debuging utils */ - function benchmark(label,stamp) { - log(label + "," + (new Date().getTime() - stamp.getTime()) + "ms"); - } - - function log(s) { - if (typeof console != "undefined" && typeof console.debug != "undefined") { - console.log(s); - } else { - alert(s); - } - } - - /* parsers utils */ - function buildParserCache(table,$headers) { - - if(table.config.debug) { var parsersDebug = ""; } - - var list = [], cells = table.tBodies[0].rows[0].cells, l = cells.length; - - for (var i=0;i < l; i++) { - var p = false; - - if($.meta && ($($headers[i]).data() && $($headers[i]).data().sorter) ) { - - p = getParserById($($headers[i]).data().sorter); - - } else if((table.config.headers[i] && table.config.headers[i].sorter)) { - - p = getParserById(table.config.headers[i].sorter); - } - if(!p) { - p = detectParserForColumn(table.config,cells[i]); - } - - if(table.config.debug) { parsersDebug += "column:" + i + " parser:" +p.id + "\n"; } - - list.push(p); - } - - if(table.config.debug) { log(parsersDebug); } - - return list; - }; - - function detectParserForColumn(config,node) { - var l = parsers.length; - for(var i=1; i < l; i++) { - if(parsers[i].is($.trim(getElementText(config,node)))) { - return parsers[i]; - } - } - - // 0 is always the generic parser (text) - return parsers[0]; - } - - function getParserById(name) { - var l = parsers.length; - for(var i=0; i < l; i++) { - if(parsers[i].id.toLowerCase() == name.toLowerCase()) { - return parsers[i]; - } - } - return false; - } - - /* utils */ - function buildCache(table) { - - if(table.config.debug) { var cacheTime = new Date(); } - - var totalRows = (table.tBodies[0] && table.tBodies[0].rows.length) || 0, - totalCells = table.tBodies[0].rows[0].cells.length, - parsers = table.config.parsers, - cache = {row: [], normalized: []}; - - for (var i=0;i < totalRows; ++i) { - - /** Add the table data to main data array */ - var c = table.tBodies[0].rows[i], cols = []; - - cache.row.push($(c)); - - for(var j=0; j < totalCells; ++j) { - cols.push(parsers[j].format(getElementText(table.config,c.cells[j]),table,c.cells[j])); - } - - cols.push(i); // add position for rowCache - cache.normalized.push(cols); - cols = null; - }; - - if(table.config.debug) { benchmark("Building cache for " + totalRows + " rows:", cacheTime); } - - return cache; - }; - - function getElementText(config,node) { - - if(!node) return ""; - - var t = ""; - - - if(typeof(config.textExtraction) == "function") { - t = config.textExtraction(node); - } else if(config.textExtraction == "complex") { - t = $(node).text(); - } else { - if(node.childNodes[0] && node.childNodes[0].hasChildNodes()) { - t = node.childNodes[0].innerHTML; - } else { - t = node.innerHTML; - } - } - return t; - } - - function appendToTable(table,cache) { - - if(table.config.debug) {var appendTime = new Date()} - - var c = cache, - r = c.row, - n= c.normalized, - totalRows = n.length, - checkCell = (n[0].length-1), - tableBody = $("tbody:first",table).empty(); - rows = []; - - for (var i=0;i < totalRows; i++) { - rows.push(r[n[i][checkCell]]); - if(table.config.appender == null) { - tableBody.append(r[n[i][checkCell]]); - } - } - - if(table.config.appender != null) { - table.config.appender(table,rows); - } - - rows = null; - - //apply table widgets - applyWidget(table); - - if(table.config.debug) { benchmark("Rebuilt table:", appendTime); } - - }; - - function buildHeaders(table) { - - if(table.config.debug) { var time = new Date(); } - - var meta = ($.meta) ? true : false, tableHeadersRows = []; - - for(var i = 0; i < table.tHead.rows.length; i++) { tableHeadersRows[i]=0; }; - - $tableHeaders = $(checkCellColSpan(table, tableHeadersRows, 0,table.tHead.rows[0].cells.length)); - - $tableHeaders.each(function(index) { - - this.count = 0; - this.column = index; - this.order = formatSortingOrder(table.config.sortInitialOrder); - - if(checkHeaderMetadata(this) || checkHeaderOptions(table,index)) this.sortDisabled = true; - - if(!this.sortDisabled) { - $(this).addClass(table.config.cssHeader); - } - - // add cell to headerList - table.config.headerList[index]= this; - }); - - if(table.config.debug) { benchmark("Built headers:", time); log($tableHeaders); } - - return $tableHeaders; - - }; - - function checkCellColSpan(table, headerArr, row) { - var arr = [], r = table.tHead.rows, c = r[row].cells; - - for(var i=headerArr[row]; i < c.length; i++) { - var cell = c[i]; - - if ( cell.colSpan > 1) { - arr = arr.concat(checkCellColSpan(table, headerArr,row+cell.rowSpan)); - } else { - if(table.tHead.length == 1 || (cell.rowSpan > 1 || !r[row+1])) { - arr.push(cell); - } - headerArr[row] = (i+row); - } - } - return arr; - }; - - function checkHeaderMetadata(cell) { - if(($.meta) && ($(cell).data().sorter === false)) { return true; }; - return false; - } - - function checkHeaderOptions(table,i) { - if((table.config.headers[i]) && (table.config.headers[i].sorter === false)) { return true; }; - return false; - } - - function applyWidget(table) { - var c = table.config.widgets; - var l = c.length; - for(var i=0; i < l; i++) { - - getWidgetById(c[i]).format(table); - } - - } - - function getWidgetById(name) { - var l = widgets.length; - for(var i=0; i < l; i++) { - if(widgets[i].id.toLowerCase() == name.toLowerCase() ) { - return widgets[i]; - } - } - }; - - function formatSortingOrder(v) { - - if(typeof(v) != "Number") { - i = (v.toLowerCase() == "desc") ? 1 : 0; - } else { - i = (v == (0 || 1)) ? v : 0; - } - return i; - } - - function isValueInArray(v, a) { - var l = a.length; - for(var i=0; i < l; i++) { - if(a[i][0] == v) { - return true; - } - } - return false; - } - - function setHeadersCss(table,$headers, list, css) { - // remove all header information - $headers.removeClass(css[0]).removeClass(css[1]); - - var h = []; - $headers.each(function(offset) { - if(!this.sortDisabled) { - h[this.column] = $(this); - } - }); - - var l = list.length; - for(var i=0; i < l; i++) { - h[list[i][0]].addClass(css[list[i][1]]); - } - } - - function fixColumnWidth(table,$headers) { - var c = table.config; - if(c.widthFixed) { - var colgroup = $(''); - $("tbody:first tr:first td",table).each(function() { - - colgroup.append($('').css('width',$(this).width())); - - }); - $(table).prepend(colgroup); - }; - } - - function updateHeaderSortCount(table,sortList) { - var c = table.config, l = sortList.length; - for(var i=0; i < l; i++) { - var s = sortList[i], o = c.headerList[s[0]]; - o.count = s[1]; - o.count++; - } - } - - /* sorting methods */ - function multisort(table,sortList,cache) { - - if(table.config.debug) { var sortTime = new Date(); } - - var dynamicExp = "var sortWrapper = function(a,b) {", l = sortList.length; - - for(var i=0; i < l; i++) { - - var c = sortList[i][0]; - var order = sortList[i][1]; - var s = (getCachedSortType(table.config.parsers,c) == "text") ? ((order == 0) ? "sortText" : "sortTextDesc") : ((order == 0) ? "sortNumeric" : "sortNumericDesc"); - - var e = "e" + i; - - dynamicExp += "var " + e + " = " + s + "(a[" + c + "],b[" + c + "]); "; - dynamicExp += "if(" + e + ") { return " + e + "; } "; - dynamicExp += "else { "; - } - - for(var i=0; i < l; i++) { - dynamicExp += "}; "; - } - - dynamicExp += "return 0; "; - dynamicExp += "}; "; - - eval(dynamicExp); - - cache.normalized.sort(sortWrapper); - - if(table.config.debug) { benchmark("Sorting on " + sortList.toString() + " and dir " + order+ " time:", sortTime); } - - return cache; - }; - - function sortText(a,b) { - return ((a < b) ? -1 : ((a > b) ? 1 : 0)); - }; - - function sortTextDesc(a,b) { - return ((b < a) ? -1 : ((b > a) ? 1 : 0)); - }; - - function sortNumeric(a,b) { - return a-b; - }; - - function sortNumericDesc(a,b) { - return b-a; - }; - - function getCachedSortType(parsers,i) { - return parsers[i].type; - }; - - /* public methods */ - this.construct = function(settings) { - - return this.each(function() { - - - - - var $this, $document,$headers, cache, config, shiftDown = 0, sortOrder; - - this.config = {}; - - config = $.extend(this.config, $.tablesorter.defaults, settings); - - if(!this.tHead || !this.tBodies) return true; - - // store common expression for speed - $this = $(this); - - // build headers - $headers = buildHeaders(this); - - // try to auto detect column type, and store in tables config - this.config.parsers = buildParserCache(this,$headers); - - - // build the cache for the tbody cells - cache = buildCache(this); - - // get the css class names, could be done else where. - var sortCSS = [config.cssDesc,config.cssAsc]; - - // fixate columns if the users supplies the fixedWidth option - fixColumnWidth(this); - - // apply event handling to headers - // this is to big, perhaps break it out? - $headers.click(function(e) { - if(!this.sortDisabled) { - // store exp, for speed - var $cell = $(this); - - // get current column index - var i = this.column; - - // get current column sort order - this.order = this.count++ % 2; - - - - // user only whants to sort on one column - if(!e[config.sortMultiSortKey]) { - - // flush the sort list - config.sortList = []; - - if(config.sortForce != null) { - var a = config.sortForce; - for(var j=0; j < a.length; j++) { - config.sortList.push(a[j]); - } - } - - // add column to sort list - config.sortList.push([i,this.order]); - - // multi column sorting - } else { - // the user has clicked on an all ready sortet column. - if(isValueInArray(i,config.sortList)) { - - // revers the sorting direction for all tables. - for(var j=0; j < config.sortList.length; j++) { - var s = config.sortList[j], o = config.headerList[s[0]]; - if(s[0] == i) { - o.count = s[1]; - o.count++; - s[1] = o.count % 2; - } - } - } else { - // add column to sort list array - config.sortList.push([i,this.order]); - } - }; - - //set css for headers - setHeadersCss($this[0],$headers,config.sortList,sortCSS); - - // sort the table and append it to the dom - appendToTable($this[0],multisort($this[0],config.sortList,cache)); - - // stop normal event by returning false - return false; - } - // cancel selection - }).mousedown(function() { - if(config.cancelSelection) { - this.onselectstart = function() {return false}; - //alert(this.onselectstart); - return false; - } - }); - - // apply easy methods that trigger binded events - $this.bind("update",function() { - - // rebuild the cache map - cache = buildCache(this); - - }).bind("sorton",function(e,list) { - - // update and store the sortlist - var sortList = config.sortList = list; - - // update header count index - updateHeaderSortCount(this,sortList); - - //set css for headers - setHeadersCss(this,$headers,sortList,sortCSS); - - // sort the table and append it to the dom - appendToTable(this,multisort(this,sortList,cache)); - - }).bind("appendCache",function() { - - appendToTable(this,cache); - - }).bind("applyWidgetId",function(e,id) { - - getWidgetById(id).format(this); - - }); - - if($.meta && ($(this).data() && $(this).data().sortlist)) { - config.sortList = $(this).data().sortlist; - } - // if user has supplied a sort list to constructor. - if(config.sortList.length > 0) { - $this.trigger("sorton",[config.sortList]); - } - - // apply widgets - applyWidget(this); - }); - }; - - this.addParser = function(parser) { - var l = parsers.length, a = true; - for(var i=0; i < l; i++) { - if(parsers[i].id.toLowerCase() == parser.id.toLowerCase()) { - a = false; - } - } - if(a) { parsers.push(parser); }; - }; - - this.addWidget = function(widget) { - widgets.push(widget); - }; - - this.formatFloat = function(s) { - - var i = parseFloat(s); - return (isNaN(i)) ? 0 : i; - }; - this.formatInt = function(s) { - var i = parseInt(s); - return (isNaN(i)) ? 0 : i; - }; - - } - }); - - // extend plugin scope - $.fn.extend({ - tablesorter: $.tablesorter.construct - }); - - // add default parsers - $.tablesorter.addParser({ - id: "text", - is: function(s) { - return true; - }, - format: function(s) { - return $.trim(s.toLowerCase()); - }, - type: "text" - }); - - $.tablesorter.addParser({ - id: "integer", - is: function(s) { - return s.match(new RegExp(/^\d+$/)); - }, - format: function(s) { - return $.tablesorter.formatInt(s); - }, - type: "numeric" - }); - - $.tablesorter.addParser({ - id: "currency", - is: function(s) { - return /^[£$€?.]/.test(s); - }, - format: function(s) { - return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g),"")); - }, - type: "numeric" - }); - - $.tablesorter.addParser({ - id: "integer", - is: function(s) { - return /^\d+$/.test(s); - }, - format: function(s) { - return $.tablesorter.formatFloat(s); - }, - type: "numeric" - }); - - $.tablesorter.addParser({ - id: "floating", - is: function(s) { - return s.match(new RegExp(/^(\+|-)?[0-9]+\.[0-9]+((E|e)(\+|-)?[0-9]+)?$/)); - }, - format: function(s) { - return $.tablesorter.formatFloat(s.replace(new RegExp(/,/),"")); - }, - type: "numeric" - }); - - $.tablesorter.addParser({ - id: "ipAddress", - is: function(s) { - return /^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s); - }, - format: function(s) { - var a = s.split("."); - var r = ""; - for (var i = 0, item; item = a[i]; i++) { - if(item.length == 2) { - r += "0" + item; - } else { - r += item; - } - } - return $.tablesorter.formatFloat(s); - }, - type: "numeric" - }); - - $.tablesorter.addParser({ - id: "url", - is: function(s) { - return /^(https?|ftp|file):\/\/$/.test(s); - }, - format: function(s) { - return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),'')); - }, - type: "text" - }); - - $.tablesorter.addParser({ - id: "isoDate", - is: function(s) { - return /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s); - }, - format: function(s) { - return $.tablesorter.formatFloat((s != "") ? new Date(s.replace(new RegExp(/-/g),"/")).getTime() : "0"); - }, - type: "numeric" - }); - - $.tablesorter.addParser({ - id: "percent", - is: function(s) { - return /^\d{1,3}%$/.test(s); - }, - format: function(s) { - return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),"")); - }, - type: "numeric" - }); - - $.tablesorter.addParser({ - id: "usLongDate", - is: function(s) { - return /^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|\'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/.test(s); - }, - format: function(s) { - return $.tablesorter.formatFloat(new Date(s).getTime()); - }, - type: "numeric" - }); - - $.tablesorter.addParser({ - id: "shortDate", - is: function(s) { - return /\d{1,2}[\/-]\d{1,2}[\/-]\d{2,4}/.test(s); - }, - format: function(s,table) { - var c = table.config; - s = s.replace(new RegExp(/-/g),"/"); - if(c.dateFormat == "us") { - /** reformat the string in ISO format */ - s = s.replace(new RegExp(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{4})/), "$3/$1/$2"); - } else if(c.dateFormat == "uk") { - /** reformat the string in ISO format */ - s = s.replace(new RegExp(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{4})/), "$3/$2/$1"); - } else if(c.dateFormat == "dd/mm/yy" || c.dateFormat == "dd-mm-yy") { - s = s.replace(new RegExp(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{2})/), "$1/$2/$3"); - } - return $.tablesorter.formatFloat(new Date(s).getTime()); - }, - type: "numeric" - }); - - $.tablesorter.addParser({ - id: "time", - is: function(s) { - return /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s); - }, - format: function(s) { - return $.tablesorter.formatFloat(new Date("2000/01/01 " + s).getTime()); - }, - type: "numeric" - }); - - - $.tablesorter.addParser({ - id: "metadata", - is: function(s) { - return false; - }, - format: function(s,table,cell) { - var c = table.config, p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName; - return $(cell).data()[p]; - }, - type: "numeric" - }); - - // add default widgets - $.tablesorter.addWidget({ - id: "zebra", - format: function(table) { - $("> tbody:first/tr:visible:even",table).removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0]); - $("> tbody:first/tr:visible:odd",table).removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]); - } - }); - -})(jQuery); \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.tabs.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.tabs.js deleted file mode 100644 index fd0009054..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.tabs.js +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Tabs 3 - New Wave Tabs - * - * Copyright (c) 2007 Klaus Hartl (stilbuero.de) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - */ - -(function($) { - - // if the UI scope is not availalable, add it - $.ui = $.ui || {}; - - // tabs initialization - $.fn.tabs = function(initial, options) { - if (initial && initial.constructor == Object) { // shift arguments - options = initial; - initial = null; - } - options = options || {}; - - initial = initial && initial.constructor == Number && --initial || 0; - - return this.each(function() { - new $.ui.tabs(this, $.extend(options, { initial: initial })); - }); - }; - - // other chainable tabs methods - $.each(['Add', 'Remove', 'Enable', 'Disable', 'Click', 'Load'], function(i, method) { - $.fn['tabs' + method] = function() { - var args = arguments; - return this.each(function() { - var instance = $.ui.tabs.getInstance(this); - instance[method.toLowerCase()].apply(instance, args); - }); - }; - }); - $.fn.tabsSelected = function() { - var selected = -1; - if (this[0]) { - var instance = $.ui.tabs.getInstance(this[0]), - $lis = $('li', this); - selected = $lis.index( $lis.filter('.' + instance.options.selectedClass)[0] ); - } - return selected >= 0 ? ++selected : -1; - }; - - // tabs class - $.ui.tabs = function(el, options) { - - this.source = el; - - this.options = $.extend({ - - // basic setup - initial: 0, - event: 'click', - disabled: [], - // TODO bookmarkable: $.ajaxHistory ? true : false, - unselected: false, - unselect: options.unselected ? true : false, - - // Ajax - spinner: 'Loading…', - cache: false, - idPrefix: 'tab-', - - // animations - /*fxFade: null, - fxSlide: null, - fxShow: null, - fxHide: null,*/ - fxSpeed: 'normal', - /*fxShowSpeed: null, - fxHideSpeed: null,*/ - - // callbacks - add: function() {}, - remove: function() {}, - enable: function() {}, - disable: function() {}, - click: function() {}, - hide: function() {}, - show: function() {}, - load: function() {}, - - // CSS classes - navClass: 'ui-tabs-nav', - selectedClass: 'ui-tabs-selected', - disabledClass: 'ui-tabs-disabled', - containerClass: 'ui-tabs-container', - hideClass: 'ui-tabs-hide', - loadingClass: 'ui-tabs-loading' - - }, options); - - this.tabify(true); - - // save instance for later - var uuid = 'tabs' + $.ui.tabs.prototype.count++; - $.ui.tabs.instances[uuid] = this; - $.data(el, 'tabsUUID', uuid); - - }; - - // static - $.ui.tabs.instances = {}; - $.ui.tabs.getInstance = function(el) { - return $.ui.tabs.instances[$.data(el, 'tabsUUID')]; - }; - - // instance methods - $.extend($.ui.tabs.prototype, { - count: 0, - tabify: function(init) { - - this.$tabs = $('a:first-child', this.source); - this.$containers = $([]); - - var self = this, o = this.options; - - this.$tabs.each(function(i, a) { - // inline tab - if (a.hash && a.hash.replace('#', '')) { // safari 2 reports '#' for an empty hash - self.$containers = self.$containers.add(a.hash); - } - // remote tab - else { - $.data(a, 'href', a.href); - var id = a.title && a.title.replace(/\s/g, '_') || o.idPrefix + (self.count + 1) + '-' + (i + 1); - a.href = '#' + id; - self.$containers = self.$containers.add( - $('#' + id)[0] || $('
    ') - .insertAfter( self.$containers[i - 1] || self.source ) - ); - } - }); - - if (init) { - - // Try to retrieve initial tab from fragment identifier in url if present, - // otherwise try to find selected class attribute on
  • . - this.$tabs.each(function(i, a) { - if (location.hash) { - if (a.hash == location.hash) { - o.initial = i; - // prevent page scroll to fragment - //if (($.browser.msie || $.browser.opera) && !o.remote) { - if ($.browser.msie || $.browser.opera) { - var $toShow = $(location.hash), toShowId = $toShow.attr('id'); - $toShow.attr('id', ''); - setTimeout(function() { - $toShow.attr('id', toShowId); // restore id - }, 500); - } - scrollTo(0, 0); - return false; // break - } - } else if ( $(a).parents('li:eq(0)').is('li.' + o.selectedClass) ) { - o.initial = i; - return false; // break - } - }); - - // attach necessary classes for styling if not present - $(this.source).is('.' + o.navClass) || $(this.source).addClass(o.navClass); - this.$containers.each(function() { - var $this = $(this); - $this.is('.' + o.containerClass) || $this.addClass(o.containerClass); - }); - - // highlight tab - var $lis = $('li', this.source); - this.$containers.addClass(o.hideClass); - $lis.removeClass(o.selectedClass); - if (!o.unselected) { - this.$containers.slice(o.initial, o.initial + 1).show(); - $lis.slice(o.initial, o.initial + 1).addClass(o.selectedClass); - } - - // load if remote tab - if ($.data(this.$tabs[o.initial], 'href')) { - this.load(o.initial + 1, $.data(this.$tabs[o.initial], 'href')); - if (o.cache) { - $.removeData(this.$tabs[o.initial], 'href'); // if loaded once do not load them again - } - } - - // disabled tabs - for (var i = 0, position; position = o.disabled[i]; i++) { - this.disable(position); - } - - } - - // setup animations - var showAnim = {}, showSpeed = o.fxShowSpeed || o.fxSpeed, - hideAnim = {}, hideSpeed = o.fxHideSpeed || o.fxSpeed; - if (o.fxSlide || o.fxFade) { - if (o.fxSlide) { - showAnim['height'] = 'show'; - hideAnim['height'] = 'hide'; - } - if (o.fxFade) { - showAnim['opacity'] = 'show'; - hideAnim['opacity'] = 'hide'; - } - } else { - if (o.fxShow) { - showAnim = o.fxShow; - } else { // use some kind of animation to prevent browser scrolling to the tab - showAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox - showSpeed = 1; // as little as 1 is sufficient - } - if (o.fxHide) { - hideAnim = o.fxHide; - } else { // use some kind of animation to prevent browser scrolling to the tab - hideAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox - hideSpeed = 1; // as little as 1 is sufficient - } - } - - // reset some styles to maintain print style sheets etc. - var resetCSS = { display: '', overflow: '', height: '' }; - if (!$.browser.msie) { // not in IE to prevent ClearType font issue - resetCSS['opacity'] = ''; - } - - // Hide a tab, animation prevents browser scrolling to fragment, - // $show is optional. - function hideTab(clicked, $hide, $show) { - $hide.animate(hideAnim, hideSpeed, function() { // - $hide.addClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc. - if ($.browser.msie) { - $hide[0].style.filter = ''; - } - o.hide(clicked, $hide[0], $show && $show[0] || null); - if ($show) { - showTab(clicked, $show, $hide); - } - }); - } - - // Show a tab, animation prevents browser scrolling to fragment, - // $hide is optional - function showTab(clicked, $show, $hide) { - if (!(o.fxSlide || o.fxFade || o.fxShow)) { - $show.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab containers - } - $show.animate(showAnim, showSpeed, function() { - $show.removeClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc. - if ($.browser.msie) { - $show[0].style.filter = ''; - } - o.show(clicked, $show[0], $hide && $hide[0] || null); - }); - } - - // switch a tab - function switchTab(clicked, $hide, $show) { - /*if (o.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click - $.ajaxHistory.update(clicked.hash); - }*/ - $(clicked).parents('li:eq(0)').addClass(o.selectedClass) - .siblings().removeClass(o.selectedClass); - hideTab(clicked, $hide, $show); - } - - // tab click handler - function tabClick(e) { - - //var trueClick = e.clientX; // add to history only if true click occured, not a triggered click - var $li = $(this).parents('li:eq(0)'), - $hide = self.$containers.filter(':visible'), - $show = $(this.hash); - - // If tab is already selected and not unselectable or tab disabled or click callback returns false stop here. - // Check if click handler returns false last so that it is not executed for a disabled tab! - if (($li.is('.' + o.selectedClass) && !o.unselect) || $li.is('.' + o.disabledClass) - || o.click(this, $show[0], $hide[0]) === false) { - this.blur(); - return false; - } - - // if tab may be closed - if (o.unselect) { - if ($li.is('.' + o.selectedClass)) { - $li.removeClass(o.selectedClass); - self.$containers.stop(); - hideTab(this, $hide); - this.blur(); - return false; - } else if (!$hide.length) { - $li.addClass(o.selectedClass); - self.$containers.stop(); - showTab(this, $show); - this.blur(); - return false; - } - } - - // stop possibly running animations - self.$containers.stop(); - - // show new tab - if ($show.length) { - - // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled - /*if ($.browser.msie && o.bookmarkable) { - var showId = this.hash.replace('#', ''); - $show.attr('id', ''); - setTimeout(function() { - $show.attr('id', showId); // restore id - }, 0); - }*/ - - if ($.data(this, 'href')) { // remote tab - var a = this; - self.load(self.$tabs.index(this) + 1, $.data(this, 'href'), function() { - switchTab(a, $hide, $show); - }); - if (o.cache) { - $.removeData(this, 'href'); // if loaded once do not load them again - } - } else { - switchTab(this, $hide, $show); - } - - // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash - /*var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0; - var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0; - setTimeout(function() { - scrollTo(scrollX, scrollY); - }, 0);*/ - - } else { - throw 'jQuery UI Tabs: Mismatching fragment identifier.'; - } - - this.blur(); // prevent IE from keeping other link focussed when using the back button - - //return o.bookmarkable && !!trueClick; // convert trueClick == undefined to Boolean required in IE - return false; - - } - - // attach click event, avoid duplicates from former tabifying - this.$tabs.unbind(o.event, tabClick).bind(o.event, tabClick); - - }, - add: function(url, text, position) { - if (url && text) { - var o = this.options; - position = position || this.$tabs.length; // append by default - if (position >= this.$tabs.length) { - var method = 'insertAfter'; - position = this.$tabs.length; - } else { - var method = 'insertBefore'; - } - if (url.indexOf('#') == 0) { // ajax container is created by tabify automatically - var $container = $(url); - // try to find an existing element before creating a new one - ($container.length && $container || $('
    ')) - [method](this.$containers[position - 1]); - } - $('
  • ' + text + '
  • ') - [method](this.$tabs.slice(position - 1, position).parents('li:eq(0)')); - this.tabify(); - o.add(this.$tabs[position - 1], this.$containers[position - 1]); // callback - } else { - throw 'jQuery UI Tabs: Not enough arguments to add tab.'; - } - }, - remove: function(position) { - if (position && position.constructor == Number) { - var $removedTab = this.$tabs.slice(position - 1, position).parents('li:eq(0)').remove(); - var $removedContainer = this.$containers.slice(position - 1, position).remove(); - this.tabify(); - this.options.remove($removedTab[0], $removedContainer[0]); // callback - } - }, - enable: function(position) { - var $li = this.$tabs.slice(position - 1, position).parents('li:eq(0)'), o = this.options; - $li.removeClass(o.disabledClass); - if ($.browser.safari) { // fix disappearing tab after enabling in Safari... TODO check Safari 3 - $li.animate({ opacity: 1 }, 1, function() { - $li.css({ opacity: '' }); - }); - } - o.enable(this.$tabs[position - 1], this.$containers[position - 1]); // callback - }, - disable: function(position) { - var $li = this.$tabs.slice(position - 1, position).parents('li:eq(0)'), o = this.options; - if ($.browser.safari) { // fix opacity of tab after disabling in Safari... TODO check Safari 3 - $li.animate({ opacity: 0 }, 1, function() { - $li.css({ opacity: '' }); - }); - } - $li.addClass(this.options.disabledClass); - o.disable(this.$tabs[position - 1], this.$containers[position - 1]); // callback - }, - click: function(position) { - this.$tabs.slice(position - 1, position).trigger('click'); - }, - load: function(position, url, callback) { - var self = this, - o = this.options, - $a = this.$tabs.slice(position - 1, position).addClass(o.loadingClass), - $span = $('span', $a), - text = $span.html(); - - // shift arguments - if (url && url.constructor == Function) { - callback = url; - } - - // set new URL - if (url) { - $.data($a[0], 'href', url); - } - - // load - if (o.spinner) { - $span.html('' + o.spinner + ''); - } - setTimeout(function() { // timeout is again required in IE, "wait" for id being restored - $($a[0].hash).load(url, function() { - if (o.spinner) { - $span.html(text); - } - $a.removeClass(o.loadingClass); - // This callback is required because the switch has to take place after loading - // has completed. - if (callback && callback.constructor == Function) { - callback(); - } - o.load(self.$tabs[position - 1], self.$containers[position - 1]); // callback - }); - }, 0); - } - }); - -})(jQuery); diff --git a/mods/photo_album/fluid/component-templates/js/jquery/GPL-LICENSE.txt b/mods/photo_album/fluid/component-templates/js/jquery/GPL-LICENSE.txt deleted file mode 100644 index 11dddd00e..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery/GPL-LICENSE.txt +++ /dev/null @@ -1,278 +0,0 @@ - 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/mods/photo_album/fluid/component-templates/js/jquery/MIT-LICENSE.txt b/mods/photo_album/fluid/component-templates/js/jquery/MIT-LICENSE.txt deleted file mode 100644 index 965a83130..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery/MIT-LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -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/mods/photo_album/fluid/component-templates/js/jquery/jquery-1.2.1.js b/mods/photo_album/fluid/component-templates/js/jquery/jquery-1.2.1.js deleted file mode 100644 index 9fb3a8e5d..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery/jquery-1.2.1.js +++ /dev/null @@ -1,2992 +0,0 @@ -(function(){ -/* - * jQuery 1.2.1 - 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-09-16 23:42:06 -0400 (Sun, 16 Sep 2007) $ - * $Rev: 3353 $ - */ - -// Map over jQuery in case of overwrite -if ( typeof jQuery != "undefined" ) - var _jQuery = jQuery; - -var jQuery = window.jQuery = function(selector, context) { - // If the context is a namespace object, return a new object - return this instanceof jQuery ? - this.init(selector, context) : - new jQuery(selector, context); -}; - -// Map over the $ in case of overwrite -if ( typeof $ != "undefined" ) - var _$ = $; - -// Map the jQuery namespace to the '$' one -window.$ = jQuery; - -var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/; - -jQuery.fn = jQuery.prototype = { - init: function(selector, context) { - // Make sure that a selection was provided - selector = selector || document; - - // Handle HTML strings - if ( typeof selector == "string" ) { - var m = quickExpr.exec(selector); - if ( m && (m[1] || !context) ) { - // HANDLE: $(html) -> $(array) - if ( m[1] ) - selector = jQuery.clean( [ m[1] ], context ); - - // HANDLE: $("#id") - else { - var tmp = document.getElementById( m[3] ); - if ( tmp ) - // Handle the case where IE and Opera return items - // by name instead of ID - if ( tmp.id != m[3] ) - return jQuery().find( selector ); - else { - this[0] = tmp; - this.length = 1; - return this; - } - else - selector = []; - } - - // HANDLE: $(expr) - } else - return new jQuery( context ).find( selector ); - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction(selector) ) - return new jQuery(document)[ jQuery.fn.ready ? "ready" : "load" ]( selector ); - - return this.setArray( - // HANDLE: $(array) - selector.constructor == Array && selector || - - // HANDLE: $(arraylike) - // Watch for when an array-like object is passed as the selector - (selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) || - - // HANDLE: $(*) - [ selector ] ); - }, - - jquery: "1.2.1", - - size: function() { - return this.length; - }, - - length: 0, - - get: function( num ) { - return num == undefined ? - - // Return a 'clean' array - jQuery.makeArray( this ) : - - // Return just the object - this[num]; - }, - - pushStack: function( a ) { - var ret = jQuery(a); - ret.prevObject = this; - return ret; - }, - - setArray: function( a ) { - this.length = 0; - Array.prototype.push.apply( this, a ); - return this; - }, - - each: function( fn, args ) { - return jQuery.each( this, fn, args ); - }, - - index: function( obj ) { - var pos = -1; - this.each(function(i){ - if ( this == obj ) pos = i; - }); - return pos; - }, - - attr: function( key, value, type ) { - var obj = key; - - // Look for the case where we're accessing a style value - if ( key.constructor == String ) - if ( value == undefined ) - return this.length && jQuery[ type || "attr" ]( this[0], key ) || undefined; - else { - obj = {}; - obj[ key ] = value; - } - - // Check to see if we're setting style values - return this.each(function(index){ - // Set all the styles - for ( var prop in obj ) - jQuery.attr( - type ? this.style : this, - prop, jQuery.prop(this, obj[prop], type, index, prop) - ); - }); - }, - - css: function( key, value ) { - return this.attr( key, value, "curCSS" ); - }, - - text: function(e) { - if ( typeof e != "object" && e != null ) - return this.empty().append( document.createTextNode( e ) ); - - var t = ""; - jQuery.each( e || this, function(){ - jQuery.each( this.childNodes, function(){ - if ( this.nodeType != 8 ) - t += this.nodeType != 1 ? - this.nodeValue : jQuery.fn.text([ this ]); - }); - }); - return t; - }, - - wrapAll: function(html) { - if ( this[0] ) - // The elements to wrap the target around - 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, 1, function(a){ - this.appendChild( a ); - }); - }, - - prepend: function() { - return this.domManip(arguments, true, -1, function(a){ - this.insertBefore( a, this.firstChild ); - }); - }, - - before: function() { - return this.domManip(arguments, false, 1, function(a){ - this.parentNode.insertBefore( a, this ); - }); - }, - - after: function() { - return this.domManip(arguments, false, -1, function(a){ - this.parentNode.insertBefore( a, this.nextSibling ); - }); - }, - - end: function() { - return this.prevObject || jQuery([]); - }, - - find: function(t) { - var data = jQuery.map(this, function(a){ return jQuery.find(t,a); }); - return this.pushStack( /[^+>] [^+>]/.test( t ) || t.indexOf("..") > -1 ? - jQuery.unique( data ) : data ); - }, - - clone: function(events) { - // Do the clone - var ret = this.map(function(){ - return this.outerHTML ? jQuery(this.outerHTML)[0] : this.cloneNode(true); - }); - - // Need to set the expando to null on the cloned set if it exists - // removeData doesn't work here, IE removes it from the original as well - // this is primarily for IE but the data expando shouldn't be copied over in any browser - var clone = ret.find("*").andSelf().each(function(){ - if ( this[ expando ] != undefined ) - this[ expando ] = null; - }); - - // Copy the events from the original to the clone - if (events === true) - this.find("*").andSelf().each(function(i) { - 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 the cloned set - return ret; - }, - - filter: function(t) { - return this.pushStack( - jQuery.isFunction( t ) && - jQuery.grep(this, function(el, index){ - return t.apply(el, [index]); - }) || - - jQuery.multiFilter(t,this) ); - }, - - not: function(t) { - return this.pushStack( - t.constructor == String && - jQuery.multiFilter(t, this, true) || - - jQuery.grep(this, function(a) { - return ( t.constructor == Array || t.jquery ) - ? jQuery.inArray( a, t ) < 0 - : a != t; - }) - ); - }, - - add: function(t) { - return this.pushStack( jQuery.merge( - this.get(), - t.constructor == String ? - jQuery(t).get() : - t.length != undefined && (!t.nodeName || jQuery.nodeName(t, "form")) ? - t : [t] ) - ); - }, - - is: function(expr) { - return expr ? jQuery.multiFilter(expr,this).length > 0 : false; - }, - - hasClass: function(expr) { - return this.is("." + expr); - }, - - val: function( val ) { - if ( val == undefined ) { - if ( this.length ) { - var elem = this[0]; - - // We need to handle select boxes special - if ( jQuery.nodeName(elem, "select") ) { - var index = elem.selectedIndex, - a = [], - options = elem.options, - one = elem.type == "select-one"; - - // Nothing was selected - if ( index < 0 ) - return null; - - // Loop through all the selected options - for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { - var option = options[i]; - if ( option.selected ) { - // Get the specifc value for the option - var val = jQuery.browser.msie && !option.attributes["value"].specified ? option.text : option.value; - - // We don't need an array for one selects - if ( one ) - return val; - - // Multi-Selects return an array - a.push(val); - } - } - - return a; - - // Everything else, we just grab the value - } else - return this[0].value.replace(/\r/g, ""); - } - } else - return this.each(function(){ - if ( val.constructor == Array && /radio|checkbox/.test(this.type) ) - this.checked = (jQuery.inArray(this.value, val) >= 0 || - jQuery.inArray(this.name, val) >= 0); - else if ( jQuery.nodeName(this, "select") ) { - var tmp = val.constructor == Array ? val : [val]; - - jQuery("option", this).each(function(){ - this.selected = (jQuery.inArray(this.value, tmp) >= 0 || - jQuery.inArray(this.text, tmp) >= 0); - }); - - if ( !tmp.length ) - this.selectedIndex = -1; - } else - this.value = val; - }); - }, - - html: function( val ) { - return val == undefined ? - ( this.length ? this[0].innerHTML : null ) : - this.empty().append( val ); - }, - - replaceWith: function( val ) { - return this.after( val ).remove(); - }, - - eq: function(i){ - return this.slice(i, i+1); - }, - - slice: function() { - return this.pushStack( Array.prototype.slice.apply( this, arguments ) ); - }, - - map: function(fn) { - return this.pushStack(jQuery.map( this, function(elem,i){ - return fn.call( elem, i, elem ); - })); - }, - - andSelf: function() { - return this.add( this.prevObject ); - }, - - domManip: function(args, table, dir, fn) { - var clone = this.length > 1, a; - - return this.each(function(){ - if ( !a ) { - a = jQuery.clean(args, this.ownerDocument); - if ( dir < 0 ) - a.reverse(); - } - - var obj = this; - - if ( table && jQuery.nodeName(this, "table") && jQuery.nodeName(a[0], "tr") ) - obj = this.getElementsByTagName("tbody")[0] || this.appendChild(document.createElement("tbody")); - - jQuery.each( a, function(){ - var elem = clone ? this.cloneNode(true) : this; - if ( !evalScript(0, elem) ) - fn.call( obj, elem ); - }); - }); - } -}; - -function evalScript(i, elem){ - var script = jQuery.nodeName(elem, "script"); - - if ( script ) { - 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); - - } else if ( elem.nodeType == 1 ) - jQuery("script", elem).each(evalScript); - - return script; -} - -jQuery.extend = jQuery.fn.extend = function() { - // copy reference to target object - var target = arguments[0] || {}, a = 1, al = arguments.length, deep = false; - - // Handle a deep copy situation - if ( target.constructor == Boolean ) { - deep = target; - target = arguments[1] || {}; - } - - // extend jQuery itself if only one argument is passed - if ( al == 1 ) { - target = this; - a = 0; - } - - var prop; - - for ( ; a < al; a++ ) - // Only deal with non-null/undefined values - if ( (prop = arguments[a]) != null ) - // Extend the base object - for ( var i in prop ) { - // Prevent never-ending loop - if ( target == prop[i] ) - continue; - - // Recurse if we're merging object values - if ( deep && typeof prop[i] == 'object' && target[i] ) - jQuery.extend( target[i], prop[i] ); - - // Don't bring in undefined values - else if ( prop[i] != undefined ) - target[i] = prop[i]; - } - - // Return the modified object - return target; -}; - -var expando = "jQuery" + (new Date()).getTime(), uuid = 0, win = {}; - -jQuery.extend({ - noConflict: function(deep) { - window.$ = _$; - if ( deep ) - window.jQuery = _jQuery; - return jQuery; - }, - - // This may seem like some crazy code, but trust me when I say that this - // is the only cross-browser way to do this. --John - isFunction: function( fn ) { - return !!fn && typeof fn != "string" && !fn.nodeName && - fn.constructor != Array && /function/i.test( fn + "" ); - }, - - // check if an element is in a XML document - isXMLDoc: function(elem) { - return elem.documentElement && !elem.body || - elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; - }, - - // Evalulates a script in a global context - // Evaluates Async. in Safari 2 :-( - globalEval: function( data ) { - data = jQuery.trim( data ); - if ( data ) { - if ( window.execScript ) - window.execScript( data ); - else if ( jQuery.browser.safari ) - // safari doesn't provide a synchronous global eval - window.setTimeout( data, 0 ); - else - eval.call( window, data ); - } - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); - }, - - cache: {}, - - data: function( elem, name, data ) { - elem = elem == window ? win : elem; - - var id = elem[ expando ]; - - // Compute a unique ID for the element - if ( !id ) - id = elem[ expando ] = ++uuid; - - // Only generate the data cache if we're - // trying to access or manipulate it - if ( name && !jQuery.cache[ id ] ) - jQuery.cache[ id ] = {}; - - // Prevent overriding the named cache with undefined values - if ( data != undefined ) - jQuery.cache[ id ][ name ] = data; - - // Return the named cache data, or the ID for the element - return name ? jQuery.cache[ id ][ name ] : id; - }, - - removeData: function( elem, name ) { - elem = elem == window ? win : elem; - - var id = elem[ expando ]; - - // If we want to remove a specific section of the element's data - if ( name ) { - if ( jQuery.cache[ id ] ) { - // Remove the section of cache data - delete jQuery.cache[ id ][ name ]; - - // If we've removed all the data, remove the element's cache - name = ""; - for ( name in jQuery.cache[ id ] ) break; - if ( !name ) - jQuery.removeData( elem ); - } - - // Otherwise, we want to remove all of the element's data - } else { - // Clean up the element expando - try { - delete elem[ expando ]; - } catch(e){ - // IE has trouble directly removing the expando - // but it's ok with using removeAttribute - if ( elem.removeAttribute ) - elem.removeAttribute( expando ); - } - - // Completely remove the data cache - delete jQuery.cache[ id ]; - } - }, - - // args is for internal usage only - each: function( obj, fn, args ) { - if ( args ) { - if ( obj.length == undefined ) - for ( var i in obj ) - fn.apply( obj[i], args ); - else - for ( var i = 0, ol = obj.length; i < ol; i++ ) - if ( fn.apply( obj[i], args ) === false ) break; - - // A special, fast, case for the most common use of each - } else { - if ( obj.length == undefined ) - for ( var i in obj ) - fn.call( obj[i], i, obj[i] ); - else - for ( var i = 0, ol = obj.length, val = obj[0]; - i < ol && fn.call(val,i,val) !== false; val = obj[++i] ){} - } - - return obj; - }, - - prop: function(elem, value, type, index, prop){ - // Handle executable functions - if ( jQuery.isFunction( value ) ) - value = value.call( elem, [index] ); - - // exclude the following css properties to add px - var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i; - - // Handle passing in a number to a CSS property - return value && value.constructor == Number && type == "curCSS" && !exclude.test(prop) ? - value + "px" : - value; - }, - - className: { - // internal only, use addClass("class") - add: function( elem, c ){ - jQuery.each( (c || "").split(/\s+/), function(i, cur){ - if ( !jQuery.className.has( elem.className, cur ) ) - elem.className += ( elem.className ? " " : "" ) + cur; - }); - }, - - // internal only, use removeClass("class") - remove: function( elem, c ){ - elem.className = c != undefined ? - jQuery.grep( elem.className.split(/\s+/), function(cur){ - return !jQuery.className.has( c, cur ); - }).join(" ") : ""; - }, - - // internal only, use is(".class") - has: function( t, c ) { - return jQuery.inArray( c, (t.className || t).toString().split(/\s+/) ) > -1; - } - }, - - swap: function(e,o,f) { - for ( var i in o ) { - e.style["old"+i] = e.style[i]; - e.style[i] = o[i]; - } - f.apply( e, [] ); - for ( var i in o ) - e.style[i] = e.style["old"+i]; - }, - - css: function(e,p) { - if ( p == "height" || p == "width" ) { - var old = {}, oHeight, oWidth, d = ["Top","Bottom","Right","Left"]; - - jQuery.each( d, function(){ - old["padding" + this] = 0; - old["border" + this + "Width"] = 0; - }); - - jQuery.swap( e, old, function() { - if ( jQuery(e).is(':visible') ) { - oHeight = e.offsetHeight; - oWidth = e.offsetWidth; - } else { - e = jQuery(e.cloneNode(true)) - .find(":radio").removeAttr("checked").end() - .css({ - visibility: "hidden", position: "absolute", display: "block", right: "0", left: "0" - }).appendTo(e.parentNode)[0]; - - var parPos = jQuery.css(e.parentNode,"position") || "static"; - if ( parPos == "static" ) - e.parentNode.style.position = "relative"; - - oHeight = e.clientHeight; - oWidth = e.clientWidth; - - if ( parPos == "static" ) - e.parentNode.style.position = "static"; - - e.parentNode.removeChild(e); - } - }); - - return p == "height" ? oHeight : oWidth; - } - - return jQuery.curCSS( e, p ); - }, - - curCSS: function(elem, prop, force) { - var ret, stack = [], swap = []; - - // A helper method for determining if an element's values are broken - function color(a){ - if ( !jQuery.browser.safari ) - return false; - - var ret = document.defaultView.getComputedStyle(a,null); - return !ret || ret.getPropertyValue("color") == ""; - } - - if (prop == "opacity" && jQuery.browser.msie) { - ret = jQuery.attr(elem.style, "opacity"); - return ret == "" ? "1" : ret; - } - - if (prop.match(/float/i)) - prop = styleFloat; - - if (!force && elem.style[prop]) - ret = elem.style[prop]; - - else if (document.defaultView && document.defaultView.getComputedStyle) { - - if (prop.match(/float/i)) - prop = "float"; - - prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase(); - var cur = document.defaultView.getComputedStyle(elem, null); - - if ( cur && !color(elem) ) - ret = cur.getPropertyValue(prop); - - // If the element isn't reporting its values properly in Safari - // then some display: none elements are involved - else { - // Locate all of the parent display: none elements - for ( var a = elem; a && color(a); a = a.parentNode ) - stack.unshift(a); - - // Go through and make them visible, but in reverse - // (It would be better if we knew the exact display type that they had) - for ( a = 0; a < stack.length; a++ ) - if ( color(stack[a]) ) { - swap[a] = stack[a].style.display; - stack[a].style.display = "block"; - } - - // Since we flip the display style, we have to handle that - // one special, otherwise get the value - ret = prop == "display" && swap[stack.length-1] != null ? - "none" : - document.defaultView.getComputedStyle(elem,null).getPropertyValue(prop) || ""; - - // Finally, revert the display styles back - for ( a = 0; a < swap.length; a++ ) - if ( swap[a] != null ) - stack[a].style.display = swap[a]; - } - - if ( prop == "opacity" && ret == "" ) - ret = "1"; - - } else if (elem.currentStyle) { - var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();}); - ret = elem.currentStyle[prop] || elem.currentStyle[newProp]; - - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - if ( !/^\d+(px)?$/i.test(ret) && /^\d/.test(ret) ) { - var style = elem.style.left; - var 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(a, doc) { - var r = []; - doc = doc || document; - - jQuery.each( a, function(i,arg){ - if ( !arg ) return; - - if ( arg.constructor == Number ) - arg = arg.toString(); - - // Convert html string into DOM nodes - if ( typeof arg == "string" ) { - // Fix "XHTML"-style tags in all browsers - arg = arg.replace(/(<(\w+)[^>]*?)\/>/g, function(m, all, tag){ - return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area)$/i)? m : all+">"; - }); - - // Trim whitespace, otherwise indexOf won't work as expected - var s = jQuery.trim(arg).toLowerCase(), div = doc.createElement("div"), tb = []; - - var wrap = - // option or optgroup - !s.indexOf("", ""] || - - !s.indexOf("", ""] || - - s.match(/^<(thead|tbody|tfoot|colg|cap)/) && - [1, "", "
    "] || - - !s.indexOf("", ""] || - - // matched above - (!s.indexOf("", ""] || - - !s.indexOf("", ""] || - - // IE can't serialize and - - - - - - - - - - -isError()!=true){ //if there is no error in index object, display the index page - $_SESSION['pa']['course_id']=$index->getVariable('course_id'); - - /* display index page from here */ - $template=new HTML_Template_ITX(PATH."Template"); - $template->loadTemplatefile("index.tpl.php", true, true); - - /* display images */ - $template->setCurrentBlock("IMAGE_START"); - $template->setVariable("IMAGE_PAGE_TITLE", _AT('pa_title_index')); - - $template->setVariable("MAIN_URL", BASE_PATH.'index.php'); - $template->setVariable("MAIN_TITLE", _AT('pa_tag_course_photo_alt')); - - $template->setVariable("MY_PHOTO_URL", BASE_PATH.'my_photo.php'); - $template->setVariable("MY_PHOTO_TITLE", _AT('pa_tag_my_photo_alt')); - - $template->setVariable("MY_COMMENT_URL", BASE_PATH.'my_comment.php'); - $template->setVariable("MY_COMMENT_TITLE", _AT('pa_tag_my_comment_alt')); - - $template->setVariable("CURRENT_PAGE_NUM", $index->getVariable('current_page')); - - - $image_array=$index->getVariable('image_array'); - for ($i=0; $i < count($image_array); $i++) { - $template->setCurrentBlock("IMAGE_DISPLAY"); - $template->setVariable("IMAGE_ID",$image_array[$i]['image_id']); - - // the TABINDEX value is used to assign a unique value to each id when looping through each and rendering their presentation GG - $template->setVariable("TABINDEX", $image_array[$i]['order']); - $template->setVariable("LINK", $image_array[$i]['link']); - $count=get_total_comment_number(STUDENT, $index->getVariable('course_id'), APPROVED, $image_array[$i]['image_id']); - if ($count >0 ){ - $template->setVariable("IMAGE_TITLE", $image_array[$i]['title']." [".$count."]"); - } else { - $template->setVariable("IMAGE_TITLE", $image_array[$i]['title']); - } - $template->setVariable("IMAGE_SRC", $get_file.$image_array[$i]['location'].urlencode($image_array[$i]['thumb_image_name'])); - $template->setVariable("IMAGE_ALT", $image_array[$i]['alt']); - $template->parseCurrentBlock("IMAGE_DISPLAY"); - } - - if ($index->getVariable('show_modification_buttons')==true){ - $template->setCurrentBlock("IMAGE_ADD_BUTTON"); - $template->setVariable("FORM_NAME", "thumb_form"); - $template->setVariable("SAVE_FORM_NAME", "save_form"); - $template->setVariable("ACTION", UPLOAD_ACTION); - $template->setVariable("SAVE_ACTION", $_SERVER['PHP_SELF']); - $template->setVariable("ADD_STRING", _AT('pa_button_add_image')); - //set the text for the save order button GG - $template->setVariable("SAVE_STRING", _AT('pa_button_save_image_order')); - $template->setVariable("CHOOSE_VALUE", IMAGE); - $template->parseCurrentBlock("IMAGE_ADD_BUTTON"); - } - - /* Display page table */ - $page_array=&$index->getVariable('page_array'); - $current=$index->getVariable('current_page'); - if ($index->getVariable('show_page_left_buttons')==true){ - $first_button=_AT('pa_tag_first_page_button'); - $previous_button=_AT('pa_tag_previous_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • \''.$first_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • \''.$previous_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - for ($i=$page_array['start']; $i<=$page_array['end']; $i++){ - if ($i==$current){ - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • '.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } else { - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • '.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - } - - if ($index->getVariable('show_page_right_buttons')==true){ - $next_button=_AT('pa_tag_next_page_button'); - $last_button=_AT('pa_tag_last_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • \''.$next_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • \''.$last_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - $template->parseCurrentBlock("B_DATA_PART"); - $template->parseCurrentBlock("IMAGE_START"); - $template->parseCurrentBlock(); - $template->show(); -} else { - $msg->addError('pa_obj_pa_index'); - redirect('../../index.php'); -} - -?> - - - - - - - - - - diff --git a/mods/photo_album/index_admin.php b/mods/photo_album/index_admin.php deleted file mode 100644 index 853591970..000000000 --- a/mods/photo_album/index_admin.php +++ /dev/null @@ -1,66 +0,0 @@ - - -addError('pa_var_course_empty'); - redirect('../../admin/index.php'); -} else { - $link=$base_path.'mods/photo_album/admin_image_list.php'; - $template=new HTML_Template_ITX("./Template"); - $template->loadTemplatefile("index_admin.tpl.php", true, true); - - $template->setVariable("TITLE", _AT('pa_title_admin_index')); - $template->setVariable("MESSAGE", _AT('pa_note_admin')); - $template->setVariable("FORM_NAME", "photo_form"); - $template->setVariable("FORM_ACTION", $link); - $template->setVariable("SELECT_NAME", "course_id"); - - for ($i=0; $isetCurrentBlock("OPTION_VALUE"); - $template->setVariable("TABINDEX", $i); - $template->setVariable("VALUE", $courses[$i]['id']); - $template->setVariable("TEXT", $courses[$i]['title']); - $template->parseCurrentBlock("OPTION_VALUE"); - } - - $template->setVariable("SUBMIT_NAME", "submit"); - $template->setVariable("SUBMIT_VALUE", _AT('pa_tag_go')); - - $template->parseCurrentBlock(); - $template->show(); -} -?> - \ No newline at end of file diff --git a/mods/photo_album/instructor_comment.php b/mods/photo_album/instructor_comment.php deleted file mode 100644 index c28374d0c..000000000 --- a/mods/photo_album/instructor_comment.php +++ /dev/null @@ -1,171 +0,0 @@ - -isError()!=true){ //no error found, so display the page - $template=new HTML_Template_ITX("./Template"); - $template->loadTemplateFile("instructor_comment.tpl.php"); - $template->setVariable("ADMIN_NUMBER_OF_COMMENT", ADMIN_NUMBER_OF_COMMENT); - - switch ($admin->getVariable('mode')){ - case POSTED_NEW: - $template->setVariable("TITLE", _AT('pa_title_instructor_new_comment')); - break; - case APPROVED: - $template->setVariable("TITLE", _AT('pa_title_instructor_approved_comment')); - break; - case DISAPPROVED: - $template->setVariable("TITLE", _AT('pa_title_instructor_disapproved_comment')); - break; - } - - $mode=get_config_mode($admin->getVariable('course_id')); - $template->setVariable("CONFIG_STRING", _AT('pa_tag_config_string')); - if ($mode==CONFIG_ENABLED){ - $template->setVariable("CONFIG_VALUE", _AT('pa_tag_config_enabled')); - } else { - $template->setVariable("CONFIG_VALUE", _AT('pa_tag_config_disabled')); - } - - $template->setCurrentBlock("SELECT_PART"); - $template->setVariable("SELECT_FORM_NAME", "select_form"); - $template->setVariable("SELECT_ACTION", $_SERVER['PHP_SELF']); - $template->setVariable("SELECT_NAME", "mode"); - $template->setVariable("SELECT_LABEL", _AT('pa_tag_view')); - - $template->setCurrentBlock("OPTION_PART"); - $template->setVariable("OPTION_VALUE", POSTED_NEW); - $template->setVariable("OPTION_STRING", _AT('pa_tag_new_comment')); - $template->parseCurrentBlock("OPTION_PART"); - - $template->setCurrentBlock("OPTION_PART"); - $template->setVariable("OPTION_VALUE", APPROVED); - $template->setVariable("OPTION_STRING", _AT('pa_tag_approved_comment')); - $template->parseCurrentBlock("OPTION_PART"); - - $template->setCurrentBlock("OPTION_PART"); - $template->setVariable("OPTION_VALUE", DISAPPROVED); - $template->setVariable("OPTION_STRING", _AT('pa_tag_disapproved_comment')); - $template->parseCurrentBlock("OPTION_PART"); - - $template->setVariable("SELECT_SUBMIT", "select_submit"); - $template->setVariable("SELECT_SUBMIT_VALUE", _AT('pa_tag_go')); - $template->parseCurrentBlock("SELECT_PART"); - - $template->setCurrentBlock("COMMENT_TABLE_PART"); - $template->setVariable("COMMENT_TABLE_FORM_NAME", "table_form"); - $action_string=$_SERVER['PHP_SELF']."?mode=".$admin->getVariable('mode')."&current_page=".$admin->getVariable('current_page'); - $template->setVariable("COMMENT_TABLE_ACTION", $action_string); - - /* start display comments */ - $comment_array=$admin->comment_array; - // print_r($comment_array); - //exit; - for ($i=0; $isetCurrentBlock("COMMENT_TABLE_DATA"); - $template->setVariable("CHECK_NAME", "commentId".$i); - $template->setVariable("CHECK_VALUE", $comment_array[$i]['comment_id']); - $template->setVariable("COMMENT_TABLE_DATA1", $comment_array[$i]['comment']); - $template->setVariable("COMMENT_TABLE_DATA2", _AT('login').": ".$comment_array[$i]['login']); - $template->setVariable("COMMENT_TABLE_DATA3", _AT('date').": ".$comment_array[$i]['date']); - $template->setVariable("COMMENT_TABLE_DATA4", ""._AT('pa_tag_view_comment_link').""); - $template->parseCurrentBlock("COMMENT_TABLE_DATA"); - } - $template->setCurrentBlock("COMMENT_BUTTON"); - $template->setVariable("COMMENT_BUTTON_NAME", "button_disapprove"); - $template->setVariable("COMMENT_BUTTON_VALUE", _AT('pa_button_set_disapproved_comment')); - $template->parseCurrentBlock("COMMENT_BUTTON"); - - $template->setCurrentBlock("COMMENT_BUTTON"); - $template->setVariable("COMMENT_BUTTON_NAME", "button_approve"); - $template->setVariable("COMMENT_BUTTON_VALUE", _AT('pa_button_set_approved_comment')); - $template->parseCurrentBlock("COMMENT_BUTTON"); - - $template->setCurrentBlock("COMMENT_BUTTON"); - $template->setVariable("COMMENT_BUTTON_NAME", "button_post_new"); - $template->setVariable("COMMENT_BUTTON_VALUE", _AT('pa_button_set_new_comment')); - $template->parseCurrentBlock("COMMENT_BUTTON"); - - $template->setVariable("CHECK_ALL_MSG", _AT('pa_tag_check_all_comment')); - - $template->parseCurrentBlock("COMMENT_TABLE_PART"); - - // Display page table - $page_array=$admin->getVariable('page_array'); - $current=$admin->getVariable('current_page'); - if ($admin->getVariable('show_page_left_buttons')==true){ - $first_button=_AT('pa_tag_first_page_button'); - $previous_button=_AT('pa_tag_previous_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$first_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$previous_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - for ($i=$page_array['start']; $i<=$page_array['end']; $i++){ - if ($i==$current){ - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • '.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } else { - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>'.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - } - - if ($admin->getVariable('show_page_right_buttons')==true){ - $last_button=_AT('pa_tag_last_page_button'); - $next_button=_AT('pa_tag_next_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$next_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$last_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - - $template->parseCurrentBlock(); - $template->show(); - unset($_SESSION['pa']); - $_SESSION['pa']['course_id']; - $_SESSION['pa']['instructor_mode']=true; -} else { - $msg->addError('pa_obj_pa_admin_comment'); - redirect('index.php'); -} - -?> - \ No newline at end of file diff --git a/mods/photo_album/instructor_config.php b/mods/photo_album/instructor_config.php deleted file mode 100644 index 4be7ad6b1..000000000 --- a/mods/photo_album/instructor_config.php +++ /dev/null @@ -1,67 +0,0 @@ - - -loadTemplateFile("instructor_config.tpl.php"); -$template->setVariable("TITLE", _AT('pa_title_instructor_config')); -$template->setVariable("CONFIG_NOTE", _AT('pa_note_instructor_config')); - -$mode=get_config_mode($_SESSION['pa']['course_id']); -$template->setVariable("CONFIG_STRING", _AT('pa_tag_config_string')); -if ($mode==CONFIG_ENABLED){ - $template->setVariable("CONFIG_VALUE", _AT('pa_tag_config_enabled')); - $template->setVariable("CHECKED1", "checked=\"checked\""); -} else { - $template->setVariable("CONFIG_VALUE", _AT('pa_tag_config_disabled')); - $template->setVariable("CHECKED2", "checked=\"checked\""); -} - -$template->setVariable("FORM_NAME", "config_form"); -$template->setVariable("ACTION", $_SERVER['PHP_SELF']); -$template->setVariable("RADIO_VALUE1", "make_enabled"); -$template->setVariable("RADIO_STRING1", _AT('yes')); -$template->setVariable("RADIO_VALUE2", "make_disabled"); -$template->setVariable("RADIO_STRING2", _AT('no')); -$template->setVariable("SUBMIT_VALUE", _AT('pa_button_config_change')); - -$template->show(); -?> - \ No newline at end of file diff --git a/mods/photo_album/instructor_image.php b/mods/photo_album/instructor_image.php deleted file mode 100644 index cb31a3b92..000000000 --- a/mods/photo_album/instructor_image.php +++ /dev/null @@ -1,183 +0,0 @@ - -isError()!=true){ //no error is found, so display the page - $template=new HTML_Template_ITX("./Template"); - $template->loadTemplateFile("instructor_image.tpl.php"); - $template->setVariable("ADMIN_NUMBER_OF_IMAGE", ADMIN_NUMBER_OF_IMAGE); - - switch ($admin->getVariable('mode')){ - case POSTED_NEW: - $template->setVariable("TITLE", _AT('pa_title_instructor_new_pic')); - break; - case APPROVED: - $template->setVariable("TITLE", _AT('pa_title_instructor_approved_pic')); - break; - case DISAPPROVED: - $template->setVariable("TITLE", _AT('pa_title_instructor_disapproved_pic')); - break; - } - - $mode=get_config_mode($admin->getVariable('course_id')); - $template->setVariable("CONFIG_STRING", _AT('pa_tag_config_string')); - if ($mode==CONFIG_ENABLED){ - $template->setVariable("CONFIG_VALUE", _AT('pa_tag_config_enabled')); - } else { - $template->setVariable("CONFIG_VALUE", _AT('pa_tag_config_disabled')); - } - - $template->setCurrentBlock("ADD_PART"); - $template->setVariable("ADD_FORM_NAME", "add_form"); - $template->setVariable("ADD_ACTION", UPLOAD_ACTION); - $template->setVariable("ADD_VALUE", _AT('pa_button_add_image')); - $template->setVariable("ADD_HIDDEN_VALUE", IMAGE); - $template->parseCurrentBlock("ADD_PART"); - - $template->setCurrentBlock("SELECT_PART"); - $template->setVariable("SELECT_FORM_NAME", "select_form"); - $template->setVariable("SELECT_ACTION", $_SERVER['PHP_SELF']); - $template->setVariable("SELECT_NAME", "mode"); - $template->setVariable("SELECT_LABEL", _AT('pa_tag_view')); - - $template->setCurrentBlock("OPTION_PART"); - $template->setVariable("OPTION_VALUE", POSTED_NEW); - $template->setVariable("OPTION_STRING", _AT('pa_tag_new_pic')); - $template->parseCurrentBlock("OPTION_PART"); - - $template->setCurrentBlock("OPTION_PART"); - $template->setVariable("OPTION_VALUE", APPROVED); - $template->setVariable("OPTION_STRING", _AT('pa_tag_approved_pic')); - $template->parseCurrentBlock("OPTION_PART"); - - $template->setCurrentBlock("OPTION_PART"); - $template->setVariable("OPTION_VALUE", DISAPPROVED); - $template->setVariable("OPTION_STRING", _AT('pa_tag_disapproved_pic')); - $template->parseCurrentBlock("OPTION_PART"); - - $template->setVariable("SELECT_SUBMIT", "select_submit"); - $template->setVariable("SELECT_SUBMIT_VALUE", _AT('pa_tag_go')); - $template->parseCurrentBlock("SELECT_PART"); - - $template->setCurrentBlock("IMAGE_TABLE_PART"); - $template->setVariable("IMAGE_TABLE_FORM_NAME", "table_form"); - $action_string=$_SERVER['PHP_SELF']."?mode=".$admin->getVariable('mode')."&current_page=".$admin->getVariable('current_page'); - $template->setVariable("IMAGE_TABLE_ACTION", $action_string); - - /* start display images */ - $image_array=$admin->image_array; - - // print_r($image_array); - //exit; - for ($i=0; $isetCurrentBlock("IMAGE_TABLE_DATA"); - $template->setVariable("CHECK_NAME", "imageId".$i); - $template->setVariable("CHECK_VALUE", $image_array[$i]['image_id']); - $img_src=$get_file.$image_array[$i]['location'].urlencode($image_array[$i]['thumb_image_name']); - $template->setVariable("IMAGE_TABLE_DATA1", "\"".$image_array[$i]['alt']."\"/"); - $template->setVariable("IMAGE_TABLE_DATA2", _AT('title').": ".$image_array[$i]['title']); - $template->setVariable("IMAGE_TABLE_DATA3", _AT('login').": ".$image_array[$i]['login']); - $template->setVariable("IMAGE_TABLE_DATA4", _AT('pa_tag_alt').": ".$image_array[$i]['alt']); - $template->setVariable("IMAGE_TABLE_DATA5", _AT('date').": ".$image_array[$i]['date']); - $template->setVariable("IMAGE_TABLE_DATA6", ""._AT('pa_tag_view_image_link').""); - $template->parseCurrentBlock("IMAGE_TABLE_DATA"); - } - $template->setCurrentBlock("IMAGE_BUTTON"); - $template->setVariable("IMAGE_BUTTON_NAME", "button_disapprove"); - $template->setVariable("IMAGE_BUTTON_VALUE", _AT('pa_button_set_disapproved_pic')); - $template->parseCurrentBlock("IMAGE_BUTTON"); - - $template->setCurrentBlock("IMAGE_BUTTON"); - $template->setVariable("IMAGE_BUTTON_NAME", "button_approve"); - $template->setVariable("IMAGE_BUTTON_VALUE", _AT('pa_button_set_approved_pic')); - $template->parseCurrentBlock("IMAGE_BUTTON"); - - $template->setCurrentBlock("IMAGE_BUTTON"); - $template->setVariable("IMAGE_BUTTON_NAME", "button_post_new"); - $template->setVariable("IMAGE_BUTTON_VALUE", _AT('pa_button_set_new_pic')); - $template->parseCurrentBlock("IMAGE_BUTTON"); - - $template->setVariable("CHECK_ALL_MSG", _AT('pa_tag_check_all_image')); - - $template->parseCurrentBlock("IMAGE_TABLE_PART"); - - // Display page table - $page_array=$admin->getVariable('page_array'); - $current=$admin->getVariable('current_page'); - if ($admin->getVariable('show_page_left_buttons')==true){ - $first_button=_AT('pa_tag_first_page_button'); - $previous_button=_AT('pa_tag_previous_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$first_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$previous_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - for ($i=$page_array['start']; $i<=$page_array['end']; $i++){ - if ($i==$current){ - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • '.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } else { - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>'.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - } - - if ($admin->getVariable('show_page_right_buttons')==true){ - $next_button=_AT('pa_tag_next_page_button'); - $last_button=_AT('pa_tag_last_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$next_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$last_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - $template->parseCurrentBlock(); - $template->show(); - unset($_SESSION['pa']); - $_SESSION['pa']['course_id']=$admin->getVariable('course_id'); - $_SESSION['pa']['instructor_mode']=true; -} else { - $msg->addError('pa_obj_pa_admin'); - redirect('index.php'); -} - -?> - \ No newline at end of file diff --git a/mods/photo_album/module.css b/mods/photo_album/module.css deleted file mode 100644 index 2b1d8f305..000000000 --- a/mods/photo_album/module.css +++ /dev/null @@ -1,342 +0,0 @@ - -div#message { - border: 1px solid #ccc; - padding: 10px; - width: 50%; - margin-right: auto; - margin-left: auto; - background-color: red; - color: black; - margin-top: 30px; - margin-bottom: 30px; - font-size: 3.0em; -} - -.pa_confirm { - clear:left; - float:left; - font-size:2.0em; - color:red; -} - -div#deny { - clear:left; - float:left; - font-size:2.0em; - color:red; -} - -div#success { - clear:left; - float:left; - font-size:2.0em; - color:green; -} - -.pa_result_success{ - font-size:1.0em; - color:green; - font-family:sans-serif, verdana, helvetica, arial; - font-weight:bold; - text-align: center; -} - -.pa_img { - margin: 0; - padding: 0.1em; - border: solid 0.2em black; } -.pa_img:hover { - margin: 0; - padding: 0.1em; - border: solid 0.2em red; } -.pa_p { font-size: 0.8em; font-family: sans-serif, verdana, helvetica, arial; font-weight: bold; text-align: center; margin: 0; padding: 0; display: block; } -.pa_p a { text-decoration: none; } -.pa_p a:hover { color: black; } -.pa_gallery { margin: 0.3em; padding: 0.5em; list-style-type: none; clear:both;} -.pa_pic_border { float: left; text-align: center; width: 10em; height: 10em; padding: 1.2em; border: none; display: block;} -.pa_page_table { - float:left; - clear:left; - margin-bottom:3.0em; - margin-top:1.0em; -} -.pa_buttons{ - float:left; - clear:left; - margin-top:0.3em; - margin-left:0.8em; -} -.pa_img_view{ - float:left; - clear:left; - margin-top: 0.5em; - margin-left:0.8em; -} -.pa_img_message{ - float:left; - clear:left; - margin-top:1.0em; - font-size:1.5em; - font-family:sans-serif; - text-decoration: underline; - color: rgb(0, 64, 128); - margin-left:0.3em; -} - -.pa_message{ - float:left; - clear:both; - font-size:1.2em; - margin-top:0.5em; - margin-bottom:0.5em; -} - -.pa_message_sub { - float:left; - clear:left; - margin-top:0.8em; - width:80%; -} - - -.pa_form { - float:left; - clear:left; -} - -.pa_caution { - float:left; - margin-left:0.8em; - font-size:1.3em; - color:red; - text-align:center; -} - -.hide { - display:none; -} - -.hide_fieldset { - border:0; -} - -.invisible{ - display:none; -} - -.disapproved{ - background-image: url(skins/swatch_yellow.jpg); - background-repeat: repeat; - background-color: #FFCCCC; - font-weight: bold; -} - -.posted_new{ - background-image: url(skins/swatch_green.jpg); - background-repeat: repeat; - background-color: #FFCCCC; - font-weight: bold; -} - -#pa_pagination { - clear:both; - font-family: Geneva, Arial, Helvetica, sans-serif; - font-weight: bold; - font-size: 0.8em; - color: #666666; - background-color: #ffffff; - border: 1px solid #FFFFFF; - text-align: center; -} - -#pa_pagination ul li{ - display: inline; - list-style-type: none; - background-color: #ffffff; -} - -.current { - color: #999999; - background-color: #cccccc; - margin-top: 0em; - margin-right: 1em; - margin-bottom: 0em; - margin-left: 1em; - padding-top: .25em; - padding-right: 1em; - padding-bottom: .25em; - padding-left: 1em; - border: 1px solid #cccccc; -} - -#pa_pagination a { - color: #0033cc; - background-color:#ffffff; - margin-top: 0em; - margin-right: 1em; - margin-bottom: 0em; - margin-left: 1em; - padding-top: .25em; - padding-right: 1em; - padding-bottom: .25em; - padding-left: 1em; - border: 1px solid #999; - text-decoration: none; -} - -#pa_pagination a:hover { - color: #0033cc; - background-color: #f5f5ff; - border: 1px solid #0066CC; -} - -#pa_pagination a:visited { - color: #0033cc; - border: 1px solid #663399; -} - -#pa_pagination img { - border-top-style: none; - border-right-style: none; - border-bottom-style: none; - border-left-style: none; - vertical-align:middle; -} - -.img_border{ - float: left; - margin: 5px; - padding: 3px; - border: thin #f0f0f0 solid; - background-color: #ffffff; -} -.img_border img { - vertical-align: middle; - border: none; -} -.img_border p { - text-align: center; - padding: 5px; -} -.img_spacer { - clear: both; -} - -/* Fluid LightBox Styles */ - -body{ - font-family: verdana, helvetica, sans-serif; - font-size: 12px; -} - -.image-container{ - overflow: hidden; width: 100%; -} - -.image-inner-container{ - height: 100px; - width: 140px; - background-color: #eee; - overflow: hidden; - margin: 0 auto 3px auto; -} - -.image-inner-container img{ - width: 150px; -} - -.orderable-default{ - height: 150px !important; - width: 150px; - border: 2px solid #ddd; - float: left; - margin: 5px !important; - text-align: center; - padding-top: 10px; -} - -.orderable-hover{ - height: 150px !important; - width: 150px; - border: 2px solid #666; - float: left; - margin: 5px !important; - text-align: center; - padding-top: 10px; -} - -.orderable-selected{ - height: 150px !important; - width: 150px; - border: 2px solid #666; - background-color: #ddd; - float: left; - margin: 5px !important; - text-align: center; - padding-top: 10px; -} - -.orderable-selected img{ - border: 1px solid #eee; -} - -.orderable-dragging{ - height: 150px !important; - width: 150px; - border: 2px solid #666; - background-color: #eee; - float: left; - margin: 5px !important; - text-align: center; - opacity: .2; - filter: alpha(opacity=20); - padding-top: 10px; -} - -.image-title{ - margin-top:5px; - height: 40px; - overflow: hidden; -} - -.image-title a{ - text-decoration: none; -} - -.image-title a:hover{ - text-decoration: underline; -} - -div .orderable-drop-marker{ - height: 160px !important; - width: 4px; - background-color: red; - float: left; -} - -.lightbox-instructions{ - color: #666; - background-color: lightyellow; - padding: 3px; - border: 2px solid #ddd; - font-size: .9em; - position: absolute; - top: 0; - right: 0; - width: 300px; -} - -.lightbox-downarrow{ - font-size: 0px; line-height: 0%; width: 0px; - margin: 5px 8px 10px 0; - float: left; - border-top: 10px solid red; - border-left: 10px solid lightyellow; - border-right: 10px solid lightyellow; -} - - - - - - diff --git a/mods/photo_album/module.php b/mods/photo_album/module.php deleted file mode 100644 index ffcf45b07..000000000 --- a/mods/photo_album/module.php +++ /dev/null @@ -1,176 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_PHOTO_ALBUM', $this->getAdminPrivilege()); - -$_student_tool = 'mods/photo_album/index.php'; -$photo_path='mods/photo_album/'; -define('IMAGE', 3); -define('COMMENT', 4); - -if (admin_authenticate(AT_ADMIN_PRIV_PHOTO_ALBUM, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { //handle for administrator - $this->_pages[AT_NAV_ADMIN] = array('mods/photo_album/index_admin.php'); - $this->_pages['mods/photo_album/index_admin.php']['parent'] = AT_NAV_ADMIN; - $this->_pages['mods/photo_album/index_admin.php']['title_var'] = 'photo_album'; - - $this->_pages['mods/photo_album/admin_image_list.php']['title_var']='photo_album'; - $this->_pages['mods/photo_album/admin_image_list.php']['children']=array('mods/photo_album/admin_comment_list.php', 'mods/photo_album/admin_config.php'); - - $this->_pages['mods/photo_album/admin_comment_list.php']['title_var']='pa_title_administrator_comment'; - $this->_pages['mods/photo_album/admin_comment_list.php']['parent']='mods/photo_album/admin_image_list.php'; - - $this->_pages['mods/photo_album/admin_config.php']['title_var']='pa_title_administrator_config'; - $this->_pages['mods/photo_album/admin_config.php']['parent']='mods/photo_album/admin_image_list.php'; - - - $link=$photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - $this->_pages[$link]['title_var']='pa_title_view'; - $this->_pages[$link]['parent']=$photo_path.'admin_image_list.php'; - - if (($_POST['mode']=='add') || ($_SESSION['pa']['mode']=='add')){ //mode is add - if (($_POST['choose']==IMAGE) || ($_SESSION['pa']['choose']==IMAGE)){ - $this->_pages['mods/photo_album/handler/file_upload.php']['title_var'] = 'pa_title_add_image'; - $this->_pages['mods/photo_album/handler/file_upload.php']['parent'] = $photo_path.'admin_image_list.php'; - $this->_pages['mods/photo_album/handler/add_begin.php']['title_var'] = 'pa_title_add_image'; - $this->_pages['mods/photo_album/handler/add_begin.php']['parent'] = $photo_path.'admin_image_list.php'; - } else { - $this->_pages['mods/photo_album/handler/add_begin.php']['title_var'] = 'pa_title_add_comment'; - $this->_pages['mods/photo_album/handler/add_begin.php']['parent'] = $photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - } - } else if (($_POST['mode']=='edit') || ($_SESSION['pa']['mode']=='edit')){ //mode is edit - if (($_POST['choose']==IMAGE) || ($_SESSION['pa']['choose']==IMAGE)){ - $this->_pages['mods/photo_album/handler/file_upload.php']['title_var'] = 'pa_title_edit_image'; - $this->_pages['mods/photo_album/handler/file_upload.php']['parent'] = $photo_path.'admin_image_list.php'; - $this->_pages['mods/photo_album/handler/edit_begin.php']['title_var'] = 'pa_title_edit_image'; - $this->_pages['mods/photo_album/handler/edit_begin.php']['parent'] = $photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - $this->_pages['mods/photo_album/handler/delete_begin.php']['title_var'] = 'pa_title_delete_image'; - $this->_pages['mods/photo_album/handler/delete_begin.php']['parent'] = $photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - } else { - $this->_pages['mods/photo_album/handler/edit_begin.php']['title_var'] = 'pa_title_edit_comment'; - $this->_pages['mods/photo_album/handler/edit_begin.php']['parent'] = $photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - $this->_pages['mods/photo_album/handler/delete_begin.php']['title_var'] = 'pa_title_delete_comment'; - $this->_pages['mods/photo_album/handler/delete_begin.php']['parent'] = $photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - } - } else { //mode is delete - if (($_POST['choose']==IMAGE) || ($_SESSION['pa']['choose']==IMAGE)){ - $this->_pages['mods/photo_album/handler/delete_begin.php']['title_var'] = 'pa_title_delete_image'; - $this->_pages['mods/photo_album/handler/delete_begin.php']['parent'] = $photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - } else { - $this->_pages['mods/photo_album/handler/delete_begin.php']['title_var'] = 'pa_title_delete_comment'; - $this->_pages['mods/photo_album/handler/delete_begin.php']['parent'] = $photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - } - } - - $this->_pages['mods/photo_album/view.php']['title_var'] = 'pa_title_view'; - $this->_pages['mods/photo_album/view.php']['parent'] = $photo_path.'admin_image_list.php'; - -} else { - $this->_pages['mods/photo_album/instructor_image.php']['title_var'] = 'pa_title_instructor_image'; - $this->_pages['mods/photo_album/instructor_image.php']['parent'] = 'tools/index.php'; - $this->_pages['mods/photo_album/instructor_image.php']['children'] = array($photo_path.'instructor_comment.php', $photo_path.'instructor_config.php'); - - $this->_pages['mods/photo_album/instructor_comment.php']['title_var'] = 'pa_title_instructor_comment'; - $this->_pages['mods/photo_album/instructor_comment.php']['parent'] = $photo_path.'instructor_image.php'; - - $this->_pages['mods/photo_album/instructor_config.php']['title_var'] = 'pa_title_instructor_config'; - $this->_pages['mods/photo_album/instructor_config.php']['parent'] = $photo_path.'instructor_image.php'; - - $this->_pages['mods/photo_album/index.php']['title_var'] = 'photo_album'; - $this->_pages['mods/photo_album/index.php']['img'] = $photo_path.'skins/pa_tool_icon.gif'; - - $this->_pages['mods/photo_album/my_photo.php']['title_var'] = 'pa_title_my_photo'; - $this->_pages['mods/photo_album/my_photo.php']['parent'] = $photo_path.'index.php'; - - $this->_pages['mods/photo_album/my_comment.php']['title_var'] = 'pa_title_my_comment'; - $this->_pages['mods/photo_album/my_comment.php']['parent'] = $photo_path.'index.php'; - - if ($_SESSION['pa']['instructor_mode']==true){ - $this->_pages['mods/photo_album/view.php']['title_var'] = 'pa_title_view'; - $this->_pages['mods/photo_album/view.php']['parent'] = $photo_path.'instructor_image.php'; - $this->_pages['mods/photo_album/view.php']['children'] = Array(); - } else { - $this->_pages['mods/photo_album/view.php']['title_var'] = 'pa_title_view'; - $this->_pages['mods/photo_album/view.php']['parent'] = $photo_path.'index.php'; - $this->_pages['mods/photo_album/view.php']['children'] = Array(); - } - - if ($_SESSION['pa']['instructor_mode']==true){ - $link=$photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - $this->_pages[$link]['title_var']='pa_title_view'; - $this->_pages[$link]['parent']=$photo_path.'instructor_image.php'; - } else { - $link=$photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - $this->_pages[$link]['title_var']='pa_title_view'; - $this->_pages[$link]['parent']=$photo_path.'index.php'; - } - - if (($_POST['mode']=='add') || ($_SESSION['pa']['mode']=='add')){ - if (($_POST['choose']==IMAGE) || ($_SESSION['pa']['choose']==IMAGE)){ - if ($_SESSION['pa']['instructor_mode']==true){ - $this->_pages['mods/photo_album/handler/file_upload.php']['title_var'] = 'pa_title_add_image'; - $this->_pages['mods/photo_album/handler/file_upload.php']['parent'] = $photo_path.'instructor_image.php'; - $this->_pages['mods/photo_album/handler/add_begin.php']['title_var'] = 'pa_title_add_image'; - $this->_pages['mods/photo_album/handler/add_begin.php']['parent'] = $photo_path.'instructor_image.php'; - } else { - $this->_pages['mods/photo_album/handler/file_upload.php']['title_var'] = 'pa_title_add_image'; - $this->_pages['mods/photo_album/handler/file_upload.php']['parent'] = $photo_path.'index.php'; - $this->_pages['mods/photo_album/handler/add_begin.php']['title_var'] = 'pa_title_add_image'; - $this->_pages['mods/photo_album/handler/add_begin.php']['parent'] = $photo_path.'index.php'; - } - } else { - $this->_pages['mods/photo_album/handler/add_begin.php']['title_var'] = 'pa_title_add_comment'; - $this->_pages['mods/photo_album/handler/add_begin.php']['parent'] = $photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - } - } else if (($_POST['mode']=='edit') || ($_SESSION['pa']['mode']=='edit')){ - if (($_POST['choose']==IMAGE) || ($_SESSION['pa']['choose']==IMAGE)){ - $this->_pages['mods/photo_album/handler/file_upload.php']['title_var'] = 'pa_title_edit_image'; - $this->_pages['mods/photo_album/handler/file_upload.php']['parent'] = $photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - $this->_pages['mods/photo_album/handler/edit_begin.php']['title_var'] = 'pa_title_edit_image'; - $this->_pages['mods/photo_album/handler/edit_begin.php']['parent'] = $photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - $this->_pages['mods/photo_album/handler/delete_begin.php']['title_var']='pa_title_delete_image'; - $this->_pages['mods/photo_album/handler/delete_begin.php']['parent']=$photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - } else { - $this->_pages['mods/photo_album/handler/edit_begin.php']['title_var'] = 'pa_title_edit_comment'; - $this->_pages['mods/photo_album/handler/edit_begin.php']['parent'] = $photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - $this->_pages['mods/photo_album/handler/delete_begin.php']['title_var']='pa_title_delete_comment'; - $this->_pages['mods/photo_album/handler/delete_begin.php']['parent']=$photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - } - } else { - if (($_POST['choose']==IMAGE) || ($_SESSION['pa']['choose']==IMAGE)){ - $this->_pages['mods/photo_album/handler/delete_begin.php']['title_var']='pa_title_delete_image'; - $this->_pages['mods/photo_album/handler/delete_begin.php']['parent']=$photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - } else { - $this->_pages['mods/photo_album/handler/delete_begin.php']['title_var']='pa_title_delete_comment'; - $this->_pages['mods/photo_album/handler/delete_begin.php']['parent']=$photo_path.'view.php?image_id='.$_SESSION['pa']['image_id']; - } - } -} - -$this->_pages['mods/photo_album/handler/store.php']['title_var'] = 'Photo_Album'; -$this->_pages['mods/photo_album/handler/delete.php']['title_var'] = 'Photo_Album'; - -?> \ No newline at end of file diff --git a/mods/photo_album/module.sql b/mods/photo_album/module.sql deleted file mode 100644 index 04a7b71e7..000000000 --- a/mods/photo_album/module.sql +++ /dev/null @@ -1,212 +0,0 @@ -# sql file for the photo album module -# this file loads the text used in the photo album module into the database - -# added the order column to the pa_image table to keep track of image location when moved via the Fluid Lightbox GG - -CREATE TABLE `pa_image` ( - `course_id` mediumint(8) NOT NULL, - `image_id` mediumint(8) NOT NULL auto_increment, - `title` varchar(23) NOT NULL, - `description` text, - `view_image_name` varchar(255) NOT NULL, - `location` text NOT NULL, - `date` varchar(30) NOT NULL, - `login` varchar(20) NOT NULL, - `thumb_image_name` varchar(255) NOT NULL, - `alt` varchar(30) NOT NULL, - `status` mediumint(1) NOT NULL, - `order` tinyint(4) NOT NULL, - PRIMARY KEY (`image_id`) -); - -CREATE TABLE `pa_comment` ( - `course_id` mediumint(8) NOT NULL, - `login` varchar(20) NOT NULL, - `comment` text, - `date` varchar(30) NOT NULL, - `image_id` mediumint(8) NOT NULL, - `comment_id` mediumint(8) NOT NULL auto_increment, - `status` mediumint(1) NOT NULL, - PRIMARY KEY (`comment_id`) -); - -CREATE TABLE `pa_config` ( - `config_id` mediumint(8) NOT NULL auto_increment, - `date` varchar(30) NOT NULL, - `status` mediumint(1) NOT NULL, - `course_id` mediumint(8) NOT NULL, - PRIMARY KEY (`config_id`) -); - -INSERT INTO `language_text` VALUES ('en', '_module','photo_album','Photo Album',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_view_image_link', 'View this picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_view_comment_link', 'View this comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_image_not_approved', 'Picture not approved by the instructor', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_check_all_image', 'Check all displayed pictures', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_check_all_comment', 'Check all displayed comments', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_my_photo_alt', 'My photo album view', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_my_comment_alt', 'My comment album view', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_course_photo_alt', 'Course photo album view', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_go', 'Go', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_alt', 'Alt', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_image_description', 'Picture description', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_image_title', 'Title ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_comment_description', 'Comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_image_delete_confirm', 'Do you really want to delete this picture?', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_comment_delete_confirm', 'Do you really want to delete this comment?', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_image_add_alt', 'Picture to add', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_image_edit_alt', 'Picture to edit', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_image_title2', 'Picture title *', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_image_description2', 'Picture description', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_image_alt', 'Alt string', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_new_pic', 'New pictures ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_approved_pic', 'Approved pictures ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_disapproved_pic', 'Disapproved pictures ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_new_comment', 'New comments ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_approved_comment', 'Approved comments ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_disapproved_comment', 'Disapproved comments ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_config_enabled', 'Enabled - submissions are moderated ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_config_disabled', 'Disabled - submissions are posted immediately ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_config_string', 'Enable moderation ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_administrator', 'Administrator ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_next_page_button', 'Next page', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_last_page_button', 'Last page', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_previous_page_button', 'Previous page', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_first_page_button', 'First page', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_tag_view', 'View : ', NOW(), ''); - -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_label_file', 'Picture file name', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_label_pic_title', 'Picture title ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_label_pic_description', 'Picture description ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_label_pic_alt', 'Alt string', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_label_comment_textarea', 'Comment area', NOW(), ''); - -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_note_admin', 'Please select a course from the drop down menu below to administer its photo album.
    Take note that photo albums are attached to courses and that pictures are not shared across courses. ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_note_file_upload_add', 'To add a picture, click the "Browse" button to find a picture to upload, then click the "upload this picture" button', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_note_file_upload_edit', 'You can upload a new picture by clicking the "Browse" button to find a picture then clicking the "Update this picture" button or if you do not want to change the picture, just click the "Skip this step" button. ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_note_image_info_add', 'Please give your picture a title and a description by filling in the form', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_note_comment_add', 'Leave a comment about this picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_note_comment_edit', 'Change your comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_note_image_info_edit', 'You can edit the picture title and description by making changes to the form below', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_note_instructor_config', 'Do you want to moderate submissions to your course album? If you want to approve pictures and comments before they are viewed publicly, click the radio button labelled "Yes" to activate the approval process. If you want pictures and comments posted immediately, click "No". Select either radio button then click the "change approval process" button to save your setting.', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_note_administrator_config', 'Do you want to moderate student submissions to your course album? Select either radio button then click the "Enable moderation" button to save your setting.', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_note_comment_disapproved', 'The following comment has been disapproved', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_note_comment_posted_new', 'The following comment is a new comment', NOW(), ''); - - -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_admin_index', 'Administer a photo album', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_index', 'Thumbnail view', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_view', 'View picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_file_upload', 'Upload a picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_delete_image', 'Delete a picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_add_image', 'Add a picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_edit_image', 'Edit a picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_delete_comment', 'Delete comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_add_comment', 'Add comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_edit_comment', 'Edit comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_image_info_add', 'Add picture information', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_comment_add', 'Add comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_comment_edit', 'Edit comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_image_info_edit', 'Edit picture information', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_my_photo_new', 'New pictures (My pictures)', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_my_photo_approved', 'Approved pictures (My pictures)', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_my_photo_disapproved', 'Disapproved pictures (My pictures)', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_my_photo', 'Photo Album - My Photos', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_my_comment_new', 'New comments (My comments)', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_my_comment_approved', 'Approved comments (My comments)', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_my_comment_disapproved', 'Disapproved comments (My comments)', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_my_comment', 'Photo Album - My Comments', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_administrator_new_pic', 'New pictures', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_administrator_approved_pic', 'Approved pictures', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_administrator_disapproved_pic', 'Disapproved pictures', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_administrator_new_comment', 'New comments', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_administrator_approved_comment', 'Approved comments', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_administrator_disapproved_comment', 'Disapproved comments', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_instructor_approved_pic', 'Approved pictures (Instructor view)', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_instructor_disapproved_pic', 'Disapproved pictures (Instructor view)', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_instructor_new_pic', 'New pictures (Instructor view)', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_instructor_new_comment', 'New comments (Instructor view)', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_instructor_approved_comment', 'Approved comments (Instructor view)', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_instructor_disapproved_comment', 'Disapproved comments (Instructor view)', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_instructor_image', 'Photo album', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_instructor_comment', 'Manage comments', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_instructor_config', 'Enable moderation', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_administrator_comment', 'Manage comments', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_title_administrator_config', 'Enable Moderation', NOW(), ''); - - - -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_new_pics', 'New pictures', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_approved_pics', 'Approved pictures', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_disapproved_pics', 'Disapproved pictures', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_set_new_pic', 'Set picture as new', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_set_approved_pic', 'Set picture as approved', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_set_disapproved_pic', 'Set picture as disapproved', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_set_new_comment', 'Set comment as new', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_set_approved_comment', 'Set comment as approved', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_set_disapproved_comment', 'Set comment as disapproved', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_add_image', 'Add a new picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_save_image_order', 'Save image order', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_edit_image', 'Edit this picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_del_image', 'Delete this picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_add_comment', 'Add a new comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_edit_comment', 'Edit this comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_del_comment', 'Delete this comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_goback_thumbnail', 'Back to the photo album thumbnail view', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_upload_image', 'Upload this picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_update_image', 'Update this picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_upload_image_info', 'Upload picture information', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_update_image_info', 'Update picture information', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_upload_comment', 'Add this comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_update_comment', 'Update this comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_skip_upload_image', 'Skip this step', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_template', 'pa_button_config_change', 'Enable moderation', NOW(), ''); - - - -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PA_ADD_IMAGE_SUCCESS_CONFIG_ENABLED', 'Your picture has been added successfully. It will be displayed in the course photo album if the instructor approves the picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PA_ADD_IMAGE_SUCCESS_CONFIG_DISABLED', 'Your picture has been added successfully.', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PA_ADD_COMMENT_SUCCESS_CONFIG_ENABLED', 'Your comment has been added successfully. It will be displayed if the instructor approves the comment', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PA_ADD_COMMENT_SUCCESS_CONFIG_DISABLE', 'Your comment has been added successfully', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PA_EDIT_IMAGE_SUCCESS_CONFIG_ENABLED', 'Your picture has been edited successfully. It will be displayed if the instructor approves the picture.', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PA_EDIT_IMAGE_SUCCESS_CONFIG_DISABLED', 'Your picture has been edited successfully.', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PA_EDIT_COMMENT_SUCCESS_CONFIG_ENABLED', 'Your edit has been made successfully. Your comment will be displayed if the instructor approves it.', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PA_EDIT_COMMENT_SUCCESS_CONFIG_DISABLED', 'Your edit has been made successfully', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PA_DELETE_IMAGE_SUCCESS', 'Your picture was deleted successfully', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PA_DELETE_COMMENT_SUCCESS', 'Your comment was deleted successfully', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_FEEDBACK_PA_IMAGE_ORDER_SAVED', 'Image order was saved successfully', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_USER_FILE_TYPE', 'Your picture is not a valid picture file. Only jpeg, bmp, gif or png picture files can be shared. Please try uploading a different picture or try converting your picture into a suitable format', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_USER_FILE_SIZE', 'Your picture is larger than the maximum file size allowed by the web site. Please choose a smaller picture', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_USER_FILE_EMPTY', 'You must find a picture to upload. Please use the "Browse" button to find a picture to upload', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_USER_FILE_LENGTH', 'Your picture file name is longer than the maximum length allowed by the web site. Please rename your picture then try again', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_USER_FILE_ESCAPE', 'The name of your picture file contains characters not allowed by the web site. Please rename your picture then try again', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_USER_TITLE_EMPTY', 'Please give your picture a name by filling in the title field', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_USER_COMMENT_EMPTY', 'To leave a comment about this picture, please fill in the comment form', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_USER_ALT_EMPTY', 'Please provide a description of the picture for the image alt attribute', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_USER_IMAGE_NOT_ALLOWED', 'You are not allowed to modify this picture. You can only make changes to pictures submitted by you', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_USER_COMMENT_NOT_ALLOWED', 'You are not allowed to modify this comment. You can only change comments left by you', NOW(), ''); - -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_VAR_UNAUTHORIZED', 'An error has occurred. A page was requested in an unexpected way. Please try to complete your task in a different way.', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_VAR_COURSE_EMPTY', 'There are no courses on this server. Please create a course first before trying to administer the photo album.', NOW(), ''); - -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_OBJ_PA_INDEX', 'An error has occurred in the Pa_Index() object.\n Please report this error to your technical support person', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_OBJ_VIEW', 'An error has occurred in the View() object.\n Please report this error to your technical support person', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_OBJ_PA_ADMIN_COMMENT', 'An error has occurred in the Pa_Admin_Comment() object.\n Please report this error to your technical support person', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_OBJ_PA_ADMIN_IMAGE', 'An error has occurred in the Pa_Admin_Image() object.\n Please report this error to your technical support person', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_OBJ_MYPIC', 'An error has occurred in the Mypic() object.\n Please report this error to your technical support person', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_OBJ_PA_ADMIN_IMAGE', 'An error has occurred in the Pa_Admin_Image() object.\n Please report this error to your technical support person', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_OBJ_IMAGE_UPLOAD', 'An error has occurred in the Image_Upload() object.\n Please report this error to your technical support person', NOW(), ''); - - -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_FUNC_MAKE_TEMP_FOLDER', 'The web site could not create or write to the images folder. \n Please report this error to your technical support person', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_FUNC_DELETE_IMAGE', 'The picture could not be deleted from the database. \n Please report this error to your technical support person', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_FUNC_DELETE_BLOG', 'The comment could not be deleted from the database. \n Please report this error to your technical support person', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_FUNC_MKDIR', 'The web site photo album module could not create the image folder for you. Please ask technical support to check that the album_image folder exists and that it is writable', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_FUNC_COPY', 'The web site photo album module could not copy the picture to the destination folder. Please ask technical support to check that the album_image folder exists and that it is writable', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_FUNC_STORE_IMAGE_IN_DATABASE', 'The web site photo album module could not store the picture information in the database. Please ask technical support to check that the database server is running properly', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_FUNC_UPDATE_IMAGE_IN_DATABASE', 'The web site photo album module could not update the image information in the database. Please ask technical support to check that the database server is running properly', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_FUNC_STORE_COMMENT_IN_DATABASE', 'The web site photo album module could not store the comment information in the database. Please ask technical support to check that the database server is running properly', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_FUNC_UPDATE_COMMENT_IN_DATABASE', 'The web site photo album module could not update the comment information in the database. Please ask technical support to check that the database server is running properly', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_FUNC_UNLINK', 'The web site photo album module could not delete the temporary picture file. Please ask technical support to check that the album_image folder exists and that it is writable. ', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_FUNC_CLEAR_TEMP_FOLDER_OPEN', 'The web site photo album module could not open the temp folder. Please ask technical support to check that the temp folder exists and that it is writable.', NOW(), ''); -INSERT INTO `language_text` VALUES ('en', '_msgs', 'AT_ERROR_PA_FUNC_CLEAR_TEMP_FOLDER_UNLINK', 'The web site photo album module could not delete temp files from the temp folder. Please ask technical support to check that the temp folder exists and that it is writable.', NOW(), ''); \ No newline at end of file diff --git a/mods/photo_album/module.xml b/mods/photo_album/module.xml deleted file mode 100644 index 20f9ae975..000000000 --- a/mods/photo_album/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Photo Album - The Photo Album module allows instructors to add a class photo album to their courses. Students can share photographs and comment on their classmate's digital images. - - - Dylan Cheon (Canassist) - dcheon@uvic.ca - - - http://www.canassist.ca/ - GNU public license - - 1.0beta3 - 2006-05-29 - Stable - Your server must have the GD Library version 2.0 or later to manipulate graphics files. This module will not install without it. More information at: http://www.boutell.com/gd/ - - \ No newline at end of file diff --git a/mods/photo_album/module_delete.php b/mods/photo_album/module_delete.php deleted file mode 100644 index 8a8a516fd..000000000 --- a/mods/photo_album/module_delete.php +++ /dev/null @@ -1,35 +0,0 @@ - \ No newline at end of file diff --git a/mods/photo_album/module_install.php b/mods/photo_album/module_install.php deleted file mode 100644 index 4d3b9bc4b..000000000 --- a/mods/photo_album/module_install.php +++ /dev/null @@ -1,111 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); - } else if (!is_writable($directory) && @chmod($directory, 0777)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); - } -} - -/** - * check if GD is installed and is version 2 or higher - */ -if (! extension_loaded('gd')) { - $msg->addError(array('MODULE_INSTALL', '
  • This module requires the GD Library. Please install it.
  • ')); -} else { - if (function_exists('gd_info')) { - // use gd_info if possible... - $gd_ver_info = gd_info(); - preg_match('/\d/', $gd_ver_info['GD Version'], $match); - if ($match[0] < 2) { - $msg->addError(array('MODULE_INSTALL', '
  • This module requires GD version 2 or higher. Please install it.
  • ')); - } - } else { - // ...otherwise use phpinfo(). - ob_start(); - phpinfo(8); - $info = ob_get_contents(); - ob_end_clean(); - $info = stristr($info, 'gd version'); - preg_match('/\d/', $info, $match); - if ($match[0] < 2) { - $msg->addError(array('MODULE_INSTALL', '
  • This module requires the GD Library version 2 or higher. Please install it.
  • ')); - } - } -} - -/** - * 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); -} - -?> diff --git a/mods/photo_album/module_uninstall.php b/mods/photo_album/module_uninstall.php deleted file mode 100644 index d62b347ab..000000000 --- a/mods/photo_album/module_uninstall.php +++ /dev/null @@ -1,64 +0,0 @@ -addError(array('MODULE_UNINSTALL', '
  • '.$directory.' can not be removed. Please manually remove it.
  • ')); - } -} - -/****** - * the following code checks if there are any errors (generated previously) - * then uses the SqlUtility to run reverted database queries of module.sql, - * ie. "create table" statement in module.sql is run as drop according table. - */ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> diff --git a/mods/photo_album/my_comment.php b/mods/photo_album/my_comment.php deleted file mode 100644 index 226fb2154..000000000 --- a/mods/photo_album/my_comment.php +++ /dev/null @@ -1,156 +0,0 @@ - - -addError('pa_var_unauthorized'); - redirect('index.php'); -} -$my=new Mycomment(); - -if ($my->isError()!=true){ //no error is occured - $course_id=$_SESSION['pa']['course_id']; //store course_id temporarily - unset($_SESSION['pa']); //clear pa session variables - $_SESSION['pa']['course_id']=$course_id; - $_SESSION['pa']['my_pic_mode']=true; - - $template=new HTML_Template_ITX("./Template"); - $template->loadTemplateFile("my_comment.tpl.php"); - - switch ($my->getVariable('mode')){ - case POSTED_NEW: - $template->setVariable("TITLE", _AT('pa_title_my_comment_new')); - break; - case APPROVED: - $template->setVariable("TITLE", _AT('pa_title_my_comment_approved')); - break; - case DISAPPROVED: - $template->setVariable("TITLE", _AT('pa_title_my_comment_disapproved')); - break; - } - - $template->setVariable("MAIN_URL", BASE_PATH.'index.php'); - $template->setVariable("MAIN_TITLE", _AT('pa_tag_course_photo_alt')); - - $template->setVariable("MY_PHOTO_URL", BASE_PATH.'my_photo.php'); - $template->setVariable("MY_PHOTO_TITLE", _AT('pa_tag_my_photo_alt')); - - $template->setVariable("MY_COMMENT_URL", BASE_PATH.'my_comment.php'); - $template->setVariable("MY_COMMENT_TITLE", _AT('pa_tag_my_comment_alt')); - - - $template->setCurrentBlock("SELECT_PART"); - $template->setVariable("DESTINATION", BASE_PATH.'my_comment.php?mode='.POSTED_NEW.SEP.'current_page='.$my->getVariable('current_page')); - $template->setVariable("LINK_TEXT", _AT('pa_tag_new_comment').' | '); - $template->parseCurrentBlock("SELECT_PART"); - - $template->setCurrentBlock("SELECT_PART"); - $template->setVariable("DESTINATION", BASE_PATH.'my_comment.php?mode='.APPROVED.SEP.'current_page='.$my->getVariable('current_page')); - $template->setVariable("LINK_TEXT", _AT('pa_tag_approved_comment').' | '); - $template->parseCurrentBlock("SELECT_PART"); - - $template->setCurrentBlock("SELECT_PART"); - $template->setVariable("DESTINATION", BASE_PATH.'my_comment.php?mode='.DISAPPROVED.SEP.'current_page='.$my->getVariable('current_page')); - $template->setVariable("LINK_TEXT", _AT('pa_tag_disapproved_comment')); - $template->parseCurrentBlock("SELECT_PART"); - - - - /* start display comments */ - $comment_array=$my->comment_array; - for ($i=0; $isetCurrentBlock("COMMENT_TABLE_DATA"); - $template->setVariable("CHECK_NAME", "commentId".$i); - $template->setVariable("CHECK_VALUE", $comment_array[$i]['comment_id']); - $template->setVariable("COMMENT_TABLE_DATA1", $comment_array[$i]['comment']); - $img_data=get_single_data(IMAGE, $comment_array[$i]['image_id'], $comment_array[$i]['course_id']); - $template->setVariable("COMMENT_TABLE_DATA2", _AT('title').": ".$img_data['title']); - $template->setVariable("COMMENT_TABLE_DATA3", _AT('date').": ".$comment_array[$i]['date']); - if ($img_data['status']==APPROVED){ - $template->setVariable("COMMENT_TABLE_DATA4", ""._AT('pa_tag_view_comment_link').""); - } else { - $template->setVariable("COMMENT_TABLE_DATA4", _AT('pa_tag_image_not_approved')); - } - $template->parseCurrentBlock("COMMENT_TABLE_DATA"); - } - - // Display page table - $page_array=$my->getVariable('page_array'); - $current=$my->getVariable('current_page'); - $template->setCurrentBlock("PAGE_TABLE_PART"); - if ($my->getVariable('show_page_left_buttons')==true){ - $first_button=_AT('pa_tag_first_page_button'); - $previous_button=_AT('pa_tag_previous_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$first_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$previous_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - for ($i=$page_array['start']; $i<=$page_array['end']; $i++){ - if ($i==$current){ - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • '.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } else { - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>'.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - } - - if ($my->getVariable('show_page_right_buttons')==true){ - $next_button=_AT('pa_tag_next_page_button'); - $last_button=_AT('pa_tag_last_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$next_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$last_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - $template->parseCurrentBlock("PAGE_TABLE_PART"); - $template->parseCurrentBlock(); - $template->show(); -} else { - $msg->addError('pa_obj_mypic'); - redirect('index.php'); -} - -?> - - \ No newline at end of file diff --git a/mods/photo_album/my_photo.php b/mods/photo_album/my_photo.php deleted file mode 100644 index c629994e5..000000000 --- a/mods/photo_album/my_photo.php +++ /dev/null @@ -1,156 +0,0 @@ - - -addError('pa_var_unauthorized'); - redirect('index.php'); -} -$my=new Mypic(); -if ($my->isError()!=true){ //no error is occured - $course_id=$_SESSION['pa']['course_id']; //store course_id temporarily - unset($_SESSION['pa']); //clear pa session variables - $_SESSION['pa']['course_id']=$course_id; - $_SESSION['pa']['my_pic_mode']=true; - - $template=new HTML_Template_ITX("./Template"); - $template->loadTemplateFile("my_photo.tpl.php"); - - switch ($my->getVariable('mode')){ - case POSTED_NEW: - $template->setVariable("TITLE", _AT('pa_title_my_photo_new')); - break; - case APPROVED: - $template->setVariable("TITLE", _AT('pa_title_my_photo_approved')); - break; - case DISAPPROVED: - $template->setVariable("TITLE", _AT('pa_title_my_photo_disapproved')); - break; - } - - $template->setVariable("MAIN_URL", BASE_PATH.'index.php'); - $template->setVariable("MAIN_TITLE", _AT('pa_tag_course_photo_alt')); - - $template->setVariable("MY_PHOTO_URL", BASE_PATH.'my_photo.php'); - $template->setVariable("MY_PHOTO_TITLE", _AT('pa_tag_my_photo_alt')); - - $template->setVariable("MY_COMMENT_URL", BASE_PATH.'my_comment.php'); - $template->setVariable("MY_COMMENT_TITLE", _AT('pa_tag_my_comment_alt')); - - - $template->setCurrentBlock("SELECT_PART"); - $template->setVariable("DESTINATION", BASE_PATH.'my_photo.php?mode='.POSTED_NEW.SEP.'current_page='.$my->getVariable('current_page')); - $template->setVariable("LINK_TEXT", _AT('pa_tag_new_pic').' | '); - $template->parseCurrentBlock("SELECT_PART"); - - $template->setCurrentBlock("SELECT_PART"); - $template->setVariable("DESTINATION", BASE_PATH.'my_photo.php?mode='.APPROVED.SEP.'current_page='.$my->getVariable('current_page')); - $template->setVariable("LINK_TEXT", _AT('pa_tag_approved_pic').' | '); - $template->parseCurrentBlock("SELECT_PART"); - - $template->setCurrentBlock("SELECT_PART"); - $template->setVariable("DESTINATION", BASE_PATH.'my_photo.php?mode='.DISAPPROVED.SEP.'current_page='.$my->getVariable('current_page')); - $template->setVariable("LINK_TEXT", _AT('pa_tag_disapproved_pic')); - $template->parseCurrentBlock("SELECT_PART"); - - - - /* start display images */ - $image_array=$my->image_array; - for ($i=0; $isetCurrentBlock("IMAGE_DATA"); - $template->setVariable("CHECK_NAME", "imageId".$i); - $template->setVariable("CHECK_VALUE", $image_array[$i]['image_id']); - $img_src=$get_file.$image_array[$i]['location'].urlencode($image_array[$i]['thumb_image_name']); - $template->setVariable("IMAGE_DATA1", $image_array[$i]['title']); - $template->setVariable("IMAGE_DATA2", "\"".$image_array[$i]['alt']."\"/"); - $template->setVariable("IMAGE_DATA3", _AT('date').": ".$image_array[$i]['date']); - - $template->setVariable("FORM_NAME", "edit_button"); - $template->setVariable("ACTION", UPLOAD_ACTION); - $template->setVariable("CHOOSE_VALUE", IMAGE); - $template->setVariable("IMAGE_ID", $image_array[$i]['image_id']); - $template->setVariable("EDIT_VALUE", _AT('pa_button_edit_image')); - $template->parseCurrentBlock("IMAGE_DATA"); - } - - // Display page table - $page_array=$my->getVariable('page_array'); - $current=$my->getVariable('current_page'); - $template->setCurrentBlock("PAGE_TABLE_PART"); - if ($my->getVariable('show_page_left_buttons')==true){ - $first_button=_AT('pa_tag_first_page_button'); - $previous_button=_AT('pa_tag_previous_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$first_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$previous_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - for ($i=$page_array['start']; $i<=$page_array['end']; $i++){ - if ($i==$current){ - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • '.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } else { - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>'.$i.'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - } - - if ($my->getVariable('show_page_right_buttons')==true){ - $next_button=_AT('pa_tag_next_page_button'); - $last_button=_AT('pa_tag_last_page_button'); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$next_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - $template->setCurrentBlock("B_DATA_PART"); - $template->setVariable("B_DATA", '
  • getVariable('mode').'\'>\''.$last_button.'\'
  • '); - $template->parseCurrentBlock("B_DATA_PART"); - } - - $template->parseCurrentBlock("PAGE_TABLE_PART"); - $template->parseCurrentBlock(); - $template->show(); -} else { - $msg->addError('pa_obj_mypic'); - redirect('index.php'); -} - -?> - - \ No newline at end of file diff --git a/mods/photo_album/skins/pa_first.gif b/mods/photo_album/skins/pa_first.gif deleted file mode 100644 index 07ab9304f45aadc78aafb9c580057e0250611fa3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118 zcmZ?wbhEHblw%NKn8?8J|Nnmm<1-+VfkE*n3nM!N6N3(r%>a^TU~-?*zw-23{>NOL z0Vzv&94mU5ImeuB*^Qa%E9&@N=WTq=via`1z;oM^?mK@pvlIzT)$p>|r&82eVU@`{ T{aj{`){0r{zH|ElO|k|6sSzxr diff --git a/mods/photo_album/skins/pa_first.png b/mods/photo_album/skins/pa_first.png deleted file mode 100644 index 15dff5257ed659f7481ad2f412e25477887681f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29906 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'; -} - - // Singleton - private static $fetcher; - - private function connectDb() { - // one of the class paths should point to ATutor's document root, abuse that fact to find our config - $extension_class_paths = Config::get('extension_class_paths'); - foreach (explode(',', $extension_class_paths) as $path) { - if (file_exists($path . "/ATutorDbFetcher.php")) { - $configFile = $path . '/../../../../include/lib/mysql_connect.inc.php'; - if (file_exists($configFile)) { - define('AT_INCLUDE_PATH', $path . '/../../../../include/'); - include(AT_INCLUDE_PATH.'config.inc.php'); - include(AT_INCLUDE_PATH . 'lib/constants.inc.php'); - include(AT_INCLUDE_PATH . 'lib/mysql_connect.inc.php'); - $this->db = $db; - break; - } - } - } - if (! isset($configFile)) { - throw new Exception("Could not locate ATutor's configuration file while scanning extension_class_paths ({$extension_class_paths})"); - } -// $this->db = mysqli_connect($config['db_host'], $config['db_user'], $config['db_passwd'], $config['db_database']); -// mysqli_select_db($this->db, $config['db_database']); -// $this->url_prefix = $config['partuza_url']; - } - - private function __construct() { - $cache = Config::get('data_cache'); - $this->cache = new $cache(); - } - - private function checkDb() { - if (! is_resource($this->db)) { - $this->connectDb(); - } - } - - private function __clone() { // private, don't allow cloning of a singleton - } - - static function get() { - // This object is a singleton - if (! isset(ATutorDbFetcher::$fetcher)) { - ATutorDbFetcher::$fetcher = new ATutorDbFetcher(); - } - return ATutorDbFetcher::$fetcher; - } - - public function createActivity($member_id, $activity, $app_id = '0') { - $this->checkDb(); - $app_id = intval($app_id); - $person_id = intval($member_id); - $title = trim(isset($activity['title']) ? $activity['title'] : ''); - if (empty($title)) { - throw new Exception("Invalid activity: empty title"); - } -// $body = isset($activity['body']) ? $activity['body'] : ''; - $title = mysql_real_escape_string($title); -// $body = mysql_real_escape_string($body); - $sql = "insert into ".TABLE_PREFIX."social_activities (id, member_id, application_id, title, created_date) values (0, $member_id, $app_id, '$title', NOW())"; - mysql_query($sql, $this->db); - if (! ($activityId = mysql_insert_id($this->db))) { - return false; - } - -/** - * I don't have this on my system yet. -Harris - - $mediaItems = isset($activity['mediaItems']) ? $activity['mediaItems'] : array(); - if (count($mediaItems)) { - foreach ($mediaItems as $mediaItem) { - $type = isset($mediaItem['type']) ? $mediaItem['type'] : ''; - $mimeType = isset($mediaItem['mimeType']) ? $mediaItem['mimeType'] : ''; - $url = isset($mediaItem['url']) ? $mediaItem['url'] : ''; - $type = mysqli_real_escape_string($this->db, trim($type)); - $mimeType = mysqli_real_escape_string($this->db, trim($mimeType)); - $url = mysqli_real_escape_string($this->db, trim($url)); - if (! empty($mimeType) && ! empty($type) && ! empty($url)) { - mysqli_query($this->db, "insert into activity_media_items (id, activity_id, mime_type, media_type, url) values (0, $activityId, '$mimeType', '$type', '$url')"); - if (! mysqli_insert_id($this->db)) { - return false; - } - } else { - return false; - } - } - } -*/ - return true; - } - -// public function getActivities($ids, $appId, $sortBy, $filterBy, $filterOp, $filterValue, $startIndex, $count, $fields, $activityIds) { - public function getActivities($ids, $appId, $sortBy, $filterBy, $filterOp, $filterValue, $startIndex, $count, $fields) { - global $db; - //TODO add support for filterBy, filterOp and filterValue - $this->checkDb(); - $activities = array(); - foreach ($ids as $key => $val) { - $ids[$key] = mysql_real_escape_string($val); - } - $ids = implode(',', $ids); - if (isset($activityIds) && is_array($activityIds)) { - foreach ($activityIds as $key => $val) { - $activityIds[$key] = mysql_real_escape_string($val); - } - $activityIdQuery = " and activities.id in (".implode(',', $activityIds); - } else { - $activityIdQuery = ''; - } - // return a proper totalResults count - $sql = "select count(id) from ".TABLE_PREFIX."social_activities where ".TABLE_PREFIX."activities.person_id in ($ids) $activityIdQuery"; - $res = mysql_query($sql, $this->db); - - if ($res !== false) { - list($totalResults) = mysql_fetch_row($res); - } else { - $totalResults = '0'; - } - $startIndex = (! is_null($startIndex) && $startIndex !== false && is_numeric($startIndex)) ? intval($startIndex) : '0'; - $count = (! is_null($count) && $count !== false && is_numeric($count)) ? intval($count) : '20'; - $activities['totalResults'] = $totalResults; - $activities['startIndex'] = $startIndex; - $activities['count'] = $count; - $query = " - select - ".TABLE_PREFIX."social_activities.member_id as member_id, - ".TABLE_PREFIX."social_activities.id as activity_id, - ".TABLE_PREFIX."social_activities.title as title, - ".TABLE_PREFIX."social_activities.created as created - from - ".TABLE_PREFIX."social_activities - where - ".TABLE_PREFIX."social_activities.member_id in ($ids) - $activityIdQuery - order by - created desc - limit - $startIndex, $count - "; - $res = mysql_query($query, $this->db); - if ($res) { - if (@mysql_num_rows($res)) { - while ($row = @mysql_fetch_assoc($res)) { - $activity = new Activity($row['activity_id'], $row['member_id']); - $activity->setStreamTitle('activities'); - $activity->setTitle($row['activity_title']); -// $activity->setBody($row['activity_body']); - $activity->setPostedTime($row['created']); - $activity->setMediaItems($this->getMediaItems($row['activity_id'])); - $activities[] = $activity; - } - } elseif (isset($activityIds) && is_array($activityIds)) { - // specific activity id was specified, return a not found flag - return false; - } - return $activities; - } else { - return false; - } - } - - public function deleteActivities($userId, $appId, $activityIds) { - $this->checkDb(); - foreach ($activityIds as $key => $val) { - $activityIds[$key] = mysql_real_escape_string($val); - } - $activityIds = implode(',', $activityIds); - $userId = intval($userId); - $appId = intval($appId); - //can use this instead: $sql = "delete from ".TABLE_PREFIX."social_activities where id in ($activityIds)"; - $sql = "delete from ".TABLE_PREFIX."social_activities where member_id = $userId and application_id = $appId and id in ($activityIds)"; - - mysql_query($sql, $this->db); - return (mysql_affected_rows($this->db) != 0); - } - -/** - * I didn't implement this yet - */ - private function getMediaItems($activity_id) { - $media = array(); -// $activity_id = mysqli_real_escape_string($db, $activity_id); -// $res = mysqli_query($this->db, "select mime_type, media_type, url from ".TABLE_PREFIX."activity_media_items where activity_id = $activity_id"); -// while (list($mime_type, $type, $url) = @mysqli_fetch_row($res)) { -// $media[] = new MediaItem($mime_type, $type, $url); -// } - return $media; - } - - public function getFriendIds($member_id) { - global $db; - $this->checkDb(); - $ret = array(); - $person_id = intval($person_id); - $sql = "select member_id, friend_id from ".TABLE_PREFIX."social_friends where member_id = $member_id or friend_id = $member_id"; - $res = mysql_query($sql, $this->db); - while (list($mid, $fid) = mysql_fetch_row($res)) { - $id = ($mid == $member_id) ? $fid : $mid; - $ret[] = $id; - } - return $ret; - } - - public function setAppData($member_id, $key, $value, $app_id) { - $this->checkDb(); - $member_id = intval($member_id); - $key = mysql_real_escape_string($key); - $value = mysql_real_escape_string($value); - $app_id = intval($app_id); - if (empty($value)) { - // empty key kind of became to mean "delete data" (was an old orkut hack that became part of the spec spec) - $sql = "delete from ".TABLE_PREFIX."social_application_settings where application_id = $app_id and member_id = $member_id and name = '$key'"; - if (! @mysql_query($sql, $this->db)) { - return false; - } - } else { - $sql ="insert into ".TABLE_PREFIX."social_application_settings (application_id, member_id, name, value) values ($app_id, $member_id, '$key', '$value') on duplicate key update value = '$value'"; - if (! @mysql_query($sql, $this->db)) { - return false; - } - } - return true; - } - - public function deleteAppData($member_id, $key, $app_id) { - global $db; - $this->checkDb(); - $person_id = intval($member_id); - $app_id = intval($app_id); - if ($key == '*') { - $sql = "delete from ".TABLE_PREFIX."social_application_settings where application_id = $app_id and member_id = $member_id"; - if (! @mysql_query($sql, $this->db)) { - return false; - } - } else { - $key = mysql_real_escape_string($this->db, $key); - $sql = "delete from ".TABLE_PREFIX."social_application_settings where application_id = $app_id and member_id = $member_id and name = '$key'"; - if (! @mysql_query($sql, $this->db)) { - return false; - } - } - return true; - } - - public function getAppData($ids, $keys, $app_id) { - $this->checkDb(); - $data = array(); - foreach ($ids as $key => $val) { - if (! empty($val)) { - $ids[$key] = intval($val); - } - } - if (! isset($keys[0])) { - $keys[0] = '*'; - } - if ($keys[0] == '*') { - $keys = ''; - } elseif (is_array($keys)) { - foreach ($keys as $key => $val) { - $keys[$key] = "'" . addslashes($val) . "'"; - } - $keys = "and name in (" . implode(',', $keys) . ")"; - } else { - $keys = ''; - } - $sql = "select member_id, name, value from ".TABLE_PREFIX."social_application_settings where application_id = $app_id and member_id in (" . implode(',', $ids) . ") $keys"; - $res = mysql_query($sql, $this->db); - while (list($member_id, $key, $value) = mysql_fetch_row($res)) { - if (! isset($data[$member_id])) { - $data[$member_id] = array(); - } - $data[$member_id][$key] = $value; - } - return $data; - } - - public function getPeople($ids, $fields, $options, $token) { - $first = $options->getStartIndex(); - $max = $options->getCount(); - $this->checkDb(); - $ret = array(); - $filterQuery = ''; - if ($options->getFilterBy() == 'hasApp') { - // remove the filterBy field, it's taken care of in the query already, otherwise filterResults will disqualify all results - $options->setFilterBy(null); - $appId = $token->getAppId(); - $filterQuery = " and id in (select member_id from ".TABLE_PREFIX."social_applications where application_id = $appId)"; - } elseif ($options->getFilterBy() == 'all') { - $options->setFilterBy(null); - } - $query = "SELECT member.*, info.interests, info.associations, info.awards FROM ".TABLE_PREFIX."members member LEFT JOIN ".TABLE_PREFIX."social_member_additional_information info ON member.member_id=info.member_id WHERE member.member_id IN (" . implode(',', $ids) . ") $filterQuery ORDER BY member.member_id "; - - $res = mysql_query($query, $this->db); - if ($res) { - while ($row = mysql_fetch_assoc($res)) { - $member_id = intval($row['member_id']); - $name = new Name($row['first_name'] . ' ' . $row['last_name']); - - $name->setGivenName($row['first_name']); - $name->setFamilyName($row['last_name']); - $person = new Person($row['member_id'], $name); - $person->setDisplayName($name->getFormatted()); - $person->setAboutMe($row['about_me']); - $person->setAge($row['age']); - $person->setChildren($row['children']); - $person->setBirthday(date('Y-m-d', $row['date_of_birth'])); - $person->setEthnicity($row['ethnicity']); - $person->setFashion($row['fashion']); - $person->setHappiestWhen($row['happiest_when']); - $person->setHumor($row['humor']); - $person->setJobInterests($row['job_interests']); - $person->setLivingArrangement($row['living_arrangement']); - $person->setLookingFor($row['looking_for']); - $person->setNickname($row['nickname']); - $person->setPets($row['pets']); - $person->setPoliticalViews($row['political_views']); - $person->setProfileSong($row['profile_song']); - $person->setProfileUrl($this->url_prefix . '/profile/' . $row['member_id']); - $person->setProfileVideo($row['profile_video']); - $person->setRelationshipStatus($row['relationship_status']); - $person->setReligion($row['religion']); - $person->setRomance($row['romance']); - $person->setScaredOf($row['scared_of']); - $person->setSexualOrientation($row['sexual_orientation']); - $person->setStatus($row['status']); - $person->setThumbnailUrl(! empty($row['thumbnail_url']) ? $this->url_prefix . $row['thumbnail_url'] : ''); - - if (! empty($row['thumbnail_url'])) { - // also report thumbnail_url in standard photos field (this is the only photo supported by ATutor) - $person->setPhotos(array( - new Photo($this->url_prefix . 'get_profile_img.php?id='.$row['member_id'], 'thumbnail', true))); - } - $person->setUtcOffset(sprintf('%+03d:00', $row['time_zone'])); // force "-00:00" utc-offset format - if (! empty($row['drinker'])) { - $person->setDrinker($row['drinker']); - } - if (! empty($row['gender'])) { - $person->setGender(strtolower($row['gender'])); - } - if (! empty($row['email'])){ - //TODO: Assumed object TYPE to be "home". Change it if ATutor starts accepting more than one email - $email = new Email(strtolower($row['email']), 'home'); - $person->setEmails($email); - } - if (! empty($row['interests'])){ - $strings = explode(',', $row['interests']); - $person->setInterests($strings); - } - - //TODO: Not in ATutor yet, skeleton field - if (! empty($row['smoker'])) { - $person->setSmoker($row['smoker']); - } - /* the following fields require additional queries so are only executed if requested */ - if (isset($fields['activities']) || isset($fields['@all'])) { - $activities = array(); - $sql = "select title from ".TABLE_PREFIX."social_activities where member_id = " . $member_id; - $res2 = mysql_query($sql, $this->db); - - while (list($activity) = mysql_fetch_row($res2)) { - $activities[] = $activity; - } - $person->setActivities($activities); - } - - if (isset($fields['addresses']) || isset($fields['@all'])) { - $addresses = array(); - $sql = "select address, postal, city, province, country from ".TABLE_PREFIX."members m where m.member_id = " . $member_id; - $res2 = mysql_query($sql, $this->db); - while ($row = mysql_fetch_assoc($res2)) { - if (empty($row['unstructured_address'])) { - $row['unstructured_address'] = trim($row['street_address'] . " " . $row['province'] . " " . $row['country']); - } - $addres = new Address($row['unstructured_address']); - $addres->setCountry($row['country']); - $addres->setLatitude($row['latitude']); - $addres->setLongitude($row['longitude']); - $addres->setLocality($row['locality']); - $addres->setPostalCode($row['postal_code']); - $addres->setRegion($row['province']); - $addres->setStreetAddress($row['street_address']); - $addres->setType($row['address_type']); - //FIXME quick and dirty hack to demo PC - $addres->setPrimary(true); - $addresses[] = $addres; - } - $person->setAddresses($addresses); - } - //TODO: Not in ATutor yet, skeleton field - if (isset($fields['bodyType']) || isset($fields['@all'])) { - $res2 = mysqli_query($db, "select * from ".TABLE_PREFIX."person_body_type where person_id = " . $person_id); - if (@mysqli_num_rows($res2)) { - $row = @mysql_fetch_array($res2, MYSQLI_ASSOC); - $bodyType = new BodyType(); - $bodyType->setBuild($row['build']); - $bodyType->setEyeColor($row['eye_color']); - $bodyType->setHairColor($row['hair_color']); - $bodyType->setHeight($row['height']); - $bodyType->setWeight($row['weight']); - $person->setBodyType($bodyType); - } - } - //TODO: Not in ATutor yet, skeleton field - if (isset($fields['books']) || isset($fields['@all'])) { - $books = array(); - $res2 = mysqli_query($db, "select book from ".TABLE_PREFIX."person_books where person_id = " . $person_id); - while (list($book) = @mysqli_fetch_row($res2)) { - $books[] = $book; - } - $person->setBooks($books); - } - //TODO: Not in ATutor yet, skeleton field - if (isset($fields['cars']) || isset($fields['@all'])) { - $cars = array(); - $res2 = mysqli_query($db, "select car from ".TABLE_PREFIX."person_cars where person_id = " . $person_id); - while (list($car) = @mysqli_fetch_row($res2)) { - $cars[] = $car; - } - $person->setCars($cars); - } - //TODO: Not in ATutor yet, skeleton field - if (isset($fields['currentLocation']) || isset($fields['@all'])) { - $addresses = array(); - $res2 = mysqli_query($db, "select a.* from ".TABLE_PREFIX."person_current_location pcl, ".TABLE_PREFIX."person_addresses pa, ".TABLE_PREFIX."addresses a where a.id = pcl.address_id and pa.person_id = " . $person_id); - if (@mysqli_num_rows($res2)) { - $row = mysqli_fetch_array($res2, MYSQLI_ASSOC); - if (empty($row['unstructured_address'])) { - $row['unstructured_address'] = trim($row['street_address'] . " " . $row['region'] . " " . $row['country']); - } - $addres = new Address($row['unstructured_address']); - $addres->setCountry($row['country']); - $addres->setLatitude($row['latitude']); - $addres->setLongitude($row['longitude']); - $addres->setLocality($row['locality']); - $addres->setPostalCode($row['postal_code']); - $addres->setRegion($row['region']); - $addres->setStreetAddress($row['street_address']); - $addres->setType($row['address_type']); - $person->setCurrentLocation($addres); - } - } - //TODO: Email is a singleton in ATutor, expand it. A person may have 1+ emails nowadays. - //added to the above with all the other member's properties -/* - if (isset($fields['emails']) || isset($fields['@all'])) { - $emails = array(); - $sql = "select address, email_type from ".TABLE_PREFIX."person_emails where person_id = " . $person_id; - $res2 = mysql_query(); - while (list($address, $type) = @mysqli_fetch_row($res2)) { - $emails[] = new Email(strtolower($address), $type); // TODO: better email canonicalization; remove dups - } - $person->setEmails($emails); - } -*/ - //TODO: Not in ATutor yet, skeleton field - if (isset($fields['food']) || isset($fields['@all'])) { - $foods = array(); - $res2 = mysqli_query($db, "select food from ".TABLE_PREFIX."person_foods where person_id = " . $person_id); - while (list($food) = @mysqli_fetch_row($res2)) { - $foods[] = $food; - } - $person->setFood($foods); - } - //TODO: Not in ATutor yet, skeleton field - if (isset($fields['heroes']) || isset($fields['@all'])) { - $strings = array(); - $res2 = mysqli_query($db, "select hero from ".TABLE_PREFIX."person_heroes where person_id = " . $person_id); - while (list($data) = @mysqli_fetch_row($res2)) { - $strings[] = $data; - } - $person->setHeroes($strings); - } - //Added with the above profile, interests is in CSV -/* - if (isset($fields['interests']) || isset($fields['@all'])) { - $strings = array(); - $res2 = mysqli_query($db, "select interest from ".TABLE_PREFIX."person_interests where person_id = " . $person_id); - while (list($data) = @mysqli_fetch_row($res2)) { - $strings[] = $data; - } - $person->setInterests($strings); - } -*/ - $organizations = array(); - $fetchedOrg = false; - if (isset($fields['jobs']) || isset($fields['@all'])) { - $sql = "SELECT * FROM ". TABLE_PREFIX . "social_member_position WHERE member_id = ".$member_id; - $res2 = mysql_query($sql, $this->db); - while ($row = mysql_fetch_assoc($res2)) { - $organization = new Organization(); - $organization->setDescription($row['description']); - $organization->setEndDate($row['to']); - $organization->setField($row['field']); - $organization->setName($row['company']); - $organization->setSalary($row['salary']); - $organization->setStartDate($row['from']); - $organization->setSubField($row['sub_field']); - $organization->setTitle($row['title']); - $organization->setWebpage($row['webpage']); - $organization->setType('job'); - - //TODO: Address: To be implemented - /* - if ($row['address_id']) { - $res3 = mysqli_query($db, "select * from ".TABLE_PREFIX."addresses where id = " . mysqli_real_escape_string($db, $row['address_id'])); - if (mysqli_num_rows($res3)) { - $row = mysqli_fetch_array($res3, MYSQLI_ASSOC); - if (empty($row['unstructured_address'])) { - $row['unstructured_address'] = trim($row['street_address'] . " " . $row['region'] . " " . $row['country']); - } - $addres = new Address($row['unstructured_address']); - $addres->setCountry($row['country']); - $addres->setLatitude($row['latitude']); - $addres->setLongitude($row['longitude']); - $addres->setLocality($row['locality']); - $addres->setPostalCode($row['postal_code']); - $addres->setRegion($row['region']); - $addres->setStreetAddress($row['street_address']); - $addres->setType($row['address_type']); - $organization->setAddress($address); - } - } - */ - $organizations[] = $organization; - } - $fetchedOrg = true; - } - if (isset($fields['schools']) || isset($fields['@all'])) { - $res2 = mysqli_query($db, "select o.* from ".TABLE_PREFIX."person_schools ps, ".TABLE_PREFIX."organizations o where o.id = ps.organization_id and ps.person_id = " . $person_id); - while ($row = mysqli_fetch_array($res2, MYSQLI_ASSOC)) { - $organization = new Organization(); - $organization->setDescription($row['description']); - $organization->setEndDate($row['to']); - $organization->setField($row['field']); - $organization->setName($row['university']); - $organization->setSalary($row['salary']); - $organization->setStartDate($row['from']); - $organization->setSubField($row['sub_field']); - $organization->setTitle($row['degree']); - $organization->setWebpage($row['webpage']); - $organization->setType($row['school']); - //TODO: Address: To be implemented - /* - if ($row['address_id']) { - $res3 = mysqli_query($db, "select * from ".TABLE_PREFIX."addresses where id = " . mysqli_real_escape_string($db, $row['address_id'])); - if (mysqli_num_rows($res3)) { - $row = mysqli_fetch_array($res3, MYSQLI_ASSOC); - if (empty($row['unstructured_address'])) { - $row['unstructured_address'] = trim($row['street_address'] . " " . $row['region'] . " " . $row['country']); - } - $addres = new Address($row['unstructured_address']); - $addres->setCountry($row['country']); - $addres->setLatitude($row['latitude']); - $addres->setLongitude($row['longitude']); - $addres->setLocality($row['locality']); - $addres->setPostalCode($row['postal_code']); - $addres->setRegion($row['region']); - $addres->setStreetAddress($row['street_address']); - $addres->setType($row['address_type']); - $organization->setAddress($address); - } - } - */ - $organizations[] = $organization; - } - $fetchedOrg = true; - } - if ($fetchedOrg) { - $person->setOrganizations($organizations); - } - //TODO languagesSpoken, currently missing the languages / countries tables so can't do this yet - //TODO: Not in ATutor yet, skeleton field - if (isset($fields['movies']) || isset($fields['@all'])) { - $strings = array(); - $res2 = mysqli_query($db, "select movie from ".TABLE_PREFIX."person_movies where person_id = " . $person_id); - while (list($data) = @mysqli_fetch_row($res2)) { - $strings[] = $data; - } - $person->setMovies($strings); - } - if (isset($fields['music']) || isset($fields['@all'])) { - $strings = array(); - $res2 = mysqli_query($db, "select music from ".TABLE_PREFIX."person_music where person_id = " . $person_id); - while (list($data) = @mysqli_fetch_row($res2)) { - $strings[] = $data; - } - $person->setMusic($strings); - } - if (isset($fields['phoneNumbers']) || isset($fields['@all'])) { - $numbers = array(); - $res2 = mysqli_query($db, "select number, number_type from ".TABLE_PREFIX."person_phone_numbers where person_id = " . $person_id); - while (list($number, $type) = @mysqli_fetch_row($res2)) { - $numbers[] = new Phone($number, $type); - } - $person->setPhoneNumbers($numbers); - } - if (isset($fields['ims']) || isset($fields['@all'])) { - $ims = array(); - $res2 = mysqli_query($db, "select value, value_type from ".TABLE_PREFIX."person_ims where person_id = " . $person_id); - while (list($value, $type) = @mysqli_fetch_row($res2)) { - $ims[] = new Im($value, $type); - } - $person->setIms($ims); - } - if (isset($fields['accounts']) || isset($fields['@all'])) { - $accounts = array(); - $res2 = mysqli_query($db, "select domain, userid, username from ".TABLE_PREFIX."person_accounts where person_id = " . $person_id); - while (list($domain, $userid, $username) = @mysqli_fetch_row($res2)) { - $accounts[] = new Account($domain, $userid, $username); - } - $person->setAccounts($accounts); - } - if (isset($fields['quotes']) || isset($fields['@all'])) { - $strings = array(); - $res2 = mysqli_query($db, "select quote from ".TABLE_PREFIX."person_quotes where person_id = " . $person_id); - while (list($data) = @mysqli_fetch_row($res2)) { - $strings[] = $data; - } - $person->setQuotes($strings); - } - if (isset($fields['sports']) || isset($fields['@all'])) { - $strings = array(); - $res2 = mysqli_query($db, "select sport from ".TABLE_PREFIX."person_sports where person_id = " . $person_id); - while (list($data) = @mysqli_fetch_row($res2)) { - $strings[] = $data; - } - $person->setSports($strings); - } - if (isset($fields['tags']) || isset($fields['@all'])) { - $strings = array(); - $res2 = mysqli_query($db, "select tag from ".TABLE_PREFIX."person_tags where person_id = " . $person_id); - while (list($data) = @mysqli_fetch_row($res2)) { - $strings[] = $data; - } - $person->setTags($strings); - } - - if (isset($fields['turnOns']) || isset($fields['@all'])) { - $strings = array(); - $res2 = mysqli_query($db, "select turn_on from ".TABLE_PREFIX."person_turn_ons where person_id = " . $person_id); - while (list($data) = @mysqli_fetch_row($res2)) { - $strings[] = $data; - } - $person->setTurnOns($strings); - } - if (isset($fields['turnOffs']) || isset($fields['@all'])) { - $strings = array(); - $res2 = mysqli_query($db, "select turn_off from ".TABLE_PREFIX."person_turn_offs where person_id = " . $person_id); - while (list($data) = @mysqli_fetch_row($res2)) { - $strings[] = $data; - } - $person->setTurnOffs($strings); - } - if (isset($fields['urls']) || isset($fields['@all'])) { - $strings = array(); - $res2 = mysqli_query($db, "select url from ".TABLE_PREFIX."person_urls where person_id = " . $person_id); - while (list($data) = @mysqli_fetch_row($res2)) { - $strings[] = new Url($data, null, null); - } - $strings[] = new Url($this->url_prefix . '/profile/' . $member_id, null, 'profile'); // always include profile URL - $person->setUrls($strings); - } - $ret[$member_id] = $person; - } - } - - try { - $ret = $this->filterResults($ret, $options); - $ret['totalSize'] = count($ret); - } catch(Exception $e) { - $ret['totalSize'] = count($ret) - 1; - $ret['filtered'] = 'false'; - } - if ($first !== false && $max !== false && is_numeric($first) && is_numeric($max) && $first >= 0 && $max > 0) { - $count = 0; - $result = array(); - foreach ($ret as $id => $person) { - if ($id == 'totalSize' || $id == 'filtered') { - $result[$id] = $person; - continue; - } - if ($count >= $first && $count < $first + $max) { - $result[$id] = $person; - } - ++$count; - } - return $result; - } else { - return $ret; - } - } - - private function filterResults($peopleById, $options) { - if (! $options->getFilterBy()) { - return $peopleById; // no filtering specified - } - $filterBy = $options->getFilterBy(); - $op = $options->getFilterOperation(); - if (! $op) { - $op = CollectionOptions::FILTER_OP_EQUALS; // use this container-specific default - } - $value = $options->getFilterValue(); - $filteredResults = array(); - $numFilteredResults = 0; - foreach ($peopleById as $id => $person) { - if ($person instanceof Person) { - if ($this->passesFilter($person, $filterBy, $op, $value)) { - $filteredResults[$id] = $person; - $numFilteredResults ++; - } - } else { - $filteredResults[$id] = $person; // copy extra metadata verbatim - } - } - if (! isset($filteredResults['totalSize'])) { - $filteredResults['totalSize'] = $numFilteredResults; - } - return $filteredResults; - } - - private function passesFilter($person, $filterBy, $op, $value) { - $fieldValue = $person->getFieldByName($filterBy); - if ($fieldValue instanceof ComplexField) { - $fieldValue = $fieldValue->getPrimarySubValue(); - } - if (! $fieldValue || (is_array($fieldValue) && ! count($fieldValue))) { - return false; // person is missing the field being filtered for - } - if ($op == CollectionOptions::FILTER_OP_PRESENT) { - return true; // person has a non-empty value for the requested field - } - if (! $value) { - return false; // can't do an equals/startswith/contains filter on an empty filter value - } - // grab string value for comparison - if (is_array($fieldValue)) { - // plural fields match if any instance of that field matches - foreach ($fieldValue as $field) { - if ($field instanceof ComplexField) { - $field = $field->getPrimarySubValue(); - } - if ($this->passesStringFilter($field, $op, $value)) { - return true; - } - } - } else { - return $this->passesStringFilter($fieldValue, $op, $value); - } - return false; - } - - private function passesStringFilter($fieldValue, $op, $filterValue) { - switch ($op) { - case CollectionOptions::FILTER_OP_EQUALS: - return $fieldValue == $filterValue; - case CollectionOptions::FILTER_OP_CONTAINS: - return stripos($fieldValue, $filterValue) !== false; - case CollectionOptions::FILTER_OP_STARTSWITH: - return stripos($fieldValue, $filterValue) === 0; - default: - throw new Exception('unrecognized filterOp'); - } - } -} diff --git a/mods/social/lib/Shindig/ATutorMessagesService.php b/mods/social/lib/Shindig/ATutorMessagesService.php deleted file mode 100644 index 2a47cebba..000000000 --- a/mods/social/lib/Shindig/ATutorMessagesService.php +++ /dev/null @@ -1,20 +0,0 @@ - \ No newline at end of file diff --git a/mods/social/lib/Shindig/ATutorPersonService.php b/mods/social/lib/Shindig/ATutorPersonService.php deleted file mode 100644 index f9e9c433e..000000000 --- a/mods/social/lib/Shindig/ATutorPersonService.php +++ /dev/null @@ -1,78 +0,0 @@ -getPeople($userId, $groupId, new CollectionOptions(), $fields, $token); - if (is_array($person->getEntry())) { - $person = $person->getEntry(); - if (is_array($person) && count($person) == 1) { - return array_pop($person); - } - } - throw new SocialSpiException("Person not found", ResponseError::$BAD_REQUEST); - } - - public function getPeople($userId, $groupId, CollectionOptions $options, $fields, SecurityToken $token) { - $ids = $this->getIdSet($userId, $groupId, $token); - $allPeople = ATutorDbFetcher::get()->getPeople($ids, $fields, $options, $token); - $totalSize = $allPeople['totalSize']; - $people = array(); - foreach ($ids as $id) { - $person = null; - if (is_array($allPeople) && isset($allPeople[$id])) { - $person = $allPeople[$id]; - if (! $token->isAnonymous() && $id == $token->getViewerId()) { - $person->setIsViewer(true); - } - if (! $token->isAnonymous() && $id == $token->getOwnerId()) { - $person->setIsOwner(true); - } - if (! in_array('@all', $fields)) { - $newPerson = array(); - $newPerson['isOwner'] = $person->isOwner; - $newPerson['isViewer'] = $person->isViewer; - $newPerson['displayName'] = $person->displayName; - // Force these fields to always be present - $fields[] = 'id'; - $fields[] = 'displayName'; - $fields[] = 'thumbnailUrl'; - $fields[] = 'profileUrl'; - foreach ($fields as $field) { - if (isset($person->$field) && ! isset($newPerson[$field])) { - $newPerson[$field] = $person->$field; - } - } - $person = $newPerson; - } - array_push($people, $person); - } - } - $sorted = $this->sortPersonResults($people, $options); - $collection = new RestfulCollection($people, $options->getStartIndex(), $totalSize); - $collection->setItemsPerPage($options->getCount()); - if (! $sorted) { - $collection->setSorted(false); // record that we couldn't sort as requested - } - if ($options->getUpdatedSince()) { - $collection->setUpdatedSince(false); // we can never process an updatedSince request - } - return $collection; - } -} -?> \ No newline at end of file diff --git a/mods/social/lib/Shindig/ATutorService.php b/mods/social/lib/Shindig/ATutorService.php deleted file mode 100644 index dba4535cc..000000000 --- a/mods/social/lib/Shindig/ATutorService.php +++ /dev/null @@ -1,121 +0,0 @@ -'; - if ($title) { - echo '

    '.$title.'

    '; - } - - ob_start(); - print_r($var); - $str = ob_get_contents(); - ob_end_clean(); - - $str = str_replace('<', '<', $str); - - $str = str_replace('[', '[', $str); - $str = str_replace(']', ']', $str); - $str = str_replace('=>', '=>', $str); - $str = str_replace('Array', 'Array', $str); - echo $str; - echo '
    ") - : headers.filter(":eq(0)"); - } - - function toggle(toShow, toHide, data, clickedActive, down) { - var finished = function(cancel) { - running = cancel ? 0 : --running; - if ( running ) - return; - // trigger custom change event - container.trigger("change", data); - }; - - // count elements to animate - running = toHide.size() == 0 ? toShow.size() : toHide.size(); - - if ( settings.animated ) { - if ( !settings.alwaysOpen && clickedActive ) { - toShow.slideToggle(settings.animated); - finished(true); - } else { - $.ui.accordion.animations[settings.animated]({ - toShow: toShow, - toHide: toHide, - finished: finished, - down: down - }); - } - } else { - if ( !settings.alwaysOpen && clickedActive ) { - toShow.toggle(); - } else { - toHide.hide(); - toShow.show(); - } - finished(true); - } - } - - function clickHandler(event) { - // called only when using activate(false) to close all parts programmatically - if ( !event.target && !settings.alwaysOpen ) { - active.toggleClass(settings.selectedClass); - var toHide = active.nextUntil(settings.header); - var toShow = active = $([]); - toggle( toShow, toHide ); - return; - } - // get the click target - var clicked = $(event.target); - - // due to the event delegation model, we have to check if one - // of the parent elements is our actual header, and find that - if ( clicked.parents(settings.header).length ) - while ( !clicked.is(settings.header) ) - clicked = clicked.parent(); - - var clickedActive = clicked[0] == active[0]; - - // if animations are still active, or the active header is the target, ignore click - if(running || (settings.alwaysOpen && clickedActive) || !clicked.is(settings.header)) - return; - - // switch classes - active.parent().andSelf().toggleClass(settings.selectedClass); - if ( !clickedActive ) { - clicked.parent().andSelf().addClass(settings.selectedClass); - } - - // find elements to show and hide - var toShow = clicked.nextUntil(settings.header), - toHide = active.nextUntil(settings.header), - data = [clicked, active, toShow, toHide], - down = headers.index( active[0] ) > headers.index( clicked[0] ); - - active = clickedActive ? $([]) : clicked; - toggle( toShow, toHide, data, clickedActive, down ); - - return !toShow.length; - }; - function activateHandler(event, index) { - // IE manages to call activateHandler on normal clicks - if ( arguments.length == 1 ) - return; - // call clickHandler with custom event - clickHandler({ - target: findActive(index)[0] - }); - }; - - return container - .bind(settings.event, clickHandler) - .bind("activate", activateHandler); - }, - activate: function(index) { - return this.trigger('activate', [index]); - } -}); - -})(jQuery); \ No newline at end of file diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.calendar.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.calendar.js deleted file mode 100644 index 5c126550b..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.calendar.js +++ /dev/null @@ -1,871 +0,0 @@ -/* jQuery Calendar v2.7 - Written by Marc Grabanski (m@marcgrabanski.com) and enhanced by Keith Wood (kbwood@iprimus.com.au). - - Copyright (c) 2007 Marc Grabanski (http://marcgrabanski.com/code/jquery-calendar) - Dual licensed under the GPL (http://www.gnu.org/licenses/gpl-3.0.txt) and - CC (http://creativecommons.org/licenses/by/3.0/) licenses. "Share or Remix it but please Attribute the authors." - Date: 09-03-2007 */ - -/* PopUp Calendar manager. - Use the singleton instance of this class, popUpCal, to interact with the calendar. - Settings for (groups of) calendars are maintained in an instance object - (PopUpCalInstance), allowing multiple different settings on the same page. */ -function PopUpCal() { - this._nextId = 0; // Next ID for a calendar instance - this._inst = []; // List of instances indexed by ID - this._curInst = null; // The current instance in use - this._disabledInputs = []; // List of calendar inputs that have been disabled - this._popUpShowing = false; // True if the popup calendar is showing , false if not - this._inDialog = false; // True if showing within a "dialog", false if not - this.regional = []; // Available regional settings, indexed by language code - this.regional[''] = { // Default regional settings - clearText: 'Clear', // Display text for clear link - closeText: 'Close', // Display text for close link - prevText: '<Prev', // Display text for previous month link - nextText: 'Next>', // Display text for next month link - currentText: 'Today', // Display text for current month link - dayNames: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Names of days starting at Sunday - monthNames: ['January','February','March','April','May','June', - 'July','August','September','October','November','December'], // Names of months - dateFormat: 'DMY/' // First three are day, month, year in the required order, - // fourth (optional) is the separator, e.g. US would be 'MDY/', ISO would be 'YMD-' - }; - this._defaults = { // Global defaults for all the calendar instances - autoPopUp: 'focus', // 'focus' for popup on focus, - // 'button' for trigger button, or 'both' for either - defaultDate: null, // Used when field is blank: actual date, - // +/-number for offset from today, null for today - appendText: '', // Display text following the input box, e.g. showing the format - buttonText: '...', // Text for trigger button - buttonImage: '', // URL for trigger button image - buttonImageOnly: false, // True if the image appears alone, false if it appears on a button - closeAtTop: true, // True to have the clear/close at the top, - // false to have them at the bottom - hideIfNoPrevNext: false, // True to hide next/previous month links - // if not applicable, false to just disable them - changeMonth: true, // True if month can be selected directly, false if only prev/next - changeYear: true, // True if year can be selected directly, false if only prev/next - yearRange: '-10:+10', // Range of years to display in drop-down, - // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn) - firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... - changeFirstDay: true, // True to click on day name to change, false to remain as set - showOtherMonths: false, // True to show dates in other months, false to leave blank - minDate: null, // The earliest selectable date, or null for no limit - maxDate: null, // The latest selectable date, or null for no limit - speed: 'medium', // Speed of display/closure - customDate: null, // Function that takes a date and returns an array with - // [0] = true if selectable, false if not, - // [1] = custom CSS class name(s) or '', e.g. popUpCal.noWeekends - fieldSettings: null, // Function that takes an input field and - // returns a set of custom settings for the calendar - onSelect: null // Define a callback function when a date is selected - }; - $.extend(this._defaults, this.regional['']); - this._calendarDiv = $('
    '); - $(document.body).append(this._calendarDiv); - $(document.body).mousedown(this._checkExternalClick); -} - -$.extend(PopUpCal.prototype, { - /* Class name added to elements to indicate already configured with a calendar. */ - markerClassName: 'hasCalendar', - - /* Register a new calendar instance - with custom settings. */ - _register: function(inst) { - var id = this._nextId++; - this._inst[id] = inst; - return id; - }, - - /* Retrieve a particular calendar instance based on its ID. */ - _getInst: function(id) { - return this._inst[id] || id; - }, - - /* Override the default settings for all instances of the calendar. - @param settings object - the new settings to use as defaults (anonymous object) - @return void */ - setDefaults: function(settings) { - extendRemove(this._defaults, settings || {}); - }, - - /* Handle keystrokes. */ - _doKeyDown: function(e) { - var inst = popUpCal._getInst(this._calId); - if (popUpCal._popUpShowing) { - switch (e.keyCode) { - case 9: popUpCal.hideCalendar(inst, ''); - break; // hide on tab out - case 13: popUpCal._selectDate(inst); - break; // select the value on enter - case 27: popUpCal.hideCalendar(inst, inst._get('speed')); - break; // hide on escape - case 33: popUpCal._adjustDate(inst, -1, (e.ctrlKey ? 'Y' : 'M')); - break; // previous month/year on page up/+ ctrl - case 34: popUpCal._adjustDate(inst, +1, (e.ctrlKey ? 'Y' : 'M')); - break; // next month/year on page down/+ ctrl - case 35: if (e.ctrlKey) popUpCal._clearDate(inst); - break; // clear on ctrl+end - case 36: if (e.ctrlKey) popUpCal._gotoToday(inst); - break; // current on ctrl+home - case 37: if (e.ctrlKey) popUpCal._adjustDate(inst, -1, 'D'); - break; // -1 day on ctrl+left - case 38: if (e.ctrlKey) popUpCal._adjustDate(inst, -7, 'D'); - break; // -1 week on ctrl+up - case 39: if (e.ctrlKey) popUpCal._adjustDate(inst, +1, 'D'); - break; // +1 day on ctrl+right - case 40: if (e.ctrlKey) popUpCal._adjustDate(inst, +7, 'D'); - break; // +1 week on ctrl+down - } - } - else if (e.keyCode == 36 && e.ctrlKey) { // display the calendar on ctrl+home - popUpCal.showFor(this); - } - }, - - /* Filter entered characters. */ - _doKeyPress: function(e) { - var inst = popUpCal._getInst(this._calId); - var chr = String.fromCharCode(e.charCode == undefined ? e.keyCode : e.charCode); - return (chr < ' ' || chr == inst._get('dateFormat').charAt(3) || - (chr >= '0' && chr <= '9')); // only allow numbers and separator - }, - - /* Attach the calendar to an input field. */ - _connectCalendar: function(target, inst) { - var input = $(target); - if (this._hasClass(input, this.markerClassName)) { - return; - } - var appendText = inst._get('appendText'); - if (appendText) { - input.after('' + appendText + ''); - } - var autoPopUp = inst._get('autoPopUp'); - if (autoPopUp == 'focus' || autoPopUp == 'both') { // pop-up calendar when in the marked field - input.focus(this.showFor); - } - if (autoPopUp == 'button' || autoPopUp == 'both') { // pop-up calendar when button clicked - var buttonText = inst._get('buttonText'); - var buttonImage = inst._get('buttonImage'); - var buttonImageOnly = inst._get('buttonImageOnly'); - var trigger = $(buttonImageOnly ? '' + buttonText + '' : - ''); - input.wrap('').after(trigger); - trigger.click(this.showFor); - } - input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress); - input[0]._calId = inst._id; - }, - - /* Attach an inline calendar to a div. */ - _inlineCalendar: function(target, inst) { - var input = $(target); - if (this._hasClass(input, this.markerClassName)) { - return; - } - input.addClass(this.markerClassName).append(inst._calendarDiv); - input[0]._calId = inst._id; - }, - - /* Does this element have a particular class? */ - _hasClass: function(element, className) { - var classes = element.attr('class'); - return (classes && classes.indexOf(className) > -1); - }, - - /* Pop-up the calendar in a "dialog" box. - @param dateText string - the initial date to display (in the current format) - @param onSelect function - the function(dateText) to call when a date is selected - @param settings object - update the dialog calendar instance's settings (anonymous object) - @param pos int[2] - coordinates for the dialog's position within the screen - leave empty for default (screen centre) - @return void */ - dialogCalendar: function(dateText, onSelect, settings, pos) { - var inst = this._dialogInst; // internal instance - if (!inst) { - inst = this._dialogInst = new PopUpCalInstance({}, false); - this._dialogInput = $(''); - this._dialogInput.keydown(this._doKeyDown); - $('body').append(this._dialogInput); - this._dialogInput[0]._calId = inst._id; - } - extendRemove(inst._settings, settings || {}); - this._dialogInput.val(dateText); - - /* Cross Browser Positioning */ - if (self.innerHeight) { // all except Explorer - windowWidth = self.innerWidth; - windowHeight = self.innerHeight; - } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode - windowWidth = document.documentElement.clientWidth; - windowHeight = document.documentElement.clientHeight; - } else if (document.body) { // other Explorers - windowWidth = document.body.clientWidth; - windowHeight = document.body.clientHeight; - } - this._pos = pos || // should use actual width/height below - [(windowWidth / 2) - 100, (windowHeight / 2) - 100]; - - // move input on screen for focus, but hidden behind dialog - this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px'); - inst._settings.onSelect = onSelect; - this._inDialog = true; - this._calendarDiv.addClass('calendar_dialog'); - this.showFor(this._dialogInput[0]); - if ($.blockUI) { - $.blockUI(this._calendarDiv); - } - }, - - /* Enable the input field(s) for entry. - @param inputs element/object - single input field or jQuery collection of input fields - @return void */ - enableFor: function(inputs) { - inputs = (inputs.jquery ? inputs : $(inputs)); - inputs.each(function() { - this.disabled = false; - $('../button.calendar_trigger', this).each(function() { this.disabled = false; }); - $('../img.calendar_trigger', this).css({opacity:'1.0',cursor:''}); - var $this = this; - popUpCal._disabledInputs = $.map(popUpCal._disabledInputs, - function(value) { return (value == $this ? null : value); }); // delete entry - }); - }, - - /* Disable the input field(s) from entry. - @param inputs element/object - single input field or jQuery collection of input fields - @return void */ - disableFor: function(inputs) { - inputs = (inputs.jquery ? inputs : $(inputs)); - inputs.each(function() { - this.disabled = true; - $('../button.calendar_trigger', this).each(function() { this.disabled = true; }); - $('../img.calendar_trigger', this).css({opacity:'0.5',cursor:'default'}); - var $this = this; - popUpCal._disabledInputs = $.map(popUpCal._disabledInputs, - function(value) { return (value == $this ? null : value); }); // delete entry - popUpCal._disabledInputs[popUpCal._disabledInputs.length] = this; - }); - }, - - /* Update the settings for a calendar attached to an input field or division. - @param control element - the input field or div/span attached to the calendar or - string - the ID or other jQuery selector of the input field - @param settings object - the new settings to update - @return void */ - reconfigureFor: function(control, settings) { - control = (typeof control == 'string' ? $(control)[0] : control); - var inst = this._getInst(control._calId); - if (inst) { - extendRemove(inst._settings, settings || {}); - this._updateCalendar(inst); - } - }, - - /* Set the date for a calendar attached to an input field or division. - @param control element - the input field or div/span attached to the calendar - @param date Date - the new date - @return void */ - setDateFor: function(control, date) { - var inst = this._getInst(control._calId); - if (inst) { - inst._setDate(date); - } - }, - - /* Retrieve the date for a calendar attached to an input field or division. - @param control element - the input field or div/span attached to the calendar - @return Date - the current date */ - getDateFor: function(control) { - var inst = this._getInst(control._calId); - return (inst ? inst._getDate() : null); - }, - - /* Pop-up the calendar for a given input field. - @param target element - the input field attached to the calendar - @return void */ - showFor: function(target) { - var input = (target.nodeName && target.nodeName.toLowerCase() == 'input' ? target : this); - if (input.nodeName.toLowerCase() != 'input') { // find from button/image trigger - input = $('input', input.parentNode)[0]; - } - if (popUpCal._lastInput == input) { // already here - return; - } - for (var i = 0; i < popUpCal._disabledInputs.length; i++) { // check not disabled - if (popUpCal._disabledInputs[i] == input) { - return; - } - } - var inst = popUpCal._getInst(input._calId); - var fieldSettings = inst._get('fieldSettings'); - extendRemove(inst._settings, (fieldSettings ? fieldSettings(input) : {})); - popUpCal.hideCalendar(inst, ''); - popUpCal._lastInput = input; - inst._setDateFromField(input); - if (popUpCal._inDialog) { // hide cursor - input.value = ''; - } - if (!popUpCal._pos) { // position below input - popUpCal._pos = popUpCal._findPos(input); - popUpCal._pos[1] += input.offsetHeight; - } - inst._calendarDiv.css('position', (popUpCal._inDialog && $.blockUI ? 'static' : 'absolute')). - css('left', popUpCal._pos[0] + 'px').css('top', popUpCal._pos[1] + 'px'); - popUpCal._pos = null; - popUpCal._showCalendar(inst); - }, - - /* Construct and display the calendar. */ - _showCalendar: function(id) { - var inst = this._getInst(id); - popUpCal._updateCalendar(inst); - if (!inst._inline) { - var speed = inst._get('speed'); - inst._calendarDiv.show(speed, function() { - popUpCal._popUpShowing = true; - popUpCal._afterShow(inst); - }); - if (speed == '') { - popUpCal._popUpShowing = true; - popUpCal._afterShow(inst); - } - if (inst._input[0].type != 'hidden') { - inst._input[0].focus(); - } - this._curInst = inst; - } - }, - - /* Generate the calendar content. */ - _updateCalendar: function(inst) { - inst._calendarDiv.empty().append(inst._generateCalendar()); - if (inst._input && inst._input[0].type != 'hidden') { - inst._input[0].focus(); - } - }, - - /* Tidy up after displaying the calendar. */ - _afterShow: function(inst) { - if ($.browser.msie) { // fix IE < 7 select problems - $('#calendar_cover').css({width: inst._calendarDiv[0].offsetWidth + 4, - height: inst._calendarDiv[0].offsetHeight + 4}); - } - // re-position on screen if necessary - var calDiv = inst._calendarDiv[0]; - var pos = popUpCal._findPos(inst._input[0]); - // Get browser width and X value (IE6+, FF, Safari, Opera) - if( typeof( window.innerWidth ) == 'number' ) { - browserWidth = window.innerWidth; - } else { - browserWidth = document.documentElement.clientWidth; - } - if ( document.documentElement && (document.documentElement.scrollLeft)) { - browserX = document.documentElement.scrollLeft; - } else { - browserX = document.body.scrollLeft; - } - // Reposition calendar if outside the browser window. - if ((calDiv.offsetLeft + calDiv.offsetWidth) > - (browserWidth + browserX) ) { - inst._calendarDiv.css('left', (pos[0] + inst._input[0].offsetWidth - calDiv.offsetWidth) + 'px'); - } - // Get browser height and Y value (IE6+, FF, Safari, Opera) - if( typeof( window.innerHeight ) == 'number' ) { - browserHeight = window.innerHeight; - } else { - browserHeight = document.documentElement.clientHeight; - } - if ( document.documentElement && (document.documentElement.scrollTop)) { - browserTopY = document.documentElement.scrollTop; - } else { - browserTopY = document.body.scrollTop; - } - // Reposition calendar if outside the browser window. - if ((calDiv.offsetTop + calDiv.offsetHeight) > - (browserTopY + browserHeight) ) { - inst._calendarDiv.css('top', (pos[1] - calDiv.offsetHeight) + 'px'); - } - }, - - /* Hide the calendar from view. - @param id string/object - the ID of the current calendar instance, - or the instance itself - @param speed string - the speed at which to close the calendar - @return void */ - hideCalendar: function(id, speed) { - var inst = this._getInst(id); - if (popUpCal._popUpShowing) { - speed = (speed != null ? speed : inst._get('speed')); - inst._calendarDiv.hide(speed, function() { - popUpCal._tidyDialog(inst); - }); - if (speed == '') { - popUpCal._tidyDialog(inst); - } - popUpCal._popUpShowing = false; - popUpCal._lastInput = null; - inst._settings.prompt = null; - if (popUpCal._inDialog) { - popUpCal._dialogInput.css('position', 'absolute'). - css('left', '0px').css('top', '-100px'); - if ($.blockUI) { - $.unblockUI(); - $('body').append(this._calendarDiv); - } - } - popUpCal._inDialog = false; - } - popUpCal._curInst = null; - }, - - /* Tidy up after a dialog display. */ - _tidyDialog: function(inst) { - inst._calendarDiv.removeClass('calendar_dialog'); - $('.calendar_prompt', inst._calendarDiv).remove(); - }, - - /* Close calendar if clicked elsewhere. */ - _checkExternalClick: function(event) { - if (!popUpCal._curInst) { - return; - } - var target = $(event.target); - if( (target.parents("#calendar_div").length == 0) - && (target.attr('class') != 'calendar_trigger') - && popUpCal._popUpShowing - && !(popUpCal._inDialog && $.blockUI) ) - { - popUpCal.hideCalendar(popUpCal._curInst, ''); - } - }, - - /* Adjust one of the date sub-fields. */ - _adjustDate: function(id, offset, period) { - var inst = this._getInst(id); - inst._adjustDate(offset, period); - this._updateCalendar(inst); - }, - - /* Action for current link. */ - _gotoToday: function(id) { - var date = new Date(); - var inst = this._getInst(id); - inst._selectedDay = date.getDate(); - inst._selectedMonth = date.getMonth(); - inst._selectedYear = date.getFullYear(); - this._adjustDate(inst); - }, - - /* Action for selecting a new month/year. */ - _selectMonthYear: function(id, select, period) { - var inst = this._getInst(id); - inst._selectingMonthYear = false; - inst[period == 'M' ? '_selectedMonth' : '_selectedYear'] = - select.options[select.selectedIndex].value - 0; - this._adjustDate(inst); - }, - - /* Restore input focus after not changing month/year. */ - _clickMonthYear: function(id) { - var inst = this._getInst(id); - if (inst._input && inst._selectingMonthYear && !$.browser.msie) { - inst._input[0].focus(); - } - inst._selectingMonthYear = !inst._selectingMonthYear; - }, - - /* Action for changing the first week day. */ - _changeFirstDay: function(id, a) { - var inst = this._getInst(id); - var dayNames = inst._get('dayNames'); - var value = a.firstChild.nodeValue; - for (var i = 0; i < 7; i++) { - if (dayNames[i] == value) { - inst._settings.firstDay = i; - break; - } - } - this._updateCalendar(inst); - }, - - /* Action for selecting a day. */ - _selectDay: function(id, td) { - var inst = this._getInst(id); - inst._selectedDay = $("a", td).html(); - this._selectDate(id); - }, - - /* Erase the input field and hide the calendar. */ - _clearDate: function(id) { - this._selectDate(id, ''); - }, - - /* Update the input field with the selected date. */ - _selectDate: function(id, dateStr) { - var inst = this._getInst(id); - dateStr = (dateStr != null ? dateStr : inst._formatDate()); - if (inst._input) { - inst._input.val(dateStr); - } - var onSelect = inst._get('onSelect'); - if (onSelect) { - onSelect(dateStr, inst); // trigger custom callback - } - else { - inst._input.trigger('change'); // fire the change event - } - if (inst._inline) { - this._updateCalendar(inst); - } - else { - this.hideCalendar(inst, inst._get('speed')); - } - }, - - /* Set as customDate function to prevent selection of weekends. - @param date Date - the date to customise - @return [boolean, string] - is this date selectable?, what is its CSS class? */ - noWeekends: function(date) { - var day = date.getDay(); - return [(day > 0 && day < 6), '']; - }, - - /* Find an object's position on the screen. */ - _findPos: function(obj) { - while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) { - obj = obj.nextSibling; - } - var curleft = curtop = 0; - if (obj && obj.offsetParent) { - curleft = obj.offsetLeft; - curtop = obj.offsetTop; - while (obj = obj.offsetParent) { - var origcurleft = curleft; - curleft += obj.offsetLeft; - if (curleft < 0) { - curleft = origcurleft; - } - curtop += obj.offsetTop; - } - } - return [curleft,curtop]; - } -}); - -/* Individualised settings for calendars applied to one or more related inputs. - Instances are managed and manipulated through the PopUpCal manager. */ -function PopUpCalInstance(settings, inline) { - this._id = popUpCal._register(this); - this._selectedDay = 0; - this._selectedMonth = 0; // 0-11 - this._selectedYear = 0; // 4-digit year - this._input = null; // The attached input field - this._inline = inline; // True if showing inline, false if used in a popup - this._calendarDiv = (!inline ? popUpCal._calendarDiv : - $('
    ')); - // customise the calendar object - uses manager defaults if not overridden - this._settings = extendRemove({}, settings || {}); // clone - if (inline) { - this._setDate(this._getDefaultDate()); - } -} - -$.extend(PopUpCalInstance.prototype, { - /* Get a setting value, defaulting if necessary. */ - _get: function(name) { - return (this._settings[name] != null ? this._settings[name] : popUpCal._defaults[name]); - }, - - /* Parse existing date and initialise calendar. */ - _setDateFromField: function(input) { - this._input = $(input); - var dateFormat = this._get('dateFormat'); - var currentDate = this._input.val().split(dateFormat.charAt(3)); - if (currentDate.length == 3) { - this._currentDay = parseInt(currentDate[dateFormat.indexOf('D')], 10); - this._currentMonth = parseInt(currentDate[dateFormat.indexOf('M')], 10) - 1; - this._currentYear = parseInt(currentDate[dateFormat.indexOf('Y')], 10); - } - else { - var date = this._getDefaultDate(); - this._currentDay = date.getDate(); - this._currentMonth = date.getMonth(); - this._currentYear = date.getFullYear(); - } - this._selectedDay = this._currentDay; - this._selectedMonth = this._currentMonth; - this._selectedYear = this._currentYear; - this._adjustDate(); - }, - - /* Retrieve the default date shown on opening. */ - _getDefaultDate: function() { - var offsetDate = function(offset) { - var date = new Date(); - date.setDate(date.getDate() + offset); - return date; - }; - var defaultDate = this._get('defaultDate'); - return (defaultDate == null ? new Date() : - (typeof defaultDate == 'number' ? offsetDate(defaultDate) : defaultDate)); - }, - - /* Set the date directly. */ - _setDate: function(date) { - this._selectedDay = this._currentDay = date.getDate(); - this._selectedMonth = this._currentMonth = date.getMonth(); - this._selectedYear = this._currentYear = date.getFullYear(); - this._adjustDate(); - }, - - /* Retrieve the date directly. */ - _getDate: function() { - return new Date(this._currentYear, this._currentMonth, this._currentDay); - }, - - /* Generate the HTML for the current state of the calendar. */ - _generateCalendar: function() { - var today = new Date(); - today = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // clear time - // build the calendar HTML - var controls = '
    '; - var prompt = this._get('prompt'); - var closeAtTop = this._get('closeAtTop'); - var hideIfNoPrevNext = this._get('hideIfNoPrevNext'); - // controls and links - var html = (prompt ? '
    ' + prompt + '
    ' : '') + - (closeAtTop && !this._inline ? controls : '') + '
    '; - var minDate = this._get('minDate'); - var maxDate = this._get('maxDate'); - // month selection - var monthNames = this._get('monthNames'); - if (!this._get('changeMonth')) { - html += monthNames[this._selectedMonth] + ' '; - } - else { - var inMinYear = (minDate && minDate.getFullYear() == this._selectedYear); - var inMaxYear = (maxDate && maxDate.getFullYear() == this._selectedYear); - html += ''; - } - // year selection - if (!this._get('changeYear')) { - html += this._selectedYear; - } - else { - // determine range of years to display - var years = this._get('yearRange').split(':'); - var year = 0; - var endYear = 0; - if (years.length != 2) { - year = this._selectedYear - 10; - endYear = this._selectedYear + 10; - } - else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') { - year = this._selectedYear + parseInt(years[0], 10); - endYear = this._selectedYear + parseInt(years[1], 10); - } - else { - year = parseInt(years[0], 10); - endYear = parseInt(years[1], 10); - } - year = (minDate ? Math.max(year, minDate.getFullYear()) : year); - endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); - html += ''; - } - html += '
    ' + - ''; - var firstDay = this._get('firstDay'); - var changeFirstDay = this._get('changeFirstDay'); - var dayNames = this._get('dayNames'); - for (var dow = 0; dow < 7; dow++) { // days of the week - html += ''; - } - html += ''; - var daysInMonth = this._getDaysInMonth(this._selectedYear, this._selectedMonth); - this._selectedDay = Math.min(this._selectedDay, daysInMonth); - var leadDays = (this._getFirstDayOfMonth(this._selectedYear, this._selectedMonth) - firstDay + 7) % 7; - var currentDate = new Date(this._currentYear, this._currentMonth, this._currentDay); - var selectedDate = new Date(this._selectedYear, this._selectedMonth, this._selectedDay); - var printDate = new Date(this._selectedYear, this._selectedMonth, 1 - leadDays); - var numRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate - var customDate = this._get('customDate'); - var showOtherMonths = this._get('showOtherMonths'); - for (var row = 0; row < numRows; row++) { // create calendar rows - html += ''; - for (var dow = 0; dow < 7; dow++) { // create calendar days - var customSettings = (customDate ? customDate(printDate) : [true, '']); - var otherMonth = (printDate.getMonth() != this._selectedMonth); - var unselectable = otherMonth || !customSettings[0] || - (minDate && printDate < minDate) || (maxDate && printDate > maxDate); - html += ''; // display for this month - printDate.setDate(printDate.getDate() + 1); - } - html += ''; - } - html += '
    ' + (!changeFirstDay ? '' : '') + dayNames[(dow + firstDay) % 7] + - (changeFirstDay ? '' : '') + '
    ' + // actions - (otherMonth ? (showOtherMonths ? printDate.getDate() : ' ') : // display for other months - (unselectable ? printDate.getDate() : '' + printDate.getDate() + '')) + '
    ' + (!closeAtTop && !this._inline ? controls : '') + - '
    ' + (!$.browser.msie ? '' : - ''); - return html; - }, - - /* Adjust one of the date sub-fields. */ - _adjustDate: function(offset, period) { - var date = new Date(this._selectedYear + (period == 'Y' ? offset : 0), - this._selectedMonth + (period == 'M' ? offset : 0), - this._selectedDay + (period == 'D' ? offset : 0)); - // ensure it is within the bounds set - var minDate = this._get('minDate'); - var maxDate = this._get('maxDate'); - date = (minDate && date < minDate ? minDate : date); - date = (maxDate && date > maxDate ? maxDate : date); - this._selectedDay = date.getDate(); - this._selectedMonth = date.getMonth(); - this._selectedYear = date.getFullYear(); - }, - - /* Find the number of days in a given month. */ - _getDaysInMonth: function(year, month) { - return 32 - new Date(year, month, 32).getDate(); - }, - - /* Find the day of the week of the first of a month. */ - _getFirstDayOfMonth: function(year, month) { - return new Date(year, month, 1).getDay(); - }, - - /* Determines if we should allow a "next/prev" month display change. */ - _canAdjustMonth: function(offset) { - var date = new Date(this._selectedYear, this._selectedMonth + offset, 1); - if (offset < 0) { - date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); - } - return this._isInRange(date); - }, - - /* Is the given date in the accepted range? */ - _isInRange: function(date) { - var minDate = this._get('minDate'); - var maxDate = this._get('maxDate'); - return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate)); - }, - - /* Format the given date for display. */ - _formatDate: function() { - var day = this._currentDay = this._selectedDay; - var month = this._currentMonth = this._selectedMonth; - var year = this._currentYear = this._selectedYear; - month++; // adjust javascript month - var dateFormat = this._get('dateFormat'); - var dateString = ''; - for (var i = 0; i < 3; i++) { - dateString += dateFormat.charAt(3) + - (dateFormat.charAt(i) == 'D' ? (day < 10 ? '0' : '') + day : - (dateFormat.charAt(i) == 'M' ? (month < 10 ? '0' : '') + month : - (dateFormat.charAt(i) == 'Y' ? year : '?'))); - } - return dateString.substring(dateFormat.charAt(3) ? 1 : 0); - } -}); - -/* jQuery extend now ignores nulls! */ -function extendRemove(target, props) { - $.extend(target, props); - for (var name in props) { - if (props[name] == null) { - target[name] = null; - } - } - return target; -} - -/* Attach the calendar to a jQuery selection. - @param settings object - the new settings to use for this calendar instance (anonymous) - @return jQuery object - for chaining further calls */ -$.fn.calendar = function(settings) { - return this.each(function() { - // check for settings on the control itself - in namespace 'cal:' - var inlineSettings = null; - for (attrName in popUpCal._defaults) { - var attrValue = this.getAttribute('cal:' + attrName); - if (attrValue) { - inlineSettings = inlineSettings || {}; - try { - inlineSettings[attrName] = eval(attrValue); - } - catch (err) { - inlineSettings[attrName] = attrValue; - } - } - } - var nodeName = this.nodeName.toLowerCase(); - if (nodeName == 'input') { - var instSettings = (inlineSettings ? $.extend($.extend({}, settings || {}), - inlineSettings || {}) : settings); // clone and customise - var inst = (inst && !inlineSettings ? inst : - new PopUpCalInstance(instSettings, false)); - popUpCal._connectCalendar(this, inst); - } - else if (nodeName == 'div' || nodeName == 'span') { - var instSettings = $.extend($.extend({}, settings || {}), - inlineSettings || {}); // clone and customise - var inst = new PopUpCalInstance(instSettings, true); - popUpCal._inlineCalendar(this, inst); - } - }); -}; - -/* Initialise the calendar. */ -$(document).ready(function() { - popUpCal = new PopUpCal(); // singleton instance -}); diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.dialog.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.dialog.js deleted file mode 100644 index 6411bba0d..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.dialog.js +++ /dev/null @@ -1,133 +0,0 @@ -(function($) -{ - //If the UI scope is not availalable, add it - $.ui = $.ui || {}; - - $.fn.dialog = function(o) { - return this.each(function() { - if (!$(this).is(".ui-dialog")) new $.ui.dialog(this, o); - }); - } - $.fn.dialogOpen = function() { - return this.each(function() { - var contentEl; - if ($(this).parents(".ui-dialog").length) contentEl = this; - if (!contentEl && $(this).is(".ui-dialog")) contentEl = $('.ui-dialog-content', this)[0]; - $.ui.dialogOpen(contentEl) - }); - } - $.fn.dialogClose = function() { - return this.each(function() { - var contentEl; - if ($(this).parents(".ui-dialog").length) contentEl = this; - if (!contentEl && $(this).is(".ui-dialog")) contentEl = $('.ui-dialog-content', this)[0]; - $.ui.dialogClose(contentEl); - }); - } - - $.ui.dialog = function(el, o) { - - var options = { - width: 300, - height: 200, - position: 'center', - buttons: [], - modal: false, - drag: true, - resize: true, - shadow: false // It's quite slow - }; - var o = o || {}; $.extend(options, o); //Extend and copy options - this.element = el; var self = this; //Do bindings - $.data(this.element, "ui-dialog", this); - - var uiDialogContent = $(el).addClass('ui-dialog-content') - .wrap(document.createElement('div')) - .wrap(document.createElement('div')); - var uiDialogContainer = uiDialogContent.parent().addClass('ui-dialog-container').css({position: 'relative'}); - var uiDialog = uiDialogContainer.parent() - .addClass('ui-dialog').addClass(uiDialogContent.attr('className')) - .css({position: 'absolute', width: options.width, height: options.height}); - - if (options.modal == false && options.resize == true) { - uiDialog.append("
    ") - .append("
    ") - .append("
    ") - .append("
    ") - .append("
    ") - .append("
    ") - .append("
    ") - .append("
    "); - - uiDialog.resizable(); - } - - uiDialogContainer.prepend('
    '); - var uiDialogTitlebar = $('.ui-dialog-titlebar', uiDialogContainer); - var title = (options.title) ? options.title : (uiDialogContent.attr('title')) ? uiDialogContent.attr('title') : ''; - uiDialogTitlebar.append('' + title + ''); - uiDialogTitlebar.append('
    '); - $('.ui-dialog-titlebar-close', uiDialogTitlebar) - .hover(function() { $(this).addClass('ui-dialog-titlebar-close-hover'); }, - function() { $(this).removeClass('ui-dialog-titlebar-close-hover'); }) - .mousedown(function(ev) { - ev.stopPropagation(); - }) - .click(function() { - self.close(); - }); - var l = 0; - $.each(options.buttons, function() { l = 1; return false; }); - if (l == 1) { - uiDialog.append('
    '); - var uiDialogButtonPane = $('.ui-dialog-buttonpane', uiDialog); - $.each(options.buttons, function(name, value) { - var btn = $(document.createElement('button')).text(name).click(value); - uiDialogButtonPane.append(btn); - }); - } - - if (options.modal == false && options.drag == true) { - uiDialog.draggable({ handle: '.ui-dialog-titlebar' }); - } - - this.open = function() { - var wnd = $(window), top = 0, left = 0; - switch (options.position) { - case 'center': - top = (wnd.height() / 2) - (uiDialog.height() / 2); - left = (wnd.width() / 2) - (uiDialog.width() / 2); - break; - case 'left': - top = (wnd.height() / 2) - (uiDialog.height() / 2); - left = 0; - break; - case 'top': - top = 0; - left = (wnd.width() / 2) - (uiDialog.width() / 2); - break; - } - uiDialog.css({top: top, left: left}); - uiDialog.appendTo('body').show(); - }; - - this.close = function() { - uiDialog.hide(); - }; - - uiDialog.show(); - this.open(); - if (options.shadow && $.fn.shadow != undefined) { - uiDialog.shadow(); - } - } - - $.ui.dialogOpen = function(el) { - $.data(el, "ui-dialog").open(); - } - - $.ui.dialogClose = function(el) { - $.data(el, "ui-dialog").close(); - } - -})(jQuery); diff --git a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.draggable.ext.js b/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.draggable.ext.js deleted file mode 100644 index b49b14a38..000000000 --- a/mods/photo_album/fluid/component-templates/js/jquery.ui-1.0/ui.draggable.ext.js +++ /dev/null @@ -1,259 +0,0 @@ -/* - * 'this' -> original element - * 1. argument: browser event - * 2.argument: ui object - */ - -(function($) { - - $.ui.plugin.add("draggable", "stop", "effect", function(e,ui) { - var t = ui.helper; - if(ui.options.effect[1]) { - if(t != this) { - ui.options.beQuietAtEnd = true; - switch(ui.options.effect[1]) { - case 'fade': - $(t).fadeOut(300, function() { $(this).remove(); }); - break; - default: - $(t).remove(); - break; - } - } - } - }); - - $.ui.plugin.add("draggable", "start", "effect", function(e,ui) { - if(ui.options.effect[0]) { - switch(ui.options.effect[0]) { - case 'fade': - $(ui.helper).hide().fadeIn(300); - break; - } - } - }); - -//---------------------------------------------------------------- - - $.ui.plugin.add("draggable", "start", "cursor", function(e,ui) { - var t = $('body'); - if (t.css("cursor")) ui.options.ocursor = t.css("cursor"); - t.css("cursor", ui.options.cursor); - }); - - $.ui.plugin.add("draggable", "stop", "cursor", function(e,ui) { - if (ui.options.ocursor) $('body').css("cursor", ui.options.ocursor); - }); - -//---------------------------------------------------------------- - - $.ui.plugin.add("draggable", "start", "zIndex", function(e,ui) { - var t = $(ui.helper); - if(t.css("zIndex")) ui.options.ozIndex = t.css("zIndex"); - t.css('zIndex', ui.options.zIndex); - }); - - $.ui.plugin.add("draggable", "stop", "zIndex", function(e,ui) { - if(ui.options.ozIndex) $(ui.helper).css('zIndex', ui.options.ozIndex); - }); - - -//---------------------------------------------------------------- - - $.ui.plugin.add("draggable", "start", "opacity", function(e,ui) { - var t = $(ui.helper); - if(t.css("opacity")) ui.options.oopacity = t.css("opacity"); - t.css('opacity', ui.options.opacity); - }); - - $.ui.plugin.add("draggable", "stop", "opacity", function(e,ui) { - if(ui.options.oopacity) $(ui.helper).css('opacity', ui.options.oopacity); - }); - -//---------------------------------------------------------------- - - $.ui.plugin.add("draggable", "stop", "revert", function(e,ui) { - - var o = ui.options; - var rpos = { left: 0, top: 0 }; - o.beQuietAtEnd = true; - - if(ui.helper != this) { - - rpos = $(ui.draggable.sorthelper || this).offset({ border: false }); - - var nl = rpos.left-o.po.left-o.margins.left; - var nt = rpos.top-o.po.top-o.margins.top; - - } else { - var nl = o.co.left - (o.po ? o.po.left : 0); - var nt = o.co.top - (o.po ? o.po.top : 0); - } - - var self = ui.draggable; - - $(ui.helper).animate({ - left: nl, - top: nt - }, 500, function() { - - if(o.wasPositioned) $(self.element).css('position', o.wasPositioned); - if(o.stop) o.stop.apply(self.element, [self.helper, self.pos, [o.co.left - o.po.left,o.co.top - o.po.top],self]); - - if(self.helper != self.element) window.setTimeout(function() { $(self.helper).remove(); }, 0); //Using setTimeout because of strange flickering in Firefox - - }); - - }); - -//---------------------------------------------------------------- - - $.ui.plugin.add("draggable", "start", "iframeFix", function(e,ui) { - - var o = ui.options; - if(!ui.draggable.slowMode) { // Make clones on top of iframes (only if we are not in slowMode) - if(o.iframeFix.constructor == Array) { - for(var i=0;i
    z^i`a5Bw$K>^xVrghU#vU}7_
    zQrw%x;=9=vLO2uFI;BA>Y(xQvYYolV42jFDpM+!Q(@yyg2`{om%i^8-=WaiVqaS
    zjpL+kHpOPy8Vyg7NKRs)ibQ?kIch>8VfbESn>9Hq4Ucm3L#sCK#wC3GC^FZErbly*
    z+xOBWm$$+dlbR+9YEp7Lc|`>?!qs61Hf;GsFc+h(1mRSdnM;yc3#ft69^ySJ7m4NQuH&Ytn3
    zl(Ft)ZTvS((^nxylN8wW5w_itRZAV*Gqm|jKbA;YF?%lzf9V%)CH&(MbFU-$ypn6jt?%YV>&m)k6r(?)J~bNofdx4
    z>|3&2KCL@G_y`se;>9dRpj-(R6Hj|A9-B7;Zy*il;&RUU1ZltOMe&>?c!gFuU-|PE
    z@s$t}$f+#hwpgirgZE1Vj-WrT+C&eLO8RY#&92wbeESDF;ko0ApOKNrin*ynK?l!V
    zL~T5)I<9d{%=4Ubr3xO1LB%*D+zJN;AYMWe0Jwp-eY0g@1z!8vn*DEJTz6@CG|q;>ScLrShU)GS+&x-+fzJ#mXhEH<-PFh8m*F9-<9)?!Y&K=_hy9W
    zu!UPlE3w^FlB8aG>`fKk-qJr7we0TQH7)@EP_w!np2rqj{(YTgBI8yJOS9FsNLr4#Am*D{K;ctF@Qv9f;{a&o$w5|@&0Z^w
    zEHFUe;7)k^P3oo6R;RzH#i$89<*iOqSP6IUn&a}n_$=9wYL8C#yD1C1>g#H-{1mZR
    z>6OghmwHicwY|_WHZs`q7o);me_z$OQQAvhfd0izlp$gBFI=p|#u+`A7c)
    zNh5pQkKu|^AMnGv&sy;lQ<&y#cePI+-sEU}p|K&YsQpjH$mH{u4h3fEF0vUl`)7vI
    zGtr;2IC{Qh^Yz!by)WfMhVF1a(ZUpzRJVKW?aPM`f@rIRi$9h*T6)`#cSEE}2T
    z)EO5crXQB==hR9lAb+)uyZvgj8YSzEfe~bExTlql0ps2pxP{Y~ll!x^yz`}EM4`Z3
    zlVUeX&<6!YSRCdyOL`9AW;o{`hS6)|FiEAoe-1>VfDxaP;#Z7b8j~j~?+a5yk@=bk
    zpv}f(VX4~`xY~3oR;LBz8@n1CDs>aVVr(42_0-x?E*$#K=|x6We2$q!DHpjF+Qm)G0E?Xwv6awJa$l0@>bIr=0w)GyhoGZ%c;
    z_dr$FLhOj)*x4^eK%R#B77E!hXH6S9D`~}p&Vg%ncAdY}p0$(UBuW=^Sf9tamvf2Y
    zm2b9m5N-biWZ$QW!4_VXdCHtiXFA{W11oyA!iSIJ%&lQ+>38x<5EWUGd(4mVtJqXS
    z-5GRCdQ~n7YK51fu!(*I^7%y*mej&0G?ppB6BNDxOrdjUK=-OVUTX;Yx;`X@4Zv8Z
    z&|VU}caoh1#jX|pGKFmNnvz_!_F#`zEx(VPG@aa1gQe+%BUm2^2Ce03JQ$SQx40D3
    z1OLU{>-_Rz)cNH1xjOZA7U<&uO9KMu`=2`a+K4nGLEyyFW%?ca4<&ba_^VKsD@AY}
    zn&()=Agu!!eD=eY>;^YZtKWv6GnvB3feLmV!rjXsgX>?Sv6U@&QeP=EsP-TT
    z{$PC+`hcShrF2_T=uAw6r)}6gqdK_-p}pgxj)Ij*FJ~oa{@8E}xV;(6x3~Q(*r&G2
    z5JHWj1@lgZi=8!lcO76j-|Vwl*U
    zgWB$ww6ik(P!@c*D8tn6=$0@!(2_$u(~-_=528cRl8q5Mw;hSO;BUa(qx{*+N1|=h
    z^r{}bM&Bb@i!zb|6gdOj^pI`t>@7M)8P>IZgXDFalwVgL!!ePim$O4lgT-eQVoJ@y
    zJ~I{tgjebS0UvO1(u-^#9lJDHaDIO?_Cp{S(q9#-GVVO6Reb`>sBTw0YLIa3>5+*E
    zORvr1O#-L$8>pDE+o?-1F!P!QvQ@&?jso^Upka+|9lKngJuwF3eV1x_O@rKl*H4Ti
    zPwjb-WQnUm-)g?bfs;La&uP}{hjWo1H!L56Ekd(A^q#Cp2I|>Z+tb!R9J%lA>pHHX
    z)ub<2Vg=tUgGC!4-^wcX&v{na6=+?B6(+yn-|6C=0;D%Y+Ry4uT<+b<;NYz>ZKXkx
    zSVn5EBi21RTAxb68EDhSqhGNEz#f7hxNbgtynKDg{giGxz$4#WzxLEL+SedR@)NFM
    zP+@A1LD|>-iEI}!mW*OY)Ts#Jf-*ul-;03#C)U;;jCQHDce*@7&
    zw@5~8<5;B$(;rlg?Y*WyMKe?!Z``W-pm$`8cX~^U;!`XgFaFF_CfuQ4wvCzd?lF1=
    z|7@6dw3bq##!RJ6kPlL5$nMdBDbu~D&{nD3&`a=M6
    ziS%*bC?NF*1Lk^wZzRv6p#|T$3LeK+c}caMBAoi2va~@~uT`+3^NZk*(N^Qs6JHuT
    z3Z;3ns;jp#6eQACv(|D+7)|7M^AL&*b?uVR-`5tG?7K`SJ
    zi4mRYS2R77&9^g^K7zL?RP?HSUWj4<%4E4hrQ|4h@X1%fTBWwiwiUmy5?;wLU`UB%
    zVWjFC2rY^jDOJN!mRCOXdEi5LYtMLpb$tcs2AH?^o6})>wKX&9jHKy5qkLS$(vWPu
    z2)?}tG)5uc@>h6ih}TISFrJY(?wr=Ii`VVDsHB9J6ncC)eKb^%P;vTYRAVEGn!=r`&7cf#lWb*%@jJIW(3MX)v^yN}giKm<9C(vN;W+X+GxiXN!;g<~vxkRI1Ec^D
    zmzCAprKf_6m4^p$Vfzz;t+67_4~(RwJU@kpc8+d4F3;^}j{q$7Z+4x0w#c1ged$cN
    zX*+tf*JWdEDl#~!eZO6yaM&k1H`Cai|H2^_??Mi|FTa|VwJtv2XzyiXN126Ooin>3
    zqpE6u!s@(oD7D=f0|=Y=FsmH|`+sAMeJ@V%>0-CX@zzVGvUifv-ch~1mgU8vUi
    zfmZAnRJ;JE=Yx&NkyVxvdO$KKX5GK
    zEnD<0;Z!?b;+4|d84rkF>=xC67Gl&Ep95d=K-R_N1>6%X1L^QRUS
    zn>|dpF47~Wqg16K*dtbTd#L-ZAcOiv#v{$_0MvIHi!*x&l}%~XDEDjqHnb7gN1r-y
    z8p|V`xW|z_V(Zyv6Z!8#p%t;F<*M#~6{@oT)#z^=qqU0~x)Gy?Db{I5QMT56DUtaX
    zng6c;Ps={QU-0Vx?)X0#{|}n~@bM2q>$KV9|Kkq+yK#%HN87r>Uvk<1H%mHy7yd2m
    z-<`~e{e$s;OYxto|GhB(-Pb=<`L{%kkbkM_A4&S>ZW(WV&(*J*aob`6^
    zzhG4Xe+}Z_%D+%t!g6O*#1Ci3E~a3>Y;>%sKP&29<@o2U=a$Z9(N?~`zD2c@`7yG8
    zw%x`e&O60I2?}A$(lNBQWb^VLW1zE;3kgiNmz=g
    z@3ErDB|n^h=>cf1KtKYJdcW8lea&rQ!AEphCS)hdOHYPH=biuKJLX@22y2z+XBD;i
    zhTNgd^37+5zk@^z{iu|0lMFX0v2*%F+7NJoo6j2T5cAS$OL&K1gim3JN*`MmNg8VW
    zCAcXobwLC
    zx&4nnq#|mAw%6<$;;aaqgL8oJLNr#@@T7D5uFTkmZhG)w`Y~VDDp`p<3!VI#mWmN>
    zRn+WPK=baL!DE?#PnME*vRb=G-Zex>$hq&VbTCq)UpiSD$pQ2747zC8Qc72!*0vb&sRc=z{7RG_0hoN>(Udq9I-)xz}f
    z!b-1sDdT)-slHLxb6=mUO3V)^6_Hj;*^Yq%+n|K-^*|8&~ve(1NV+4#vbU?m1J7E=1&m015Sf;T;DC4zTXcY54eKT+;Tug+Ps=CXNZ
    zVo+pa+s1&!+WQ2J+RJGyR5IT=v}c&j-swM%Jel%kpL7sfWe`F%x$ymT`J(qerFHtd
    zU+m4A?mT9xR}5uh3}5K$ihpSQZu<76`%c|Ph_efk&|AGwHDDZUREWLFEMa!ew)Wy@
    zgtM44bG%i{SLy}mgRb8TP#&cg3Fi5d+!r$iCVC$%Tle6dUM521PO(yA61eG#+Clia-%>p2EoU+>6~6?H3y^E;dJ)YYowSetZit0y|_N3tgcb
    z>;FsAZD|h5~?V2MsY;GZU9wn(L
    zUjIGH789GX_kng|q8@eWGY$2N3092~&&s2^tE%n^ZtvNymfCZjy%(vsRT!|lEvb2B=wU}MwvGS|oByx&jr_Cm#g>t*nD_-L
    zY873zJFo8XJ&5`B{dR)NTQ%438Ga|o8)^f_6&wrx;-Kl>h+o&}bIHDAF0;_G+^1H^+Sy?Wv8km#
    zcG`^>SgvY#Ge{u>KRYx1nusJh1F@(bD9jDkPQV{;4gs;bXUugK$9()Eqnj-7crAii
    z`8=d*-VKxJn`P=?VmV!91$jN1MHG?20Eu`ERN_>dB-E5d{asqjS`n^C?7y7`B|0;s
    zoJM&R8yMy8;Ni(W{ore8eczg{#og9>-^Fyv#?7b=fk91_-8Bm%7Z~4Gb3@
    z*iHYZF8!5R`e2EwmC!=ciJQoQ@$nLt(`?tNS>m+Z|I5(!z9S`M%U&((Fy*YhB?Wzw
    zg@?=@#RZ24fY3he-NJ3jcv3j=gvpGEs3$tbTMx@?Qmy7zGELKj+$dA
    zG~sT)qRrw6{q2GaBKxrU{M6$Ht~H&7XM?a12`(>1K0xHCVAEYT=XL}<6Ln+O-smnj
    z!uJYX2VP5?cxKD
    zF<(nG>9y>hKiqBD{`J`&%Gf+%xn>XetbT_=7*WEPw(8~qR7$~v6BPk4g=c*@qwJ1R
    z*pFjgAw1c}vKS?aaY6
    z)LUXE6w^iYMVP89nmz~QD+&?(&h|I!rd-CS;|Tyc)qa~z^)Ja_QNY*MLZ8he|1FKc
    zc8R}8&gCEUQPjQZzg~Ck<|vwRS!6-(QN;Aqm2>Rh3~Srx1Zd_ugp+w
    z)AW6TFLt1WURdm%I9b{&4j=!lP*Kdxt0}olN?wBcJ`N6^jU8i~1wMKw)ALzJ-v5pJblu
    zxj$YpzW)n|y4kcOioZQ`ve9{@Y7Zst2MJ8XQ8Xj~p`6Y*KRI%OJV14+4Kc6M`}?~E
    zmXGT+>r*`<@D+#qhAKE2f1_eu9YIz)lQ|kR5;Qjev+X~)flF6S2F8nu?er~_RX{u{
    z3ey~XTMtO1Z0Ky*N9c7U%UteX9yfhp6mL0ly)5;wr0xC
    z0!G8&*E!l0mp{h?;{Yu6Ih&bxj4*J&{hs>xdEa40*k&cH=n(z#kn|}IW3rHVDC8lM
    zq6n)wk_Yd~(G3lU)JJDTa1&s2TVQRp4CP-s^28~#zyC|eb*B13m#zind0GFedaJ%jt{_uLm$Ix%B%-p1>AlS-z;8x#wTw16N*u0>oI>(>J0=w%RaoqYd
    znRcx25d+i?Q$>;q;mR%;nw-nCAb0-hK-=RAe|kr{qNa!$WY`A@X)u$$y`bnzbd62j
    zZ#jb}NZ1a0=EKGb;1hjo-4I_)Au-RQ39V19EvfxzCsObJdc@
    z(DnR^eV(zYXu}YQ7{skdilc
    zS;v02>{TOqN&j05abOty6D
    z35TM(MXYl3uaHRTV@Q?GK~=eNIaH-dDrFByN2{f{86qnq|5`5fU;#$V5kh#A9W{3+
    z1ZX{9X6xIrZy_oXW2wwmaax2mqe1oER4+c>9Se1my;;Z_TnvyQu@9K40XM83@HKHR
    zx|(aZ;5?T(EZBz8HI5M>;rAPmL0s-zO=}o2X}^yWN$k@iW5Vp&fkM9fGB^Q3A1Uvo
    zS~FLd$gj}kP-1R3ogkoYz!}96Y!Op46v0&ol6Y?3PN^BOTl3c
    z)dF4d%VAnXX<**UQU@S8=tVDx+xu$8&JU
    zc`fg@ORY)(AIg23ZqeW+JnqtTM@rqITzkphZ?Uth0Bx~<^$Y?b8dW$t+P65|qQ5p43QA4weD|1z`fBLE
    zk`+Zf_H=I(4#@@vugRc`;cH&`rDV3}=uVQ(4kn5y9!w$J}siP^TqLX8=E8nFA*fm=jdl>-%skAW1E`e1+g+#$&8GB__y
    z+wo&=%_NApaW=O+S`61htpi%PmeB_rODl*xh&DCzl2^Wybs|*@P*(V*%G_VHqlY~I
    zd1JnMkOQj6RctSmeFT6KvBQj|c%XsZ3~2|L)%t0exa;;?*T4_K9%uj<7hVe$8B_Qj
    z@=4CX)3^DV!r(ncG^2hN0rMR)1Y;!~h%z_!5Vz&9+^5Kmd}1;Iz_Hd*KPyjEF}-^s
    zVn}!?N@xDti<2C!G~vSrVS)YlCJS5O`zd%EUc*hm)T~G7tdPU0RkJZ@6>K4pMyY!98Ap2*qh{#QWwkPch7ZWuFo@f^<;*
    z8!wYugxYE5_}6VBBZW>~0*)NJb;>t>5s(r(c>?HJ0R6Gq?9MlWy!ZGNWUWu!ony?N
    z@%Rz1`1^pi6`Nsd|1vaaR2XN!I>1sJEaq!dKp{nIURtg^-Qy#0Ea~jn=O6p
    zde-i?l$KPUH228rGKdQ8bRlg9ZJb&8&L$M!_hAZI!Q&M-68Yi6*`fPKyt
    zGj+sC-t0ghdW}!ytG4dwjezPseQe@i+>0%b+ENVi8Q6;R`jsca-0lkuvneJYk`9Z=bVjy`q7osc&l6xeHCtPp+t}ookgI>e%{1xv1jIDSub=HZ-4A*xRU8V240(R-{8)
    z7CI^jnTi^IULX$ILA?T=NQL)(s5$mK9(+GM;RE#>>PIz(>a)K>Zy3Tol0pxq%8=7g
    z_^Uhx$}EA@yrXBEh$LF~G!(l|Pxk6bzp4$JYw+{ZP|
    zlf=#S36?`h!~r|1nB=r(q;X0cg1fulZ_JQB`
    zYm}SNb3%;@r*WdpetP~&Zg<^e(_X>4j?q&Y4@)d{Re-H_`XBykG>MAr5Fq+X1^
    z{a^_hJlGfyZV?y1N9&T}X(p*J9qqCUdlb|&p5>mE*6wS&xOvHMY{wK=iuJG9qfz~R
    zP&bSP$HL4>uqs7+*;7HdD{P{TV&2V9s@c4}W&)Z_tbo9*foM`ca$OPIr){v)DvxP2
    znX^0@?Im&G^0>jiws^(WZQrI*Ela~*QdUhYWAQ22bJ|zYYWsi
    zyX|BlMK+TZ_nX33j(pF=IPB2O&&{fYNrFKDX__
    zWO0_G@gFx`)Yorpm#q8hUwi~&ZqedUtJO@qyxC~T@%*fXyB6&qyO&h5b18ny5jN=E
    zeTrbe;c+9TMusvE3{jRJyBWwc69)6Z@G03GO&gQfDfe6~v^>&k%LfDAsuF~91bnC;
    z(W;x#;y#qVnWW>*U*xx#&8Y@kR3IvjJm%$H=;Z@~)lZJkeS1o5@sSH=gdd*$QCUyO
    z>$3Z}G}E{0C_RCBZ+ys)w&Rv>TNMHz^FwF)57xv7*8?X$N&bX{9Zdv&X86)^4^D3PiRWUQQyj7mdJnVx_+g`d*ocO-M478oSDOp_`s|@)^@+Mf?VNQ=uVKWp
    zW8Bhi^8t@ZjA@AFP{sS5nev8TN7VvZnKMVIreQzxIg;c*2l>3^=N^kWWYLLpZvR!Z
    z&-Zo#+d>WV68eMDna>C0ZqF^^;FU;OdDXW$HHw*JJHCjDDyA7(IW!Y0;B&)WH>S7;
    zT1Zhgc+kIzBA
    zj>s<(JQ{29-F!%=Noy=i)FW24=~_&_pF&qt&}Q=L4LOzK)02~!(M|(mwr90io9o=N
    zvm0qPX11^|xXPv8Eu;Pt@0y1-qHI5R^4k#7GwYo#5V31(S4Cos+m^WgnDV!CU_!Rn
    z^JUBG))JOVB<+O1WYr9!A&(!a4~RjQy)EZCVHId=1S^#@l;Xh)mT;zu2dT
    z$_WEXeKd7VNWZxON?H0E~wAA^zj*~MHEl`%SA10M0m-!MARw=AvCpC31B0rBQrA0)@FJ%N+Z&9X4N)OF;xbtEXMCsp*Eal`}>ZVhpe=0c*XClr1(FM(o)_N~|uY
    z--y%;O7`SqkMb@g$sCu*EFZTcMu~EcdogJ%VF0i_LpOZ|m6aU7B|K`F-RT-yU8XW1
    z!fXf6O!U}u_P#t>!f_o~0pI7A*@{svClCZ&kBrYCTfp-dr>V_xm$LOdzLe|Yflv}f
    z3y}tvv?G_%b#M+WGkpk=#{=z1v8KV{BsA?Q+N&}U`3BC%s=B?oJ=a+b2r_|&jf$7l
    zq`6A=I1-uNafT=0Q9rv)@3VtOWw0Lv12gSwgUW`Y!>UN{oE86NHUIUH`)fUMh+d@&
    z8lS_V;yXhaNTp|OHGLB>2fBA|8fO7t6nxx@x?m1w9+3$3lVAYp+5y=FElv_NpzG@+
    zJ)(-wrVHf^3Y4{ISf{na|U#24JQ!%D5n%qT{H;p@}GdB
    zg&`*BX@jy%DMEW8M_X2oR7!Uv>gAakYw8RYXB?M{(^5NtHEYC5=1Ga>wdSBh0h
    zkC|AWQ|c!0+td(*{XBdY-F6#U7w1GI_bxoJ)|D6A!Ug9~
    zR6zo2wdO4W+7(D!C?;tuzHK4yY=v;>t+A4+E0OK-PKmTX?8t6Ms1;A)9@<%~yjTQG
    zi{2pZ?5pip5Y5r)iSS6msoDK~!=d42^UageK_XsTwq1<(Svz9=S%|kP+bCY9xddMf
    z587Pv`7}t}l_Yl&{l>VRreh9!W0=Kd0A~}!>6XWC2AV_i1G6W*xUvZG0}D{`u^w|@
    zI8!{bcyY9Y6u
    z))n*rdPnnBQR3W2&RK1)>iu~-CAIhWwW=Yd`*kpZ{G_+9`TjZ)plCFjxVPu@It&(C
    z&6%o!qu;UA)z4mXmE1fz@giZdSg(*FpF&Rk86o|4U_gNM?1i^eQHCPna5$0IKBa+*
    zc_arMWQCNbpr8;kPv%ALl22A!(ngexIgf3e2Tue|
    z3$pbxjoH*%^x7}Fqp8opkoNcY4`aUq{0q>18r*>A8FyPJ)-umj@gM_^A<5R%cndT@
    zA<Y|23PL~Ke?aKKU3M5R@ZY*kvX|?9aD0EnqMb*67hm!BNP%=y=iwvX2eu-ZnWVkD
    zsg+g$wvl!xEPBea?ku2Au~d30eZYAnFlK@TaN!1@sKW5-PWMVPP$y20hNO2@@#~^3
    z;H2g4z!a!pnGX0N(s{(eU<({Ys9wZzTh7QGXP*5LZyE);JV0AW+uuwLl73j}SM#uS
    zL1rjzFVZLO)NUpn+x#{REi==mA>d-zhhqJ1XpzTR*d54&ewEsW%ooefL#8^r?cq>jrD}3+7Jl%r%f0o@b5|
    z;z_Eu3aS92Vh@QGct-s0yO!C;8hb8I8ZcrAacsk8rUqR)57a9}J#WyqfE*82jw>*r
    zYZSe*0^$aP%j*w;FjcT+l!+FVDE+
    zA0!O${>h_L+!CoqEW5;p2x;PwMTI2z2%R4B0YbrFhve$@&qZ78S?V_kGH|P2_cd#H
    z?bD#Fb8+;exa3fv)6qQ_UY9}8Tt6vKEc-;bKg4u~51{u%6>1{;Io2`IS1Wp4&%
    z0dT!@;AV?S!jM<{fh7qF4+xo8gd#`)+l4?R^kAW$fE`A|!31yxmJ^CDK|d>>_QPc=
    zPiJ#Lo&L=l7X8;>Sp1)b^Jj|JF{O=f=lSi($oQH6qu!~*3jp%}Gm!s1)x~>wfIuVS
    z(ac$bnjn2-_x*Ua2TZINDR;cl1A5lTnCR%}7{N544lWZ30_|X?NK;=;yml1ygP>HE
    z!UrwFdRuUS1c+?DCSIr)s`4%(uj`V#dCwImGFVth*NHX9%BSnM$m_4Oje#C?`Yk2S
    zRek9^8VUBoA1S$!C1)%>7nt@CuWxtOX1u-PpY?3@(az&TtELJ8MKl%t&qY1KUzRZx
    z6_TGCz09%}mLWeZUO0>L;g#r4k|$_s1*V)99wAi%wC+otro4ZnG;Ar&)IXu1ef9A}
    z=aMIlaj#qih{!$H?|#SyRpvO)p33u>v=wqWo#IdrD%$beR00*L)nRIh0BUSbd8cho
    z0|(F}uBkjEfo9dX-vaO
    z;Gb~Fg^-2asO6ND)ZJzK)VHd&H2p#cx;nFevRC*!$wzYq9TXRfd-}hcyUM0GxMqp7
    zxJ!aVumpEsT!NGE;O_43EE?P`xF$FRcL@%Q1$TFc#g=`!|Kff-pQdW2&Z(KM>FzT^
    z&n8)>GWr99)J}*L%`Qi!x6>g+a0%!25aDyVM~LQMf3Av%WqRS6OT3VrN{Utk*=>`>
    zWM(kNZw(oGc`Y*zWh=xXv5rS(c6S@=6wA!}e`qtU+7V)7W8@Y1<1*uaZ+4l9(&t5R
    zSdRG~+<5+O_XaKS=J;-zUI9yrzEWLnJ?N8(d{8AKFnkxZ`N(F9wIa7$rAnlWpCrLByT!!JyuU!Q0NERJzV-NVR6<{=OHd0#)
    zrc^L+UIduS%6a_BIad{46b>5XP52Q%76Y~dMWZqh`Rd+Z*z%uMPPVbX0*lCAYg)jT
    z>@Bvst--Vty`GxM3=}?!4@#!NR}Cibsz_aa7(KE?XyXm_Q!069e8KjVi6!Ug9(oi3YFZtk8Rb
    zbfav1Wxso)gy7zVeZmW=wNrZ#$dPGDbhvp$vz1WIx}INr-UzPDBNq#NOODuI+ggf9
    zYDYPi6nt*lL5sjxC_xa=tgcif$CeuK{9|i+ilc;aw0|hoiEtV0Q;S@PaYz{_T;f1t
    zi=oCgk4&BMxO*vWcTLoP;`R0}C=7yh8j31q+
    zAJz!KJ{rxB|00YMfQsZ+O)87KOQFt0si;tW0V&g7&j}lMnXl)}
    zbiebdhXSrWa=0LA^M?FO}C={LrjelqurD?MRdUkT?
    zhBYXbxLd^i*nGLM#-~>{W0h8sfvKSsw-oog;t8)BNYcWD8OPwY&c-iA7bxim2sNmk
    zLtos<(45yoXu#ypn&k|#wF?ZjNHvq|=y4?;AAX{m-j!ZrBf}TH8&~|Zc5w>$E55F^
    zK3uPikNCo|ADoD|`*MD?*U2%ZkFs*(9h7)m;|X@zRM9QM5TipH!UBcGZb`~ypk#C6#uyMl`^Ns-bluES&EKpNjR??Q$^4r1n+3L(dD_HTDLj4D_r5$1zM
    za@=k7aS@$#mCV4SPVgsWcsDBYO*BL!UQvREa~<+wNewzyJ6abxHP&eh{5RS|%j!Nr
    z|2F-?FII30Hzohc^xnjXz`U|x)`t-Aj}Jds$f}O^j6ORG%ZK(o56KWq4%J6cESTB%
    z1U^n()E{Dv=jwst+1*U?ty&d`NMrz9`z*eQvz#j=?jdAC$#zOZbB9xXD20>f=B7ylal>{{T|A=b*mdZYNBmMNOShdi9=Re2{lWR>ndr4|LD?<9J3RR_XWE7M5Kl`^pNeycKa$os*W%ZBen>(I;
    z)t870d}+2rhf&cyh~$ICE?~E19?sbfD-ZYImy0``xYd}W9{=cV8UEwjU0Au@HKu0G
    zHfO-!{w&%|KiE5Fsgo?yW0(wDYB4tA%dOZP@wcXEoj672UMds|4&$Q!pw^E2>;hZl
    zM>elZz#OzhUJ{}ZAFI@m&tgNoS-$*H$Jc+|SwFxRZ=1LeUv73Fr|PWAiiP`J
    z%|{_mG7EiP8w*m*9sPQ+s@XerMl96+br{s0`vW@aDPrXtzZ-jmbWME?18~ZIc5%pJ
    z6;8oYxQQc##?C4_*oa1tFtA3XR;7rD`+HkL$L}a
    z5%QNFd!+nRh%nAhCy)}VUgb&}$JgkrhRAQ+X_6JudTb~fh8hMP)i`W6B8j-qYGigO
    z4jUHhmFA|S>@UXbG-AX$RCw#B7_IienT(O@8)MaobHugStqp5z0N+x%xux}9D1j$L
    zMylBfnzqO^nEjR9jW|1wZ~8<$?gM1drAK`2`>#I{%Fp3pf4NivP#6($o%Oh(n!&Hu
    zvfjALC;i7(@S(9Z>h2?KYJMSsF*xZmHY=Pd0AtGut>IkA;Hav6m9JdZ+TN=^qEkF}
    z)_2H{uU*Y33y2Bdj3skQHoHzbZQWS(u-R4&8t^PSP^`pce~~<@-H@X0E?e{WK6YnKz?y;ltiFMuyO>ROC8kE18LaxP(C
    zyg2ZfReWC_4!1p`bnaOHGNhF!9QD!`>ENP?GAcwsrzk)IS1m`RejQm3QDjQ&fnjY4
    zA3*&yZwbRMFt%OE%bKmFnF$HeioD0e&U&4!aZG<-q`NC2%V;vX{;D7+>ozWJ+mOfM
    zP6dC?g(Vwq0tqJnr*cnROU}QD1f>gDDvH5T*-E{Wl^<8w@=xbZfwQj51_LgV-wF)r
    zoQQAU*zAMpk$e$$c0yvXY6l@Yv%7&dQG2N%wHml67hK9y4+egwFl6#4O<_rd!eo1D
    zU)fXd#dws)kfIpn9LV?$28+L%CFXzk3k45$p-GH6D(!cs6RGTlpJY_h+J2+UBT6jV
    zY`myrh=zKwQn7zOP?wMvOewCIwfc9ab$+!)ucLceqaU2VVlrP^vdf#OT5aoEfipgH
    z{p-<#R&aMga>>^jG*PwSX>-R
    zeDl7%{-(H8Cadp`5vx$@u^SeRadpMyi9>ukJ1Ku9WVeFiWXtrr;=lCdi-<(`leMUG;Jn;`kM+YqSoi8iMO1?Q6HcVy
    zuVDC;bol1|Y_{?^FwK#V5fY#0xc(4*d(MFOyyEd!oYzh2h*0WZy~EFIDgk*?(5{8$
    z^<~?TJ7)5fh}u_O*j;>`I4I#V@o8iYc0^IwLClk@=wFjSXN*k}Kw^?_ho_;k11n(6
    z2vpFd>9@Plf)5T+ip|koyqC^IQc+CnD@BG(6l(6GU>5%b4?>{p!hf=@Ch#wn0!^6S
    z>DC)GlD3{lOf!}@!}nChJ#BaTEw_^U$N|X`9`X>4!jb|!lqm$be^#fE%!`l8R2LW(
    zBK(nBj;m!5C=YwbI*tP^J
    z;@gyRQAu+tsG`#EmJQAwqlUH+@z&8j`y-HG>om^X=DN;wLW-~PRhM)HwZPss|k>l?OBUzYIwEgm4`9Jznf(J;>*zYLU*K)Yty?<
    zc~UG20oT3dc@)L7xZqLm_HzmHJE1WytQ9B!Y`dd+aqTOQ<1yh90q@s2w=l2JHABqb()keU3Y^fm
    zyI9|c(2nNfO{f4YZHrv(G}R!(H<#q8k*pSvP$MxSOD+#Z1=E
    z{5FGZeG`$Qy~~LL5+&~Smm^x;O|5pf4L{q6Xd+~a8VKO_k>nao^z-kAA@eqtw?+nx
    zi+TIGFq!l;tj>g*6atZh-jqd{(k4f!nP_u_`JyaGUZ>UX8f%opxh4W4yz-(bhn&oue*SyG%BBqH1c(k
    z87zeg5n@_S6wV-5=N9XFH|4t^kraT3>K71FHNrVJ-Di)URa%Igw4Z-F
    zZo^FsT{>I&GH2^{HRv20)(Y697h(9|?#B&`Ee2HitDrDD^W&Lj%_9U|>>dN>O-gL`
    zqzRg|>;XZ^#PEe(S5ev-`3SwbD`LVPkGaexc20=QbXwaZli#u(Ys@sdyzf%|^m^U2
    zJvmFN1bL(JjH*6XaVQ>>-uIFIz-#`O#lIq!2lw5%kT)`>b@@+;{YUQ7Z?CjVxhF~&
    zT~XSJC*g;=m3rH}4iANo*qH4->Tsg89sv(YL(bsL&)#vS5C5XuFLpC_>1>q0G(L%U
    z=+Y#jy|sXA0&TZubyC->h)9zP|IB`(1oHk!D{w$@Kkby|e|SZ#RD
    zO`~8OUt~sHtP5GzUyzQOgco4lv$i3^4TgjekP}dZD!epd&8|qA_n#!=Ju2p_r>Y}9
    z)dw(=?6;fH&QZ*Jl%bN7y32_Tbw5!%YyPZW66O8cUN3F+C+Amv&&$b_DOGk@Guz*X
    zmFqV2yEql@mPvUs4-hFWV#jn*NZoL=rvl)D8O*5arL
    zR~GnGd~YiL>B%I`eZOK9gncd&Zh=&Y0`7V!AiZOnB#h_MrcW$XQ#DG}Ef(pt3CO->
    z`}7JM5fUeMYZD}R8hiFM+#b&YTPqQo0;4>wzsFt7APG~c+56*r)h8NP-<~j&
    zq7vS3^^=YZ8O4oJcy#@QB2XS~pM*6&+TTP4vl`HonY&GpR7j{g(tZzvSgT$_Cmp&Z
    zoc!c)*QTFmp~V*RqMho%;`dQ|7p4SFdBm&9ChG(o%#QU`0o-;Lare5WhmnDQp-QWM
    z&VWB3(q5^e*_S?#E78Ugnj86GQe6h++p+LmV8~6RLuX8-#aQ~lY)*Fgv`}f`2!H-`
    zJvJipCg}yKa}tT4`FMMD(Kf>e$M&$-+Gucop~6DdH1Q2!=XQfiy2qu<;L8T7g$!ES
    zO}bGfD{Da(s0?GJ&g>U?PUF#Gu;F7*snQ*Orb|6%Al@miRN|&o3M}<8Pbx*QFdkr~
    z5{I{U3x&OWOu3gIK@yN8wzEDtto+&+Pp4bLYW)0Ph*No%^0*1LperdJ$tO61i+}Be
    zh`Owu*0*-nH&p0UK&g~ZEod)>>DTUq36LH^bEYH#Vzu>fgO%p&;zch#{33WSd(vaD
    za8s;#+Pq`NV#J-(lw##kocR-`{KvA5Fed5e+VI-jCa9G!cVCT|;GRM{u|HgW
    z{FzL8amCBbhcD0ma6h3l$r;&7U9YZj5Nk)p;yAwWqAlN5jWQN}g`ET%8wV1K!AP^s
    zEmM%-4;lCxgI-^|3}u3dzNS0G;1m8ncHbEBE0xM<%ITVrszNX`?z&j!7z_8LE5C44Mh*wPkIiR>%H5(GRC;p3b^}w9qG{@`Dh~T&_H0yi|Gl
    zt@L{T5mKmt_TQtNXrtC+5DmO5-*JxDj6C;kJ!uE=%d9i)HO1m;3<)NDTVZH1ofY3_
    z?@~dktD3M&J3slv8WF9;iU+{?nk2FMW}NC_503JGNO(`-eu~!j`Gz7BvOz@AT38e!
    zdreBc5yMa+uTTDUPCCIqS=9|h2*xTWS7^3r_Ve0au4KWKF5FasYo+gRuHSIJjH~#c=}hXpX2tVCZOJlR5jkf#iR^eDpKTbmM?bt;g7k&f
    zENV77A=GPuZEAwq`?H+qn{f$^=nqs84E*r|>V+oG7Wc!~mk~z~QM}ZGPHtt&D?S-$
    z_liiYGpimyN<4@K57tm6&As{MBmc|lURYu%Gs3B;&83mLDYl0vwNk>ShH>yj*9W!u
    ze1jmA2Kc|ZEH`f0O<$eCFF#M1*0>45TedT@PrrutVpHsPHj2}{8PK^M;wlpMUR>
    zyIXtF{BTECt1(X|B{c+eH}@VUzl(TOGL9Vz5h%YuJvO&;`@RFjQRWL^!9+01%}$}F
    zO4kpyTdqRdc+9hRp9-_Dbt{Mwa-ii}+~sXCg}2Z*0O;Rfj_0iH`FWdcDmk^qsLuu2
    zt9dE%$DJL&2f8SYhBGu_`A22+W^c+g-^&>ZyzV&#p`71hgSk^E!q#IA`HNN`gsyPI
    z$2UL&1BUG$ZdKrH7s)n(&wX)6*1>Y#u~cvvf?;c3TP^quq6JBFLiew
    zK7{WTKEx`v0`eV7emdm#4Q<8^xW?pmz3)h*QmRX`Upu*?(E(JDpoMKZ(10`Jr$4fZ
    z<2~Xuvwj?TB>#osmFZ~xTIzSQsAl=~gYkEaJY#zg#Q4w^$~m>Oazq58%bt9{pBmrN
    zKd$2v=(Hzn1|{oCQcPP9`low0w8-CzWAUx(_}XYu*@t0bhsA+~@mWzJBI#
    z5-$oNGgwWDHe@nZ!@(PKIj`&oc{W#DShm0)gFP=8vsEQTC4*lmV?pbo&U=?qDPQT(
    zJ1cN87xMBF%3&^P2fX!I8Z!eIB<;bcAzuG6oQE@G&i?`}JBm9yUB(?Y7_3kDaaVaZ
    z3t>EClMX*OMQjY{Bppp!em2p%oHdGMU_}3F$KhBST~sUG>V1^(5`>Ye&n};`HZdxV
    zx$S{C<$|M|uD=p1_hmn=NgE^ROt%-|!xN;@LQv`EY^Xorz6IO@er_)F&
    zV{5Ohxfw%xYx*BkTT)Pl{W{4B;p?+0DTRd>0%Z#x6fd~>r|q%{(NEr-@UUPGV{vGfmxs
    zUS+gw{{g^h;Sj^ih5^COFjeY5CU278bc&jJj>Jp0qN(1EzBrGUZSnqeAV75AUYy26r-HyV~j=;G#
    zTD6v1@7Vz2$d8e_?(47Dh@h`f5*d33x&Cq!(F6<8N;~H__~~9D?Hfaob6s(JNhGNlvmr4kUYDu@Btx5cq5>BzLH*B
    z71$NX#qhMgM1IkVD(h-%TZBhiL=i3!m4o3UF*dYE^0{6M7Y(nlksvzw*DS6=;w)Y!
    z1Sv(3y{+6M)Rg%?M7PnNROl4bZMze@jar}qz}wsV^*&oH5N7iyl*PC
    z%Ye+%=26(;Uo{!qT8EJpPoYco5lV`v9;D0J4Of-!T0O6cyIkL`&kyxKc*y}VX22p_
    zs(jc!X=+ufWiEeHQwC7cXy&6@?hGRfwVN)J(|0WYq?3UZeOCIDqtxUV>#*cAA5h=p
    z-`g>LG&4nZ614Gh9l80AmBhD*IQ$u31~XdB&%;bCn=?UcuojP@P3biI!Kj~gvUT|N1Z|nsdQ>6RTB>^^Po#?!Q@4y{C`hvu4t$L$fw8f_j!VpiT<
    z-ZGTk7!LWev~#?OSsA7%iFMAq!?~GCtFz<;ldAm87DFZ$s)pbD!NIz4aZ&X#x#z~!
    zbFgCwZN?M;{@k>QqKz4;O9ZsoJ-K!rX<>B5*-S+7`qTO72yz$zspRCmTbHFv+SJho
    zg*X$HxDb9c$XIiWf1mGI^!n*PGmsae)Qf{Cq&qEd2WHzOBA2r)-BK~T##t&r8)7|g
    z+&W%Z{
    z`|g#aHt_Ejd!+>S`b`LWy5hbABow|LSIiK$uBB7t5<%Mpk55p#BSH$8iIDx#Fm?Lb
    z47IIG=%e?lSD1gvWS&=b20hfmTEnVtf9VqOe`@d3{~?p{wUX{)R_
    z>q9XyAnb`wL7rbs
    z*IhtWIl?q`Zk})~%TqJ6#%47qXTb_Jyph~j3%y)3nIOb
    zW?pv!v6M{#SZ;8{i-c-2-W?IcOOe7my%004K9bnaj`|3h3&1Q`!eWmnNJtfMU(YRW
    z*-ZuNpVa^}3|Xw++}~0VT@E`Sr|UT^|CB-vi#*}ABw>2RR9@IySXQw??1|UWp7x%u
    zASgZfCtA*f?lUM)s+uISm&f6sop2aLPQZOvI)MwA(1Sflq6r0=b0*R1E~|d}qUa5=
    znMfABbj#fT+WHneZ&emGf{7fsX``p%%NRl0nTzR}hup(9p)CzQ_s&xYw
    z0P|pWjT;h>Ma2QvzfFUGr|iVj6|Vfn485=1T7gjge^g7x=xzLpXgGa9lkF#38?|%fgX{zb!P6lQuEJS_iAi^b(o;uu*LX<
    zg04m1CLljP$B>q`>{@ZR6B%MGSyxMK47V?KOvsO54nR;HaSd*tnLvd`@rhi0krh=A
    z$JPS@CPLZw49(Mzk2hgm9Y`^`Ue&bhJdGO*3GYy~`$DQ)-B=IVPqi@xsoiYEvDP3B
    zvH44y->P5rVduubDGU`nnh@@^5RsaV;s4G<&wRX(S!krt53)=f*a}Vn_Ld8a`+bj$
    z*kQAM`qYd0Q{eO6Q!5V^+^No%)@(0UcH+BD?$y$#_Um(%y7L`vrW`XYQ2gAE)4ejD
    z^i`7E*oPvM7P?nD4nH%jzLDN5`X&!)Eh$NOf>PaJiQ`FKz7Ce9gu@qaC;xpuH;c;qbbR3d^X(6-GC~*n_It~`6YwcEYo5Z(+AMb=
    z2=iZ~18nfpK5^Ar_;XfD09w@AdcZdZ`*Y
    zdR~KYlgtV+8G?_z-lg$tTDH&?EV@)0N0l$WYRQ8usRTP{eTukNI}Lps-(_N1Q2XKg
    zo`z3>jir9ah8jT?((9$7e~>gvJq&#ZYRqbr%Nr+9OBtlGJCULpZTNW}zY&dp?IPby
    zO*m(eFFnxwMJBh^L9U1Q61r{X3K*Cy3;7}PoE%d~x!4m(`4-I+uo6z1cWzx&Hzi#A
    zdSmbW?vC<@K3RKSmsr@nMjaSNP!EAnVCUWXWL?^Eei>@?;OnQ*tNb;wa1?>LEq$M5
    z#?v$ObLDn={j+&kn&kV(FdHxnv0*n82kXK%*ohpsnc*SjL56^b;B9A98re>3)MhAH
    z^VlacQc~CwgH|WeMsz{C97A+$hdi{8C+YkLLt%XK#-e|>6f|X)yJHZNZDp_&`1+Qk
    zWo3(E{Y^nz6FVh|mQ#XPmNLkd2W1i8?{$0aRAMjV*xokZtM&WU)OPy1JD&)}CA&&r
    z0d<`IOUeChrADdy@C$aPi9hC$O~u5dSoC+cY%QmEwSaeQ8o0Jor}JRM@35r>&VdE>
    zYlEMaRlulcAoGa<4#~`c+q>QN;}JwVCpzTdD3ekyL$zm(%PvE^lB
    zxDcDTgA094-%(_0{rhw?r-4G^0Yqg>PY|j-GLby(Txg$|z>%SoBL`VA`e;{5@54MI
    zziGAaWexw3W{%C|;#{0*`VjqJQTgaH
    z-?yS={(b)Y@RytZ!uOk$ndn27A|ewuZ{G#Ib9i{p@wmaL*DAfZ1@I~AWN9po?a5-0fuso&SjhEbB
    zl-=9@&v&*xlR_pe|d1V?9-_`|G^c$bbJvJ!CIOCl+^S(
    zQB&scY#biVM_Q;jKN+gR-iSMwpW;jvUr|8|IIE=I|}I%jD2*n#Nbk3<0Fl%e;tB=L9xgk)ny(YvyIPW(zQ
    z@n%XPt9xEY(t!B;@3Nh|MAWQ=L)i0-q6_jU8^U&1u-d|^7a6Q`U`|3#|1Mjr9~=|1
    zv?KVmiw)-bM%kFLFQI>wqND$F(?@i;;!4gI(mioJeE+YgU-?4(<4&ymd}wo+C!%yv
    z_bUk7cj`;S@`NPzV7q=xe${K|z`v?+$nq)Q_^MqNpVC|FSlNokrjaYuG1uN-QvzIz
    zD}sk!)Hd#4)<6^5D%_6WCy-^txn_0jwh{L)E5m5Igx#GCJ^prMa!%5Y)i|yRS5VZi0mF`gX81-{lBU`
    zx9$XgJ$8GoDT=XXW+7EFAq!7)ok=Rz5l}>|GrT<;)rCE0Z!7>}%INAD6rPN7U;d{5)a|4AuZNj~yWZ
    
    diff --git a/mods/photo_album/skins/pa_next.png b/mods/photo_album/skins/pa_next.png
    deleted file mode 100644
    index 04328506acc3c7c386ddb1837f270f68bc6001f4..0000000000000000000000000000000000000000
    GIT binary patch
    literal 0
    HcmV?d00001
    
    literal 28513
    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
    
    diff --git a/mods/photo_album/skins/pa_prev.gif b/mods/photo_album/skins/pa_prev.gif
    deleted file mode 100644
    index fb55684e8a6e27f19dadc256a8797a7e7b647c57..0000000000000000000000000000000000000000
    GIT binary patch
    literal 0
    HcmV?d00001
    
    literal 80
    zcmZ?wbhEHblw%NKXkcJqFh2AD|9{1wER5_7j0`$J0S1r^1Cx4B|H{*E`4`U-4&Zo`
    i8<~H#^1fhKa%SC&8B=m@?=AS1W>oR~*EwZY25SJ*%pDN`
    
    diff --git a/mods/photo_album/skins/pa_prev.png b/mods/photo_album/skins/pa_prev.png
    deleted file mode 100644
    index 0896fac0f7e870fe5b55923c722bc5505c9b40a5..0000000000000000000000000000000000000000
    GIT binary patch
    literal 0
    HcmV?d00001
    
    literal 27892
    zcmb@u2UJwOwd=Qi
    zlwpSHf4=Wm?z?xr|6T8`ce9e6oAaU;lc@#cJ&_Ch()0<~aCx
    z??qP^414lTbiCx-#uNLI_3euwc@P+OhW<|xaTaW$5QslGuYp`9Bv3_1MCqUHkcr33
    zgkG%a1{e%_1@I#XN)z2Ki*=NC>=DQQD+vHL@sWLpe34A>IfHt6`6YvD&W=hdn3Z9|
    zW%}A>_aSRt5$%2i}Nzp?p|e-$3v{
    z&!AhgW9F-?lL{S+yGxpx<`;EsvmMzyRLQyPPv9wqBCiEg^!mz4vm^8cnTOld(Z(q}Z$`d;MPYdsDsZiPlti
    zU%AEyZtle_y=A&>{?7hmUiY6dwu$qEPZevoHv1_&cxH^J3oNGoY=xHbD*__i1HKvc
    zk%%~6;c!l$5YSP|zZJb?e3f?gL%U1Db8E?5G39KvU#TQBwJu>->kdc`pC88G*g5EyU&S6
    z2!5pGNSi2h&Xkzk1Ps|6aam*@6+TQAzPLL}Ysfo&FaGu;+y22(Ip0+F+UZvvOAfdZ#-T~TqQ}M4SD4@
    z!AE(5_jA*|W|1kn9Zr)!9(Ka20lwy{^2yn8k_1I!6f8@Z&cz)wpPu3#KOOVaB5RkU
    zCE(;KTl0XJxgxjlXhe?qxHHp>zUejwFXjhclA%GlO|_a%bW~$JFL^SsgQD^0;fOap
    zJVQ~bxkb4)HXQo
    zpC51C5BpZo{g(MA%Q>UuoPNfQ-!^QWscPzdHTm1dwsh(1lvio8$3LjgMN@(cII
    z`aW!GIB3PQ*<|Wne^fxD8&;KuGG>irkPT$tyCiBUXZkE%Arb$*sPwJY(Q{Cya^uzA
    zC*{`7PnZi}zj*3+swA$_2O)pAmrCyPb^oH;xVYb)1m)B2?{;6f>5idf8=AdE(^GSh
    zewfJ>`b>(e_zIJOV&1Kf`lK^a^s-Aupns~y1Hqh;cV!{dp{%I
    z`^C1?7A|i48--S9(FkW|kR>JD6bOCIqgI!oq;oyhB-ZN&kc&#=OM%48gBJ$^FYCyqpf=0vzJ4xEA{G|QR}g{neJp)^v%EQ?M2}h
    z)V3pgd*!&hug%i_7JpQ6o3w24ZfEnow+#u=kdq(uEWI}xi*HeVxu(~^Z8c>fq~w?yKIH2e-^Spv0Pl4R}vIFL#Ahh71`1=DLrS)>&Q%!R0{U|Qeep}*`s6DrXNNnkl;+^4(
    zLW+d2J#xhy;Ipwrl^DOZp~QRiz8exteg;c0KF3orGh=u~V9d*qBJZ
    zc&}0TU5W?zmS^?dHt2%~sq)7CLnvbD3y^zG^5-a-y|6hvoS917z1w0O`Cg(U%i?2$
    zaW^)3+m+)J%S{euz1U_iIkZa+!w;5D?t7gQo0HL7Q;&AveR$4kiF{n;DimFM#^vS~
    zRrNzWT%M{)v%w@)Q(44JG>&e8$B3E*5&NgM{M-Da+p8MN1x~--G19z
    zU)yi5!;usXB&#fBQpX&WRasK@KYZTA-KHvZBo`3M!m&**;hIIFZlo)B`#E*W84r({
    zlg3dz<$;Y(z#mYG4tZdd-bB;-S|NXS#kBB@Lt*E{H!DdVlH8P%h+o<~9U}0ESynw`1Au3OPFu&WmmTM{WJK^DO0@d_8%XiE#(x1JIu;p*OQ(LL#CFj}x
    zm~vX2Gk*YZPmlAqUPA)g?>{0fwj)}s^;{y#_fxMqZjSM2lFyCO%%3>j&HIR9C)xPK
    zGCaR$%(sudpRW6Ibil*)y3hOPLFpwxzjgs|Lm&FCdS>~)M|B0o?b{q&*OzH>-&b`J
    zQjfFcT6*nv%&<4UUnIT}jrjFFH%d*~+h<5!)A}$z3f`GqqDJl6-@-9KGApGu1KIpU
    z=7N?Z|Cw8>?&Mku^N)M1qh{4>o-O(5#}nRPkwNyNZ3&4KD>R;7)Y)t*lFwNhHC)DB
    zYp6AH-kr7u+*d3dgGfnuf0^vJ?|*H|YaRE3YMawJvA?#*&tX6Ko_Og&W@svaRyf*#
    zvh<>`vy(cT{`~NI#o0>jzARNU{aSXQifizFb6Yjb2d!;;lOZ1U)l5%=-HRUU*x_4&wC^$o-btq
    z)SJ2s_E%@L)j18w4^@JyMl^E7rXW-_%t6auH0j$^kEbOkMbZ!-{Mby3`MiEx&`ehw
    zXqtk)CY;&bvXQ@Xd`cTNFWu63+r4IcS7ndSBc1GhByOLC0MU-8D
    zH}~w4L}F6gpO<;cK8Y&l=AAEFX%$|NtG<7D
    zp6Z`Al+xq>=Hj{fnpnACQ!Vy9k&b=hidC$isEBaiSd?GNlgbZ8CP|GSxLbME>$DaV
    zmDq|Oc)kqREPwH;{^hp_u&X(5_FIvp{Jzv-rjryA1Pbp{yF1gm;IDx%TSHp2x@O-kb1+%)uf@~|jI_{AqHqLuK0fdfK*}4{CI|YD8)lm=`LgfSI#D|G|kPf4*2nzQJRw>6p1DC3fQb9oEz4
    z4My*+M=V(J$L?3C3Qh0`C>7WUlmZ1S@&?6rc$Aob!Z+sLO^
    z4%O3d%&WVmO?Fld$`ncbG+Abw*{HJ>C}A}j3M@Bnn6q0d;WACWzYMQL@4tz>U3hnA
    zVcm)D*XN8mrWO|ylMf^eYa|S@OfCWz^EVv@jMyCw9aQ^QKJLU8DmMWimjzbL=N^XC
    zQh!2L98QJXH9D>^%o_B>G{o>ViP!Eg2x|=0RqbZfQF1lhurivhP7cbfN_En$cp6ZY
    z)gf5m$CL6Uc$0Q-o9Bwxe03TBBW8yeS_?HdUya<;HhPliXSF<{^hQ>)XS%otAVs^T
    zEdf~m#vwbgYb;YICmPhzX{V{aNf$JCeXNGzS#DD{Ou^PSR?55N8_`Z&W{lK$?#0~U
    zV@bqyeAd^jc#(w9AkxgzsEg@Q5F1K<%=*J`r
    zj<(LT87|V=6S;hn-d^wb3zz60d`do<#$Lm;1=Wr(5R`q4n_3#+>MP0=B6XhGN+6ZVcgCa<-tQBSewj~RxT~F2h=^?{
    zAN!QFo<7vGO7eC2>ic-W`*fIi?NP{QWW%dlR+&74`Ojik8SQ?wtWVp46uA|qBRf8M
    zE>*MkoJXwpy+$Xij;_0iWNAEZ{^Y$9KZjgNM&YWT9u=MSz}
    zh}F#hvwp9sIm5roS=NMUPi|Ivz;XN^^Wuya{=xFf|!htDKJZ%WPOX1zq!k
    zztLX|!>T4MH^y6rRiM|I%@12koxE)FzHdsl$Np8Uono%(FFe?=H2si!kem$s2}LkH
    zzgOK^MfF5V*tk{hU)0CinZ;W!(dG|^ZRt-+I)MMB3RSx1>qfZ*QU7qL)_po@%nN3?
    zl@V9@c~83b=%VjvB`tefj7nAp10QaIpK-=+2Ua^K-0AR0^v6iH&m%b&N>D4
    zC;r^KG4k=4aH*^55`<%HbWHEfA*6EB(?d9fMhj`R4E$I(a)H{3a)_!j_y0MMM7vw-
    zbSa6}y1vg1JpQVugoty_J^yEi7*xFbMTdE1t&=jT$&BZJ+^4mdcA;Tu$L|uz5V$W?
    zY+7D0w<~mAytDs#_KkpOL*oc`vDz8GJC$84*QBR87LRmCzakfeob<}S+GM!G6J@N=
    zOuq4JS;n$u@=f%3wejYCjt
    z85OO9VT}2~AhE?o(6nC-lA@$#{_VCV5fEo}Dy?;T|BBQ*AF_hggfN=Hwb_qnuLC$6
    zS1d^r&oJYr$F38Q$FeeQPk#PRcc>#!$nGaf5%4-Z
    zW5o{#jGNkzgPwEmcse^+uuaMarJTLe`E!m2Rg<1a_HbY1Y*ua^;3Y*dnX}lP3S1jF
    zcscl|V-}wtiFV6cK-|<`d=MpZ{LoK-{NMosjs=!^i59!3R3(?kNYQA4#^1|?bh?jQdY_GBG
    zagpB#6^8^_c2!Zh5?cP&c2$^%d75%y?t!jl$QOn?o|XY}RaxXt4!jHwM*N!iPkl;Y}prC{}?
    zs~X{Of!G&;IJ5rwE}7^ok?+mdvjKg$0P_9lnxCW{lX*<>-afg{>}fxn!kEf8Hy8V=
    zS@vZ+Q2PnPFZN(fW&-qqw!_xPatplqiL$av%X!{eAH%e`UcGZ_U-1`d8z@yIg4fhb
    zJLP|ltd>8|QS}+5G}8Psh!sS0=?XzUpQtGI%#zJ)@8^N$cQ
    zWuKy2=_bZ{r>E_WOqliloTP5t%9%JWY}+x!TiDSu-csU+!OFf{(U|WJRvm=0_
    z)a&sNjt`+fa&q#><5GNYwNn%ANlo63_;yZQdHX)rpva#AO2wQgr}+K-e4nglV_G;bk?WHD9%3-swOgzZ3u;S2l}@_I#);g1NZ~xqQ>KG9?>ZXtUIQ)fpTAmX
    ztUb$KQJ@yfT9e&gOtI>uER0aySv@SLAuPuGz8yHR1Z
    zk?1hjq7l_P{-Atjz1c{Z(C~3?G1@_We=+?TnXk?U<^G#gEiTJ_)e^>GR>m6$ZO%CJ
    zR?sKU!*p9G#E_vVp(cP8#7^cl8|bI)W*~1L3<`kN@h8bR8MQH?%d54(9pQ8q;e7Ep
    zGe*-5-A7yp&3t(Ntiw@SnR<;|}6fpKZ-_@2ZJ%O#V5C$(U(%&>lyM^wxv@VlBCKA&MEEILz^<
    zvU29_-H6<__8+6(5kIr50Q|xGyO|dIA0>71+jDEYwBx(I3=%k7N21qH^jK)<^bo@>
    zNx9>!@jK?5wZF#y`{Nn9fI0e<;I1}!WCY92ke`2`-G*!*O7%Ou^WS@#s7hDcvoh+}
    zuI1ke6TEemqGL?=>}K7uDa*aOz=P3~8OA6b)7mP5fZ6{3UB&aLy}F%53!Rz6sP$_U
    z9e}CUjB8X2DWBm|H}SJ$n_Bc0_QeDsKXzPZC+Zd%c4ChZvhVcvp3Ez`bUQ825cxo@=bQpdpBTsm;Yt<
    zS4nnJi3hM`*uUfnEJ`Izk6I`BbuZ1YNbWb(I{6QQYRa++>#|Kt=4m6WaZ);hzWI`u
    zp!NINribdce}MrzPoUY6n)|=NpR40ZBdomt2JWku6#gdjH=rK-U#Wldd)Vji(Zu<`
    z0UJ+YLtC-;|8IbPFHIoZ$;&6}QJ1NIw&E|2|7QEY2P5kq16F_W?D(GxY=Zw2dscj$
    ze@o?(Z`!{r`oH4uzaS4}bEnC?`42#?v&nFB`Id_5Qk<8P|8HdTzmwPB*K{IW{!MTA
    zf9a+5y4(TM)?`&zjaU7-^DuN7DNhIRT+Lh{8D@QsOn^eOA759`5mZ)-U_c#7v&ur;
    zW2-(!{oHu{vhI*&)mdio&JDi^S5{rs84J*rp0*I8$b}WX)vankUZO<|LTAD2knnup
    zLkWKG8xNs!SO-y4j$_A#=s@>+JJvk40=Fx6@NaRcG}TN~la_hE|jyFgtm7lzfQTcPKU?O6ptRneo^LaQyw{
    z8WRxU_ijaVm0oSWsGBD2@hvf3#rgjI2lp$``XBG=v$BPaW3WFX!LbhMY+b{l&QsHK?V)`>WIY(x
    z%^LizQeSB@i6j?*kgV>OUP;jKw^QCR3wqLhPkc(s5SKo&@RGwm3%
    zpN@F4cR2ar>H7xN;7m^$A91YD&Yx^-)xb0=&7lq6fH5VR7}qtOBJ2mhK7n+9_%g3$
    zVy0!XbbITzmRwfC7OkNXjiFJFvv(2OCLC!Zkz_vO?{@R`MlOeP!;c`o;kR$M;Potx
    zdCF9a&TSvqwp|>l+P=;?2F0hF5Sa_7I-V%lX%{F&=sfT;Q%bAL)
    zTR&Hk8);>xj}ck~ILKfkNf|j~gHOcX&IG*#nXEF&?b$X*XHBiAh+Lq*T#UV|w*~
    z_fbrK{QX3gH)<~NS-xjS6lz1pm8^??qQKd`i2R%Pev-sv(4Gw8@Bi)nUbO>=ghlv3
    z96OP&W9&LQ_k9?5ry{phDH?
    zcA$I+?$6w;I^l@u1i&D6Ay8LnJ05qsH3Go=MAFw)p7K5s8sB1oC1~T#Di*+13$ExS
    zpBz(r6U*7E_h9w$9D!vcM1iJc%6KV}4+=1S!r=W32*HUS;W*Bv&_J_r
    zWs4bkuxTlBdQrKv34Xe%1gN7-@T{Xn8E+1Vt;)Achs%=;Tgg2=m>(jR5p>YLaLOJ3
    zO$$J&00(5Do*zH@b_g0kvV%ijPtfR#GgN{y3BcjBOv_g&|c<0W$CBP
    zFaS+b{S7H1p1BIajZc>`Y-W3o&En@3eqTp+4jstA+jeR>$EnEnmQ>VP4i5b1BrYi2
    zABgg9?-guI!4bm=XLM!+M9q6}PhqUqW4!O~Vh{bM<1S|oI3DvzVcZ;jRSV{tA8i(g
    zA8hAe6gq@16r`Otu&?VbDh@+K#MwO+c!Q(H`I|VHo!Spz*$9e1c5gX24}7k}bYZnr
    zNl3c})&)wG5-@}A^ypwd!(tffjVRvuTtU3*{jqJe-B}?vIM6(LLNH`7c*4gLMO2sB
    z_k+2P+NmS=5ys|;D>eH7#roZ=f(NC%8EdZYfETH_jwFR(sJ!9;_ARJ$9GZU0Er280
    zoE{?bv>7ERfRUK2>Z;c7h`vR77-nVn1|n*ayt%KL!H3YF+yUO-)X5&sK)fMjL(n}0
    zp95131=Huj1quRqU*zFd-Hh|(Yyv)5R&~&7OXF)w$J5}*)*|n%6TfZEfR#cvHUmPB
    zFy&wVwUy~X7EV^a!_G_&`H9i0gS|fZq(-a#J4G8Upa<7uXJ#GqplbGi3EWRR10OV;iS0!05@BzL00l%N
    zpJPNpkq#>}@8Lsim6h-~%ZQKhYSN!R3Q8i(jL+v71m*TY_&hj2`Pr<1dW$|Jo1xoGX
    zSYGz0jk99)QW!Sa_#<9ot*ET11%zyoxxT5}@wm*|32g=Fdfeck!Izc2pW34=*^F?=-JZ&b+wG1L=0qW3Nl8{{T}CHIXG6=
    zO)DgO4T$h6;6MS>o*tK=bA$@;Lq!KRJ^nNB02^l06d*|Wg=@j*;HK$k`W{YJP9Ek1
    z5VxC_pW^P%oo#lVsM0T4DPtgkF7UM^U5x$R&jIGp7Xi>
    zAmA0N+oozq3XY<3L*sy?Y%Y5|a4c|s2x>D3r@&^arT`M2itG+7mREw^D~mGhy`638
    z(~{&n1UqI4%fV$8WBaGs6(PX)2mk7^-Mi-6yx9_1anJFetX{kTy{W^ZWlW1=Wp~{c^cNgUdVb%v&
    z`L>MRb7S>`)hh@?zPHkI62*Yf)r)}bfyuaxP^%8}!kX$_zdII~J*SA%)*mTU69YUn
    z5LO5%pQXA+Iq==9Z>)7|Duyokz(OksR5Y+j;+IMl}fph0uqA77%
    zoe+kP4;l9q+_<-J)jxZZ81EeVY`$J+=@3pEq{K!nx5fcaQ5Qn6i+QqiLe~c|!s1ZJ
    zpg&>x0&ei{A^%UE_z%q}+$z}nnl3Gb>KZ%Y$=vu;MOCwPP{-zy#_;jVU8sk~TVi^h
    zrwCxZiU(S73Tuv4-#=)eYnDuojpmkLPkgJmp4xh6T(=CXi)Z?fx4Phth|M|m^^2l7
    z_<-U~>exSOv>et5N{LJG8K>u1S$YbKoz-d;zw3C@24o{3GLQwwh@nAJX=kho8Wyq2
    z&G{iwQm5c5U3gW6aRo%BNiuaGKux8suoWUBEvGJ<2492{as>{&NKTr26aBTHuP_hn
    z+O-f~5Ms&A*09?6^|!+sdug7$+`ASUL_4#Pb(lzSmiS@tOif3_8l1O@ZOO%4rv>Y=
    z!fL@himGvl2nm1Ka1_Yyw%xRj7LoG(B%aJND>Na<0tyiDIh4lo;RlF$XVqGPD@JK-
    z_&BV(aZ{xUs(g5_?&mwMhUnXeQ~6F(abd0ZU@3>d`V5xYN-(Dm*dTy!r^|q-AajJL
    zL3_r+maH>F*nCb_wHvY`Ugp3go(LMlN}2h5q^JFDWDpmUBf*6syTs+7u!d^Bo`jV!
    zZGsdaZ*{pdI3-Z2AIRx-qjEPL;&&9kFbKRp<
    z#djRbexGg8gpVG_Mw4awxOS$vCysOy9p2kRw#d_ovM?Fg63q+U#+>
    z`~sm>VGMCE3|ZSTZD9$F^Z(wOS8+P#&qQu@eK6p8N6`wR1(C2KGkxR>|5{r0X+SEi
    zj3!{nGr*`L8LL*2eRgnWcxj|2N+kL51;er0!IeisatHDs3)sZZ|8omi7GBCQ)<_z6
    zjyt_kl6T40U$P8Z?C!}!TI^mag29Bhl@1PeE%tZs-JA#orlobg6K0^i5&ExaRRM=N
    z-`|3PL4crjX;cYp-Ls&K#O4CkMbzCzePq(08!S-M*QU?B8
    z!sZ$RtEw`Ctp%n4bh;#uz$e5gi+f)oG*RN#)l6#n951J&ji-drq1@lv{t
    zZCCUq0r>bdvbBlcrqn`>9&+x#_rso3NJo_w5rB&UmkPC1kawuMp`xOg*b06LLT7zK|uHS?5HX39B}tPNI{&sU`%{I#opbn$~?p?a7V
    zqR(DpCjdGLh7d5Lv}HJeq3s-T7m(BXd6cl{TC8X2d%zN47(6Ms9x5~;UmWsT*3iSJ
    zSy6uYfdY!wAP0|*2aiA*iSVcNjeUe2Sq$g-(PjZ51s}}1-dX=gj-X=7aoNO>@G^w%
    z!gr;!T%4cfUCx9$sb!>re-nK>>0V3dI7@pu|eB7S+
    zk^3_KQ9EaiLcoN0>aNoCuQ7Z2K{#?i;Zzg1#W*HW@nA#rK*v%ycmhP~eGcDqWrVV1
    zvSsX=V&s4YR9=n+gWs_iTAjp%e)t3KV4*&_6xDw
    z%=)j#L|PJ+whS0Mb?uUC{K_XOaP};?ZxPsSwbfhj7HsYQIq-u4VQ-!mH0Pck*Zpg}
    zVyAK48UCQOzrNJ&$#}^ryMb9i1I`p(tNMIvPL9T+h|k0O1Q%GhuW7h7izAT33oC9gu%PU##=B)xpZjTB?AYu9h>dKsK7acq3#)Ad%=D@2+Vm4S
    z>O6|hn(ng)XTyZvLw&lGnrY*Lt91${_t
    zM%wQ-cK^@N0BW6AC{jmnoWj3)-vE>J7xyA7<2F}^c@1quxqT~=VF`Asb{Vm9aCJh3
    z#lOeqt={%XboLi-4##u@{t^uu&qY=OjO|Z?*e4e@Py?1%s7)i7dvfTpWckr71okRVo-Bti
    zE$>8e>mZrREd#-#+Xq@Z8&tI-n5329a!$?qOGfuFv8}z#2K_W;2hf~`Yv!XVME)aUgz*6_5{K19=7QUht*aixEnfT!^25Yo+5LyJnLy
    z;~?4dr`rB~WkJdk1V_w2T7vqma9%M-3=ne6T7t-L%4ULzaxvox!P=m)trmvQ<6&qZ
    zDI-pP%X`bnzudZPxU8ab$~u7MUxVk#&XSpekz}W8Ug8LZot+fCe#N*2%QiYI{RKY-
    zeo1RrinMCCll@LHiWK3iZv1pKKZ_@F?;F+8R*AO(-Ch2G0)b>6JKnH|zKya|`i_Wk
    z!3;Kp*$=uVNqQkAw%d>Y}^(IcxYzk4Rj8}FQ!BI@`yzEQ|_4HG%}f`v8=d?l5}-+Z(L55qSn
    zgIYvIA5b}`dYDNVNJTsEL3slECUe|!GTMD?mbR|=PVAau%P@YG`*&1};dP^!j##KU
    z5n82SCv(mZbAe8^U0rbXm25VzsF{MK5GujY4*(Q#@MuE;GoWL*+bV}{G?}+N8}BEw
    zV)HmVd~9$EYdbzoGnW%VMN8ENd=eI}g)w}RNp>mTUaT^@zd9S4`S-x+Y-2}luTIGIep
    z?X0muu~WL?W6(cNFt=#2uhnj*TG?tex_n#Q!dZ**i``Ey-Mx~q?EoG2>ODVTp>U^&
    zsgWkj>i{duP23LPnhS%vqj_Igoy;1O)+zU0ZnWGpYAc5Q->BjRa{0U|d8jnZsIVW)
    zUQbhV7c4!o_>)`RVNrQddE&kx=X_7jKS<;3^unjF)CL!|XogSs82py=jI<6kz%Cb?
    zbrNW_*N9nuI)%kv%aM^=ZrD2YV_Ddzal^{ED#~NBk_XdwZ|IxN#NzqbUQ{LBkb45p
    z7%B})?@&EfXVqzZF}!uv$Q+$Y>lgb}uqFdu_k&8xQW-Q+^=tih8{QD_K0qKn2MllU
    z`b_b_iZ^}?Cj^5JI!sl!uAQJ+eT%a}M+41QSQil+fdcEHu8204B|TPaNQ&hM5IznG
    z9VT3eY|XIB*y}$A`96V;`(h#*GLock%-m=$8W^yHl-DQe5p;4l$UH|6RvhA%_nP5c
    zCNZWVmLrwcyK@x{`6tzUIoWe3h^A3r^Le7gKRfxN<;OmQIe5vDZT|38w0C?vpG}db
    zdFeg)_}mvbsq1r#IN0wa89CKAxit#eB)dKbl~r_eGO{Q-g#VWY4p+LkN7_eEnPIh&
    za?;R(*GGmMw4^|9P@Zh<0Eg`3Qe4NLs79$j&5K`+3_|qiXQ_EC9s|7ga&?3!LP6uP
    z7V+jIx=q>>IZxeVRhw?c6!^;bGzD&@tWn6Sl$@WP#f*0u5s_f;V{5k!7V7dT1qCici3RGxM0EqVN?
    z$wIl0CAE*%n9Iu(N317<8Ti^RaNsSbAkEgW^YztpVI;BTDUR^h67?v|3E%L|=2HWr
    z0v&579aaHpKB@nf1AJ!$LGg=@=xivIwk437r?p=FU$BDX+2B%PM00G=SCEmxrj|{64%Uqa}CVkdUd8$3C
    zo4bjP6=Jb)kzZ|*dNM|h--n5g(UxG1NpSL6xulX1*>YFTNA!*|c=iW-8uxdpJzoWY
    zhRl?o^r;{7ar1TA)Po?!da6aMnqF{Q1#LtT+7Pqqzur$v)?#(3#1t1(WA)g4$0U`=
    zSW-^iD|(KI=GZ)Xxwu^sGK5o{(zK1ZVXzGn)f5RVFFk#O=V|z}+cUDZLT*Ta+6*I2
    z^jUKEzdl>Wvcum4tbdl)!$;`v-ojFI4Nz=hIzT65eLkiPrZ3OyVELcH2SxC2ez
    zmCfpbUjWKYAA{v^09#_LX;3&3MRkty{2g%g8pg}0x^wwCSXW7Kpa~>wT(q<%!$qRc
    zfk5wuH9G4U_qE;fLc$xBJAA=tsOdl(L?#p!Rz-a0r0_4T`L9Xtul>X^YK=N@avqCF
    z=nA1BmLc0}2Bx6))bCt1k^W!hyKk}I8;)VS8!^YcTpgi_y@r-6bvD}BI~^49w#-My
    zlo2KWRHkn2f*f3d3M~uF)sBFbk(ZbYD6}dU32<%=$K!p;X5d43v%ZQ#iIRCV)quiO`EYgLncE_mT5KQz@)of6mR$@4uTaxjGK0To#
    zx6GBV*whG!`7(-(Zo3FK$k_Y^hwEmX<2|^MsJ0_B7@(XRmgtqOZ`=s>MSL3#5PW%7
    zAXmI(6f`{);x1>I+fL$N(yrCAbOM{7CmkC=rB-eZ#5od3y^7!;^yEagu|Wk>Rbc;G
    z?FGwVoysE{2s(K?p=~h^xr#sb(p=5f69>7!dqF%Lbzrf@*NUccj_fY|zT5=NKBXY;
    z9;zKy63kJVNw6sVx!J=*qmj`S^R2V8VFFG^rd@Q%&U1(<^i0zgxq>^b;^p+$)3M4!12j4t7*
    zWNF#YcM6DDmR?AcU-18S+3UF{RFRJye(w9W(OrH#>;E5H+@IqALtEU;DCd3QyVuSC
    z(-}>qg7}4%tdrV&mGwm?8KqbJdez8_hjmcCg5)>qyng{a1cgEo_V*pt!=RznY-yU<
    zd%Ko;2B2jZiLJ9UPa+0`@eCQcJcu)x6EJ88`1?!!xm@j3mLrH*ELKR}yDUHf;bNIXfM^D6kFeY(8EW)m)G$J>lEy+4jMWP*X3>KDHc-X1<4&>wz{62n;rK^69YZJ#zmb3(*!N!4N}>me0g148$W0Qn^NCO5yk7ewO3n
    zgif51bwF)^(9XuI*t&U??V0XeC@vsy@I-dndURKO*E+)mEwfX(Fib3{)@{F<>WmEx
    zM2Q_f!gpe?*-sYwZQm!_$@V`weK=;(&Ly{ptNgpCfO=^QurV*VjSzY+d7mTg_xoVx
    zv35rcYR0k->0hT%CN+~e*D
    zQX%~1x*d;?oW|@8w>!S!tCz5xmUFVF*~o6urg5P2Bb0@d-R-nMsmH&4YaX{QN{?jh
    zM|sDc+sr03c+`J9ag5RCCg7I|z%y#ZXPS7~iW1tOrlqckViJObE+x!zWx
    z-SHXHsC8*TV288ptejlIQ0O4d%7WPN0QKN*Afxwa-Egfz;rtoXd;^i@dG;hefv9RD
    zuNq8H=p!-$kc4=j_3Spr*b7nO&|8`ihc--hTHuw70R1Aw^9CIY@agdHNqHJnje=*6
    zf820TMg1`Vs>%y`T_`K`bna=0Na`dI5)OJJ)XgAq5l6y2-G0~883kbX^oTo6C!zrl
    z&v?$U%fuQHP^lFG+{7w_2ubu7I6vVH4(*5>k*znlc-mseP``^)p37
    z;RE6~a@gk=SvuH#EvIq4#7D3Gi)Wv7XMwfDbzo8>b-t*MW*wBPImDA?z%#RO0DQoJ
    z=SR)7dDD$l%UTQwQv%u}yx`SVDZw@GeagqMa&>@Ni4H={k!AgUprO=0Xe%Hm7~4PJ
    z(QGk|AMtF5TM{8K|BwX*$N@3fW-;Ih0$;4hV@6T14tz%?h7E!$MJZOy`eL({XF;qG
    z$A7biLH+eli2pNpp{Q^RUDo(!;fXB?$rJkj5bw~d^Ga~>0SeNJU!F-JeJafoI
    zHU4{1y$=)A9?>yg#+(UnAKhb&iiwVnj^WP$=wh>vfWTe!3~?sX#B*2PAP_?STM*tN
    zsJ{&h76+0n)FcS>LsZ^H%}Gw-|ZNCFKD={ftry88LnUDEnn%oD&zUB1gn^HpEF
    zPR4>faVIZaNm8CoO^^~+IQI
    zMo+Vx#T9V6g_6@#Ufc`nvy>?+D!v)VMV=!Sf9;2o=c(4OUyNEx(G5)a52>{R-!
    zG47Q!AK_@!H?xarysQv2m5@R!uAx!8
    zSNa|>Nvk{Sx*KmjEe9>KH(P*ZmQBR1lbb5STf_a`mG;^(%ZAm3?N0Vtp~eiXIPMv%
    zYzRphMJ=0zgx((W=Ycitld_s8pyu^o@eSQJR6=
    zF-yC%)%mm3A1WN|%9A4R&jx)#BE{kJTr!hz>d#rFtc~U>Ywsb6ykLrwH_BXUMpnXF
    zc31o5TP}EoyzDQ`ipZ-o}{5%iU9jbP_zVv3i
    z<_}NttnsT_p>OvF(Mncta~=<*tGCg3U9)Ks97f*56@&l3=B}zK4rYnsEbfxv5G=vn
    z7nk591a}SYZp)&sd>Mv8VX@C-&*ltT&;HLZy
    zuBM&Qlry7&hS@X>F-ibNu1l!bJt4M5_6LYxuIFrv5F(#T_QE9~xCN@B5%?^Bm7!p8
    z8IJ1h#hL{X1hP@?N_xj*#-TZ>ZVr{M5jl>dj@nBA?+!;)mhCR^8c4)L*6@}Yy}|lX
    z-~Hsj`k;aEZ^J$ifNJbD?uD}DniCzbA295s)HAPU7oOHbDsm|$f?ks&_Et9+Ba+(C
    zj--X38n-bbu;z=AgtV(Flqqp#`n~?znV;aPU>)uq$aElGg!tB=7GNDv$B7m@lG$Nt
    zaLl68W<2a%$l70#^c{P@7HGre`uak6Z&%BEQgib=R`P2Fo#9xv|EcUOy=(Je40>>c-L-
    ziGCg^iodV`MEQKkDU+REXkN#|&n+aq$>HjNcaW`hE%!z
    z;h(D!31R_4ptxcpmf?Mtvmx;OC@eG?oat6K^2g!nFTwJ$$O1MP=+B$+8+>VRPzsW
    zVLL;6RtKpbTQGBmJJ`-XDAX#|LZQ9ejdX12k!ET~c9DaEQ2cgG`S0ra3E)4;HJ!Dg
    zI#ojCXRf`FMC6_4v%}pEu1Q0*Nwc~NkBI|oec8AL4T2pdEPpD2j$R#JZ?BovaLghs2MQH<
    zTN&dbIv6TgfrlNC52%RlG?W_{$R_;aMD=HSlta>54D9ywt_m9LQ&xnp^as{ey@0+g
    z#`)jukQ82O!Q-jj@nNA^RpHEcAjpq*KiDWL4|h#II*BTV_C5{DkxCENMNrLKICKX+
    zOrF;r;Ed%Mfa5vc&GKwolt{?r06cqae#kT2%VZuP3Xx=cmBD`plf7sK6K9menE<@K
    zq8J6%eacyXLcvkz%d!8QEXyB?51TKy()=ae?lgW%;1AmOdB@r>baoYBF|^>>>ylaf
    zCK1ld4MDSprG8IH_X+oTs^ZtKtn+Dzx0;~*b4X4cw9!eZUW{B*OCz3RNH=lHj8wQN
    zc0qQ*V$%<&CWLEyW(y3bK>NRyX8)^g+2fK^P7?eW&B(IpFLQ64|1NnOC;zzAO-&IFlzd*cQ;vQm|#lC{Ni#j_F{!^6z
    zl_J>;>}hp0SUG3p^Ztr<&*UkoNZaQja97R`*oc>yjbHpu>>yTlkk(Se3y-0YJ=F)qw8~wL4pt-1xVm1RE(*F(fPgLF;n;QMO0-1i
    ze~h@pWgkGIc-tL7YM5rF8+n{SgNp{TplOF$W<<-8v3MAI7;HrApviI?haF#%WSWR#svOwog$4LWgs91;NBg8PoJ_uhFE{hJhZf^-lN4~%
    zxY61##}^Aiqf2ja1>!sG{zOl_ld8VMjmjg{ds}F77je|0{==ex4zJbU@Lg7L4g2KH
    zMZl`&_k4e_ml7|}eK_c-)5{#g4)8;{y%e#IreNr+40g6{<gC+K_BZYo%#8X?LRpZdg;NsuKBmGV(rR2r!u*@4zi
    z{={b?9<2dX7^9jE9lOS23(&B}{&qK?e{Ua}#GI|xc56PK%31J1PA#qV52hlr)WY}m
    zXH6{eP)~Lm&aeBLQnJD+MddR#bEi6Imz#`w`WMxPA$iMYvn9nl{E6ySc5dZ(W7Ai^
    zA3W)Wcjl!R{anD~mGfQ>B~=dMSYZ4FYLbx_z0<=X-#n7lE`ASWSa|6S0oH<}92n%6
    z`|0Hm)rBfWT~~}mxk|VFka&!n8#Z4Y^5f}o*$XkJ4Gb?!uE&k=wI@g;g1pp8dcz>U
    z+R(;;#J`{-GTG*R(T?5u
    ztkX%`c^$G$TVD^|(G+#J-WoRFNbjKrCQErLLbVEt^9j%cG`W0i{u
    zMq;bSG>Z(MjT%551w7BZ?&H^nM0w-)8^woT&b_IQ%DiKps1KiO;15p;87RfYye`VG
    zld6TqO(o#+3jZ4p1P`og`U2z|Cy%W6K%&i)ILq%>wdUh80u49fwWD$v4e#=)tElI2
    z!`VVgD5k5`hcWAa-Ep+)WfdCEGz{2rrGFg%~Wl7(tLOqUvS~d4J2B
    z42rc4WU97KXDVovr1yVZ(VFfWH9M_@Stcaoph;RFfY(==XCTo(pbL)5-%!>P88{~4
    zfqJVn1(Zp+e&g8nyfSx7R_H+(;=j%fNcd=Nfb
    z-yV@5Mt2iufS=o<=Dl>=WHzw+&{U`&65rz!ZK&npm4!HCtpE9J&CHMmag=&kKT|_4
    zJ>dj?PRsoxYrP1yz&3spnse%l#s&R?kf=g8?29|0iL8M)o{N9Rpe6aQj)||vEKe98
    ziJ4~vF?S$lvq_1hQf^2{cjQ6IZEgUQube3Tqi-(EoCXpcGuH9%Jtspnj!*5{^s49}
    zkJei~|HL5PZNHn}QWu1r71~~;%>C4kzcB`s*`wUzv}cvBuNWtejN5EOL;_th%
    zM2$KQfZ$|O#DdPtDBX-aq#pfc2~p379M)ocXJl3eovq=CFIi627FwM?x2gUHJ?^?*
    z+{Kl`{Lus^mG3LLl#j^oddYtfG|goSE=%Mhe03?{kBn(q`djSqp10)73;klwvC4U8
    zly2g2_(4vE!4|*ceZd1Rc3Zb5f;hcr;C<4d3*_fVpE&dTx#+g@os1oZ@2Z~~9wpoL
    z=@Kzsn<3RfcAGPLscV%aZqANhOUAZ_gQ`zn(i1BxCsk4W1G
    zeE^GDmF2$Vh6J-8W-c*W*n$dvWlcln3KH2#WYh0X0sX}39-#nJia~)jdZfKrT}18;
    zlMp;VRAzjfb9wgP(DvzsXJGARwHcx31=+%Zs7c#YD=aIw!n|BF22R53?YL%*Ht91GVRKLR%+`Z!`s6JKnai{LzaHokK#h4FOQw7IMVTQ7ve*`AOdCMy~dAee5z
    zK|@ob!a|SP*@MCc@1u{^}H~(8_2!PB|yLMmu^1cChtV}*wR6SIUW0%Tamt3Oi`@~iOC3S
    zfFE+7AkZW{L`SN0#w|*pI70n!uID2KSx{!r@VyIm46qHR$-=gz#3`gVx`ZsiS58_1
    z+N~UB_7yhf=H5Jfm2su8pWq%l_EuU=+&|-e2w|1U~wd
    z2-93vhh5nFD<)Qp=_Hol1I|{ZNi{d()DODxRKKARJcj!#+ur3Fi;c?%lSJ#_P>Jm}
    zs`Nw*!9=`21k^g~h5TaIG!i2kt(aJ*+oIdcZGFC!hfupp;s^3t7ic{&Qnmk#b0!&h
    z3l?8Ah2~Zxdv|^HiuY+uE#OpdLhmIrUI1oCk>Q5SJ;`yW4lT>(r6KS10uPN3N9_2i!Zt^xY_p$
    z6saUI;MH}hVcmY}@)U9DY23WpT?Em(jhS=mCA0^ZYNw+?lJ3=ru@$`P$FLwi@VVH1
    z$dorDSclfiPb^MDN#Pn#CMC4`nX6p#kne2hxf=_4Zk_s>zXgfkrZLS2ZV`X>wOiqK
    z^;!GfEkljgEQO5BAkf3oXNdAP;z7kUb`T^~c6V}QY2*HN8;GYW5Xgp&WRjDWLQ9iw
    z7;3*%iL(BX>)1yTOIj{`G29Y=@E81Ow!U#r;-UY
    zc&vya%d9;raQvJ(22>6cVgj
    zjBf;dacyXhTKfD}sR)7$S)h@%s{c2EkD*_7#UitpR;)7PxY+XPDi(31{*EnnbsXG>
    z?-tz0Dz^ag9E*QB=JXD3#Pz$yhDoUN+Ze*a+p6Qju7)(tg1aD#DAZZ98_fEltT-uhGPOZxjY
    zd?LNJgpJ^2eQByG+kt>|pZaFS8%Z326+OT2Iy4Sp-kLfZ0)w
    zk3FB8n@|RKP21%0G#h(2QUUHIjalVKNSKb1`EQ$;6EL*`CX(B)YIhw#DZ#;W-#9)sRy$Wp#W+7JJJR
    zdD0b6KizOSR^iiLTB9yj@Tq>uR|!960>MYkNRTT*c35kCSL;aZ84`o?wid@Vr%Xya
    z`nUO2n<34G;mY#8qn#TXL#%E5Q`44apylcc8Mkjk>Yk_Siojr_kiM>wQ2&FmOZXpe
    z%@b0&t^*t?!@0$?j0BfSC5oG&4}`2%IHrD;(u)&
    z9(L2{*F#g5q$*0{Zn+o)c!e5THaE{hHzq3PEm{plM>zlGp5QwGE4C9;b6M$X=M5^N
    z<@@#l&hrOY-rt#!?2S`pzOi^ny1eM{{Daox-uS<{se=?V6ttY`Q6{2etq4$L%%6Nv
    zXQOLDe~ttcdK-R2sgf$=G{fgDc?1o|7b`4(eMzDi5jSj?M=G=a*uiy_M1{Okgs_UM
    zu7RBRG{n#17N)5RO;1PaZCt}L1-hz9iY|-_=rr8QcU3Fk*
    z5D(Mi+9Kt73%b0Uon0XTc_CG}P*gUSuhi(^F4@OA9efOef(D}Kkl!=-N{KTBKcOfo
    z!kn#To}uQfcOd-+2Xc`UZ1=4W+*VqldH{b<&*!@=i6Hp*zo1{B#HpK~N@9ujIcK*w8ZL#h;H$y&BZdv;hN5I#j`(90FIHYhsHM@X4uZyCzh
    zV(CA2F1=%%8K;Oz9+&~H!}&}bQ7S9Fa~7yg{Fej^C@BeB@#$~ZxGMC{(5|W_Q>+7j
    zmNbpP5B}4Tv#W6&UiK2X&>W_wit0wWm|1sI>#8yE9>2};+x&Q6_k*7j5Mu!>w4=#`
    z?~$igrdsC+Ha2Del})DKYvfEbv(dWivp9dn2}nBbPcdX?JU&cKezpxuKJ^9nKKyqx
    zYKUQ>%t?kZR;H&g+rFIm8WBf0?Z;$6kNt6og>7Rxcop94dnT9X%97=a{?p*Dqn^^$
    zbk8hbPCYV*+loZkC-r;AjP(ZbOLaDr~Kn
    z4>)*?PS;w2kxXg7yrs6ZqW*Tt_YZWPG<6YZTUCWtpfkd9EFohKNE8jMizkCXD
    z0?}to0uay48>w1ZQ98xI3tbbdSCLjGm)uPxR4>0=4iBLRfzS$W?%OqahNKNWT`qaS0Ig0EOeNc4ebYbFDiyhuY3-hh-8sfq4qlh&e&yAJ
    zP|l{20Ync(7;NQKDi?AL5Vh1TV@3^^o`;>LbkZv^Sl!N#U`<@S!ruK-SD&A7KO
    zTs1-eZE{vf;jUeSFw>Ry9HF6zb@&p-@HHL1Le~iTMnpoQl5H_^z;uNCkNU}zj~3{y
    zog(jjR=mRkiYIctt1=j2R<>F;wR?+Ci2JMimfgY!e_zJa{*3i|ti`_ah|>E}E!6P~cp?FAN52i(>1N?Lc(
    zfcs{&AWVZ+E7x~7R3sNej;QGdj!VB}(8D5+`K`%VUa(c?cjuSXz9V*-GUOqCOr
    z?9Yjp@nQN7D3YruiS6cc1!N^01XB|6-j4B7M-cHW3nI44_6J5;8f>jCLW^xZ#cn-#HJ{
    zdF^p<+yMVf`C$#@%Y}8ci*#O(gYZ&Jie^*2XrB|Po>ezR?Q=z3Cgy|dX>hkG<4oos
    zx7_U(<6XUtKFCKF1yaHbN!ooYa26Jx+04nA=MHPtA}3$PXPsN`=Wl1Z*f8(Phv04P
    z+d=7rsxj2yfoDv;G_AkUC4AcgpXd@&10{nzBkgJ}JaS}apEmC_IR4XPf%(7};uG>a
    z7yKH5f`nXyI=b?!MP1Gm$gvci%{4K+ez-B9A0b?T;9AmZ{9X&8a;>6cg}Oo;nryDk
    zdm?P4(ytlXC+{Dw!#dkhVsgBz=sEcs*5?!6sA|`_OqZsq0jj@xLkdcp#jsP2Q5tg7
    zr!@Z+|EhzI^|?tbH3B*iZyHFfdVT2IS?H;+&k-A)4Ca2Oc|Aw|F~Grkeqpcoff+Y!
    zrq_^mA#W0LwsT_R$%a4K(cF^d&CW@ByTQ9s^4NBDrdE5lt;>>afdh{Jx9xnVN+5fg
    z|Xo
    zg|ov3j@+MM`XHQI#bJzYl$X$-mpLeNHvUN>^OW}j{3#6;#y@ysRE*}D6B#z(QfkMH
    z=~g4$*dZ@FT*(?Fg1vJ{)Rvbatl+qMn&QKgT=K{cbVo~fGgF}V_0nztxtNJ+;o%`w
    z9K7j%1K?j|wBu5FhD>BnttpsrU>w5$`l%Df${E+Pl~r8l-xSLr=VaHtrm7k`1iGPm
    z4P!-Ci7w~Hli?(e>VXbG(rlBsqHp^Vs5=b=B$EYy#~dJmUER53@aSl{lPKFDp9!o3_78BF-Gy9fDEzLzelW<%ZA>E*!wti
    z0&FPpKQh(|E|*;^5&w&#RpM#v*I#W>lU&v?j$Xnfi`#(`&HP=E@8Ju{*ym2ljnsrQ
    zCdHC{?cWp%o9&ba1ka&c7H)w4iBixHv8Uvi0_uhCAnMm>zQE;h^4v4q!rDpEnwM(_
    zmp6Bmzl_Pcv-+f>9@Uz_FrqprlnOWZ#y9iAp8L~agQq|rl|jYt@%h6D>@C^5Obfp5
    z!C%WaQ)?eB!_uS~=mOW_RuV(*W{$Q6t?*+7UJK&`>irBMPvM)6#x#oUmZ*(Ti1v|h
    zWTdpHH5R>I;&<_R*)lBg(QV4mUcRKWA4~=D$?FRNT{5tg8Q%5*XqJu9V$jQLwvLS*
    zn(Y@QU2WWyBzkTsetGI(H$JolLjRYo)f1`Rj3WoTJnxpTmy=uRYaRk(R2Q6Tz4^3p
    zhR?-!Hx*hX9z)N#Kg|NL2fvq(Pe??6<;c=;etRw86PpI9>Co%gAND_JZbooqL;qaw
    zZ(|cU;uXYtY=lQPz3)y3^nN&m>SjlS_78tjD`d#mmN?J}#z$!Xnh%h1+9I{SXb2bK
    zkaToqtnNLGOs#vHZvJVZk$D2qInonEY7Wh$Pdet?#>esG7!)YMHq5@d6|#G9&&V%2
    zZM&I6KV(^BfAVlIOgFxZ{?-^}W}{QNsS)2$?;6*6PyrcEhF~F2kh-VR0E7FQ(j@n6
    z=vn`q{W7YkQTk~%v|6|F}KtfIj
    ziSXDA{LSVx=&K{I>;*{Z3)4*{dqFgm5he7E`O%gVnFHvhR?gc{DN)a`Ew1<&oD#KdqG#{tFFJhM?6j-|(VbuTPettQ$cB5y@RdEVzW(1y4(EJ5_eG{`<#3xez|
    zvjI7)Pxb68-FatUU?=yJDBwBT74kcNmKY^e`5PMqYZLPE?V`T=*l(={Y9{*hYPTK{
    zq5a}iU3pnY9_ZTwiRWMy&(*rXx<>cK4}K&9s3(nmo}@{~5};)3%gR0#W&b2E4HB;>
    zl`^|#^`wnRzy2xR&P_zmOgMl)O)I;ij&LAtb%tonuXt0yJNo}gDHz^n>GVNjK#SYL
    zk2|;!o-fo58GBNOhbel7zczfuhsrM%?4VuaM?-gWg?*~$lJB=;J!V6j!n}}WgS%e9
    zxPFtL>X*i)aR=HAoAWAPI{N1-!=Xzj0%I%onF1=WEu*E&S{o*AFsB@c0BtEq4Zauw
    zW?}1CKxsW)Xp3kYVXsi83HPeak^6ew&)FbJC`d?ou%2hQExMZM|IkctXf5ELf(;;=hrSoCDWh7*Pe@yB<*)C+{Y8eBhSr%
    zVF(l+y!XlEaa5=4I;|$)|Nlr50!LrVdY9?VS_*wz^wd$3mHMg}eKrTeK%m7(>gh_e
    zgJak+8PEl8(Yb-ZIu8g_A7_+j@fxCA_dvrgXlYw)AA50ABaB#3MKv+K4&D#G*FFe~n-o7hCKv0rXldYCE4gDXz^^>oX*YOlaa(yn#a@9koD$U|1ewsfi%LmcmG2^?$<)Ctj_tBeto#NolikQLGav5W@cuNjK80ihyErrjEs!^V!YA^8LW2LOKnEC2ui
    z05SkF000O7fPaF6goTEOh>41ejE#Ixc4C3X1V^FxQAQWw#YQT2=$2Nez+P`Uzy
    ztEO20#2ILnk!T^DYSf%D(Iku7zie9wnCna^U6glae9G&G$lu3n8|u?W>dQM(gby!t
    zaWtI
    zsByu_MISG@)oNiv{R)NaM}*||b7lc@
    zjE**m9wI;hFhK+XMjg~?2N`k3(FZ{v%qikrAEH5)02pfofdB$v1VEq`(Q)S;eLBc6
    zo+2{HKtpaZln@{SL9CHs9b805g?#kAuz(D7EP|5>(IsFZi!SR1mp=s9zR6*m;*=F*aaO-9x~Q`M7Duvo{Sa&MRZxGwCS(rufh2MxRGJ89L)gh`r$EecC1fV_!R2utxZr}N
    zg&0LgTDfhyE2A3xkXx*y(wBy@iO@lZn7Or~!Ly9|`d1cSurlj$861lUXEONtmjWq(
    zn`g8KkXvGj5s*NtvB(mlEuxS)3$6xycyX@`Z%lwh4o)EF!4%1?J63dU4&BvX12j1*gzvym5(WSir)}GcVCV7bW*=h_ShLYcT;BYpg9D
    zF&9vP4K{2cM-Fz}P;w&=7+dFKd=%mG&~&I^^wv=@?R3PC7|ShWLEFMhn+a
    
    diff --git a/mods/photo_album/skins/pa_tool_icon.png b/mods/photo_album/skins/pa_tool_icon.png
    deleted file mode 100644
    index fc89f1f970d6be9b8e40db9d8c132dadf0f9986b..0000000000000000000000000000000000000000
    GIT binary patch
    literal 0
    HcmV?d00001
    
    literal 46615
    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 diff --git a/mods/photo_album/skins/photo_logo.jpg b/mods/photo_album/skins/photo_logo.jpg deleted file mode 100644 index edae2138826dd5e741276697efeb83fe539c053c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4899 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%0AYArOJpJk`W2Do1#dD20b`W#e=X3K; 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 K?HVS?`1}G~FeIS> diff --git a/mods/photo_album/skins/swatch_green.png b/mods/photo_album/skins/swatch_green.png deleted file mode 100644 index ab213954c2240fda9ac90ee14862039fa66778e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29409 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 diff --git a/mods/photo_album/skins/swatch_yellow.jpg b/mods/photo_album/skins/swatch_yellow.jpg deleted file mode 100644 index 15f0683837bf6f9cb87946fe332f7ac3b0ca90b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 290 zcma)%OAf*?3`EByO+%WJL}^jgcEL?RLR7#(IR^_4!Dquwg3F>3T``s=>)EnB>7L&3 z=ixMfh;ZaUdSMSGrOc$tGPP8kg;q)z)|kQ=>+M(GuAFx(8)H?)*mqsmZzhdPD9`iK zmW}sKTZg)xn*SE*ilE`(1O+Sti9qRwnqS4QG~>$8DVVO=){ILvPKOy~-%nUUd`ARq LacK@ai1hdXb%G<| diff --git a/mods/photo_album/skins/swatch_yellow.png b/mods/photo_album/skins/swatch_yellow.png deleted file mode 100644 index 52d320bede4f2b8e2a46d1e4da9a03f9b625cadc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27000 zcmb@t2UJsEvp5P^5J6CpCQStuq=WPl5a~_2bd)B&_YzSlB1L*9B2uJE?*ycT9(tsP z9!emTKuAK8zrXL^@80{~T5qlYy6f$=&zU*r%-Lu5%$eCUYu5h!N>}aH&HFdW$jEMK zsJ}G$3+etjZe0I+mYqx2{0px7zR)nb@wbKDu#f$FP35I-=1WFKefOV(d}=x3^6yPf zKb6;hhMtaofp2^q$aLP=`FOfJ*gL;@pz7@75a{XS>ia;d@!eF=UsA?@NR@pY-uO9t zdOR?4c6T5X78eo~7ZR4($r}ImmjdABV`3VVcQB@OhwS!kvhL}NJsz(2qW5j(9v}U( zu*JJ^iTbdM|0Vp}R<*XaF?d1*nDalb$yOt8nLNEYQd1lU|9eN>-SvekZe^JG7r*+S z6#r|$`$MddjEp_m-POqOFMC$|zKg0U5C>ST!$^%iA7-tqY;SL`yn2|nAPgya{McDX z!}3F&gK4?t1NGNSg8?Qrl}Qj1p)K_K17YU(WPLGjdo`bPU%xVX*@lP7%U{_!GTv}p z*p+;0=srin-?`_~_(e^qm`o2m7@A>*IVQ}J2h@27-3a_ZK`UDyyd~Ccw16+vtEs@ zUVe+h3#%jjv5n6mFD_x|7fY#ak!G#;@(l@>n-U%gZ|rtjCnvS9C-ts+Gs}rz*GuRz z%$@HH^vYZtZ3>>3y*|TFNqa;$PZl;#?)D6%)T(eL{+szXzcsO5+uu=CI?I~M(?jn| zzBxO;yP31i50jz#t*Js$xa|7tes203bxtpJR{JFS{;l^4TkjXhN+{b}iqLD*;%uw} z4d%QVIZlEwk6X>(mSutuB&dqq6DJkezz_WQUmTPg&%4tCzFuMV7yl!d@Wxk*U{+VU zB==%bgqp8X{=56uB#4oA zDQY=pw>-#Po=0{Ql3ct7rfzxgb?=HvHCKpVPx$$;#g!55_Uxmo!$cX){dA=w(RVX9 zo-eZHSiOp;K03U05uWhC`#p!(`?}!g_ndEl;)ck+ta znunA(d1NjN6IndPPfU+U|_|e>iIq)c8#C6O0N8zl}^J6yPxpC z$ack9GHZ7h+!}q#Hu{8TNxIlp;p%R*(1+RY1`(g2pmgXi)qRhqoMh?OFe5SWviURR zlpEy9=qX32{>ZFrcI|VQFb?;3MN5B*S^fO`zE!l+v>vDYz9}wHIYFIbB{3LBfe!pN zO;x}^KG?vlxbSL10DvzQjbD1MtkU?p(&A<8!@Orpyk8Bf$jVwgu0@;ADB@qqa$g~& zl{=b;w}vz=?XJ6^k)er`tVh>O4gAVK#8K(1Ex6s!RXv)NOr+bw@O)l~O(qtR)rjTn zw|o=P{VH+R_){Z-o);iL&U7^8XBwBKcwsCF*36bO-SZlaPtKkXWRx6^21##KKLMo3 zKO$B1S13`W6lC}KhIAqNf*x^wC2#hA!285ZA@K(2K#fb?gP;Ex@Su)g@ECyhRSpB> z2#;J5!p29PQW+qYE)s+7KP23-9X=6aSXEdpPlC{hO*;RuGvQXuNPSe5#;uIl!@A4e zND|0bf(VaB=Sz%hCq%CA7WkbkaMPVcg*hj;n)$h?8h-k~vdZWqV?}>6@L&vMJoY4ig!#j33ytG#b=S#lCll>1f>IsFfop=ml8DHpk3dB88PX3v7 zPt}tCCEM9OHi3fc?|;P=tM9RCR0lCs2Q!FKjoLblQ%7Haf-!+e2JG~vvY`UR( zJ$Ejct*bowkc(~iIro(x%&1cCUzRbE<-V`1tg@owgSf{W<)|-(%LG3*4tQ6I*jja2 zjcj$diHnr?(1nwf!#4B*7ppOAoeG#GLKomp!$#`;Y#xql(_ry#&v?-uA#HmKv|;@; z)t%xYF3r?8o-H(?&u%@Va*qCf&)H}FhA?jkh&RF{i1Yf9wf^R3R)4|zK0w4C+$Loz z@7O)_hm_rG3cHut3|PjVS%dDXENu5#>Fh?m}&F0B7)GVXjRx}nJQzhoMKZ@uL?s zW>Fly8^0V7!fmQ=75(6gS+B?o;WtdCW`rd*5FP{_R_noT5D)d@VyI;=gd=H`$3$78 z(|MwGX>afu$QwD_u0!i56Yh2~ss;}3Ti*Klyv%;iVr@H@y#cQoM6KH?w%8%i;E0j;tM)9jL1xbYml&aw%uKBbFtR=*S zx0LK1G?RraRPx~mBlMvq3g48NhwtW`?8Mr+3<~?Z`UF}de4#RWG%!9l4i()+XubHh z?h>?}sJl-=wjW?kN8S-s$BgV<= zL!SutPswJV`pm$d&mVuh07=Ex@Y)7CGo3w_Z;$?|6PETa#w5ra6oI4o@!SbAH&S0s z#quSU*CS1jmocu?VAS$d_pt9)7o1-6cUCDp*dCN2{JvYW@Ir`AO51{yk|9SP$GA5I!*Wr}DaNnw2M1s=!hloM zU4*K|AgLz7VMW7&&wf!!Jy=!NMtDRn@u2kXn~Hln$u9Fu0w0Eo^oPJx`)b=?3fh-2 z2vPiT>*%AM0!pO`Y4@#>T!wU^cT3i1?^0j!2<)ksN_L$%Xs~@QOg6%XDIh6Z$AVsF z&%RGuyI=^;Rnhw((EGj$iG4)gi+d|{h?2g&EvY4HV?%i*up@*$ULZ+JzCpi6#rL#e z#&s}L_LCKBbsmKSdE3Q9XAd3!yi;FEXCT;2QWMCdTn!wc?Dt6-jrCgq<+OUzT&jcj_tSEX{k z__9XXJdGUsLZcg7_rk-tZY1`cdxD(wk@MwwkYAFr{k~eE7l={DG2dg~ae=CaJ2Xsd z?9-GF?B!jio^c(aKSj^KV+``3x_4b$>}6;&XblHx4J&kWzwM(f{4~MPy&I9v5&aV7mXvX=^VpvPtJ$lvXgh2B4B7&Pp#=}LZ;q$ zitF#f`HhOP#+T_&Ut<{eXBKVL_=2dwH%U>O=buKZ=muMa&GSwoZvVh=e@#Z_rP3ho zrIz(_@1@-x^@xGSLQ~<9L&mJux|+Cg(wMa6m+gS4UO@{}X|VG?P2dXM^TT6ZJbBAZ3xw3u^Qed^>%O zq(2w{GQW&jYfDXQdz*5awb`K#X}ThQpHI11<-1goF()t>X3APiv{wqR)pZHe{NkWR z{cyo~H`!BlGnWM`(Oog_7@F2CIQ!g6hngJCe|17UZ?;qi=jnU~a?i=?wO7ZRn9de* z9OmMta_EHJk%In~-Co9$^Y^-;*WN2n;25p?({xawQdHSnn~xD*KX>v%WV{JrOTTocGi6Fa#;a)!rrf_-%5 zaipgK7TY4G{;4`W?fq+wyHOsJ_W%M9zP0I7cByXuQ@^}ipI*mRcic9}zclCN`0a8dgHh3y zhMXxQ`p~q`hKGI_N%pt4W1gEfzaK{Po=qCpf2XRK;d(_{E88}w=)K;^V9M!wq6kDL zL?7}94v+c0nWjpUkQY_5Fn1;aZ<`C%>05~}Wo^);S+dSmEC_21HP-HCn|w$y&8w|& z(a_`o|9W!HlbW!ydnm+(T|8{?C^^u5XXUG1?yV@Bt-tv<{#W*tI)n8O^lUsx^bvQ( zAak87<_BzQc!b~aamY6$B(FvK41sELkHD{{T)Lv`iK9iTH++=cIaL-ornG`+(-=KZ zZHA408n~-WuBsXPZCwisSi2GN+l~vT5_La4f?uZoCRn_z$FqLWs(IVa==v~| zJ$nQMXgD*NO{eVCRjBr+I!!F%Fz`>&;Czy@6JB;z@b&qVcZSCNg*vR&H_7jHO1@$j&WdMC_@|Ywo1%R6+Q#*nPUL zaS(@uJQ-`(oQX#ed%s?eetDU|VBv91K&71#dg-aSZn^`E`5|1gL;Rq%!F=dV+csiN zgTCW;B4&1Zjg4Atktz?^SD?HZ7<}*TQvPkkT@@xed z=wrzN>9HEzJBK)FjSEVL&gNBR=2`g!49&Ah;U6N9f%c)ORSwSX5Y0qE>5y4A_Y5{G zAHShVX;IFHiGu%(pDxy*FX}fm@mQIXMqqN&(+81nQg_O3i||2M4UOB#%0e4`S&*0R z$PT`Ftl%%-*3;^L7_R?y+T8pX-D&Th*cxyDhokY{3HbOwD2hTkQx^5lEM%zvg^hQy z=2;zf@JY9CBKh+O0{@^mK`+0*V{PuF6rI{Dbmiv?!wy!bBUbnO4XN#Tu~``=F;|?*+cIL?%7T zi`jNxOfDr3yD5p-*m={fC!-YU45K*d$1&jvGc+Cf5p+C{nt2FfaIr}Ah z>z;i7oh-a8bLfm92TxJFbZ6+RT#kpy*IqW*vxY%#Jc@U1>(w2M$cnhUTGVypyP-$& zF!Z}I(;VZK0oV8Fm_FW7iy0-lh8uWW!j0uPgK2mx! z$qv#?9`tEeyYqYB@L*x%NsMILj^U##da@ojs_X9;9jL8 zPwO~8%w;$`t-qd_4gI`7T*nZD{{{w6<_No-W_H^QV6M7F&2{QCsea}NHs+%d4OVf8 zpsP-TW+W*a9NyNd^EYdfEmEf)E|TYcrcU7vnU7cFyLvkNGTl*%CuwZlYm>`5roVp@ zIN&=;G$hK(Nj6cN5^tGG-c*0_lx4?Wnzpu$x>&~C{$IDXL*A11F7XTl8`){foDf2+?r6%#ni14hxj$!0Z3OT!fL^J*dGtNgq zOl7D%CVjHsf%eGR#7k{{DCkE#P7T!F6a*J7+y!HmnFE~YK=V~s5^piVc!6Gw<+-P92-@UMiz;4G-dyZ$d)MAQDkD1? z1PZW{HvTv%L>^nfW&W`{zFH{CDh?R1EgmHR)DBuFhQ~Kr4xg6Y^9O&+c?eCo|KM># zhxj5_qCPC^tz`T-j4SGgz8cr#nDG!g%rSJ>Q4*kOVSQ?_^rrn#4j&#RAIQAie*g}( z1>sJxe86$xw%!P==i~Ce1^$SsSM=umAyc=DkR4D!tSe@#KH5#~1-5bxc3SyHXQFFN z!RZw7$;ow-9|`6>jIBVtnY{Pup4t<(k8aAFZ;>bv{SUA8$57dyvVzR9}JeRi`-Y?jM_)8Md` zBUy%snrz)4df~)Ef|XGNCIoYZ!YYxUw}p=8H>bK0-3v<31Jqv|So(jN9l9TUC}Jit zq6K@G{wOcAdVoH;o<-z7nGi;@U8y@D^wZ9r z01xQldTn+12bC`jR=M004Rp0;?amvvi7N}0iCqVDw8xL|AA5>PIWQ4k6v}9-X=dIz zW?Wv%tw#g6l_L|a2bk6~!~!k|1uIP-J!`s3{M-3Lrf$N;BQx($J&i$e0k~{{w=x6Y z(O#su?Ow_A9;k_Q(&J(6KYtRaCmD#ER!&*`rYB7CHWu#enyGk@m$FTuvqW%u#n5^E zPznp9!VJi^peyH@-a1Oq%gH?VEID!&tr{&mdR+}$mUt0`c4zoZpUR9Nl2BEX7k5sY*{Z7C9wjM5e7-_rp zCUvIO-c5d}TfU(n&GHSAZ*B0tXxrnsL4d4Ie$$nl%E_opSevZ~{y(oIQctidb2Yq=| zOpoe?Xoe+jbkR1u4cVc8LGErt*$6FbM2aL)RT^BNlKa?%urq2D0TE`2(4+ z`O;dV(KF1-<-0U2?UQab@V4wjk@^)o$Ih4*76u-8o#^lH^_`3_2SNqf=B@V`OvrtX z0AY)2Pgfo40mfmG6cHdmdNTJ4kQp0u=dvv4f-%|Xru zy^ly&0A&(czsz~>{jKbF{Vn+ZEzVl$j?jJ(zKtA%AJLP2T)i{g8(nq3>`q5yEtRQG zPSzN)UEl#FLNqlye{ArX`0JUlmmu@i`|^8^ZJ)L6ZXfRQq^SaKmW{I}B$vf{npcXaJ?r&KC(d(wp(Y1~A;+82f9^u9QccGPmG0lGvrIU* z)XsIpSp+#BxIv4G=m{T^YcjH%jeloigd6``x(1rI{jY1*|Kr8KCF}fzTs z)HpFTb8Q}bwASkhuCW0V%P|XGP6Siwa++RzWCwKp{3wIi+TN5n>-iK|t!8>FR3YN> z&)lpg@sQ*O#G!X#a8Gy_;qqi_1c>{7&eT|Q!uw2Ue2W>8tV^)0UVzpvcw$on@-3Xr zZDwoVKsCqni9#}1An_6llQ`2O3ACose3ce`3qTkV2k&LWh;B@1*YU@IX8Hw+E!K17 zrj6*yMa|A8RAlo7u#qO&w~+y3wh0kmRp^q5Rv;U;lNUkG50NT~de}e|%}(&9HLyb9 z0c@d(pD_A*2p&SVgHJE;@15|~!E(V;jIH(+)NL?X-N6@TDUg7+hl`)j;TmV2&k5@*#xpGI~LTqvR2PU`tb8RuQ?8JN@jOX#2Dq_F7V0*rrG zpI~SDB`KPC%4kVM*S~@GmL%#tAq4I&_A+g{?sDZrzv8$7<5t)!Itb4n@s>%1!7lzq zp#%6rapp-g=equ);xIfyg3}kk8~%Bmzx4sDTNe_Mho=7H^!fo8GT<6QAJIUUdhXQB zzCeR{QIO4ea)_MIwjPH2qsulTt4UY<-*v8bxdRfzL#^T`1S1B+Cjx9RBu&}c4dyw5=VoQo_MuOzah=`KQ0K zvq0uv$|-=IEalJNv)F+-o5GLlb-KP#cQOEbFMFMwoTm3KSLdj9Xd#~vOWkOJ7uNfy zt~O49(UWgAs(`$r`icjn^krCpa9G%%#0l0vKzT^1I{4MV;i4157umca1bN5#C;3?8 z7Q~OR6u|@wO+G>3JgiH@Bb!j>+ZS|g!7mH;Gf$z&=2P*V*j*Ch^$@U_WEyaUE-uw$ zXXQP3gs-&|9%mZ~Fk4Oi(@#x9LYSYR!Xj2%Z5|6juknwgfnJvHM}}I1$AA5OA~Z3y zD=QQf%`~?*?t6A=vwOW+8bD&Ncs06IBfi{jd0^4G5gfKMPr=-aIO|K0%AbKQUx1v* zHu2z*;acs`O~Ak8B20r|wpn!*>*_{CD>S5RTu^{m7ncT@EB9r=u5t3cq|Nf~x1RK-+_M_R}0Ph0a`Y_hY8|m;n0j^b*e>%CU zSN{sb0sr-om((C8CuR+!Tx4x({q1^GY43)$1NJ;=cG2R?&D-(>K5{t0$q8-@7ue?Z z>{;`Og^Zp+&v*Q9f_h5a7WpLFaqxhK!(6%SXxQ!EnwVQ%u98+HA-8EeRtsB#-oiO{ z!XvyBhB(RjRDq&SRvU)zC)Qrif%S#>eZA9S9RS}Huc?C*)sFGtKlrnyi^T_yI)UYF!q& zyf=5c*>kMs1S1`U@=YaOX-)ycINb1oa^wX0aJA)5SU9+KuB&(du8xI`|ogacb45Fy9>MB2C*!6(jfr>%3?Pl6=>f}%notszm}`e)u561Y|DP&O58Gj&x<_> z(F72Ned%E0B8eBkS1&@gA(KhjAMLE8XCWI;(s@%Koz81al#TxR|HRBKEu$CoT?w2ZM>r7bxTZ zGWq}XiT~jlg*ycMUNL4y&|T#uKARgCQB<>B2Z1-2w1$sXZo_@FUX!vKeMN!mwLI|R z6GU60=038Su}vy1G5)E-ddh3X^^6YMas5iXKH>h`qSXa&bYlKVV9;l3W75m$Q}~tvA&6jCHtHR zj)3D;-R9hwm-z_EXM$#k3Rb=Vndx8$S@ea}NO(!aE@?R|s=1D@H+dyWmnaP^T3zlA zPY-=DP{8GPy=FHH7IgS^W46jS>GcrUwI<%MlGEfM_flvU(eAG)@3}{#MgSkleVJ|7 zeo88;JJqf{k)hjsX;mk&;z0K!nSsATUZ3go$ ziCEjQXlDye3jWejRDCiQe4onh+F*zhxO4^Gj!s^YojwdieX6K^50TESqz@VL4KW3$ z;nl12PLZc3F>ivzNMzqW;2x}k9~Y64(Zc>afK7?~A93ja8vTy|mW`JtianOz`vGm= zXQ|ti>o3^`t#|hnVC_yCicl!=b&ZRQQ@iu+yEi627G!4j*a|b#T>toQunM@uo$YTS zpdet_x(ucqvF=-3N#<~Y=^^RwV&jNnVI(49Yr0hLUynt@uqRt^s9;w({#+LIOVZ&g z8n320gKsEEFVH&!Q%Fn_tIuuD^l<^{C8@9jI5ywP=%jM*A4Wr-P1A1uqvw zMaVvqbITR(-`e0A%8^4Ce65^V6YOx7hz9|HL`>+8z!c%)cmvZJ6x~)PMEz2xlVexx zC9&YiNo+?elS75IIuqxuW~>CRH`9dMd61U)8Nltqr;1D)C+aP>@XwF zawh@MaX5^K`&&=A1e!R`k#>Rk9g(BNJjlRzX}h)MXQ;QB|Q35BwVNI4UqfHp;i z;fDYWgK<6q`xQC@XCa|Pm|FUYJ90R#v%}3|Vmcw5eZ9Nsk33P;;=$i3MnqSl^%uUp zI4#u87CdSeU)DLe-UB%4GgT@3yi3 z`!|u1!elN3$4)$ZfjOqSbhaskpj%*vnae@v8sxW=nuZ8USX-78SyWM$MvRSisIkVp~VZ9 z8^MVz1?NVTrRQLVJKTqx2iNTz<5K_OUUX&L;mRxYnCy8xfZ?eB0CYm@h4gQy$6Tcb~QidI^yl?z)%|CwRO%)aNyjN zW!zado<*!$AC?w*p<8*R?+^gvq)M`)EUOu4Zac4WvQw|YjT9hQ4xKymF>#@Xndnia z60w3^vx{v_~Z*nV`%9~L+=h;I34%%*|aG(~u)eLRw?I-G?eG>Q}`^Z7E1 zjup3%X>?xMXg2+R(Aw#snjO(Rv-~pu#B!i~bPt!<(Z^~$KwpW3=Qm%q8lA!lUC11e zc7~y1_6XUb3K^#t(t`&134>@3yPrLi8HQFKqXMFVk6^Sh3_mdS9?sF%EKSGaoYx zlRFd94eqZDQ;{UP;{IbMm|uXi>N!$~kZbM|Okq??;Wt81q0L)iXpJkNHPECHrc-D*WCBQQ=*a_BmRSv#I%bXMjAVG8<^ z!KvchuFFa83-#!^C|_O6`@{KJ0_o|#X(L0eL}!7w#~)B=0j1B5KjKkfi`X-YOn7t6+>w%A$|3i{UZ?6dm(b?-vB0qe46MvA_9~_^tE3RoR7J z_u~Vk+63o*I?=De#KI2-Th=M`USWaAB$^11#~bgADOc2<)0QGGcx>=dz8+zw;YLnR zf~@WK(W(5Z2ZX352$tbj?_^aA?MVf?k#8f8TCQi9#Kjjbv|$`5^<41VFr#i1Jcm_(fSyk6h!P1E}Q21LQhBSD%0l-1@Om;iuu`TBFHmBnQBzAle z7dXJ-60o)t&^oSbV>&>}uTNwsKLh)$m}$S?U+|Poyp8<@8W*W|s+0CIu})WOj8Mq7 zu=z{hqN~?zh+$^|F^K(pE$jexBX$;0`YkEVT^1W0s4m!_ZmIwWpq}MDS8FMj1SRgLRqRqEZ@a*U{rb+3Y}DS=3H36R zMPR6k{KT!0$8%9|Z!E8}-SMm$d811I-$cthyP+z6%Lo57cB`{K7(=j&&eA>5Kj5T+~ZKw zy%yZE$P^xbHD6YKxq0g(h;3n?-U~15si=U4VVlSts>P_9kAF8>UbJya2v z1y(!KWY=p^9^SfQYK6^U2uc(Ytj|U@exsANQ2|ZV{#?J+NiZRJLx|*Oz~K$vfGHkC z*~Yiw1=c@$qC44^4B72r={6$;sBzfGVd918 z)(pF>v(Xb!;4}DmATFjkJ5}cT%=NZX2*e3i)s$*T)GOSe^c_X6xFjv_wV@uHCs;(- z{M~l4J6GNO2OGVtP8 zhb9{gi0~LB(L$}h`sO414&rVMh#(PYNAfGzXPLKH&H&4=^gg>Q_uv+&f z&)g=8r|aHtkyQuZr@xFG`sCX>0FiqRjWF^8zSB!;+wX4vVOD1zuhc{t4x> zX(qXNQbxQCHr}G^uC^}671)ZCiVD2q+bFjf@vg0hF`kV8nICMkBh`ctW#h z5GAns5;U@}0GQSafNsesH4#t4Rb-k6$89P+*!V&xiTdT zZrot+6Ob#Q4J_#pBqWJ>kA|nyZ4>~X29*0B1#+9zrc`>|Pn`@{JK?GGscZX9YN-}a zM2Y_Fj5U-sZTT`xa*elvYE44ZPOGF|2vIKg-A!#SokwxFuw#DKul{Aag!WNn4Yga~&SJ~uaFE8PF| zd>PM)dIPloUgaQ4xspQQ^Efs;hi(HeUYupNB~gHkygyYNUIJmHEA2#Dc-pR9ZZGNr zSY`19Dt`%dBqdseMUyaeXBgjKA&0LJyew)vTRZbT<>8^`u&8mdiu!C1$$l3ilNa9f z6g(d2xaD__YEc0PLa}fQNGDA8BPObrWa|d_x7YmlBKJ=|afDgB6FNDMM<@40(32|9 zJL@4+aOXR=p4#WZpA`H(fA+$iExkV@wNAtSmW5DcQ*?OAf+52If9Wwb%)#+bWDVHv zcNf?B{H{VXKh(wZsOlsz^lUa7$8kGmj&->%MjL+>D_`Mmy0dpODC%$X<2<2~B=x5z zV`~@W;#mM_Utq0s1+I*|#9hGQwT0(E_l{@+A&_!L0o_ZBeDg1ZGjk6MXTo#I7jnB?KZi%);ty+Q!y0u`qESz!Sd@*Jh}DIao_u8% zrUkeUqv!FR7tzMqn?F$~{p>S>&(m{E=b(rI5hM$FHXk3ldQHJgwmS0cGzDeA4Eyy!MQtaz#x8r-0}U=yxa zbLarWrfny8E+(C?5{~?|SMv-dK;E{>q=QixHb+8(SO(X~?$WQnNx-ZKHEH)i{h)?u zg~>@pd?uV(J~}WR8C|j3I;|WgUh2tqi9S{ALT)HV_^GjuU&^#qT$Uq3x0d}QhlzWV zCXr^EpirtfF|s>cp)OD`;^DXv&u}pO8GX2osy=w+cWoCLfkBEe8co z6`+@87BUqUg5&;bz3`YWmfPj~eqbl#-yMa)|DED~m-t`jwg2PAzbS6cXZL;K+t;lA zA2pg-fW(EJoSXW5t^Gv~C5_+L_1Y2TM~!g4;xq$I-hWO67zTqO?(e&5M!`SUab#-a z@9x?d8iSTSB)3jaeMvYR&NpJjzm&sxPQbVe7#uA9=Wn!AQ-vns@pvIk|H=?R5y=@3 zT_t5JC@4fMkol6k7gh7c2lV(y%_d(kjCY#l_>W4}H{k01by=nWKTKaK42x*`{)jVm zHX$J{lLDPGzB%7V=At{pB$*Q!unIW@0OTv$IOFk%Yz69W()X&% zB%x#X^Tq;QpwP~SMq=YU#_?2t?&D=h=-{#3wEgI=#IAj|2Ud2cW?`6AT&Lf4CBq#b z8j2A=;3jnAuR2eb1a03VImr!hpFA3~?s_c0cUkiIlf3iaVy)u^?%Wt_X{TG6q0&!&1=c_5SdB{54~s=XMTePgo<&5cIct+6 zpv(37xoO7|L|})j^0bNyU?POfw6i8PKg2w|9m?WA+Bn=`Trz)pf4-SSuaq}QNG7Q{ zD5!-K0sSNv;5qSYznB6A`Uq8XC~uxOBh&~IkRizG7E>8{(p?ie7auTRoR76}V{ zbjovvUnbRyf-3BY&{lR?bVQ23z}Ycx_(yQ;h+LELg-E*-bJHe42JvRVYyB;vK|D17 zLJY%`l>QOudi>D+srzuj{2-}F6m%*$7-2ET8?FW)Z+n|G`C4U3y9NOx%;S4VNo>|26v83C*oJf3&?9txxHFhtm5tllSd^ zklKz&>gJM%q&O->q;jqveqYCJ+%Sb(?9#*Q-vm^R;pH2Fvyxz9!l6ymeyEA`K4>c> zKO8?W4{o!bCXD!Yp=?MnL~z6c0EQ%mJ1mAA!cdD%1l%YF0VaTJa2zm91xB%YHV~hu zG7Dmdx&9YxILtp=+W+s`g(Bc4wz9=w;h7^D*)yj97Vpf_-vP+~?*{q*rur-1aK08K z&)j*6I{)3zeUFmWxfxmhLayZ3+;>?%C&b6cC-7$j_3?R!1qHj<8PZIwx$mxmaVU)H zmmsQL&}bVGE>S?XP@gO?08_P%De9&0vg*I)N(PUL=skVQz8ZP+HhI%c)`m&eMUWa+ufN_?~4VohCcdJOkggYp&Ecy@)4-n7>60Wef|zbzT@|FB88 zQX?7J;%k||xB|_xe&Hs^k~Soe|CS%&>9%Yl>1 zH?q6`M}QySH93z~&n;QySoGL*9_w-ONN!53%9Jw7Q{|WM5vIRTnkf}wet%TI z)l_lgtM)fviQMrkIv-!}4Psx|z0Q9E$95-?HhMTX%1hu`rb_{y8F4n@>Bf{ z+MOX#BA@K_aLTK`Rm`flH`w)gIJ7jX4lyOKmvcW2l-+CkQ*~fGpdeyshXqnuPcHKh0caQyW~<#tJF! z(Be?6h2k#3<;GLNp*Y3eJ!o;a;@aX++@%Bw1SszA!6A4a-hc6aJD+xDclONg&Ls}D z_V0qr2aV=L#zRkiWE5e!`C1ZWgASI2+qR){hc}fLV%Xy4Pq*YI{~jed8aE4bvuy@X zZ6mm4^7Nh9t~cLx)1b6PK=KopZlF$2{J0LIZ$_QJrRWSM-@U%~fHmIiQ!ae;x>j2qsW@-n))eTBmmZ6?J}i6p4nNvK0HnssF7AaufT-MY7dz6nz~*gjwBPtARah0 zW?e=;{dHyudum7=zuOK_=HU=W_t>7TPg~h(BY3#(BIq2a#jle${los#x&d$V z4Ly97J;82SxOvvij`9_Cuaw?Lna-f1Q%a0fi}SGPSTN|*+Ewr%*j~~+Lpk{1+3xx3 zf>j;QB;0(UP?4{dIX1k5se&E2-vN8~3e}a4dhIp3v48|gJzSR>A_HRLv}JTw)a0D7 zAbw`tv#ja`^ldQD{^Eos^U(?&PHaPmgs0U+GT#Kle!Tg?K~=fGZT#LrOev)Ieo&rV zX0R@tX4cHEJK%Qwq;3yyG)EsC$K`60XVs!iMj;R2-Qn;-pW<1ha0{jqO|n%T{I@sW zi&-!Rryj}#5bP91E3)rWPx}%JjX0i-{&g@fzb)QxKHEt3m2$b(%#b7;wC(eZv7PJe zD!^fCA+Xhh6?Pzj$-~d7-G?kx!F7^7fDZy3vf_ z*6iZt);D_2EOQp(jrS5w%mY0mmbyve-9|~^`Q~rNf;r`DLw?pYEzqM^eDej8L7}|# zZ#3Ho@12ozLRe(5xCWf38T>~Mb=NMNc7;p{nZ_TF-*C#|!40XhWfwOX-{Za{v7>?x z65^#)|E^(9Rfk3+qiE2YA!YWa;=CjZO35JS+Is5#R)tR5ovmAh4t3l2*zLIbYYqEK zMd_y%!se?ff6=D*Z@WfG+;ImiU(JisNR3p0lrle}Uo4#ds1@ux@2Kk+jI&ADK`k@e zRn&0O;KU=muM(tDqL_NRUmgim$r=7{cj-&d_%XR?+kX&nSI&>8VGnUDpSZ1uvUGXe3J8GoqkU9cFzW(Sb=NvqO@GFGs`NfTY@TZc(zc*}v2L?~A1(=ceS z$(SPiIAaIPB0cN+dIMuigh5g*s2L_sE1wB zxw@wIoT$Q};zLzjB#rA-Aa*}hH)EdmgNt5q_iKN7Y`GyHyT0>xq)PvY@IRcY189uN zc#peXvCL4HYB(=kloG#w%zx8R5_$C&IX*ob&l;3?8j~5u=8v=P__`i0YPernwj@}l zU~T7F7v3QiGvzbrE7+!KoC(B5ZNig3qMBNvoUm>vyjg240{43q?y6Maay`f#Fse;G z*ISGA%$=X#Q|w_()D<{(AF*43(Cq2^-&G29bI_;AgS{TvfWJjanyh-h95sefD0J}W zW*+v?zusRb2V6F;wf4*N#{^?Cq%}AL3GKEsuoAANtFQ4R^T>5y2u-e{_8{8dY>HUO zTD>*zMMdY(51!ma?CL%bH+viIk-Ar$e_2w?;`e(P3v~%!ORy@3KaJCXh0mJzDSg{B z?IWpFxdK94LILQ9^%=p-excZV?#EjvCwz(M`jaM^((4E=}_#U~P0@kcXiF78UJ#uFeVhepm zefLF72CX2;j^0P%$ZIYRvmv-JS}hwfdV#~?r)i1%^?Ek{#x^98HCw&y$`qQyRq#$; zJ+<{Wwi3GZ-1pT7EgXpucTPI4&%0XEaw5q^imvVy9$@5>g?u;T^voiBOPGD%|tcP7mm7N3*m@uA}Y`8`Dcpu`ON4DH0;D-Jb zRysw5GiNUk4))3Y@c5hNRE?^xD_XK#wc8dV5$)oF%O8t=cYIj(NXljPM35!l<3jx0 z6QCJRS?VCOrk`JJV5LvyTTl^^Wc9XaOLqy~1C*!DN);Y~?WYtM7KiW=jKgSO(? zg@vw)oDoZ)5h`bSm$>)rb#JzK+dsjbhZ7u^>#%YYbqQx7x?gnvD<$A6yH6@RQ)mD4 zoK9GY61-($d4AeD=!Tm#F0T2X9`Y)#Rtg+{ns7I?jNGRwXeZ~-QSqyeXZnUu;ZI?b zXG;W9-$drKrUxj0Vd%5H&_)dkR*lKlo4c0Fz))97?JaqQfEIk&!o)552^&B>t%&`} zvVszyss@;_8Sd1qGRW9??6XZ;UO=wtin?2`44N-xc3$}>NxLf{Kn2D5M401fC^J?^ zh>VlBYIG+!<>EpSxEj&TqC@ZzeT2QBJKWML0K)-Zw%X$kWSwD(3|9)O;3Y8UXxRj_J zk$>IrCZD#7b_PF;BdCOGvRY#ZyZ+}jcdPZYN5tsMg^?siE75j(t@f3K*(ev?FCFz9E(p~G_3gd~x}wr6cgBr9Jf0tyw(4^#PoG189FYrqE?|k1 z<+yMie?eIpLT$mNc9aB#HHvbB6TUQiUw#Hd5#&aD)!g!b{0;}C^CSZQ{c{cV3|Th9 z{VkV=ur4PEiM@*Pxd~}+Dq4FIMy9S)YaXQ-ru*bjoL#o@G*Nk#Yz9!EJU0F(%w*QZ z91QCssctq?@HM|or&?JbLu$y|9t`_V9RdhRaxe!rT^h&xNZdlY!;irb4}-xE`-41CX0X7V4Cd-hc2F z69YEX5!xZWOilT;_#@;AJp-Gl0!sPLlTCJNL&qfxIn-^^}k2*Kcm)~Crc8DHWqjR0k~7*}}hStVO#Y};M= z93_!?yp$1-bL=o#EQBcALV{R2wHBXb=QIBX`#p2y-L$FT35AR>>XSh}DP04KQ{#2k z@NtEO_+cCT(?Kg?Ldg8_;)j1Wu4e;IF`+GhHD+;^H*UUsz?dRHrJp(`yOR)+Y34Lq z;K|kjaN4B!`?efOqqZF&Fo_(spz|zJCp{0XM{iM5%>6cpz1Y?fot;U0V`%JCmP54} zsMG5z#aF+_RmX#;xKczQipaR~Z6&wL0p)cs()Y%V08DtNgQ;7WxV%_HNBaMYCG9V z-(vc%_MzcUs$GvE;q`MftUADEeM&cFrIL&?vEa|tJ6fQ?kJNm7Ot(Y#NJIJv<~XT1 z#7dYbKEJi_61XL!pxw>=n1ZiI>>hhOQKOhgn#(1+8>1`p6*ko%5e)QRpyy?zjUInr zX0c(y(52-SZF{E&U^A&Q-<4XEWc9($CB+P#QzfjdX{cO6qd1Ca`qe3@moV8Q?Dvgo zP;iA2Z6`(tm1oU3h`{F+D zVZFw}ee}?9Af|f*!%+Bi5z;Y?dyP3*d{}!5UDfiHu(cM-?4eNGsp;|5(YkYbH1Ieb zOCHzYLN%y#+dC)LvWEo8)c-ujL~2n+`;4Nc1OFF zk7F%`g;rKM$#-T!OegrP?w6KC(bW4ZT3O8dB>oaehc4`D`ez=|HdEAh$nJq1^06igmRF!WTRA~~0oc4;rIYJ+ z?lks za+@ogEK(2$uu_jD+P-{3KDMP*mOYI-M0s*1z%EFv#C3BG)g9xBXrZsu0`11w(s4M9&OYcUbyi`HM4jO$ zf=5Pyq>@O=EOX0b4Aeaq!G^%c$4(>pK(hbR?4yZEe;>H54*8bIrZ;AHLS-w_%)WJ= zEO3v6dC&^b^!Is*Z-XxlM0C-bSCD2K4|5aS{ydA^f{b&27-r)y^NvIg&Fw^4({LYn zlo)%(mDHQiSPXFn1YkGuf=wb226AOMj~HXZFzxM$u9q}yPK7hw`#R9x&pMDU3)h?) zuaMF33^s>cI%)-cY5izoTVZ8t>dDJr8C&|40q(KkY^B%2{|)U!(J)WroW+>!6;=O1 z`r2HvEPb>@ZQ;4(eCHNXp#1vlt)fJO_H7^os*B)3w&$c0-(?+TJNd(u6XQ9}+)^|J zE^2E*ND-5j;CrtU5xTSL&{JDqrG#p6?S%3h0DM`7Tx%^>W3QV)?JEY+U6`+m^>v<+ zI8-5!EJ_=XMtr+bwI>|%BXl2E$Hn>%*A>jMiC-(4Wt; z0CdYt)1DFQNH*{iEUst*)1^l4`r`bV;KQi8-?8qP?qg=0;FAqix(hnbBoCP_|Ly&E zR-NHDkCtEq(PfM3)eZ#xazLx5NY>624}2{)z5)A&E}TUuPFSnJ#L40sa()`Ve-kM{ zFXHH0sGfCJ~}YBa{assBv2Fd z=fFiX&dExqr%N*kv0bRdSiQ})a~lt}t8vYb7PV*Oo!b&M$0X*+M0%O82@nL+)G@&ao zMnZ*4H=<{RVWX?y{(hr2ch^c-ma|N&@cZ7_ed{1auNb;o-RGC=>;=%kY5{QHPjps2 zA`bhBAe}TCS%3YzifD>FYb=d%H`(lT9wu$ReXRFc529k7EXI@(ilj?RA%9qYD)~jN zOsx0r3xud9Mj^%dhry>82Bxn{A6_aIPLwVOG_+Ln{VMoAM@f}0qX7C@eT@lX4l-odrlewXN+&KHbCHo2-e>#>733L8L&2%Ozu z0{1(yzWbw)FxoA}Fy+ggOYt?7s8m<`*Lh^gg(tYA>+@Zk&Mwqbi=-Eqh}2IUIQOycjG<^ttHom51E{p=_aX<)}Q)_FP98+IN% zd7bBX`uLvPQK~SQ%5W(;%82coCIQiiGrXb??9o(ZVcCp&0P{Fu&C-yTkO_LAjRCKO zIBlQGCjZBT-BC`6JDZyuUxsu}-4&?A15NgyP_zXd1$%yFfrqifi((>y><#^kF3uy3>jXb|%UWZH?<{9gcyc zF{x~VK3;IiCbwgKon5wqXw3~(mhT*FUD6rgY!V)SYiS0WFE3H>csHc%xT`G*4mJww z=@<(4-x@iE{r1#4BA4&l!(#!Q#za){kXyQtfU?kgRlYx*?@hcTR4gVRC;4|az49|B zehGp)kxEG$Q*&m`#~R#I-FKVPoQw(a?Vu(_t;?dN6%(5cP{_YgIpGtUu+1V(gSv|Y zoNgM;N8)z&BR|NN2foQF24v#Kf;I>e5o$iIgYkRaLR9PyC{sazU%MDL)AV-o==h2> zRNiBDoe`qM&_twi>?%CTk*-eWSX|m5E+)%BFy8!Z|4E^A-I;D3Rxli<6{Ww~$RloB zezKz8FS&|L|HSNf6f!=Mdg_Y$*?rK?qW3z~&HE2gkALa=Viz5(l&%PJsK*$K zim@QVkTt#cdNmzY8~pn~P_eh+7lJ0SGFB^W)|^+!06Je`{_|5J)v$y?y8>F7<@*lq zgG3tir6QDNd<{+XgnNhpn@gzPS|*8?RwAJuxg?+@Krvt1f>xdLdg~5pqkFY1ls?tv zAa?Hn{MX8;*<9l_~=A%Z%GAcT{qUg|q3Uh~lyq436dJ7&F&~YH8&gw0=LCY3f z^>3Q4VAjz9b_VdW+^x)0pR`~pxY*bf5>Xb?gb7Dx<9JJt3~p1ruhS-cO;pf85*74o zicmRWiYNntku1X1TIL>N%6=WJ*I-8}dW7q`(ShGeFI*20=;`_II!iJD`TbAu&)|fK z%M4}l1lt@qeqR$_T0O3$1*T4Ub@p#o}Z;#NY&s}=4F zT{z}>wN$dDe@02uFmms&ro2s!{m`O^=&9BaElp%M#_80mi+Wd$z9;l5$7lWhP2CRx zYCyCZu+WAs54l5`Qki0zBh=WK4pcFoe5;u=$;v_Rs>kN|8P6~Aus_*=llgEzCF#LB zH0jtI+U@ZnF<%h>(Me@#p(9Ngy-;B;z=JCGe+F^5H^mr$-re~vo~Bm&zUXD z8!JQqx}%=j`9=PpFQhZjv9caOi0pkX?gCYpOmOWE`&uVihn+(iORaAE-x5i90y17M zn*4{E^vEBf!25p(NN7`{JFz;AwePYO1;OP#(9QXGZlpb&W2ex)P#>Y&ce&{3hQuuR za1}(#P+@Jkxc8CQ@OY&a7{QYI(^Gl_6#1u1p?{$3sHuzSi$zsP1s3yDjyY`94vnhe z`)zRa;kH_>8BCjOOvD)BZkU&mU32!*jKw zz?8VAs{;;pA}e+#eQTJ$>>Bs7-*M>oF~4V_F2Jml0@KKKSYGx|wMs`UWLmnW;C7C3 zl!I3#yPx@VVbs&96acY3Q6_77)ylaXeN>Q!dGrX8k>Wv?bnNIa%e4SqhNsbqZTX!; z%5#7NMKk`@BX>=}-*v7EY5bLoVC*!N9eYFwY8|1Z5pqRax6nD9u@RM+q-0Z^5-=IA z@S}eG=)DhIBhk6gYU z4?H=m%vkF^Nl75`g6|;8I!{;5Ho;1Eiw%9Gm9P)|dpb4tYVOl8YIAty^iRKiJR)AL z-bWGsUu@@{Kn+FGR4qRKFg(j6GqZ*!O-Cp6&q2B-;52QvB1t+3QmV>rONT%5+nK6j z=|ZkkDj<3|bj##)E9-Bq9j!sJzDS7K1Fzua<`?`xTs1*UjpAC)zR zo`1`a@YzeqL9y#YRY@HhePHg#5Q{nX4<_JG4CA=&@yI$naKFLZV#}i z2H?7mPs*~34%{~dg0T!*EL~h*(vY1(>|dqn+b{f-#R`o$6tJXVd&E_n-JV@g|Bl`r zr>isJHBnAdvO6PD#*ghiphT&WD88M`?Uxn57f4OQcU1x<1VHtXH!`n91I>978TA%4 z-hEKFEpA2TszH!J=?QdU0lTd%f z)V|>MHCP8Z+UOMVOOL}wMI`&Td!9H!a{t~ms$oTLkl*T98Vidv`_ZD12pb<~MmZ5{ zUh;&8ZJmT_Klj+#uYog?e^>(fbDuieMLRE`!34?1MbjxB^bheg4{GaTwz;BCW3z$v zboiUpvBtA^8?H9ngnv`;14Dd@zf^#GgiWoPTaN7X{ra`$$G^I4 zPhQBmxcL0eIiE(L5Ha_lwvNJbQI{hXdJI)(b4@g#4}Ns;k05S9U@dtyVXv8RIjHDR zv98dHE}MJ(h6ER_^mF=`qqnygp`Gm*(K((~j9mN;tF!Shr)t-UY?szI{a3yk4apd7 zW|4R%ga>)QK2^`BH<$t5+dk;UUM~UI!cuve>(sru8554*_n=Zv}0T~1q829=~lFG%`eOi!?#V?KWG!RrZ! zO^-REu5o_PGib7BZ1{sVP1THUgn@I9Qr{r^O)}x{2}$#lfdASVKJt2 zPDJQ{Q>hIrwo8pjV~2v=P$heSDDKuiNn2jJh@$=Sak3Y0Qpp`B&=oVy#YBjSjP^pm*Cus78bFcf0E4u9Fv@P znyP9TP#7Tfnnp_Ol3k9CM?;Aps|Pv&iPKFIO5W{ng#LW`!>NYWiM{bMGOvWai_DtF zi89y9oJm6cmYD#n0*rUO6Nxwxc8&H-=}%vxCP(nwkDn|a$BW0mhK~=KQm7@6f{Vv8 zULkCxp=LsuU3zrb+lG=j{GC>&H`oJYPv_UJuX(jWu4F1!=y1VR!0sL%tE;dx9hJ}d z=g;~nplp550hBRz<>+*gTLG_urCMR5fL(CmN<;M3Ew4V<;rj*MmDKKdifLKKUfOll2+&Zx@4b{r})|j5Ls4+ z^8t^~+1ge%nAV?^b-v&yCo=L#3nPy}wX*Ub_6T4|Uj3|^kO$;LNPUmGJ$th6iFHRBrUont%qDqurNFdXzTa@Q0( zU|?TUs??4ZBl~ao@4a8H2D6_pHm`hFQ4cFD`K%C8j%bt5Fd8F5Pf??z4n~yJ72j6M z-{wpWWRwiBaJO~;UmOmD-r5Q(9)S41P@NQF{xqOSGf?-KExVt)V) zI<%yEJX6zl5Ht=AhR5{SZ`MD2TKd<);X9LyQo}WoviTLI;GzA4xH#TC z6i{5<<48}Nx4F8vKOJGA?sR9QfqW+KSh$PR@W62fHPIK5cq*YP@I9;quSqyQ#fv?D z3$RTB!O%Tr*I@Aa6!*T;tv9v>Hu4!Heh*R3uwQZ0q!=M8UpZhn>#+APANASGc4OIJ zE5WPxOX~p%=1(rQrN>qDfxeAki5#5bnOdi(u901dy&nkx+HoVVdl~Z4cm&1jqKa2V z**~c>{e+8g<;<>WT^U32&%aAIa}%&K{Sb6(|RNB>M^7-Hc_aCFHwQ&9D}Wu$Zwv}Ww`3jc9jWq}KTT|9_GNA+c7n-eh{Rmm*$>p47^6(x2H9%^s1S qhk=;9s3fg#6$RpLXlG*3QBaQ8(W_H0ycYkD5UMP%E>|t{E#!Y)Q9w)p diff --git a/mods/photo_album/view.php b/mods/photo_album/view.php deleted file mode 100644 index 6b6dbc9c5..000000000 --- a/mods/photo_album/view.php +++ /dev/null @@ -1,173 +0,0 @@ - - -isError()!=true){ //no error is occured with the view object, so display view page. - $_SESSION['pa']['course_id']=$view->getVariable('course_id'); - $_SESSION['pa']['image_id']=$view->getVariable('image_id'); - - $image_array=$view->getVariable('image_array'); - $template=new HTML_Template_ITX("./Template"); - $template->loadTemplatefile("view.tpl.php", true, true); - - $template->setVariable("IMAGE_TITLE_STRING", _AT('pa_tag_image_title')); - $template->setVariable("IMAGE_TITLE", $image_array['title']); - $template->setCurrentBlock("IMAGE"); - - /* display delete and edit buttons for the image */ - if (user_own(IMAGE, $_SESSION['pa']['image_id'], $_SESSION['pa']['course_id'])==true){ - $template->setCurrentBlock("IMAGE_MODIFY_BUTTONS"); - $template->setVariable("IMAGE_CHOOSE", IMAGE); - $template->setVariable("EDIT_FORM", "edit_form"); - $template->setVariable("EDIT_ACTION", UPLOAD_ACTION); - $template->setVariable("EDIT_DISPLAY", _AT('pa_button_edit_image')); - $template->setVariable("DEL_FORM", "DEL_action"); - $template->setVariable("DEL_ACTION", DELETE_CONFIRM_ACTION); - $template->setVariable("DEL_DISPLAY", _AT('pa_button_del_image')); - $template->setVariable("IMAGE_ID", $image_array['image_id']); - $template->parseCurrentBlock("IMAGE_MODIFY_BUTTONS"); - } - - /* display the image */ - $template->setVariable("IMAGE_SRC", $get_file.$image_array['location'].urlencode($image_array['view_image_name'])); - $template->setVariable("ALT", $image_array['alt']); - $template->parseCurrentBlock("IMAGE"); - - - /* display image information */ - $template->setCurrentBlock("TABLE"); - $template->setVariable("IMAGE_DISPLAY", _AT('pa_tag_image_description')); - $image_owner_name=get_member_name($image_array['login']); - $template->setVariable("IMAGE_NAME_STRING", _AT('name')); - $template->setVariable("IMAGE_NAME", $image_owner_name); - $template->setVariable("IMAGE_DESC", convert_newlines($image_array['description'])); - $template->setVariable("IMAGE_DATE_STRING", _AT('date')); - $template->setVariable("IMAGE_DATE", $image_array['date']); - $template->parseCurrentBlock("TABLE"); - - if ($view->getVariable('show_modification_buttons')==true){ - $template->setCurrentBlock("ADD_COMMENT_BUTTON"); - $template->setVariable("ADD_FORM", "add_form"); - $template->setVariable("ADD_ACTION", ADD_ACTION); - $template->setVariable("ADD_DISPLAY", _AT('pa_button_add_comment')); - $template->setVariable("COMMENT_CHOOSE", COMMENT); - $template->parseCurrentBlock("ADD_COMMENT_BUTTON"); - } - - /* display comments */ - $comment_array=$view->comment_array; - if (count($comment_array) >= 1){ - $template->setCurrentBlock("COMMENT_HEAD"); - $template->setVariable("COMMENT_DISPLAY", _AT('pa_tag_comment_description')); - - for ($i=0; $igetVariable('show_modification_buttons')) && ($user_own==true)){ - $template->setCurrentBlock("COMMENT_START"); - $color=''; - if ((is_admin_for_course()==true) || ($user_own==true)){ - if ($comment_array[$i]['status']==DISAPPROVED){ - $color="disapproved"; - $template->setVariable("MESSAGE", _AT('pa_note_comment_disapproved')); - } else if ($comment_array[$i]['status']==POSTED_NEW){ - $color="posted_new"; - $template->setVariable("MESSAGE", _AT('pa_note_comment_posted_new')); - } - } - $COMMENT_DEL_FORM="blog_del_form"; - $COMMENT_DEL_ACTION=DELETE_CONFIRM_ACTION; - $COMMENT_DEL=_AT('pa_button_del_comment'); - - $COMMENT_EDIT_FORM="blog_edit_form"; - $COMMENT_EDIT_ACTION=EDIT_ACTION; - $COMMENT_EDIT=_AT('pa_button_edit_comment'); - $COMMENT_ID=$comment_array[$i]['comment_id']; - $COMMENT_CHOOSE=COMMENT; - - - $template->setVariable("COLOR", $color); - $template->setVariable("COMMENT_NAME", $blog_owner_name); - $template->setVariable("COMMENT_VALUE", convert_newlines($comment_array[$i]['comment'])); - $template->setVariable("COMMENT_DATE", $comment_array[$i]['date']); - - $control_button="

    "; - $control_button.="
    "; - $control_button.=""; - $control_button.=""; - $control_button.=""; - $control_button.=""; - $control_button.="
    "; - - - $control_button.="
    "; - $control_button.=""; - $control_button.=""; - $control_button.=""; - $control_button.=""; - $control_button.="
    "; - $control_button.="
    "; - - - $template->setVariable("CONTROL_BUTTONS", $control_button); - $template->parseCurrentBlock("COMMENT_START"); - } else { - $template->setCurrentBlock("COMMENT_START"); - $template->setVariable("COMMENT_NAME", $blog_owner_name); - $template->setVariable("COMMENT_VALUE", convert_newlines($comment_array[$i]['comment'])); - $template->setVariable("COMMENT_DATE", $comment_array[$i]['date']); - $template->parseCurrentBlock("COMMENT_START"); - } - } - $template->parseCurrentBlock("COMMENT_HEAD"); - } - - $template->parseCurrentBlock(); - $template->show(); -} else { - $msg->addError('pa_obj_view'); - redirect('index.php'); -} -?> - - diff --git a/mods/photos/addComment.php b/mods/photos/addComment.php deleted file mode 100644 index a67becb77..000000000 --- a/mods/photos/addComment.php +++ /dev/null @@ -1,54 +0,0 @@ -0){ - $isPhoto = true; - $id = $pid; -} else { - $isPhoto = false; - $id = $aid; -} - - -//Error checking -if (trim($_POST['comment']) == ''){ - //if comment is empty - $msg->addError('PA_EMPTY_COMMENT'); //sql -} else { - $pa = new PhotoAlbum(); - $result = $pa->addComment($id, $_POST['comment'], $_SESSION['member_id'], $isPhoto); - - if ($result){ - //TODO: AJAX - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - } else { - $msg->addError('PA_ADD_COMMENT_FAILED'); //sql - } -} - -if ($isPhoto){ - header('Location: photo.php?pid='.$pid.SEP.'aid='.$aid); -} else { - header('Location: albums.php?id='.$aid); -} -exit; -?> diff --git a/mods/photos/admin/preferences.php b/mods/photos/admin/preferences.php deleted file mode 100644 index a2d214523..000000000 --- a/mods/photos/admin/preferences.php +++ /dev/null @@ -1,39 +0,0 @@ -addError('PA_MEMORY_INPUT_ERROR'); - } else { - $sql = 'UPDATE '.TABLE_PREFIX."config SET value='$max_memory' WHERE name='pa_max_memory_per_member'"; - $result = mysql_query($sql, $db); - if ($reuslt===false){ - $msg->addError('PA_MEMORY_SQL_ERROR'); - } else { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: preferences.php'); - exit; - } - } -} - -require (AT_INCLUDE_PATH.'header.inc.php'); -$savant->assign('max_memory', $_config['pa_max_memory_per_member']); -$savant->display('admin/pa_preferences.tmpl.php'); -require (AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/photos/albums.php b/mods/photos/albums.php deleted file mode 100644 index 356907dd0..000000000 --- a/mods/photos/albums.php +++ /dev/null @@ -1,177 +0,0 @@ -'; - -$id = intval($_REQUEST['id']); -$pa = new PhotoAlbum($id); -$info = $pa->getAlbumInfo(); -$action_permission = $pa->checkAlbumPriv($_SESSION['member_id']); - -//TODO: Validate users, using permission and course album control. -if ($info['member_id'] != $_SESSION['member_id']){ - $visible_albums = $pa->getAlbums($_SESSION['member_id'], $info['type_id']); - if(!isset($visible_albums[$id]) && $info['permission']==AT_PA_PRIVATE_ALBUM){ - //TODO msg; - $msg->addError("ACCESS_DENIED"); - header('location: index.php'); - exit; - } -} - -//Set pages/submenu -$_pages[AT_PA_BASENAME.'index.php']['children'] = array(AT_PA_BASENAME.'albums.php'); - -$_pages[AT_PA_BASENAME.'albums.php']['title'] = _AT('pa_albums') .' - '.$info['name']; -if ($info['type_id']==AT_PA_TYPE_MY_ALBUM){ - $_pages[AT_PA_BASENAME.'albums.php']['parent'] = AT_PA_BASENAME.'index.php'; -} elseif ($info['type_id']==AT_PA_TYPE_COURSE_ALBUM){ - $_pages[AT_PA_BASENAME.'albums.php']['parent'] = AT_PA_BASENAME.'course_albums.php'; -} -//if this member has the permission to edit the album, show the edit/organize menu -if ($action_permission){ - $_pages[AT_PA_BASENAME.'albums.php']['children'] = array( - AT_PA_BASENAME.'edit_photos.php?aid='.$id, - AT_PA_BASENAME.'edit_photos.php?aid='.$id.SEP.'org=1', - ); - $_pages[AT_PA_BASENAME.'edit_photos.php?aid='.$id]['title_var'] = 'pa_edit_photos'; - $_pages[AT_PA_BASENAME.'edit_photos.php?aid='.$id]['parent'] = AT_PA_BASENAME.'albums.php'; - $_pages[AT_PA_BASENAME.'edit_photos.php?aid='.$id.SEP.'org=1']['title_var'] = 'pa_organize_photos'; - $_pages[AT_PA_BASENAME.'edit_photos.php?aid='.$id.SEP.'org=1']['parent'] = AT_PA_BASENAME.'albums.php'; -} - -//TODO: handle add_photo -if(isset($_POST['upload'])){ - //check file size, filename, and extension - $_FILES['photo'] = checkPhoto($_FILES['photo']); - if ($_FILES['photo']===false || (!$action_permission && $info['type_id']!=AT_PA_TYPE_COURSE_ALBUM)){ - //owner and course members can upload pictures. Not edit though. - echo json_encode(array( - 'aid'=>$id, - 'pid'=>-1, - 'msg'=>htmlentities($msg->printErrors()), - 'error'=>true)); - exit; - } - - //computer album folder name and photo filename, if exist, shift bits - //goal: generate a random yet computable file structure to disallow - // users to browse through others' photos through URLs. - $album_file_path = getAlbumFilePath($id, $info['created_date']); - $album_file_path_tn = $album_file_path.'_tn'.DIRECTORY_SEPARATOR; - $album_file_path .= DIRECTORY_SEPARATOR; - - if (!is_dir(AT_PA_CONTENT_DIR.$album_file_path)){ - mkdir(AT_PA_CONTENT_DIR.$album_file_path); - } - if (!is_dir(AT_PA_CONTENT_DIR.$album_file_path_tn)){ - mkdir(AT_PA_CONTENT_DIR.$album_file_path_tn); - } - - //add the photo - $result = $pa->addPhoto($_FILES['photo']['name'], $_POST['photo_comment'], $_SESSION['member_id']); - if ($result===FALSE){ - $msg->addError('PA_ADD_PHOTO_FAILED'); - } - - if (!$msg->containsErrors()){ - //get photo filepath - $added_photo_id = mysql_insert_id(); - $photo_info = $pa->getPhotoInfo($added_photo_id); - $photo_file_path = getPhotoFilePath($added_photo_id, $_FILES['photo']['name'], $photo_info['created_date']); - - //resize images to a specific size, and its thumbnail - $si = new SimpleImage(); - $si->load($_FILES['photo']['tmp_name']); - $image_w = $si->getWidth(); - $image_h = $si->getHeight(); - - //picture is horizontal - if($image_w > $image_h){ - //don't stretch images - if ($image_w > AT_PA_IMAGE){ - $si->resizeToWidth(AT_PA_IMAGE); - $si->save(AT_PA_CONTENT_DIR.$album_file_path.$photo_file_path); - } else { - move_uploaded_file($_FILES['photo']['tmp_name'], AT_PA_CONTENT_DIR.$album_file_path.$photo_file_path); - } - $si->resizeToWidth(AT_PA_IMAGE_THUMB); - $si->save(AT_PA_CONTENT_DIR.$album_file_path_tn.$photo_file_path); - } else { - if ($image_h > AT_PA_IMAGE){ - $si->resizeToHeight(AT_PA_IMAGE); - $si->save(AT_PA_CONTENT_DIR.$album_file_path.$photo_file_path); - } else { - move_uploaded_file($_FILES['photo']['tmp_name'], AT_PA_CONTENT_DIR.$album_file_path.$photo_file_path); - } - $si->resizeToHeight(AT_PA_IMAGE_THUMB); - $si->save(AT_PA_CONTENT_DIR.$album_file_path_tn.$photo_file_path); - } - if ($_POST['upload'] == 'ajax'){ - $photo_file_hash = getPhotoFilePath($added_photo_id, '', $photo_info['created_date']); - //return JSON, relying on jQuery to convert entries to html entities. - echo json_encode(array( - 'aid'=>$id, - 'pid'=>$added_photo_id, - 'ph'=>$photo_file_hash, - 'size'=>number_format(filesize(AT_PA_CONTENT_DIR.$album_file_path.$photo_file_path)/1024, 2), - 'title'=>$photo_info['title'], - 'alt'=>$photo_info['alt'])); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - exit; - } - } //if msg contain error - header('location: albums.php?id='.$id); - exit; -} - -//paginator settings -$page = intval($_GET['p']); -$photos_count = sizeof($pa->getAlbumPhotos()); -$last_page = ceil($photos_count/AT_PA_PHOTOS_PER_PAGE); - -if (!$page || $page < 0) { - $page = 1; -} elseif ($page > $last_page){ - $page = $last_page; -} - -$count = (($page-1) * AT_PA_PHOTOS_PER_PAGE) + 1; -$offset = ($page-1) * AT_PA_PHOTOS_PER_PAGE; - -//get details -$photos = $pa->getAlbumPhotos($offset); -$comments = $pa->getComments($id, false); -//TODO: Can improve performance by adding this to a session variable -$memory_usage = memoryUsage($_SESSION['member_id']); - -include (AT_INCLUDE_PATH.'header.inc.php'); -$savant->assign('album_info', $info); -$savant->assign('photos', $photos); -$savant->assign('comments', $comments); -$savant->assign('page', $page); -$savant->assign('num_rows', $photos_count); -$savant->assign('memory_usage', $memory_usage/(1024*1024)); //mb -$savant->assign('allowable_memory_usage', $_config['pa_max_memory_per_member']); //mb -$savant->assign('action_permission', $action_permission); -$savant->display('pa_albums.tmpl.php'); -include (AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/photos/course_albums.php b/mods/photos/course_albums.php deleted file mode 100644 index 78606ba75..000000000 --- a/mods/photos/course_albums.php +++ /dev/null @@ -1,47 +0,0 @@ -getAlbums($_SESSION['member_id'], $type)); - -//paginator settings -$page = intval($_GET['p']); -$last_page = ceil($album_count/AT_PA_ALBUMS_PER_PAGE); - -if (!$page || $page < 0) { - $page = 1; -} elseif ($page > $last_page){ - $page = $last_page; -} - -$count = (($page-1) * AT_PA_ALBUMS_PER_PAGE) + 1; -$offset = ($page-1) * AT_PA_ALBUMS_PER_PAGE; - -$albums = $pa->getAlbums($_SESSION['member_id'], $type, $offset); - -include (AT_INCLUDE_PATH.'header.inc.php'); -$savant->assign('albums', $albums); -$savant->assign('page', $page); -$savant->assign('type', $type); -$savant->assign('num_rows', $album_count); -$savant->display('pa_index.tmpl.php'); -include (AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/photos/create_album.php b/mods/photos/create_album.php deleted file mode 100644 index 4e5cf9a10..000000000 --- a/mods/photos/create_album.php +++ /dev/null @@ -1,74 +0,0 @@ -createAlbum($_POST['album_name'], $_POST['album_location'], $_POST['album_description'], $album_type, $album_permission, $_SESSION['member_id'], 0); - - if (!$result){ - //TODO: sql failure. - $msg->addError('PA_CREATE_ALBUM_FAILED'); - } - } else { - //album name can't be empty - //TODO: user input failure - $msg->addError('PA_EMTPY_ALBUM_NAME'); - } - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - - if($_POST['album_type'] == AT_PA_TYPE_COURSE_ALBUM){ - header('Location: course_albums.php'); - exit; - }else{ - header('Location: index.php'); - exit; - - } - -} elseif (isset($_POST['cancel'])){ - $msg->addFeedback('CANCELLED'); - header('Location: '.AT_PA_BASE); - exit; -} - -include (AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('pa_create_album.tmpl.php'); -include (AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/photos/delete_album.php b/mods/photos/delete_album.php deleted file mode 100644 index da4951fdf..000000000 --- a/mods/photos/delete_album.php +++ /dev/null @@ -1,63 +0,0 @@ -getAlbumInfo(); - -if (!$pa->checkAlbumPriv($_SESSION['member_id'])){ - $msg->addError('ACCESS_DENIED'); - header('Location: index.php'); - exit; -} - -if ($_POST['submit_no']) { - $msg->addFeedback('CANCELLED'); - Header('Location: index.php'); - exit; -} - -if ($_POST['submit_yes']) { - //delete - $pa->deleteAlbum(); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - - if($info['type_id']== AT_PA_TYPE_COURSE_ALBUM){ - Header('Location: course_albums.php'); - exit; - }else{ - Header('Location: index.php'); - exit; - } - -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -$hidden_vars['id'] = $id; -$msg->addConfirm(array('PA_DELETE_ALBUM', htmlentities_utf82($info['name'])), $hidden_vars); -$msg->printConfirm(); - -require(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/photos/delete_comment.php b/mods/photos/delete_comment.php deleted file mode 100644 index 7dbd5fca4..000000000 --- a/mods/photos/delete_comment.php +++ /dev/null @@ -1,88 +0,0 @@ -checkCommentPriv($comment_id, $_SESSION['member_id'], $isPhoto) && - !$pa->checkAlbumPriv($_SESSION['member_id'])){ - $msg->addError('ACCESS_DENIED'); - header('Location: index.php'); - exit; -} - -if ($_POST['submit_no']) { - $msg->addFeedback('CANCELLED'); - if ($isPhoto){ - header('Location: photo.php?pid='.$pid.SEP.'aid='.$aid); - } else { - header('Location: albums.php?id='.$aid); - } - exit; -} - -if ($_POST['submit_yes']) { - //delete - if ($pid==0){ - //not a photo - $pa->deleteComment($comment_id, false); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - Header('Location: albums.php?id='.$aid); - exit; - } else { - $pa->deleteComment($comment_id, true); - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - Header('Location: photo.php?pid='.$pid.SEP.'aid='.$aid); - exit; - } -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -$hidden_vars['comment_id'] = $comment_id; -$hidden_vars['aid'] = $aid; -$hidden_vars['pid'] = $pid; - - -$msg->addConfirm(array('PA_DELETE_COMMENT'), $hidden_vars); -$msg->printConfirm(); - -require(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/photos/delete_photo.php b/mods/photos/delete_photo.php deleted file mode 100644 index 7f5c6f438..000000000 --- a/mods/photos/delete_photo.php +++ /dev/null @@ -1,72 +0,0 @@ -addError('PA_PHOTO_NOT_FOUND'); //no such picture - header('Location: index.php'); - exit; -} elseif (!$pa->checkPhotoPriv($pid, $_SESSION['member_id']) && !$pa->checkAlbumPriv($_SESSION['member_id'])){ - $msg->addError('ACCESS_DENIED'); - header('Location: albums.php?id='.$aid); - exit; -} - -if ($_POST['submit_no']) { - $msg->addFeedback('CANCELLED'); - Header('Location: photo.php?aid='.$aid.SEP.'pid='.$pid); - exit; -} - -if ($_POST['submit_yes']) { - //delete - $pa->deletePhoto($pid); - - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: albums.php?id='.$aid); - exit; -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -$hidden_vars['pid'] = $pid; -$hidden_vars['aid'] = $aid; - -$msg->addConfirm(array('PA_DELETE_PHOTO'), $hidden_vars); -$msg->printConfirm(); - -require(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/photos/edit_album.php b/mods/photos/edit_album.php deleted file mode 100644 index 10257e638..000000000 --- a/mods/photos/edit_album.php +++ /dev/null @@ -1,86 +0,0 @@ -checkAlbumPriv($_SESSION['member_id'])){ - $msg->addError('ACCESS_DENIED'); - header('location: index.php'); - exit; -} - -$album_info = $pa->getAlbumInfo(); - -//handle Edit album info. -if(isset($_POST['submit'])){ - $pa = new PhotoAlbum($_POST['aid']); //new object - if (isset($_POST['album_type'])){ - $album_type = (intval($_POST['album_type'])==AT_PA_TYPE_MY_ALBUM)?AT_PA_TYPE_MY_ALBUM:AT_PA_TYPE_COURSE_ALBUM; - } else { - //default is "my album" 'cause normally user can't create course album. - $album_type = AT_PA_TYPE_MY_ALBUM; - } - - //private or shared album? - if (isset($_POST['album_permission'])){ - $album_permission = ($_POST['album_permission']==AT_PA_SHARED_ALBUM)?AT_PA_SHARED_ALBUM:AT_PA_PRIVATE_ALBUM; - } else { - $album_permission = AT_PA_PRIVATE_ALBUM; - } - - if (isset($_POST['album_name']) && $_POST['album_name']!=''){ - //TODO: photo_id = 0, should default to use the first one after multi-file uploader works - $result = $pa->editAlbum($_POST['album_name'], $_POST['album_location'], $_POST['album_description'], $album_type, $album_permission); - - if (!$result){ - $msg->addError('PA_EDIT_ALBUM_FAILED'); - } - } else { - //album name can't be empty - $msg->addError('EMPTY_ALBUM_NAME'); - - } - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - if (admin_authenticate(AT_ADMIN_PRIV_PHOTO_ALBUM, true)) { - //if admin - header('Location: index_admin.php'); - exit; - } - //header('Location: albums.php?id='.intval($_POST['aid'])); - header('Location: index.php'); - exit; -} elseif (isset($_POST['cancel'])){ - $msg->addFeedback('CANCELLED'); - if (admin_authenticate(AT_ADMIN_PRIV_PHOTO_ALBUM, true)) { - //if admin - header('Location: index_admin.php'); - exit; - } - header('Location: '.AT_PA_BASE); - exit; -} - - -include (AT_INCLUDE_PATH.'header.inc.php'); -$savant->assign('album_info', $album_info); -$savant->display('pa_edit_album.tmpl.php'); -include (AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/photos/edit_comment.php b/mods/photos/edit_comment.php deleted file mode 100644 index 08ec4065b..000000000 --- a/mods/photos/edit_comment.php +++ /dev/null @@ -1,46 +0,0 @@ -0){ - $isPhoto = true; -} else { - $isPhoto = false; -} -$cid = intval(str_replace('cid_', '', $cid)); - -$pa = new PhotoAlbum($aid); -//validates -if ($pa->checkAlbumPriv($_SESSION['member_id']) || $pa->checkCommentPriv($cid, $_SESSION['member_id'], $isPhoto)){ - $result = $pa->editComment($cid, $comment, $isPhoto); -} - -if ($result===true){ - //TODO: AJAX - header('HTTP/1.0 200 OK'); -} else { - header('HTTP/1.0 404 Not Found'); -} -exit; -?> \ No newline at end of file diff --git a/mods/photos/edit_photos.php b/mods/photos/edit_photos.php deleted file mode 100644 index 1300d73c7..000000000 --- a/mods/photos/edit_photos.php +++ /dev/null @@ -1,143 +0,0 @@ -checkPhotoPriv($pid, $_SESSION['member_id']) || $pa->checkAlbumPriv($_SESSION['member_id']))){ - $msg->addError("ACCESS_DENIED"); - header('location: index.php'); - exit; -} - -//get details -if ($pid > 0){ - //get only 1 photo - $photos = array($pa->getPhotoInfo($pid)); -} else { - $photos = $pa->getAlbumPhotos(); -} -$album_info = $pa->getAlbumInfo(); - -//Set pages/submenu -$_pages[AT_PA_BASENAME.'albums.php?id='.$aid]['title'] = _AT('pa_albums') .' - '.$album_info['name']; -$_pages[AT_PA_BASENAME.'albums.php?id='.$aid]['parent'] = AT_PA_BASENAME.'index.php'; -$_pages[AT_PA_BASENAME.'albums.php?id='.$aid]['children'] = array( - AT_PA_BASENAME.'edit_photos.php', - ); -$_pages[AT_PA_BASENAME.'edit_photos.php']['parent'] = AT_PA_BASENAME.'albums.php?id='.$aid; - - -//handle organize -if(isset($_GET['org'])){ - $_custom_head .= ''; - //reset pages/submenu - $_pages[AT_PA_BASENAME.'edit_photos.php']['title'] = _AT('pa_organize_photos'); - - if (isset($_POST['submit'])){ - foreach($photos as $index=>$photo_array){ - $ordering = $_POST['image_'.$photo_array['id']]; - if(isset($ordering)){ - $result = $pa->editPhotoOrder($photo_array['id'], $ordering); - if (!$result){ - $msg->addError('PA_EDIT_PHOTO_FAILED'); - } - } - } - exit; - } - include (AT_INCLUDE_PATH.'header.inc.php'); - $savant->assign('album_info', $album_info); - $savant->assign('photos', $photos); - $savant->display('pa_organize_photos.tmpl.php'); - include (AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -//handle Edit. -if (isset($_POST['submit'])){ - //update photo description - foreach($photos as $index=>$photo_array){ - $alt_text = $_POST['alt_text_'.$photo_array['id']]; - $description = $_POST['description_'.$photo_array['id']]; - $deletion = $_POST['delete_'.$photo_array['id']]; - //don't have to update description if it's deleted - if (isset($deletion)){ - $pa->deletePhoto($photo_array['id']); - } elseif (isset($description)){ - $result = $pa->editPhoto($photo_array['id'], $description, $alt_text); - if (!$result){ - //TODO: sql error - $msg->addError('PA_EDIT_PHOTO_FAILED'); - } - } - } - - //update photo album. - if (isset($_POST['album_cover'])){ - $result = $pa->editAlbumCover($_POST['album_cover']); - if (!$result){ - //albumcover error. - $msg->addError('PA_EDIT_PHOTO_FAILED'); - } - } - - //if no errors - if ($_POST['submit'] == 'ajax'){ - //ajax, return 200 status - header('HTTP/1.1 200 OK'); - exit; - } - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - if (admin_authenticate(AT_ADMIN_PRIV_PHOTO_ALBUM, true)) { - //if admin - header('Location: index_admin.php'); - exit; - } - header('Location: albums.php?id='.$aid); - exit; -} elseif (isset($_POST['cancel'])){ - $msg->addFeedback('CANCELLED'); - if (admin_authenticate(AT_ADMIN_PRIV_PHOTO_ALBUM, true)) { - //if admin - header('Location: index_admin.php'); - exit; - } - header('Location: albums.php?id='.$aid); - exit; -} - - -include (AT_INCLUDE_PATH.'header.inc.php'); -$savant->assign('album_info', $album_info); -$savant->assign('photos', $photos); -$savant->display('pa_edit_photos.tmpl.php'); -include (AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/photos/get_photo.php b/mods/photos/get_photo.php deleted file mode 100644 index 8052753b0..000000000 --- a/mods/photos/get_photo.php +++ /dev/null @@ -1,103 +0,0 @@ -getAlbumInfo(); -$photo_info = $pa->getPhotoInfo($pid); -$album_file_path = getAlbumFilePath($album_info['id'], $album_info['created_date']); -if (isset($_GET['size']) && $_GET['size'] == 'o') { - //if original - $album_file_path .= DIRECTORY_SEPARATOR; -} else { - //if thumbnail - $album_file_path .= '_tn'.DIRECTORY_SEPARATOR; -} -$photo_file_path = getPhotoFilePath($photo_info['id'], $photo_info['name'], $photo_info['created_date']); -$photo_file_hash = getPhotoFilePath($photo_info['id'], '', $photo_info['created_date']); - -$file = AT_PA_CONTENT_DIR . $album_file_path . $photo_file_path; - -//if file does not exist, quit. -if (!file_exists($file)){ - //TODO: Clean files silently, cleaned but garbaged link remains on page. - //Remove node from the DOM tree? - $pa->deletePhoto($pid); - header('HTTP/1.1 404 Not Found', TRUE); - exit; -} -//if hash doesn't match, then don't load the picture. -//to prevent trial and error on URL for photos -if ($ph !== $photo_file_hash){ - header('HTTP/1.1 404 Not Found', TRUE); - exit; -} - -$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="'.$photo_file_path.'"'); - - /** - * 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/mods/photos/images/loading.gif b/mods/photos/images/loading.gif deleted file mode 100644 index 5b33f7e54f4e55b6b8774d86d96895db9af044b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1849 zcma*odr(tX9tZI2z31lM+(&YVk%mZ}5P~KlG2s=WSbGzm0!x7^P##Mnh7t-jP!X0Q zk_SQ}Po-L1tlDK;6l?(>v)e5ZBQx4|Y-Q?nr@Px3?9h(3ZWr3^tj=`TP57gKr87N$ zp2wWee1GRRCwo_xahnw)5cxNPJbCg2L6DV|6`#+yw6v6!mDS$f9-JvFD^n;GQ&UrZ zzh5jCkByB101O60U0q#p_1BM>Cv-vP?&s4@g_((4_1L=L$(a91)0=J91Gas#R{McE znYG^9*0A5YZ>#;~+Wkn(W5B0^yELIYLP!K}mB~<)AM@1&nqekynuaEGqPrzoH|KodRXJy)%+w_fu3nE5>@Bd_b zqC$EQ;{c`T&?EsNO|igL9gC7Ygxv?aQUEXMq?~>wg{EyW;VcJ37CUF#HjrT=KQO_* zS>M9yydXk18D(+QDJ1>r);Lav_uYKp$T?4vr{Q$lTo&pKv^?(>L-)G2*lwH!Ah7k? z7oH<8h-(KTKt5V6$8gF)C7Io&P5=SjTh)=zV=E2EUhQZP##L8S{d%UK>>+y82>+FV+#^BzW7u3F)Bb>=lYQ%%j`F>ASe zo*cw@V#u6T`A2He;70mR(V&iV&-7{qP~=SRf&jm9-T{*ZeZ}$rd0#6c&fLG^xJcf5 z+p<`wJYgW+_s*V{uI$nMB;%8`S_3>PfGOj3Rq}@Cx^+j?rk92fANSFDBYnOqQ>Vdj z)(|$AhP4t&Lb=Gvo2#3Gl%9<=Gv`Mz?Po@P4iLF!x}GUWJICDlFk-hS^Whyh7x~VH z@0vD1>HYD4&e+~yzS*-sFR{9`{QEEZO1zg7>R&7cHts-6j!xHVdA8eI+ZlVzd%`es zJT@$#GX(gvCJ1oJN%yLBK}{V=V;seo;!w|Yte!W1%5qLNFWqvZW>h&IiH+oPT=b@E zPhGzv5=(Un*X>v`>%8h_nj^NdYcE6NHS_ifkCV$*D)Tqrbu`s;<=t<4 zAHNqNV?6(g<1PY-w@#I-WYFViz?9TrkMr)u0g`O`u|>T;k|2sV*YF^punvT;$SuTy{j3Gv)yqD!R_CF>yR)MzmmYS5v+~R zXAdD%ng9?df;wd8GxR#%3O+gz};Vo;)sK%Bj-q>Oq%R7JU-KD?vYu>#2UjaDo z&8$>5xW~?KPD_#XFToU1hIb*VOMidUr6iYiO0N|i-7s`T8!cFT`rN!^1Pt78J93i6 z5HI1wIM$94m{3SLDvISDe6$ZG1;eq_D9RTaaC>=cO{@Bs>$IlPCPJJ$h$)-3vzNUQ6OsN#_zWxey!_9%hxwH2_dEJi=yY|1c7nDm2_Lm!Cof8-R_+9UkS zcBE(o47yE)oMR(Q=dp1a2wTX5KvvGyLqlWTa7V&!A*|w|)ax~1_~aJ0=_Lilg*0iQk7#ZD EAHN$8j{pDw diff --git a/mods/photos/images/next.png b/mods/photos/images/next.png deleted file mode 100644 index facc49220f94e33cc2abd7704298f9b71cbbb78b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5946 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 F0RRv1<|F_B diff --git a/mods/photos/images/photo_gallery.png b/mods/photos/images/photo_gallery.png deleted file mode 100644 index f18d9954aede100787e9010d40e7c51f60889a9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7430 zcmV+h9r@ykP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000s(NklzHqtIK12TTkM_dl^PFfcGMu)rjRRJa*_F>^EU@i8#S zN~76%_~_Grrw`s|a1&-=czp3T1B#v400000|Np`%$;80Gz#!*0Kf7S|z5jRLF#JFF zkl}w&P!L2y&CFv;sJ#-y{m%>xT2e?l?w#G(%q+;jz{AhLFy}G@0|O(|LM8?V1_lGh zU3G6685sUCF)#>-GBEIax5UAned*{U2A&U}7)+SHF+4c2<1S8D0RR91|Nmr>u}cDR z0EIvAY*M&vD8cgDlnaE$CJ8ZHe}t2>s|XH}|AFAp(Bjw<1aV_z4nadCA$SB8o`tU@vYhpiXXhkD2~&3~l;w$<_9+;8+4G^{F0yTs}6h|9qlsqHktR^TLn!PEW5 zs-AN$-l32=<|_kxQ~3FXWgnbKwhgQYM*C~lhwFKyqo8YH)DVnk;An6+nh-Uzi3Jis z@2Y?M=uLKBpS$+br*#8V03SdDz+?^p0RR7tl)Fn?0T{)9*JzS^_1>EVqF6QJp!fhm z)S+qw!9jEoBMMIb3ASUWf-WxN;2`263Jwl&(RQkcpx`SAF2%%(iI2RD38qOj(R2_4 zF*JDAkMo`L!TCWE>^xlgjD(S7J#BKET|!r5fNOOUaS!`?50GKUQc|s4~D+04}4i36m92&6edzz-`Tn zemvya3#CMgMELE2L<&?9j50h4Q1q$0Ip-$--r}JrHAP7RHm~N`b~I4lvQ7Fvz(D;1 zuDD4tyeAC}b)ceZgK>%|?0>mamS8*!e!`%D1W`6d2vjK8`zoKd(< zLP`UY1eF$ZZiN8+ak`v(A&yysDhVn|z@&mKLn0w$oMn;x-n;4AGLbSJREtodgHkY`GJb_V@L+BE-XKwl#&t(ype*S zi@Gi7D!h>Bu8Sho61euHK!%U+TDRmd(}z&0?)Hnbc;BW@@q9ZH?t6HtBG65p~Xd zs*6Mh$D#Lb_v#VLWI3?8`_t^%=wqa<;ndj+!+HL7ti?7yzq*4#1knJZ2$BS{1hN4P zDM-X2sKc>J&|K|y0+ViFDCN)rH=g6DNJ@?&iZLIlT1_NWv#uZjWF~T|=tpG)i(ewTpx1Mj&dOe?%8lZo^m&!wN zOh8fuTY-%)%Vo}gF4o;@EAy_07AJ=Tx&ea#t1*zx@bE_ug=IsG`c`;+v4e^A0orSt zm`Sbk+7F|P5Q>4dq7>k2R_g$Qp^fhOmC!&{rNTm3XK+F0%87f32DsJ&@x&A4ILzy? z9ff!T^fZ{v(9m4VyCLTd^S0;Fz7qi~{PupB`sLBJf*dxZ5mGszOOTX6G=idn-2zrC ztfg@np;XynMy5&?C{`ff1i2cRH881w z0Ova!6`(1rbpVlY&5xr8Gz3X4=M5(tSj3!ylkxfm0(8wA7KI7|}tPL2AC zTpXH_uKQCd0d8huzHcMh_jUC9C)dhxgV9k_Vnz+B#L`Cmp)@ngNhaqvnfCglYrb!R zslZ5JI1!x#`hm9sEM-Mdh717Hi`z9-g*lDDU|(O~%zk(GQicrwjdg#xFSih>>Nt*n z&i%}p`|b?0tM2T2+qD#03#lNJqz6%7#E_5@dI-YksUYYnf{37pdZ?Zg0)tQyQXiy? zg_rWu#dKZWi@U3{v*XO{%$zwh=ghhEa5ljQ8|$H<1LyJlKm2~b@A>|||9=G}{^za@ zaHf!_aOT5%%a8Acp%FEa&1N)BeMr-y+f-HCP0;RNZyy|xW%*85$Nux#^U)y=Kl-Yy zZhAkZMq-1}cx+SD(4X4){Jzb(Oe#OTvXAwvvy7~W(wBr6-}?=7?BM>C%sX8xx#aC! z?fBBmV{aYVyyb=G)(tMt^{gFAvu-d=KC6?8f+&C=fa^iWg_Z;BN3u+f$&WlxyCgmF z^`~#_%|nhZa*bC2~zi`^lSSSD{e8jfwE z7;#cDNJl{QpxT5&11viX;*tnS9gtu}MrPTDZG#j((}DJ1s;gsL!AxDi>v#w<48-Be zG+et43pMclaM8(P*tT005M+o(0L1`!va5sxr?ybGL6ihsKXhVI1XY5h0g?u)0&xut z6-;NTjRB~!IKUHKA#S^Ttm%NL2v|-))ea9lG5;}-zXk)x-{s-+pY!F-PnfaJvpflg z2J;Qb4fLZ$;!k&lv>LUeR?9?G6q>frf(5CV%XoR5tve6!_Np>x>*pw#GaR1$g4e%$ zlb8f^4d`3Zi`uhxuMm_QEP;8C)0A z{XHU6^aF+a&SclFd|)=JKiNST_#B|=Lo--<1wa8s162cE2VDbA3stysb@m>G-PeWN zw);)P>X3{}fQO=iu7;9LXpmGPrb9%B$e$oJ1Pu+|3%RdBR;txArE-IH!%<33hlC=b zi-Z=l6!vT%ECB=|ysP>?cpgLz4NJ;y=?ZC>?nJR{5>KWm&zi&~ornag7#`~S;Vguu zIP0t6xnZ0NkZ31|GhHFxrJt+S(w4fa?L6<@+vHh?rK@3&Z_MvXJxpt$< z^lXimG1S`?vg_Ger`>2yIzFSC7+}Z{SHK{k+47iMaJW3vV5Vpx20m+Y5w@<1^U{ti zb*qP0_J1%2ySp!~PQyGsUvftacO0g_y-lZWlh8!gE;HCLm}K*+933y9X1R>bS)BTP zksl|fnVg!a=G@Bl2MT);P5b`p+3WlFY!pc+3`8YHwIwlA2{>}L#CXACcH)Pn$oqfgu0Oalw-CFoI*kAJW$m@koclR*W+s`Lw3%rW(@;u6 ztxb#6VzDA94vJ8$sL#?Dp}zFh7cWosO%N2J6e|gcifw7FRIR2oNeeA$G95G1$xLSE z+|Rz8efMGQm=a?znX!T!7Mrv8KIg1&t^fYk_kHVQldAtS5&1#F^1a8YQ>Sity|MUZ zI?Ja%^zWWpJ!V#lG#g^l+!4<8xKjfAW^-}wF`pZt!l z9eKh;+QKXpinc7)g(X^sX-=EEcB>`CL1Ejsi{iHr+fvNlKUXkol?sh|8B3PAJSecb zd=6v%nKdVgzFV3QCvOlq><-MS3r8hdK|cHFlT|IFu3b<4uEkW$>A5q1t@no=>+PTijo>gs$t&sV4iT%QVW8dRbB}2})AKmP#+{ z8ffns%M4}DwY=#%q*t9ns-7Ju;D&0MKYD0}E>attw0x;2%3m z_xqtrq0>~&f~l*S(D?VX%`}ueX%C<@p}y-!Fj*ies>&&E>~O)FEt@c@xqu?2PaW#uj|6lSEXYaAcZ;`IS}$v)AKSj40XR~!}buG zHfRD8O@X{)vB5Ah@Qs<~^=9a%!31&iS{(G=@JCzpBk0Eh-PG{>m>`BI1uuoE3J3#i z6GD2N-ToVYc*EtLEodY=%wBngiWN~Sfo1iPmc#xkG)s9|rpn#vx|-GL$pWp}7OSIb zzQ?W|V3{_}%w`|Ez%A`vEr72*dGZe(JHu;IZ@u!5FpRAh;% z;ylOiDv}(WWPa{zEFAj+#jMOvDl;TV+z_1HJC1XP`|SnAa%s*MR>5FyVVafp{>ic` zwdZyX#IOg$YTlF@H;ocg{~0HQD%F7IeRVb+huO)$G#U?bLHe zXS`wO^=@ZCtb;Wn(6R()9N}j$N}wA+dki~1v_sW;5p*NiiJ+T+uPMe#b;u0JOwa`w z0)(ZSWhq}w2GweTxm#OoCbLt(-FqU<2i@VS@B4pgcY1hHhAbHrYzV`En2gMX)PzK+ zmgaFC0!&Mp_o59Gw#umr6YAQ8tvW7kMe(+!Oum$03P=;3g~b+GNL5Bh1Z@0=S9`fqKwheR6G>w>ZXBMd1TP&S~Fce-lk zK+L=e1+HqUXUYbYOqei1<}r&Ul`OK%Yv)V@%`iE1`?NN+7motB>{>Mg_`~t0<3)em zX^-w5xKmhAr_>Bs%}&{KbPyZxlQ(j@SE4RaN?z)~h@lhG_hN!D zAx^-ybgBh|Mny1FlN_vBH0R4mQB{kjrjaBWPLR-ZBf6uA^P4Wyh0vQj|Ff5YAM8n) z0c#nu>Z7)+J~&5Frf#iqL7q9|>2AqW$lAck?6 z(sLuW1`+F>kTWYIwgw?P!+>_DH+FhgoOrb9=-w4a_#2KHcE`X-DAj!WY5=<@V7_$Q z@_3LwblU3-*A{28L&q01VkB;4;D$OqKjTt2qUXoB5rjdIZmg|2&S2X~ye%git&g

    Q$^{0RJ=H&;U8mu+-Xy^zn8X6itu$FhS2V4S{ zPo6ya?#+Z@dmc5t&!1{Q6X*l+#~CeMpU(VWKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000a!NklLe~1oVULJzTsv^~*PgFW}(9oOiT=a|Nmp0K6mN!X%ku*W>4+@ zFC`)VpW+|~00030|ICvyO9Md^gy-ERXL11z=|v1i@PAlX31VeoYnj5r%737Zl@?-c zCxVS3f{I|N0TDY0MU@KfIuDQanQ2(dFxJ3W zOU#__p;n#3%JR~JfY9y6NRk0*W5De4fzz||c4MxN?X4!>-apVw`q0MWd%GjRW^-fl z;_?PUg3fIV+8D8x;hf9=QdBNseQlNEIFYDShWA4NBq?S2ri;Z8N-5N;layr{p6;*U z{SfnwS;+;I3J|COLV!p{t@bsJ_IL1mf&Z|rU+k1UYg9oLhMzO{-q}@1f)OhTqJ_jt zf*-*Ti1`D82!Z792!f4vrm@i~AU2lTWV=+$YBX-Z-=NuKvwQD7XJ#xmqzdR2vC-4b zVc?y4&wHNV+Pc32#(!5NKdJfT={jbHs#2?>s;C;OhM6WcBUr#fB!obSfy_BJUOty! z7V$+6Bw`G>;1FPNFifo?M=fA#s2OH~5CSnJsX}aKSG(P&-EQH%r`!7!fpogvLiLDV zWkpriT)H^7T-PdfT~n(z6Pcc#;^X$t>df?1TDrR^31M7T91IT`4u{|*9F9iP?S0-H zmnGE+1o^35vu9?~%ES9dr$j<{^!OPuMVw@UBoZLUH$aePKRI`HRyJP0tuD-+=gRzL zZrxa*^ZpIrz7N>jAEf1_+pFWz_!yd1Ra4bfvyK0<`xRg0c<t;HA#G0^XI==VD84fY8!rnQv^<$pl_k@~@o`NLRML}C0p zGjs2I2@A`*Z((=M8WS)?42V(?Lo`y5Xh>*GEHt5k*gzx!3yp=16dL~(1P#r0TiBQw z3JVulBP1J9!H@+60xYb-Xk-l$bcx+grGBRKc( zZFl?5-G%idEmBpe2vQmwL~;>QV*d90A0JLkJU*tT5K)L$ zC?tZ78=fpK{QBFQ!adMR2mvAZB<3859G;jMf8Qhtu%uQ+7OWmvWph`qH$@m?QvXb{ zEC2>bP%tydk(s5oaK&1Y8D(VLUtDx53N?eO))&e197F_#VP)lSBM{USEZt!!(J4v* zMj{F`gPH-_!-lBY$kAvv@bKZ14X#;(5IlqxouWjiC{Pp;DoSOPs;cg!_0X2-m+EfB110OUuhP(i%pykz;sh2xH^x@$8P> z$g&LHIU<)xJt!7Roxf@1_r zRf+aE!d&OwM#QFRh*ohdiwC8121d!1GT5?)}6cX z-lq)nsj4gloceCsUfcUBoKFc&L{=K#<>lf8R()8(tz zp=Ol{6Gb? znmq3MnA#WlZ$m+6GCrAcVUgbH;}=yZ4g# z6>)tax9R3?Hv2IDnKOI-=Xd6RiLNVVwyHv^LaIWlLaIXk)@c9H-wQ8qhhYX+T;`Gz z+rSu`dSO%X&Y3flcIJ$FNX2YnA$HcXg|)5>Q!W5ZTsbj}rAroX{B`OqWfEFSX{dxx zkof$xkV~Ah6Ej>K{jyXl*`}sBJ}lA!vq?mh2X0u}I#CqkriHB&hM9T}_kQ$OB;c|_ zE0@z?Lofi4V;~kgZDG-r69okdDm?V z!jKZsl)P)w5H#5c@jVZ|mxt$j@I4&rujGz?YVktxvg-8&EB5k86R-~b|+1%t&`m0AVp4Vc%Fy4x>`K=z--*!zD^D&Il4Rh>RCZ=U;j{&Z!S3s zMK1f;y@@CGP$H z;GPWfNKQa%&Rse$Ty53eE9jNic5E9tHJ*Nf*zwIIs}J^eVW4+!>am7~hRLwC8`iIx zN^OhF_$GA$8RZeJ9SGDKN(mTD;{Vxap4dA7`X+k*#aGXkN+G}~J6UT}Cp_4<*NGIj z`|+;N>Oo{TcRbu_SS$>)NsVPDq4m>n(cx4%OO}YxN`n;1nFf+)Z|?knpX%5|$@>XQ zS1yzk2(3%nkc1XMn0w7EoIW#2W%CL2{|V>4O!q5;C#}*!DOHYfxKBR;c=GXw)EhhA zZ~5jxx6~Vu8iP}2%oym~mzqXc#>DBLVXd|8%a`%L^;`dFMT)1!pdgzU$;vonuM~mY zJ*l!#B88preAu~m&8m$}jdP$N`6t=XNeR$;b6dL6;a2bIjz=aocRboyC5=@fRUuU& dSFVuX2LLrTK^oNQum=DD002ovPDHLkV1hhIMjQYD diff --git a/mods/photos/images/search_bg.png b/mods/photos/images/search_bg.png deleted file mode 100644 index d6a18a0b12e2b20494dad4c40a9ff92aa294c7c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3290 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 1) { - clientTop = 0; - clientLeft = 0; - } - - var top = box.top / zoom + (window.pageYOffset || docElem && docElem.scrollTop / zoom || body.scrollTop / zoom) - clientTop, left = box.left / zoom + (window.pageXOffset || docElem && docElem.scrollLeft / zoom || body.scrollLeft / zoom) - clientLeft; - - return { - top: top, - left: left - }; - }; - } else { - // Get offset adding all offsets - var getOffset = function(el){ - var top = 0, left = 0; - do { - top += el.offsetTop || 0; - left += el.offsetLeft || 0; - el = el.offsetParent; - } while (el); - - return { - left: left, - top: top - }; - }; - } - - /** - * Returns left, top, right and bottom properties describing the border-box, - * in pixels, with the top-left relative to the body - * @param {Element} el - * @return {Object} Contains left, top, right,bottom - */ - function getBox(el){ - var left, right, top, bottom; - var offset = getOffset(el); - left = offset.left; - top = offset.top; - - right = left + el.offsetWidth; - bottom = top + el.offsetHeight; - - return { - left: left, - right: right, - top: top, - bottom: bottom - }; - } - - /** - * Helper that takes object literal - * and add all properties to element.style - * @param {Element} el - * @param {Object} styles - */ - function addStyles(el, styles){ - for (var name in styles) { - if (styles.hasOwnProperty(name)) { - el.style[name] = styles[name]; - } - } - } - - /** - * Function places an absolutely positioned - * element on top of the specified element - * copying position and dimentions. - * @param {Element} from - * @param {Element} to - */ - function copyLayout(from, to){ - var box = getBox(from); - -/* addStyles(to, { - position: 'absolute', - left : box.left + 'px', - top : box.top + 'px', - width : from.offsetWidth + 'px', - height : from.offsetHeight + 'px' - }); */ - } - - /** - * Creates and returns element from html chunk - * Uses innerHTML to create an element - */ - var toElement = (function(){ - var div = document.createElement('div'); - return function(html){ - div.innerHTML = html; - var el = div.firstChild; - return div.removeChild(el); - }; - })(); - - /** - * Function generates unique id - * @return unique id - */ - var getUID = (function(){ - var id = 0; - return function(){ - return 'ValumsAjaxUpload' + id++; - }; - })(); - - /** - * Get file name from path - * @param {String} file path to file - * @return filename - */ - function fileFromPath(file){ - return file.replace(/.*(\/|\\)/, ""); - } - - /** - * Get file extension lowercase - * @param {String} file name - * @return file extenstion - */ - function getExt(file){ - return (-1 !== file.indexOf('.')) ? file.replace(/.*[.]/, '') : ''; - } - - function hasClass(el, name){ - var re = new RegExp('\\b' + name + '\\b'); - return re.test(el.className); - } - function addClass(el, name){ - if ( ! hasClass(el, name)){ - el.className += ' ' + name; - } - } - function removeClass(el, name){ - var re = new RegExp('\\b' + name + '\\b'); - el.className = el.className.replace(re, ''); - } - - function removeNode(el){ - el.parentNode.removeChild(el); - } - - /** - * Easy styling and uploading - * @constructor - * @param button An element you want convert to - * upload button. Tested dimentions up to 500x500px - * @param {Object} options See defaults below. - */ - window.AjaxUpload = function(button, options){ - this._settings = { - // Location of the server-side upload script - action: 'upload.php', - // File upload name - name: 'userfile', - // File Title - title: '', - // Additional data to send - data: {}, - // Submit file as soon as it's selected - autoSubmit: true, - // The type of data that you're expecting back from the server. - // html and xml are detected automatically. - // Only useful when you are using json data as a response. - // Set to "json" in that case. - responseType: false, - // Class applied to button when mouse is hovered - hoverClass: 'hover', - // Class applied to button when AU is disabled - disabledClass: 'disabled', - // When user selects a file, useful with autoSubmit disabled - // You can return false to cancel upload - onChange: function(file, extension){ - }, - // Callback to fire before file is uploaded - // You can return false to cancel upload - onSubmit: function(file, extension){ - }, - // Fired when file upload is completed - // WARNING! DO NOT USE "FALSE" STRING AS A RESPONSE! - onComplete: function(file, response){ - } - }; - - // Merge the users options with our defaults - for (var i in options) { - if (options.hasOwnProperty(i)){ - this._settings[i] = options[i]; - } - } - - // button isn't necessary a dom element - if (button.jquery){ - // jQuery object was passed - button = button[0]; - } else if (typeof button == "string") { - if (/^#.*/.test(button)){ - // If jQuery user passes #elementId don't break it - button = button.slice(1); - } - - button = document.getElementById(button); - } - - if ( ! button || button.nodeType !== 1){ - throw new Error("Please make sure that you're passing a valid element"); - } - - if ( button.nodeName.toUpperCase() == 'A'){ - // disable link - addEvent(button, 'click', function(e){ - if (e && e.preventDefault){ - e.preventDefault(); - } else if (window.event){ - window.event.returnValue = false; - } - }); - } - - // DOM element - this._button = button; - // DOM element - this._input = null; - // If disabled clicking on button won't do anything - this._disabled = false; - - // if the button was disabled before refresh if will remain - // disabled in FireFox, let's fix it - this.enable(); - - // create the first input button on the fly - this._createInput(); - - this._rerouteClicks(); - }; - - // assigning methods to our class - AjaxUpload.prototype = { - setData: function(data){ - this._settings.data = data; - }, - disable: function(){ - addClass(this._button, this._settings.disabledClass); - this._disabled = true; - - var nodeName = this._button.nodeName.toUpperCase(); - if (nodeName == 'INPUT' || nodeName == 'BUTTON'){ - this._button.setAttribute('disabled', 'disabled'); - } - - // hide input - if (this._input){ - // We use visibility instead of display to fix problem with Safari 4 - // The problem is that the value of input doesn't change if it - // has display none when user selects a file -// this._input.parentNode.style.visibility = 'hidden'; - } - }, - enable: function(){ - removeClass(this._button, this._settings.disabledClass); - this._button.removeAttribute('disabled'); - this._disabled = false; - - }, - /** - * Creates invisible file input - * that will hover above the button - *

    - */ - _createInput: function(){ - var self = this; - - var input = document.createElement("input"); -// var input = document.getElementById("upload_button"); - var div = document.getElementById("upload_button_div"); - input.setAttribute('type', 'file'); - input.setAttribute('name', this._settings.name); - input.setAttribute('id', 'add_more_photos'); - input.setAttribute('title', this._settings.title); - - addStyles(input, { -// 'position' : 'absolute', - // in Opera only 'browse' button - // is clickable and it is located at - // the right side of the input - 'right' : 0, - 'margin' : 0, - 'padding' : 0, -// 'fontSize' : '480px', - 'cursor' : 'pointer' - }); - -// var div = document.createElement("div"); -/* addStyles(div, { - 'display' : 'block', - 'position' : 'absolute', -// 'overflow' : 'hidden', - 'margin' : 0, - 'padding' : 0, - 'opacity' : 0, - // Make sure browse button is in the right side - // in Internet Explorer - 'direction' : 'ltr', - //Max zIndex supported by Opera 9.0-9.2 - 'zIndex': 2147483583 - });*/ - - // Make sure that element opacity exists. - // Otherwise use IE filter -/* if ( div.style.opacity !== "0") { - if (typeof(div.filters) == 'undefined'){ - throw new Error('Opacity not supported by the browser'); - } - div.style.filter = "alpha(opacity=0)"; - } -*/ - addEvent(input, 'change', function(){ - - if ( ! input || input.value === ''){ - return; - } - - // Get filename from input, required - // as some browsers have path instead of it - var file = fileFromPath(input.value); - - if (false === self._settings.onChange.call(self, file, getExt(file))){ - self._clearInput(); - return; - } - - // Submit form when value is changed - if (self._settings.autoSubmit) { - self.submit(); - } - }); - - addEvent(input, 'mouseover', function(){ - addClass(self._button, self._settings.hoverClass); - }); - - addEvent(input, 'mouseout', function(){ - removeClass(self._button, self._settings.hoverClass); - - // We use visibility instead of display to fix problem with Safari 4 - // The problem is that the value of input doesn't change if it - // has display none when user selects a file -// input.parentNode.style.visibility = 'hidden'; - - }); - - div.appendChild(input); -// ajax_uploader = document.getElementById('ajax_uploader'); -// document.body.appendChild(div); -// ajax_uploader.appendChild(div); - - this._input = input; - }, - _clearInput : function(){ - if (!this._input){ - return; - } - - // this._input.value = ''; Doesn't work in IE6 - removeNode(this._input.parentNode); - this._input = null; - this._createInput(); - - removeClass(this._button, this._settings.hoverClass); - }, - /** - * Function makes sure that when user clicks upload button, - * the this._input is clicked instead - */ - _rerouteClicks: function(){ - var self = this; - - // IE will later display 'access denied' error - // if you use using self._input.click() - // other browsers just ignore click() - - /* Accessibility, use onClick - addEvent(self._button, 'mouseover', function(){ - if (self._disabled){ - return; - } - - if ( ! self._input){ - self._createInput(); - } - - var div = self._input.parentNode; - copyLayout(self._button, div); - div.style.visibility = 'visible'; - - }); - */ - - - addEvent(self._button, 'click', function(){ - if (self._disabled){ - return; - } - - if ( ! self._input){ - self._createInput(); - } - - var div = self._input.parentNode; - copyLayout(self._button, div); - div.style.visibility = 'visible'; - - }); - - - - // commented because we now hide input on mouseleave - /** - * When the window is resized the elements - * can be misaligned if button position depends - * on window size - */ - //addResizeEvent(function(){ - // if (self._input){ - // copyLayout(self._button, self._input.parentNode); - // } - //}); - - }, - /** - * Creates iframe with unique name - * @return {Element} iframe - */ - _createIframe: function(){ - // We can't use getTime, because it sometimes return - // same value in safari :( - var id = getUID(); - - // We can't use following code as the name attribute - // won't be properly registered in IE6, and new window - // on form submit will open - // var iframe = document.createElement('iframe'); - // iframe.setAttribute('name', id); - - var iframe = toElement(' - \ No newline at end of file diff --git a/mods/plog/index.php b/mods/plog/index.php deleted file mode 100644 index cbc091717..000000000 --- a/mods/plog/index.php +++ /dev/null @@ -1,62 +0,0 @@ - -
    -addInfo('PLOG_URL_ADD_REQUIRED'); -}elseif ($_GET['enter_blog']){ -?> - - - - - - - - - - - \ No newline at end of file diff --git a/mods/plog/index_admin.php b/mods/plog/index_admin.php deleted file mode 100644 index d319e18c4..000000000 --- a/mods/plog/index_admin.php +++ /dev/null @@ -1,40 +0,0 @@ -addInfo('PLOG_URL_ADD_REQUIRED'); - require (AT_INCLUDE_PATH.'header.inc.php'); - require (AT_INCLUDE_PATH.'footer.inc.php'); - -}else{ - - require (AT_INCLUDE_PATH.'header.inc.php'); - $sql="SELECT * FROM ".TABLE_PREFIX."admins WHERE login='$_SESSION[login]'"; - $result = mysql_query($sql, $db); - - while($row = mysql_fetch_array($result)){ - $pw = $row[1]; - } - - ?> - - \ No newline at end of file diff --git a/mods/plog/index_instructor.php b/mods/plog/index_instructor.php deleted file mode 100644 index f26eb8df2..000000000 --- a/mods/plog/index_instructor.php +++ /dev/null @@ -1,75 +0,0 @@ - -
    -
    -

    -

    -
    -
    - - -
    -
    -
    -
    - - - -
    - -
    -addInfo('PLOG_URL_ADD_REQUIRED'); -}elseif ($_GET['enter_blog']){ -?> - - - - - - - - \ No newline at end of file diff --git a/mods/plog/module.css b/mods/plog/module.css deleted file mode 100644 index 5ae893550..000000000 --- a/mods/plog/module.css +++ /dev/null @@ -1,188 +0,0 @@ -/* -This stylesheet is not being included because pLog is in an iframe. It is here for future reference -*/ -/* 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; -} - -/* - -*/ \ No newline at end of file diff --git a/mods/plog/module.php b/mods/plog/module.php deleted file mode 100644 index 41a08bd6b..000000000 --- a/mods/plog/module.php +++ /dev/null @@ -1,81 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_PLOG', $this->getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -$this->_stacks['plog'] = array('title_var'=>'plog', 'file'=>dirname(__FILE__).'/side_menu.inc.php'); -// ** possible alternative: ** -// $this->addStack('hello_world', array('title_var' => 'hello_world', 'file' => './side_menu.inc.php'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ - -$_student_tool = 'mods/plog/index.php'; - -// ** possible alternative: ** -// $this->addTool('./index.php'); - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_PLOG, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/plog/index_admin.php'); - $this->_pages['mods/plog/index_admin.php']['parent'] = AT_NAV_ADMIN; - $this->_pages['mods/plog/index_admin.php']['title_var'] = 'plog'; - $this->_pages['mods/plog/admin_plog.php']['title_var'] = 'plog_admin'; - $this->_pages['mods/plog/index_admin.php']['children'] = array('mods/plog/admin_plog.php'); - $this->_pages['mods/plog/admin_plog.php']['parent'] = 'mods/plog/index_admin.php'; - -} - -/******* - * instructor Manage section: - */ -$this->_pages['mods/plog/index_instructor.php']['title_var'] = 'plog'; -$this->_pages['mods/plog/index_instructor.php']['parent'] = 'tools/index.php'; - -// Instructor and student plogs are the same, so grant access to sync dabatases only if the user is the course instructor. -/* -if($_SESSION['is_admin']){ - $this->_pages['mods/plog/sync_plog.php']['title_var'] = 'plog_sync_dbs'; - $this->_pages['mods/plog/index_instructor.php']['children'] = array('mods/plog/sync_plog.php'); - $this->_pages['mods/plog/sync_plog.php']['parent'] = 'mods/plog/index_instructor.php'; -}*/ -// ** possible alternative: ** -// $this->pages['./index_instructor.php']['title_var'] = 'hello_world'; -// $this->pages['./index_instructor.php']['parent'] = 'tools/index.php'; - -/******* - * student page. - */ -$this->_pages['mods/plog/index.php']['title_var'] = 'plog'; -$this->_pages['mods/plog/index.php']['img'] = 'mods/plog/plog_logo.gif'; - -// If pLog was installed with something other than the default database table prefix "plog_" -// adjust this setting below -define('PLOG_PREFIX', "lt_"); - - - -?> \ No newline at end of file diff --git a/mods/plog/module.sql b/mods/plog/module.sql deleted file mode 100644 index 3e98e8c6b..000000000 --- a/mods/plog/module.sql +++ /dev/null @@ -1,34 +0,0 @@ -# sql file for pLog module - -INSERT INTO `language_text` VALUES ('en', '_module','plog','Blog',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','plog_own_window','Open blog in a new window',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','plog_login','Blog Login',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','plog_summary','Public Blog',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','plog_course','Course Blog',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','plog_admin','Administer Blog',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','plog_current','Current Blog Entries',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','plog_sync','Update blogs when new students are enrolled in a course so they can post to the course blog. Update blogs when a new course is added to the system to enable its blog.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','plog_sync_button','Update Blogs',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','plog_location','The location/URL of WebCalendar being used with this installation of ATutor',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','plog_edit','Edit pLog Location',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','plog_save','Save pLog Location',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','plog_add_url','Type in the URL to pLog. This should be the the URL to the root directory, with no filename added (e.g. http://www.mysite.com/plog/ ).',NOW(),''); - - -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_PLOG_UPDATE_NOT_REQUIRED','No updates were required.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_PLOG_UPDATE_SUCCESSFUL','Blogs were successfully updated.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_PLOG_UPDATE_MEMBERS_FAILED','Update blog users failed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_PLOG_UPDATE_MEMBERS_SAVED','Update blog users successful',NOW(),''); -#INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_PLOG_UPDATE_ADMINS_FAILED','blog text',NOW(),''); -#INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_PLOG_UPDATE_ADMINS_SAVED','blog text',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_PLOG_UPDATE_COURSE_FAILED','Update course blogs failed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_PLOG_UPDATE_COURSE_SAVED','Update course blogs successful',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_PLOG_UPDATE_PERMISSIONS_FAILED','Update course blog access permissions failed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_PLOG_UPDATE_PERMISSIONS_SAVED','Update course blog access permissions successful',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_PLOG_UPDATE_CATS_FAILED','Update course default blog category failed',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_PLOG_UPDATE_CATS_SAVED','Update course default blog categories successful',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_PLOG_URL_ADD_EMPTY','The Location/URL cannot be empty',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_PLOG_URL_ADD_SAVED','pLog Location was saved successfully.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_PLOG_URL_ADD_FAILED','pLog Location was not saved',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_INFOS_PLOG_URL_ADD_REQUIRED','The pLog location has not yet been recorded. Select Administer Blog, then enter the URL to the pLog.',NOW(),'') - diff --git a/mods/plog/module.xml b/mods/plog/module.xml deleted file mode 100644 index 5b97d269d..000000000 --- a/mods/plog/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - LifeType pLog - This module links the LifeType Blog into the student, instructor, and administrator sections of ATutor. Each course gets one blog, owned by the coruse instructor, that all students can post to. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - GPL - - 0.1 - 2005-12-23 - stable - pLog must be installed and functioning before installing this module. See the README_ATUTOR_MODULE file in the plog module directory for IMPORTANT additional information. Be sure to run *Update Blogs* after the installation is complete to import ATutor user and course information into the pLog database. Instructors should also be told to run their version of Update Blogs when they create a new courses, or when new students enroll in their courses. - - \ No newline at end of file diff --git a/mods/plog/module_install.php b/mods/plog/module_install.php deleted file mode 100644 index 784c35332..000000000 --- a/mods/plog/module_install.php +++ /dev/null @@ -1,48 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/plog/plog_logo.gif b/mods/plog/plog_logo.gif deleted file mode 100644 index af3680bff091e73a9758674eb6fdd8cafe4252e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1604 zcmV-K2D|x3Nk%w1VK4wN0O$Vz009641_1{O1quuZ3l0ho5e^a*5f&I08XFlL9UC7Y z9w8$jBP1dwCnYE;Co3%~F*7hTH8M9jHak2zKS4f1L_tMHL`O+RO;1cwQczV_R9IS9 zTU}ZJqXJ-JUjU^B51;@5rwRb27h`2&3ZWAKtpEk74*;(MXK7{tuNDBZ2n(wb0Js1E zx&Q#T5^Zm62(%6Wyaf-hBpa$J2EGaa!~g)o5CFyibar$2OaLdaFbBy88@Dxidw2lN z4*<{r_EP`?(f|O^6@Gwy4AccEy*v0@5`lw&FTON{hJ*KF6f4CrhKPlSiH7-OA&82H z6WJml(4WmSCAz%1dFP1wseqN(oAbOey}!Ki zz%z{FmGQwnz{0-%u8Q=-K#1&){IiV2#=?#3mGQ_*^~Ora$;PSQsq@NI{JNLP%gC7P zqoU@grsb~n&0fsT%l^Kg_0MLqB`yL*#6JC+uhpt-IKrZ!rkB8`_;nU z;NAG(oBh|t;NsuT?$G(;q~he^`sJ+3_t5;`(Bb>df z=-u_%|K!{2?dkjN#{B8t;`ZU-_}uO9>;3P@`|r;0@$UcZ;r#N~^7Qfl@9FFM?fmuN z^!D@o^z8Ea?(O{V@cQ)o_vrTc^!NGp|M&0x`Re)m`273w^#1w!{Q3X-`1}3(|NQ&> z|NH*`{Qv*|A^8LW3IP8AEC2ui05AYB000R70R0IZNU)&6g9sBUT*$DY!-o(fN>r%t z+pt&C=uMocPoNzqKyrvwvM1d}hr`A&ie)87NFXp>W=aT8k{&&ZTIGw#&1KA(K3yU@ z$Yllz5g|l~Fp+|35g0DoY(pqbiO7&aVPXYB>Yx-5B*1eE+`BSb|#*6k9Ck#g%NYX ztI`IJ6HqPraC1l28Oe1QAexLybOhM1o8?(#!`_CigYOnmb{rm!z0W z65+`{`lPeWDr*!c;w|&+gQA@Kpn@BQG>%Ec9ntu6PdbYzaau@m6dI?N0__uxC24?J zBOmtw6VEQGkfRNtFIj=iq5cqUYABzE`a@14&}5ScAiO4`%slht1FJ-bs#fbcjsQYV zF@Wrv$gYMyc+x`mT(T=U!0@UqAgoN=&@R1JlkFtE?h1{!3eB@CuakK5?6!aulO?*z z72|9oz^qFyxrxL>??L?7vTY*P_S$SByZl>_a-aZ0Zn^LhtS~|RurtcN+dk~+P>Rt#P^ge&^+1{yz;^8R&vR_6SI~NG|nEp@~*bvT(WZI95b-C z4MP13kzOvmrMN&C)re za||mq^XfF(c%>suB+v5Vy_$0TR5M8;&amV6!ocanPC4J4efVlw*82G5lvmDBKma?2 CL|S41 diff --git a/mods/plog/side_menu.inc.php b/mods/plog/side_menu.inc.php deleted file mode 100644 index e17716d6b..000000000 --- a/mods/plog/side_menu.inc.php +++ /dev/null @@ -1,38 +0,0 @@ - 0){ - echo '
      '; - while($row = mysql_fetch_array($result)){ - $sql2 = "SELECT * FROM ".PLOG_PREFIX."articles_text WHERE article_id = '$row[0]'"; - $result2 = mysql_query($sql2,$db); - while($row2 = mysql_fetch_array($result2)){ - echo '
    • '.$row2[3].'
    • '; - } - } -echo '
    '; - }else{ - echo ''._AT('none_found').''; - } -?> - -assign('dropdown_contents', ob_get_contents()); -ob_end_clean(); - -$savant->assign('title', _AT('plog_current')); -$savant->display('include/box.tmpl.php'); - -?> \ No newline at end of file diff --git a/mods/plog/sync_plog.php b/mods/plog/sync_plog.php deleted file mode 100644 index 212e1eace..000000000 --- a/mods/plog/sync_plog.php +++ /dev/null @@ -1,202 +0,0 @@ -addError('PLOG_UPDATE_MEMBERS_FAILED'); - - }else{ - $msg->addFeedback('PLOG_UPDATE_MEMBERS_SAVED'); - $message = 1; - } - } -//debug(md5($row[2])); - } - - - -//exit; -// The synchronizing of admin accounts is a problem because they are not admin members -// and don't have a user ID. or a course they are associated to. The following code was a first attempt -// at merging the admins into the plog_users table. - - -/* - $sql = "SELECT * from ".TABLE_PREFIX."admins"; - $result3 = mysql_query($sql); - - $sql5="SELECT user FROM ".PLOG_PREFIX."users"; - $result5 = mysql_query($sql5,$db); - - $i=''; - while($row5 = mysql_fetch_array($result5)){ - $i++; - $existing_admins[$i] = $row5[0]; - } - //update the plog_users table with ATutor admins - - while ($row = mysql_fetch_array($result3)){ - - $admin_pref = 's:0:"";'; - if(!in_array($row[0], $existing_admins)){ - $sql3 = "REPLACE INTO ".PLOG_PREFIX."users VALUES ( "; - - if($existing_admins != ''){ - $sql3 .= ' \''. $existing_admins[$row[0]].'\','; - }else{ - $sql3 .= "'',"; - } - - $sql3 .= "'$row[0]','".md5($row[1])."','$row[3]','$row[2]','','$admin_pref ','1','0')"; - - if(!$result4 = mysql_query($sql3, $db)){ - $msg->addError('PLOG_UPDATE_ADMINS_FAILED'); - }else{ - $msg->addFeedback('PLOG_UPDATE_ADMINS_SAVED'); - $message = 1; - } - } - } -*/ - - - // get a list of course titles and create values for the mangled_blog values in the plog_blogs table - - //update the plog_blogs table with ATutor courses. Creates one blog per course and assigns the instructor as the blog owner - - $sql5 = "SELECT * FROM ".TABLE_PREFIX."courses"; - $result5 = mysql_query($sql5,$db); - - // But first check to see if the course already exists - $sqlb = "SELECT id FROM ".PLOG_PREFIX."blogs"; - $resultb = mysql_query($sqlb,$db); - $i = ''; - while($rowb = mysql_fetch_array($resultb)){ - $i++; - $existing_blogs[$i]= $rowb[0]; - } - - $default_blog_settings = 'O:12:"blogsettings":3:{s:6:"_objId";N;s:3:"log";N;s:6:"_props";a:14:{s:6:"locale";s:5:"en_UK";s:14:"show_posts_max";s:2:"15";s:8:"template";s:7:"blueish";s:17:"show_more_enabled";b:1;s:16:"recent_posts_max";s:2:"10";s:17:"xmlrpc_ping_hosts";a:2:{i:0;s:27:"http://rpc.weblogs.com/RPC2";i:1;s:0:"";}s:16:"htmlarea_enabled";b:1;s:16:"comments_enabled";b:1;s:16:"categories_order";s:1:"1";s:14:"comments_order";s:1:"1";s:11:"time_offset";s:2:"-5";s:21:"link_categories_order";s:1:"1";s:29:"show_future_posts_in_calendar";b:0;s:27:"new_drafts_autosave_enabled";b:0;}}'; - - while ($row = mysql_fetch_array($result5)){ - //echo $row[0]; - - if(!in_array($row[0], $existing_blogs)){ - $course_title = addslashes($row[6]); - $spec_chars = array("'"); - $temp_course_title = str_replace($spec_chars, "","$row[6]"); - $temp_array = explode(" ", $temp_course_title); - $temp_mangle = strtolower($temp_array[0]."_".$temp_array[1]); - $sql2 = "REPLACE INTO ".PLOG_PREFIX."blogs VALUES ('$row[0]','$course_title','$row[1]','','$default_blog_settings','$temp_mangle','1','1')"; - - if(!$result1 = mysql_query($sql2)){ - $msg->addError('PLOG_UPDATE_COURSE_FAILED'); - - }else{ - $msg->addFeedback('PLOG_UPDATE_COURSE_SAVED'); - $message = 1; - } - } - } - - //update plog_users_permissions with enrolled courses. Allows course members to write to the course blog - - $sql6 = "SELECT * FROM ".TABLE_PREFIX."course_enrollment WHERE approved='y'"; - $result6 = mysql_query($sql6,$db); - - // first check if permission to write to course blogs already exists - - $sqlk = "SELECT * FROM ".PLOG_PREFIX."users_permissions"; - $resultk = mysql_query($sqlk,$db); - $i = ''; - $existing_permissions = array(); - while($rowk = mysql_fetch_array($resultk)){ - $i++; - $existing_permissions[$i]= $rowk[1].','.$rowk[2]; - } - while ($row = mysql_fetch_array($result6)){ - $this_permission = $row[1].','.$row[0]; - if(!in_array($this_permission, $existing_permissions)) { - $sqlx = "REPLACE INTO ".PLOG_PREFIX."users_permissions VALUES ('','$row[1]','$row[0]','2')"; - if(!$resultx = mysql_query($sqlx,$db)){ - $msg->addError('PLOG_UPDATE_PERMISSIONS_FAILED'); - - }else{ - $msg->addFeedback('PLOG_UPDATE_PERMISSIONS_SAVED'); - $message = 1; - } - } - } - - //create an initial category for each course - $sqlcat = "SELECT * from ".TABLE_PREFIX."courses"; - $resultcat = mysql_query($sqlcat,$db); - - // But first check to see if a default course blog categoy already exists - $sqlm = "SELECT blog_id FROM ".PLOG_PREFIX."articles_categories"; - $resultm = mysql_query($sqlm,$db); - $i = ''; - - while($rowm = mysql_fetch_array($resultm)){ - $i++; - $existing_cats[$i]= $rowm[0]; - } - - - $default_cat_properties = 's:0:"";'; - while($rowcat = mysql_fetch_array($resultcat)){ - if(!in_array($rowcat[0], $existing_cats)){ - $temp_title = str_replace("'","", $rowcat[6]); - $temp_cat_array = explode(" ", $temp_title); - $temp_cat_mangle = strtolower($temp_cat_array[0]."_".$temp_cat_array[1]); - $course_title = addslashes($rowcat[6]); - $sqlcat1 = "REPLACE INTO ".PLOG_PREFIX."articles_categories SET - id = '', - name = '$course_title', - url = '', - blog_id = '$rowcat[0]', - last_modification = now(), - in_main_page = '1', - parent_id = '0', - description = '$course_title', - properties = '$default_cat_properties', - mangled_name = '$temp_cat_mangle'"; - - if(!$resultcat1 = mysql_query($sqlcat1,$db)){ - $msg->addError('PLOG_UPDATE_CATS_FAILED'); - - }else{ - $msg->addFeedback('PLOG_UPDATE_CATS_SAVED'); - $message = 1; - - } - } - - } - if( !$msg->containsFeedbacks() && !$msg->containsErrors()){ - $msg->addFeedback('PLOG_UPDATE_NOT_REQUIRED'); - } - -} - -?> diff --git a/mods/plog/sync_plog11.php b/mods/plog/sync_plog11.php deleted file mode 100644 index 354562c72..000000000 --- a/mods/plog/sync_plog11.php +++ /dev/null @@ -1,236 +0,0 @@ -addError('PLOG_UPDATE_MEMBERS_FAILED'); - - }else{ - $msg->addFeedback('PLOG_UPDATE_MEMBERS_SAVED'); - $message = 1; - } - } - } - - -// The synchronizing of admin accounts is a problem because they are not admin members -// and don't have a user ID. or a course they are associated to. The following code was a first attempt -// at merging the admins into the plog_users table. - - -/* - $sql = "SELECT * from ".TABLE_PREFIX."admins"; - $result3 = mysql_query($sql); - - $sql5="SELECT user FROM ".PLOG_PREFIX."users"; - $result5 = mysql_query($sql5,$db); - - $i=''; - while($row5 = mysql_fetch_array($result5)){ - $i++; - $existing_admins[$i] = $row5[0]; - } - //update the plog_users table with ATutor admins - - while ($row = mysql_fetch_array($result3)){ - - $admin_pref = 's:0:"";'; - if(!in_array($row[0], $existing_admins)){ - $sql3 = "REPLACE INTO ".PLOG_PREFIX."users VALUES ( "; - - if($existing_admins != ''){ - $sql3 .= ' \''. $existing_admins[$row[0]].'\','; - }else{ - $sql3 .= "'',"; - } - - $sql3 .= "'$row[0]','".md5($row[1])."','$row[3]','$row[2]','','$admin_pref ','1','0')"; - - if(!$result4 = mysql_query($sql3, $db)){ - $msg->addError('PLOG_UPDATE_ADMINS_FAILED'); - }else{ - $msg->addFeedback('PLOG_UPDATE_ADMINS_SAVED'); - $message = 1; - } - } - } -*/ - - - // get a list of course titles and create values for the mangled_blog values in the plog_blogs table - - //update the plog_blogs table with ATutor courses. Creates one blog per course and assigns the instructor as the blog owner - - $sql5 = "SELECT * FROM ".TABLE_PREFIX."courses"; - $result5 = mysql_query($sql5,$db); - - // But first check to see if the course already exists - $sqlb = "SELECT id FROM ".PLOG_PREFIX."blogs"; - $resultb = mysql_query($sqlb,$db); - $i = ''; - while($rowb = mysql_fetch_array($resultb)){ - $i++; - $existing_blogs[$i]= $rowb[0]; - } - - // the 1.0.2 default blog setting - //$default_blog_settings = 'O:12:"blogsettings":3:{s:6:"_objId";N;s:3:"log";N;s:6:"_props";a:14:{s:6:"locale";s:5:"en_UK";s:14:"show_posts_max";s:2:"15";s:8:"template";s:7:"blueish";s:17:"show_more_enabled";b:1;s:16:"recent_posts_max";s:2:"10";s:17:"xmlrpc_ping_hosts";a:2:{i:0;s:27:"http://rpc.weblogs.com/RPC2";i:1;s:0:"";}s:16:"htmlarea_enabled";b:1;s:16:"comments_enabled";b:1;s:16:"categories_order";s:1:"1";s:14:"comments_order";s:1:"1";s:11:"time_offset";s:2:"-5";s:21:"link_categories_order";s:1:"1";s:29:"show_future_posts_in_calendar";b:0;s:27:"new_drafts_autosave_enabled";b:0;}}'; - - // the 1.1 default blog settings - $default_blog_settings = 'O:12:"blogsettings":1:{s:6:"_props";a:11:{s:6:"locale";s:5:"en_UK";s:14:"show_posts_max";s:2:"15";s:8:"template";s:7:"blueish";s:17:"show_more_enabled";s:1:"1";s:16:"recent_posts_max";s:2:"10";s:17:"xmlrpc_ping_hosts";a:2:{i:0;s:27:"http://rpc.weblogs.com/RPC2";i:1;s:0:"";}s:16:"htmlarea_enabled";s:1:"1";s:16:"comments_enabled";s:1:"1";s:16:"categories_order";i:0;s:14:"comments_order";s:1:"1";s:11:"time_offset";s:1:"0";}}'; - - while ($row = mysql_fetch_array($result5)){ - - if(!in_array($row[0], $existing_blogs)){ - $course_title = addslashes($row[6]); - $spec_chars = array("'"); - $temp_course_title = str_replace($spec_chars, "","$row[6]"); - $temp_array = explode(" ", $temp_course_title); - $temp_mangle = strtolower($temp_array[0]."_".$temp_array[1]); - $sql2 = "REPLACE INTO ".PLOG_PREFIX."blogs SET - id ='$row[0]', - blog = '$course_title', - owner_id = '$row[1]', - blog_category_id = '0', - about = '', - settings = '$default_blog_settings', - mangled_blog = '$temp_mangl', - status = '1', - show_in_summary = '1', - create_date = 'now()', - last_update_date = 'now()', - num_posts = '0', - num_comments = '0', - num_trackbacks = '0'"; - -//VALUES ('$row[0]','$course_title','$row[1]','','$default_blog_settings','$temp_mangle','1','1')"; - - if(!$result1 = mysql_query($sql2)){ - $msg->addError('PLOG_UPDATE_COURSE_FAILED'); - - }else{ - $msg->addFeedback('PLOG_UPDATE_COURSE_SAVED'); - $message = 1; - } - } - } - - //update plog_users_permissions with enrolled courses. Allows course members to write to the course blog - - $sql6 = "SELECT * FROM ".TABLE_PREFIX."course_enrollment WHERE approved='y'"; - $result6 = mysql_query($sql6,$db); - - // first check if permission to write to course blogs already exists - - $sqlk = "SELECT * FROM ".PLOG_PREFIX."users_permissions"; - $resultk = mysql_query($sqlk,$db); - $i = ''; - - while($rowk = mysql_fetch_array($resultk)){ - $i++; - $existing_permissions[$i]= $rowk[1].','.$rowk[2]; - } - - while ($row = mysql_fetch_array($result6)){ - $this_permission = $row[1].','.$row[0]; - if(!in_array($this_permission, $existing_permissions)) { - $sqlx = "REPLACE INTO ".PLOG_PREFIX."users_permissions VALUES ('','$row[1]','$row[0]','2')"; - if(!$resultx = mysql_query($sqlx,$db)){ - $msg->addError('PLOG_UPDATE_PERMISSIONS_FAILED'); - - }else{ - $msg->addFeedback('PLOG_UPDATE_PERMISSIONS_SAVED'); - $message = 1; - } - } - } - - //create an initial category for each course - $sqlcat = "SELECT * from ".TABLE_PREFIX."courses"; - $resultcat = mysql_query($sqlcat,$db); - - // But first check to see if a default course blog categoy already exists - $sqlm = "SELECT blog_id FROM ".PLOG_PREFIX."articles_categories"; - $resultm = mysql_query($sqlm,$db); - $i = ''; - - while($rowm = mysql_fetch_array($resultm)){ - $i++; - $existing_cats[$i]= $rowm[0]; - } - - - $default_cat_properties = 's:0:"";'; - while($rowcat = mysql_fetch_array($resultcat)){ - if(!in_array($rowcat[0], $existing_cats)){ - $temp_title = str_replace("'","", $rowcat[6]); - $temp_cat_array = explode(" ", $temp_title); - $temp_cat_mangle = strtolower($temp_cat_array[0]."_".$temp_cat_array[1]); - $course_title = addslashes($rowcat[6]); - $sqlcat1 = "REPLACE INTO ".PLOG_PREFIX."articles_categories SET - id = '', - name = '$course_title', - url = '', - blog_id = '$rowcat[0]', - last_modification = now(), - in_main_page = '1', - parent_id = '0', - description = '$course_title', - properties = '$default_cat_properties', - mangled_name = '$temp_cat_mangle'"; - - if(!$resultcat1 = mysql_query($sqlcat1,$db)){ - $msg->addError('PLOG_UPDATE_CATS_FAILED'); - - }else{ - $msg->addFeedback('PLOG_UPDATE_CATS_SAVED'); - $message = 1; - - } - } - - } - if( !$msg->containsFeedbacks() && !$msg->containsErrors()){ - $msg->addFeedback('PLOG_UPDATE_NOT_REQUIRED'); - } - -} - -?> \ No newline at end of file diff --git a/mods/pnATutor/ATutor/index_pn.php b/mods/pnATutor/ATutor/index_pn.php deleted file mode 100644 index 4f4f38e92..000000000 --- a/mods/pnATutor/ATutor/index_pn.php +++ /dev/null @@ -1,100 +0,0 @@ - \ No newline at end of file diff --git a/mods/pnATutor/pnadmin.php b/mods/pnATutor/pnadmin.php deleted file mode 100644 index f628988c1..000000000 --- a/mods/pnATutor/pnadmin.php +++ /dev/null @@ -1,246 +0,0 @@ -Text(pnVarPrepHTMLDisplay(_PNATUTORNOAUTH)); - return $output->GetOutput(); - } - - // Add menu to output - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->Text(pnATutor_adminmenu()); - $output->SetInputMode(_PNH_PARSEINPUT); - - // Return the output that has been generated by this function - return $output->GetOutput(); -} - -/* - * Main administration menu - */ -function pnATutor_adminmenu() { - - $theme = pnUserGetTheme(); - pnThemeLoad($theme); - - // Create output object - $output = new pnHTML(); - - // Security check - if (!pnSecAuthAction(0, 'pnATutor::', '::', ACCESS_ADMIN)) { - $output->Text(pnVarPrepHTMLDisplay(_PNATUTORNOAUTH)); - return $output->GetOutput(); - } - - //Title - ob_start(); - OpenTable(); - $oTable = ob_get_contents(); - ob_end_clean(); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->Text($oTable); - $output->Title(pnVarPrepHTMLDisplay(''._PNATUTOR.'')); - $output->Text(pnVarPrepHTMLDisplay(_PNATUTORMODIFYCONFIG)); - ob_start(); - CloseTable(); - $cTable = ob_get_contents(); - ob_end_clean(); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->Text($cTable); - - // Start form - $output->FormStart(pnModURL('pnATutor', 'admin', 'updateconfig')); - - // Add an authorisation ID - $output->FormHidden('authid', pnSecGenAuthKey()); - - - // Start the table that holds the information to be modified. - ob_start(); - OpenTable(); - $oTable = ob_get_contents(); - ob_end_clean(); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->Text($oTable); - $output->TableStart(); - - // pnATutor location - $row = array(); - $output->SetOutputMode(_PNH_RETURNOUTPUT); - $row[] = $output->Text(pnVarPrepHTMLDisplay(_MODSUBJECT)); - $row[] = $output->FormText('_loc', pnModGetVar('pnATutor', '_loc'), 50, 50); - $output->SetOutputMode(_PNH_KEEPOUTPUT); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->TableAddrow($row, 'left'); - - // Warning - $row = array(); - $output->SetOutputMode(_PNH_RETURNOUTPUT); - $row[] = $output->Text(pnVarPrepHTMLDisplay(_MODWARNING)); - $output->SetOutputMode(_PNH_KEEPOUTPUT); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->TableAddrow($row, 'left'); - - - // ATutor DB - $row = array(); - $output->SetOutputMode(_PNH_RETURNOUTPUT); - $row[] = $output->Text(pnVarPrepHTMLDisplay(_MODDB)); - $row[] = $output->FormText('_db', pnModGetVar('pnATutor', '_db'), 25, 25); - $output->SetOutputMode(_PNH_KEEPOUTPUT); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->TableAddrow($row, 'left'); - - // ATutor DB prefix - $row = array(); - $output->SetOutputMode(_PNH_RETURNOUTPUT); - $row[] = $output->Text(pnVarPrepHTMLDisplay(_PNATUTOR_PREFIX)); - $row[] = $output->FormText('_prf', pnModGetVar('pnATutor', '_prf'), 15, 15); - $output->SetOutputMode(_PNH_KEEPOUTPUT); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->TableAddrow($row, 'left'); - - // ATutor version - $row = array(); - $output->SetOutputMode(_PNH_RETURNOUTPUT); - $row[] = $output->Text(pnVarPrepHTMLDisplay(_PNATUTORVERSION)); - $row[] = $output->FormText('_version', pnModGetVar('pnATutor', '_version'), 5, 5); - $output->SetOutputMode(_PNH_KEEPOUTPUT); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->TableAddrow($row, 'left'); - - // Open in New >Window - $row = array(); - $output->SetOutputMode(_PNH_RETURNOUTPUT); - $row[] = $output->Text(pnVarPrepHTMLDisplay(_MODWINDOW)); - $row[] = $output->FormCheckbox('_window', pnModGetVar('pnATutor', '_window')); - $output->SetOutputMode(_PNH_KEEPOUTPUT); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->TableAddrow($row, 'left'); - - - // Create users - $row = array(); - $output->SetOutputMode(_PNH_RETURNOUTPUT); - $row[] = $output->Text(pnVarPrepHTMLDisplay(_MODUSERS)); - $row[] = $output->FormCheckbox('_users', pnModGetVar('pnATutor', '_users')); - $output->SetOutputMode(_PNH_KEEPOUTPUT); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->TableAddrow($row, 'left'); - - - // Allow guest access - $row = array(); - $output->SetOutputMode(_PNH_RETURNOUTPUT); - $row[] = $output->Text(pnVarPrepHTMLDisplay(_MODGUEST)); - $row[] = $output->FormCheckbox('_guest', pnModGetVar('pnATutor', '_guest')); - $output->SetOutputMode(_PNH_KEEPOUTPUT); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->TableAddrow($row, 'left'); - - $output->TableEnd(); - ob_start(); - CloseTable(); - $cTable = ob_get_contents(); - ob_end_clean(); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->Text($cTable); - - // End form - //$output->Linebreak(1); - ob_start(); - OpenTable(); - $oTable = ob_get_contents(); - ob_end_clean(); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->Text($oTable); - $output->Text('

    '); - $output->FormSubmit(pnVarPrepHTMLDisplay(_PNATUTORUPDATE)); - $output->Text('

    '); - ob_start(); - CloseTable(); - $cTable = ob_get_contents(); - ob_end_clean(); - $output->SetInputMode(_PNH_VERBATIMINPUT); - $output->Text($cTable); - $output->FormEnd(); - - // Return the output that has been generated by this function - $output->SetOutputMode(_PNH_KEEPOUTPUT); - return $output->GetOutput(); -} - -function pnATutor_admin_updateconfig() -{ - // Get parameters from whatever input we need. - $_loc = pnVarCleanFromInput('_loc'); - $_window = pnVarCleanFromInput('_window'); - $_db = pnVarCleanFromInput('_db'); - $_guest = pnVarCleanFromInput('_guest'); - $_users = pnVarCleanFromInput('_users'); - $_version = pnVarCleanFromInput('_version'); - $_prf = pnVarCleanFromInput('_prf'); - - - // Confirm authorisation code. - if (!pnSecConfirmAuthKey()) { - pnSessionSetVar('errormsg', _BADAUTHKEY); - pnRedirect(pnModURL('pnATutor', 'admin', '')); - return true; - } - - // Update module variables. - pnModSetVar('pnATutor', '_loc', $_loc); - pnModSetVar('pnATutor', '_window', $_window); - pnModSetVar('pnATutor', '_db', $_db); - pnModSetVar('pnATutor', '_guest', $_guest); - pnModSetVar('pnATutor', '_users', $_users); - pnModSetVar('pnATutor', '_version', $_version); - pnModSetVar('pnATutor', '_prf', $_prf); - - // This function generated no output, and so now it is complete we redirect - // the user to an appropriate page for them to carry on their work - pnRedirect('admin.php'); - - // Return - return true; -} -?> diff --git a/mods/pnATutor/pnblocks/courses.php b/mods/pnATutor/pnblocks/courses.php deleted file mode 100644 index 64a9e0b9e..000000000 --- a/mods/pnATutor/pnblocks/courses.php +++ /dev/null @@ -1,184 +0,0 @@ - 'courses', - 'module' => 'pnATutor', - 'text_type_long' => 'Available courses within ATutor', - 'allow_multiple' => true, - 'form_content' => false, - 'form_refresh' => false, - 'show_preview' => true); -} - - -function pnATutor_coursesblock_display($blockinfo) -{ - if (!pnSecAuthAction(0, - 'pnATutor:courses:', - "$blockinfo[title]::", - ACCESS_READ)) { - return false; - } - - - // Get current content - $vars = pnBlockVarsFromContent($blockinfo['content']); - - // Defaults - if (empty($vars['amount'])) { - $vars['amount'] = 5; - } - - if (empty($vars['trim'])) { - $vars['trim'] = 30; - } - if (empty($vars['usejava'])) { - $vars['usejava'] = 'n'; - } - if (empty($vars['loadjava'])) { - $vars['loadjava'] = 'n'; - } - if (empty($vars['enrolled'])) { - $vars['enrolled'] = 'n'; - } - -$amount=$vars['amount']; -$trim = $vars['trim'] ; -$usejava= $vars['usejava']; -$loadjava = $vars['loadjava'] ; -$enrolled =$vars['enrolled'] ; - -$db=pnModGetVar('pnATutor', '_db'); -$prefix=pnModGetVar('pnATutor', '_prf'); -$std_db = pnConfigGetVar('dbname'); - -$pcModInfo = pnModGetInfo(pnModGetIDFromName('pnATutor')); -$ModName = pnVarPrepForOS($pcModInfo['directory']); - -$username=pnUserGetVar(uname); - -$true = mysql_select_db($db) or die("cannot select database: " . mysql_error()) ; -if ($enrolled == 'n'){ -$result = mysql_query("select course_id, title, description from $prefix".courses." order by course_id DESC limit ".$amount." ") or die("cannot select from table: " . mysql_error()); -} else { - if (pnUserLoggedIn()) { - $result1 =mysql_query( "SELECT member_id FROM $prefix".members." WHERE login='$username' "); - if (mysql_num_rows($result1)< 1){ - $userid = 0; - }else { - $row99 = mysql_fetch_row($result1) ; - $userid = $row99[0]; - } - - $result = mysql_query("SELECT $prefix".courses.".course_id, title, description FROM $prefix".courses.", $prefix".course_enrollment." WHERE $prefix".course_enrollment.".course_id = $prefix".courses.".course_id and $prefix".course_enrollment.".member_id = ".$userid." order by title limit ".$amount." ") or die("cannot select from table: " . mysql_error()); - } -} -$items = array(); -while (list($id, $title, $summary) = mysql_fetch_row($result)) { - if ($trim != 0){ - if (strlen($title) > $trim) { - $title = substr($title,0,$trim); - $title .= "..."; - } - } - - $items[] = array('id' => $id,'title' => $title ,'summary' => $summary); - -} - -$url1="index.php?module=pnATutor&func=main"; -$urllink = _PNATUTORMODULE ; - -$true = mysql_select_db($std_db) ; - -// Create output object -// Note that for a block the corresponding module must be passed. -$pnRender =& new pnRender('pnATutor'); -$pnRender->assign('items', $items); -$pnRender->assign('url1', $url1); -$pnRender->assign('urllink', $urllink); -$pnRender->assign('loadjava', $loadjava); -$pnRender->assign('usejava', $usejava); -$pnRender->assign('modname', $ModName); - - - -// Populate block info and pass to theme -$blockinfo['content'] = $pnRender->fetch('pnATutor_block_courses.htm'); -themesideblock($blockinfo); -} - - - - -function pnATutor_coursesblock_modify($blockinfo) -{ - - // Get current content - $vars = pnBlockVarsFromContent($blockinfo['content']); - - // Defaults - if (empty($vars['amount'])) { - $vars['amount'] = 5; - } - - if (empty($vars['trim'])) { - $vars['trim'] = 30; - } - if (empty($vars['usejava'])) { - $vars['usejava'] = 'n'; - } - if (empty($vars['loadjava'])) { - $vars['loadjava'] = 'n'; - } - if (empty($vars['enrolled'])) { - $vars['enrolled'] = 'y'; - } - // Create output object - $pnRender =& new pnRender('pnATutor'); - - // As Admin output changes often, we do not want caching. - $pnRender->caching = false; - - // assign the approriate values - $pnRender->assign('amount', $vars['amount']); - $pnRender->assign('trim', $vars['trim']); - $pnRender->assign('usejava', $vars['usejava']); - $pnRender->assign('loadjava', $vars['loadjava']); - $pnRender->assign('enrolled', $vars['enrolled']); - - // Return the output that has been generated by this function - return $pnRender->fetch('pnATutor_block_courses_modify.htm'); -} - -function pnATutor_coursesblock_update($blockinfo) -{ - // Get current content - $vars = pnBlockVarsFromContent($blockinfo['content']); - - // alter the corresponding variable - $vars['amount'] = pnVarCleanFromInput('amount'); - $vars['trim'] = pnVarCleanFromInput('trim'); - $vars['usejava'] = pnVarCleanFromInput('usejava'); - $vars['loadjava'] = pnVarCleanFromInput('loadjava'); - $vars['enrolled'] = pnVarCleanFromInput('enrolled'); - - // write back the new contents - $blockinfo['content'] = pnBlockVarsToContent($vars); - - // clear the block cache - $pnRender =& new pnRender('pnATutor'); - $pnRender->clear_cache('pnATutor_block_courses.htm'); - - return $blockinfo; - -} - -?> diff --git a/mods/pnATutor/pndocs/credits.txt b/mods/pnATutor/pndocs/credits.txt deleted file mode 100644 index 0fdd7658a..000000000 --- a/mods/pnATutor/pndocs/credits.txt +++ /dev/null @@ -1,10 +0,0 @@ -/************************************************************************/ -/* pnATutor (/pndoc/credits.txt) */ -/************************************************************************/ -pnATutor 1.4 for PN 0.72x -(with full props to the ones below) -Cas@nuy.info / www.nuy.info - -Feature for removing Scrollbars based upon idea of Carlos Pelaez -http://www.solidealia.net -/***************************************************************** diff --git a/mods/pnATutor/pndocs/license.txt b/mods/pnATutor/pndocs/license.txt deleted file mode 100644 index 4dfd6b7fa..000000000 --- a/mods/pnATutor/pndocs/license.txt +++ /dev/null @@ -1,346 +0,0 @@ -/************************************************************************/ -/* pnATutor (/docs/license.txt) */ -/************************************************************************/ - - 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 - - Appendix: How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; 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 - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. - - -To read the license please visit http://www.gnu.org/copyleft/gpl.html diff --git a/mods/pnATutor/pndocs/readme.txt b/mods/pnATutor/pndocs/readme.txt deleted file mode 100644 index cef251e63..000000000 --- a/mods/pnATutor/pndocs/readme.txt +++ /dev/null @@ -1,21 +0,0 @@ -/************************************************************************/ -/* pnATutor (/pndocs/readme.txt) */ -/************************************************************************/ - -The pnATutor hack for Postnuke is very simple and requires no tables in the DB. - -Tested with : -Postnuke 0.760 -ATutor 1.4/1.5 -Linux/Windows - -Location of the ATutor installation is not important. - - -INSTALLATION -====================== -0. Install ATutor stand alone and verify it is working correct. -1. Unzip the contents to your /modules directory. -2. Copy ATutor\*.* to the root of your ATutor directory -3. Initialise & activate the module -4. Link the module into a menu block as : {pnATutor} diff --git a/mods/pnATutor/pnincludes/overlib.js b/mods/pnATutor/pnincludes/overlib.js deleted file mode 100644 index 330e8b4f1..000000000 --- a/mods/pnATutor/pnincludes/overlib.js +++ /dev/null @@ -1,1315 +0,0 @@ -//\///// -//\ overLIB 4.00 - You may not remove or change this notice. -//\ Copyright Erik Bosrup 1998-2004. All rights reserved. -//\ -//\ Contributors are listed on the homepage. -//\ This file might be old, always check for the latest version at: -//\ http://www.bosrup.com/web/overlib/ -//\ -//\ Please read the license agreement (available through the link above) -//\ before using overLIB. Direct any licensing questions to erik@bosrup.com. -//\ -//\ 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. -// $Revision: 1.68.2.1 $ $Date: 2004/03/23 16:29:38 $ -//\///// -//\mini - -//////// -// PRE-INIT -// Ignore these lines, configuration is below. -//////// -var olLoaded = 0;var pmStart = 10000000; var pmUpper = 10001000; var pmCount = pmStart+1; var pms = new Array(); var olInfo = new Info('4.00', 1); -var FREPLACE = 0; var FBEFORE = 1; var FAFTER = 2; var FALTERNATE = 3; -var olHideForm=0; // parameter for hiding SELECT and ActiveX elements in IE5.5+ -registerCommands('donothing,inarray,caparray,sticky,background,noclose,caption,left,right,center,offsetx,offsety,fgcolor,bgcolor,textcolor,capcolor,closecolor,width,border,cellpad,status,autostatus,autostatuscap,height,closetext,snapx,snapy,fixx,fixy,relx,rely,fgbackground,bgbackground,padx,pady,fullhtml,above,below,capicon,textfont,captionfont,closefont,textsize,captionsize,closesize,timeout,function,delay,hauto,vauto,closeclick,wrap,followmouse,mouseoff,closetitle,cssoff,cssclass,fgclass,bgclass,textfontclass,captionfontclass,closefontclass'); - -//////// -// DEFAULT CONFIGURATION -// Settings you want everywhere are set here. All of this can also be -// changed on your html page or through an overLIB call. -//////// -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_cellpad=='undefined') var ol_cellpad=2; -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=RIGHT; -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_relx=='undefined') var ol_relx=null; -if (typeof ol_rely=='undefined') var ol_rely=null; -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=BELOW; -if (typeof ol_aboveheight=='undefined') var ol_aboveheight=0; -if (typeof ol_capicon=='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=null; -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_wrap=='undefined') var ol_wrap=0; -if (typeof ol_followmouse=='undefined') var ol_followmouse=1; -if (typeof ol_mouseoff=='undefined') var ol_mouseoff=0; -if (typeof ol_closetitle=='undefined') var ol_closetitle='Close'; -if (typeof ol_css=='undefined') var ol_css=CSSOFF; -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=""; - -//////// -// ARRAY CONFIGURATION -//////// - -// You can use these arrays to store popup text here instead of in the html. -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"); - -//////// -// END OF CONFIGURATION -// Don't change anything below this line, all configuration is above. -//////// - - - - - -//////// -// INIT -//////// -// Runtime variables init. Don't change 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_cellpad=2; -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_relx=null; -var o3_rely=null; -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_wrap=0; -var o3_followmouse=1; -var o3_mouseoff=0; -var o3_closetitle=''; -var o3_css=CSSOFF; -var o3_fgclass=""; -var o3_bgclass=""; -var o3_textfontclass=""; -var o3_captionfontclass=""; -var o3_closefontclass=""; - -// Display state variables -var o3_x = 0; -var o3_y = 0; -var o3_showingsticky = 0; -var o3_removecounter = 0; - -// Our layer -var over = null; -var fnRef, hoveringSwitch = false; - -// Decide browser version -var isMac = (navigator.userAgent.indexOf("Mac") != -1); -var olOp = (navigator.userAgent.toLowerCase().indexOf('opera 7.') > -1); -var olNs4 = (navigator.appName=='Netscape' && parseInt(navigator.appVersion) == 4); -var olNs6 = (document.getElementById) ? true : false; -var olIe4 = (document.all) ? true : false; -var olIe5 = false; -var olIe55 = false; // Added additional variable to identify IE5.5+ -var docRoot = 'document.body'; - -// Resize fix for NS4.x to keep track of layer -if (olNs4) { - 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 (olIe4) { - var versNum=parseFloat(navigator.userAgent.match(/MSIE (\d\.\d+)\.*/i)[1]); - if (versNum >= 5){ - olIe5=true; - olIe55=(versNum>=5.5&&!olOp) ? true : false; - if (olNs6) olNs6=false; - } - if (olNs6) olIe4 = false; -} - -// Check for compatability mode. -if (document.compatMode && document.compatMode == 'CSS1Compat') { - docRoot= ((olIe4 && !olOp) ? 'document.documentElement' : docRoot); -} - -// Add window onload handlers to indicate when all modules have been loaded -// For Netscape 6+ and Mozilla, uses addEventListener method on the window object -// For IE it uses the attachEvent method of the window object and for Netscape 4.x -// it sets the window.onload handler to the OLonload_handler function -if(window.addEventListener) window.addEventListener("load",OLonLoad_handler,true); -else if (window.attachEvent) window.attachEvent("onload",OLonLoad_handler); -else window.onload=OLonLoad_handler; - -// Capture events, alt. diffuses the overlib function. -var olCheckMouseCapture = true; -if ((olNs4 || olNs6 || olIe4)) { - olMouseCapture(); -} else { - overlib = no_overlib; - nd = no_overlib; - ver3fix = true; -} - - -//////// -// PUBLIC FUNCTIONS -//////// - -// overlib(arg0,...,argN) -// Loads parameters into global runtime variables. -function overlib() { - if (!olLoaded || isExclusive(overlib.arguments)) return true; - if (olCheckMouseCapture) olMouseCapture(); - if (over) cClick(); - - // 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_cellpad=ol_cellpad; - 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_relx=ol_relx; - o3_rely=ol_rely; - 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_wrap=ol_wrap; - o3_followmouse=ol_followmouse; - o3_mouseoff=ol_mouseoff; - o3_closetitle=ol_closetitle; - o3_css=ol_css; - o3_fgclass=ol_fgclass; - o3_bgclass=ol_bgclass; - o3_textfontclass=ol_textfontclass; - o3_captionfontclass=ol_captionfontclass; - o3_closefontclass=ol_closefontclass; - - setRunTimeVariables(); - - fnRef = ''; - - // Special for frame support, over must be reset... - o3_frame = ol_frame; - - if (olNs4) { - over = o3_frame.document.layers['overDiv']; - } else if (document.all) { - over = o3_frame.document.all['overDiv']; - } else if (document.getElementById) { - over = o3_frame.document.getElementById("overDiv"); - } - - parseTokens('o3_', overlib.arguments); - if (!postParseChecks()) return false; - - if (o3_delay == 0) { - return runHook("olMain", FREPLACE); - } else { - o3_delayid = setTimeout("runHook('olMain', FREPLACE)", o3_delay); - return false; - } -} - -// Clears popups if appropriate -function nd(time) { - if (olLoaded && !isExclusive()) { - if (time && !o3_delay) { - if (o3_timerid > 0) clearTimeout(o3_timerid); - - o3_timerid = setTimeout("cClick()",(o3_timeout = time)); - } - if (o3_removecounter >= 1) { o3_showingsticky = 0 }; - - if (o3_showingsticky == 0) { - o3_allowmove = 0; - if (over != null && o3_timerid == 0) runHook("hideObject", FREPLACE, over); - } else { - o3_removecounter++; - } - } - - return true; -} - -// The Close onMouseOver function for stickies -function cClick() { - if (olLoaded) { - runHook("hideObject", FREPLACE, over); - o3_showingsticky = 0; - } - return false; -} - -// Method for setting page specific defaults. -function overlib_pagedefaults() { - parseTokens('ol_', overlib_pagedefaults.arguments); -} - - -//////// -// OVERLIB MAIN FUNCTION -//////// - -// This function decides what it is we want to display and how we want it done. -function olMain() { - var layerhtml, styleType; - runHook("olMain", FBEFORE); - - if (o3_background!="" || o3_fullhtml) { - // Use background instead of box. - layerhtml = runHook('ol_content_background', FALTERNATE, o3_css, o3_text, o3_background, o3_fullhtml); - } else { - // They want a popup box. - styleType = (pms[o3_css-1-pmStart] == "cssoff" || pms[o3_css-1-pmStart] == "cssclass"); - - // Prepare popup background - if (o3_fgbackground != "") o3_fgbackground = "background=\""+o3_fgbackground+"\""; - if (o3_bgbackground != "") o3_bgbackground = (styleType ? "background=\""+o3_bgbackground+"\"" : o3_bgbackground); - - // Prepare popup colors - if (o3_fgcolor != "") o3_fgcolor = (styleType ? "bgcolor=\""+o3_fgcolor+"\"" : o3_fgcolor); - if (o3_bgcolor != "") o3_bgcolor = (styleType ? "bgcolor=\""+o3_bgcolor+"\"" : o3_bgcolor); - - // Prepare popup height - if (o3_height > 0) o3_height = (styleType ? "height=\""+o3_height+"\"" : o3_height); - else o3_height = ""; - - // Decide which kinda box. - if (o3_cap=="") { - // Plain - layerhtml = runHook('ol_content_simple', FALTERNATE, o3_css, o3_text); - } else { - // With caption - if (o3_sticky) { - // Show close text - layerhtml = runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, o3_close); - } else { - // No close text - layerhtml = runHook('ol_content_caption', FALTERNATE, o3_css, 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; - } - - // Created a separate routine to generate the popup to make it easier - // to implement a plugin capability - if (!runHook("createPopup", FREPLACE, layerhtml)) return false; - - // 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 - runHook("disp", FREPLACE, o3_status); - runHook("olMain", FAFTER); - - if (o3_status != '') { - return true; - } else { - return; - } -} - -//////// -// LAYER GENERATION FUNCTIONS -//////// -// These functions just handle popup content with tags that should adhere to the W3C standards specification. - -// Makes simple table without caption -function ol_content_simple(text) { - txt='
    ' : '>')+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize))+'
    '; - - set_background(""); - return txt; -} - -// Makes table with caption and optional close link -function ol_content_caption(text,title,close) { - var nameId; - closing=""; - closeevent="onmouseover"; - if (o3_closeclick==1) closeevent= (o3_closetitle ? "title='" + o3_closetitle +"'" : "") + " onclick"; - if (o3_capicon!="") { - nameId=' hspace=\"5\"'+' align=\"middle\" alt=\"\"'; - if (typeof o3_dragimg!='undefined'&&o3_dragimg) nameId=' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"'; - o3_capicon=''; - } - - if (close != "") closing=''+(o3_closefontclass ? '' : wrapStr(0,o3_closesize,'close'))+close+(o3_closefontclass ? '' : wrapStr(1,o3_closesize,'close'))+''; - txt='
    ' : '>')+(o3_captionfontclass ? '' : ''+wrapStr(0,o3_captionsize,'caption'))+o3_capicon+title+(o3_captionfontclass ? '' : wrapStr(1,o3_captionsize)+'')+''+closing+'
    ' :'>')+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize)) + '
    '; - - set_background(""); - return txt; -} - -// Sets the background picture,padding and lots more. :) -function ol_content_background(text,picture,hasfullhtml) { - if (hasfullhtml) { - txt=text; - } else { - txt='
    '+wrapStr(0,o3_textsize,'text')+text+wrapStr(1,o3_textsize)+'
    '; - } - - set_background(picture); - return txt; -} - -// Loads a picture into the div. -function set_background(pic) { - if (pic == "") { - if (olNs4) { - over.background.src = null; - } else if (over.style) { - over.style.backgroundImage = "none"; - } - } else { - if (olNs4) { - over.background.src = pic; - } else if (over.style) { - over.style.backgroundImage = "url("+pic+")"; - } - } -} - -//////// -// HANDLING FUNCTIONS -//////// - -// Displays the popup -function disp(statustext) { - runHook("disp", FBEFORE); - - if (o3_allowmove == 0) { - runHook("placeLayer", FREPLACE); - runHook("showObject", FREPLACE, over); - o3_allowmove = (o3_sticky || o3_followmouse==0) ? 0 : 1; - } - - runHook("disp", FAFTER); - - if (statustext != "") self.status = statustext; -} - -// Creates the actual popup structure -function createPopup(lyrContent){ - runHook("createPopup", FBEFORE); - - if (o3_wrap && !(olNs4 || olOp)) { - if (olIe4) { - over.style.pixelWidth = 0; - } else if (olNs6) { - repositionTo(over, 0, -over.offsetHeight); - } - } - - layerWrite(lyrContent); - - // Have to set o3_width for placeLayer() routine if o3_wrap is turned on - if (o3_wrap) o3_width=(olNs4 ? over.clip.width : over.offsetWidth); - - runHook("createPopup", FAFTER, lyrContent); - - return true; -} - -// Decides where we want the popup. -function placeLayer() { - var placeX, placeY, widthFix = 0; - - // HORIZONTAL PLACEMENT - if (eval('o3_frame.'+docRoot) && eval("typeof o3_frame."+docRoot+".clientWidth=='number'") && eval('o3_frame.'+docRoot+'.clientWidth')) { - iwidth = eval('o3_frame.'+docRoot+'.clientWidth'); - } else if (typeof(o3_frame.innerWidth) == 'number') { - widthFix = Math.ceil(1.2*(o3_frame.outerWidth - o3_frame.innerWidth)); - iwidth = o3_frame.innerWidth; - } - - // Horizontal scroll offset - winoffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollLeft') : o3_frame.pageXOffset; - var parsedWidth = parseInt(o3_width); - - if (o3_fixx > -1 || o3_relx != null) { - // Fixed position - placeX=(o3_relx != null ? ( o3_relx < 0 ? winoffset +o3_relx+ iwidth - parsedWidth - widthFix : winoffset+o3_relx) : o3_fixx); - } else { - // If HAUTO, decide what to use. - if (o3_hauto == 1) { - if ((o3_x - winoffset) > (iwidth / 2)) { - o3_hpos = LEFT; - } else { - o3_hpos = RIGHT; - } - } - - // From mouse - if (o3_hpos == CENTER) { // Center - placeX = o3_x+o3_offsetx-(parsedWidth/2); - - if (placeX < winoffset) placeX = winoffset; - } - - if (o3_hpos == RIGHT) { // Right - placeX = o3_x+o3_offsetx; - - if ((placeX+parsedWidth) > (winoffset+iwidth - widthFix)) { - placeX = iwidth+winoffset - parsedWidth - widthFix; - if (placeX < 0) placeX = 0; - } - } - if (o3_hpos == LEFT) { // Left - placeX = o3_x-o3_offsetx-parsedWidth; - 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 (eval('o3_frame.'+docRoot) && eval("typeof o3_frame."+docRoot+".clientHeight=='number'") && eval('o3_frame.'+docRoot+'.clientHeight')) { - iheight = eval('o3_frame.'+docRoot+'.clientHeight'); - } else if (typeof(o3_frame.innerHeight)=='number') { - iheight = o3_frame.innerHeight; - } - - // Vertical scroll offset - scrolloffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollTop') : o3_frame.pageYOffset; - var parsedHeight=(o3_aboveheight ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight)); - - if (o3_fixy > -1 || o3_rely != null) { - // Fixed position - placeY=(o3_rely != null ? (o3_rely < 0 ? scrolloffset+o3_rely+iheight - parsedHeight : scrolloffset+o3_rely) : o3_fixy); - } else { - // If VAUTO, decide what to use. - if (o3_vauto == 1) { - if ((o3_y - scrolloffset) > (iheight/2)) { - o3_vpos = ABOVE; - } else { - o3_vpos = BELOW; - } - } - - // From mouse - if (o3_vpos == ABOVE) { - if (o3_aboveheight == 0) o3_aboveheight = parsedHeight; - - 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 olMouseMove(e) { - var e = (e) ? e : event; - - if (e.pageX) { - o3_x = e.pageX; - o3_y = e.pageY; - } else if (e.clientX) { - o3_x = eval('e.clientX+o3_frame.'+docRoot+'.scrollLeft'); - o3_y = eval('e.clientY+o3_frame.'+docRoot+'.scrollTop'); - } - - if (o3_allowmove == 1) runHook("placeLayer", FREPLACE); - - // MouseOut handler - if (hoveringSwitch && !olNs4 && runHook("cursorOff", FREPLACE)) { - cClick(); - hoveringSwitch = !hoveringSwitch; - } -} - -// Fake function for 3.0 users. -function no_overlib() { return ver3fix; } - -// Capture the mouse and chain other scripts. -function olMouseCapture() { - capExtent = document; - var fN, mseHandler = olMouseMove; - var re = /function[ ]+(\w+)\(/; - - if (document.onmousemove || (!olIe4 && window.onmousemove)) { - if (window.onmousemove) capExtent = window; - fN = capExtent.onmousemove.toString().match(re); - - if (fN[1] == 'anonymous' || fN[1] == 'olMouseMove') { - olCheckMouseCapture = false; - return; - } - var str = fN[1]+'(e); ' + 'olMouseMove(e); '; - mseHandler = new Function('e', str); - } - - capExtent.onmousemove = mseHandler; - if (olNs4) capExtent.captureEvents(Event.MOUSEMOVE); -} - - -//////// -// PARSING FUNCTIONS -//////// - -// Does the actual command parsing. -function parseTokens(pf, ar) { - // What the next argument is expected to be. - var v, mode=-1, par = (pf != 'ol_'); - var fnMark = (par && !ar.length ? 1 : 0); - - for (i = 0; i < ar.length; i++) { - if (mode < 0) { - // Arg is maintext,unless its a number between pmStart and pmUpper - // then its a command. - if (typeof ar[i] == 'number' && ar[i] > pmStart && ar[i] < pmUpper) { - fnMark = (par ? 1 : 0); - i--; // backup one so that the next block can parse it - } else { - switch(pf) { - case 'ol_': - ol_text = ar[i].toString(); - break; - default: - o3_text=ar[i].toString(); - } - } - mode = 0; - } else { - // Note: NS4 doesn't like switch cases with vars. - if (ar[i] >= pmCount || ar[i]==DONOTHING) { continue; } - if (ar[i]==INARRAY) { fnMark = 0; eval(pf+'text=ol_texts['+ar[++i]+'].toString()'); continue; } - if (ar[i]==CAPARRAY) { eval(pf+'cap=ol_caps['+ar[++i]+'].toString()'); continue; } - if (ar[i]==STICKY) { if (pf!='ol_') eval(pf+'sticky=1'); continue; } - if (ar[i]==BACKGROUND) { eval(pf+'background="'+ar[++i]+'"'); continue; } - if (ar[i]==NOCLOSE) { if (pf!='ol_') opt_NOCLOSE(); continue; } - if (ar[i]==CAPTION) { eval(pf+"cap='"+escSglQuote(ar[++i])+"'"); continue; } - if (ar[i]==CENTER || ar[i]==LEFT || ar[i]==RIGHT) { eval(pf+'hpos='+ar[i]); continue; } - if (ar[i]==OFFSETX) { eval(pf+'offsetx='+ar[++i]); continue; } - if (ar[i]==OFFSETY) { eval(pf+'offsety='+ar[++i]); continue; } - if (ar[i]==FGCOLOR) { eval(pf+'fgcolor="'+ar[++i]+'"'); continue; } - if (ar[i]==BGCOLOR) { eval(pf+'bgcolor="'+ar[++i]+'"'); continue; } - if (ar[i]==TEXTCOLOR) { eval(pf+'textcolor="'+ar[++i]+'"'); continue; } - if (ar[i]==CAPCOLOR) { eval(pf+'capcolor="'+ar[++i]+'"'); continue; } - if (ar[i]==CLOSECOLOR) { eval(pf+'closecolor="'+ar[++i]+'"'); continue; } - if (ar[i]==WIDTH) { eval(pf+'width='+ar[++i]); continue; } - if (ar[i]==BORDER) { eval(pf+'border='+ar[++i]); continue; } - if (ar[i]==CELLPAD) { i=opt_MULTIPLEARGS(++i,ar,(pf+'cellpad')); continue; } - if (ar[i]==STATUS) { eval(pf+"status='"+escSglQuote(ar[++i])+"'"); continue; } - if (ar[i]==AUTOSTATUS) { eval(pf +'autostatus=('+pf+'autostatus == 1) ? 0 : 1'); continue; } - if (ar[i]==AUTOSTATUSCAP) { eval(pf +'autostatus=('+pf+'autostatus == 2) ? 0 : 2'); continue; } - if (ar[i]==HEIGHT) { eval(pf+'height='+pf+'aboveheight='+ar[++i]); continue; } // Same param again. - if (ar[i]==CLOSETEXT) { eval(pf+"close='"+escSglQuote(ar[++i])+"'"); continue; } - if (ar[i]==SNAPX) { eval(pf+'snapx='+ar[++i]); continue; } - if (ar[i]==SNAPY) { eval(pf+'snapy='+ar[++i]); continue; } - if (ar[i]==FIXX) { eval(pf+'fixx='+ar[++i]); continue; } - if (ar[i]==FIXY) { eval(pf+'fixy='+ar[++i]); continue; } - if (ar[i]==RELX) { eval(pf+'relx='+ar[++i]); continue; } - if (ar[i]==RELY) { eval(pf+'rely='+ar[++i]); continue; } - if (ar[i]==FGBACKGROUND) { eval(pf+'fgbackground="'+ar[++i]+'"'); continue; } - if (ar[i]==BGBACKGROUND) { eval(pf+'bgbackground="'+ar[++i]+'"'); continue; } - if (ar[i]==PADX) { eval(pf+'padxl='+ar[++i]); eval(pf+'padxr='+ar[++i]); continue; } - if (ar[i]==PADY) { eval(pf+'padyt='+ar[++i]); eval(pf+'padyb='+ar[++i]); continue; } - if (ar[i]==FULLHTML) { if (pf!='ol_') eval(pf+'fullhtml=1'); continue; } - if (ar[i]==BELOW || ar[i]==ABOVE) { eval(pf+'vpos='+ar[i]); continue; } - if (ar[i]==CAPICON) { eval(pf+'capicon="'+ar[++i]+'"'); continue; } - if (ar[i]==TEXTFONT) { eval(pf+"textfont='"+escSglQuote(ar[++i])+"'"); continue; } - if (ar[i]==CAPTIONFONT) { eval(pf+"captionfont='"+escSglQuote(ar[++i])+"'"); continue; } - if (ar[i]==CLOSEFONT) { eval(pf+"closefont='"+escSglQuote(ar[++i])+"'"); continue; } - if (ar[i]==TEXTSIZE) { eval(pf+'textsize="'+ar[++i]+'"'); continue; } - if (ar[i]==CAPTIONSIZE) { eval(pf+'captionsize="'+ar[++i]+'"'); continue; } - if (ar[i]==CLOSESIZE) { eval(pf+'closesize="'+ar[++i]+'"'); continue; } - if (ar[i]==TIMEOUT) { eval(pf+'timeout='+ar[++i]); continue; } - if (ar[i]==FUNCTION) { if (pf=='ol_') { if (typeof ar[i+1]!='number') { v=ar[++i]; ol_function=(typeof v=='function' ? v : null); }} else {fnMark = 0; v = null; if (typeof ar[i+1]!='number') v = ar[++i]; opt_FUNCTION(v); } continue; } - if (ar[i]==DELAY) { eval(pf+'delay='+ar[++i]); continue; } - if (ar[i]==HAUTO) { eval(pf+'hauto=('+pf+'hauto == 0) ? 1 : 0'); continue; } - if (ar[i]==VAUTO) { eval(pf+'vauto=('+pf+'vauto == 0) ? 1 : 0'); continue; } - if (ar[i]==CLOSECLICK) { eval(pf +'closeclick=('+pf+'closeclick == 0) ? 1 : 0'); continue; } - if (ar[i]==WRAP) { eval(pf +'wrap=('+pf+'wrap == 0) ? 1 : 0'); continue; } - if (ar[i]==FOLLOWMOUSE) { eval(pf +'followmouse=('+pf+'followmouse == 1) ? 0 : 1'); continue; } - if (ar[i]==MOUSEOFF) { eval(pf +'mouseoff=('+pf+'mouseoff == 0) ? 1 : 0'); continue; } - if (ar[i]==CLOSETITLE) { eval(pf+"closetitle='"+escSglQuote(ar[++i])+"'"); continue; } - if (ar[i]==CSSOFF||ar[i]==CSSCLASS) { eval(pf+'css='+ar[i]); continue; } - if (ar[i]==FGCLASS) { eval(pf+'fgclass="'+ar[++i]+'"'); continue; } - if (ar[i]==BGCLASS) { eval(pf+'bgclass="'+ar[++i]+'"'); continue; } - if (ar[i]==TEXTFONTCLASS) { eval(pf+'textfontclass="'+ar[++i]+'"'); continue; } - if (ar[i]==CAPTIONFONTCLASS) { eval(pf+'captionfontclass="'+ar[++i]+'"'); continue; } - if (ar[i]==CLOSEFONTCLASS) { eval(pf+'closefontclass="'+ar[++i]+'"'); continue; } - i = parseCmdLine(pf, i, ar); - } - } - - if (fnMark && o3_function) o3_text = o3_function(); - - if ((pf == 'o3_') && o3_wrap) { - o3_width = 0; - - if (olOp || (olIe4 && isMac)) { - var tReg=/<.*\n*>/ig; - if (!tReg.test(o3_text)) o3_text = o3_text.replace(/[ ]+/g, ' '); - if (!tReg.test(o3_cap))o3_cap = o3_cap.replace(/[ ]+/g, ' '); - } - } - if ((pf == 'o3_') && o3_sticky) { - if (!o3_close && (o3_frame != ol_frame)) o3_close = ol_close; - if (o3_mouseoff && (o3_frame == ol_frame)) opt_NOCLOSE(' '); - } -} - - -//////// -// LAYER FUNCTIONS -//////// - -// Writes to a layer -function layerWrite(txt) { - txt += "\n"; - if (olNs4) { - var lyr = o3_frame.document.overDiv.document - lyr.write(txt) - lyr.close() - } else if (typeof over.innerHTML != 'undefined') { - if (olIe5 && isMac) over.innerHTML = ''; - over.innerHTML = txt; - } else { - range = o3_frame.document.createRange(); - range.setStartAfter(over); - domfrag = range.createContextualFragment(txt); - - while (over.hasChildNodes()) { - over.removeChild(over.lastChild); - } - - over.appendChild(domfrag); - } -} - -// Make an object visible -function showObject(obj) { - runHook("showObject", FBEFORE); - - var theObj=(olNs4 ? obj : obj.style); - theObj.visibility = 'visible'; - - runHook("showObject", FAFTER); -} - -// Hides an object -function hideObject(obj) { - runHook("hideObject", FBEFORE); - - var theObj=(olNs4 ? obj : obj.style); - theObj.visibility = 'hidden'; - - if (o3_timerid > 0) clearTimeout(o3_timerid); - if (o3_delayid > 0) clearTimeout(o3_delayid); - - o3_timerid = 0; - o3_delayid = 0; - self.status = ""; - - if (over.onmouseout || over.onmouseover) { - if (olNs4) over.releaseEvents(Event.MOUSEOUT || Event.MOUSEOVER); - over.onmouseout = over.onmouseover = null; - } - - runHook("hideObject", FAFTER); -} - -// Move a layer -function repositionTo(obj, xL, yL) { - var theObj=(olNs4 ? obj : obj.style); - theObj.left = xL + (!olNs4 ? 'px' : 0); - theObj.top = yL + (!olNs4 ? 'px' : 0); -} - -// Check position of cursor relative to overDiv DIVision; mouseOut function -function cursorOff() { - var left = parseInt(over.style.left); - var top = parseInt(over.style.top); - var right = left+over.offsetWidth; - var bottom = top+ over.offsetHeight; - - if (o3_x < left || o3_x > right || o3_y < top || o3_y > bottom) return true; - - return false; -} - - -//////// -// COMMAND FUNCTIONS -//////// - -// Calls callme or the default function. -function opt_FUNCTION(callme) { - o3_text = (callme ? (typeof callme=='string' ? (/.+\(.*\)/.test(callme) ? eval(callme) : callme) : callme()) : (o3_function ? o3_function() : 'No Function')); - - return 0; -} - -// Handle hovering -function opt_NOCLOSE(unused) { - if (!unused) o3_close = ""; - - if (olNs4) { - over.captureEvents(Event.MOUSEOUT || Event.MOUSEOVER); - over.onmouseover = function () { if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid = 0; } } - over.onmouseout = cClick; - } else { - over.onmouseover = function () {hoveringSwitch = true; if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid =0; } } - } - - return 0; -} - -// Function to scan command line arguments for multiples -function opt_MULTIPLEARGS(i, args, parameter) { - var k = i, l, re, pV, str = ''; - - for(k=i; kpmStart) break; - } - if(k >= args.length) l = str.length-1; - else { - re = eval('/,' + args[k] + '/'); - l = str.search(re); - } - - k--; // reduce by one so the for loop this is in works correctly - str = str.substring(0, l); - pV = (olNs4&&/cellpad/i.test(parameter)) ? str.split(',')[0] : str; - eval(parameter + '="' + pV + '"'); - - return k; -} - -// Remove   in texts when done. -function nbspCleanup() { - if (o3_wrap && (olOp || (olIe4 && isMac))) { - o3_text = o3_text.replace(/\ /g, ' '); - o3_cap = o3_cap.replace(/\ /g, ' '); - } -} - -// Escape embedded single quotes in text strings -function escSglQuote(str) { - return str.toString().replace(/'/g,"\\'"); -} - -// Onload handler for window onload event -function OLonLoad_handler(e) { - if (!olLoaded) olLoaded=1; // indicates that all modules have loaded now - - // remove the OLonload_handler for Ns6+, Mozilla based browsers, and IE - if (window.removeEventListener) window.removeEventListener("load",OLonLoad_handler,true); - else if (window.detachEvent) window.detachEvent("onload",OLonLoad_handler); - - // Route the event to the normal handler in Nx4.x - if (olNs4) routeEvent(e); -} - -// Wraps strings in Layer Generation Functions with the correct tags -// endWrap true(if end tag) or false if start tag -// fontSizeStr - font size string such as '1' or '10px' -// whichString is being wrapped -- 'text', 'caption', or 'close' -function wrapStr(endWrap,fontSizeStr,whichString) { - var fontStr, fontColor, isClose=((whichString=='close') ? 1 : 0), hasDims=/[%\-a-z]+$/.test(fontSizeStr); - fontSizeStr = (olNs4) ? (!hasDims ? fontSizeStr : '1') : fontSizeStr; - if (endWrap) return (hasDims&&!olNs4) ? (isClose ? '' : '') : '
    - -
    '; - else { - fontStr='o3_'+whichString+'font'; - fontColor='o3_'+((whichString=='caption')? 'cap' : whichString)+'color'; - return (hasDims&&!olNs4) ? (isClose ? '' : '
    ') : ''; - } -} - -// Quotes Multi word font names; needed for CSS Standards adherence in font-family -function quoteMultiNameFonts(theFont) { - var v, pM=theFont.split(','); - for (var i=0; i- 1) { - i = j; - break; - } - } - } - - return i; -} - -// Runs plugin functions to do things after parse. -function postParseChecks(){ - if (typeof postParse != 'undefined' && postParse.length) { - for (var k = 0; k < postParse.length; k++) { - if (postParse[k]()) continue; - return false; // end now since have an error - } - } - return true; -} - - -//////// -// PLUGIN REGISTRATION FUNCTIONS -//////// - -// Registers commands and creates constants. -function registerCommands(cmdStr) { - if (typeof cmdStr!='string') return; - - var pM = cmdStr.split(','); - pms = pms.concat(pM); - - for (var i = 0; i< pM.length; i++) { - eval(pM[i].toUpperCase()+'='+pmCount++); - } -} - -// Register a function to hook at a certain point. -function registerHook(fnHookTo, fnRef, hookType, optPm) { - var hookPt, last = typeof optPm; - - if (fnHookTo == 'plgIn'||fnHookTo == 'postParse') return; - if (typeof hookPts == 'undefined') hookPts = new Array(); - if (typeof hookPts[fnHookTo] == 'undefined') hookPts[fnHookTo] = new FunctionReference(); - - hookPt = hookPts[fnHookTo]; - - if (hookType != null) { - if (hookType == FREPLACE) { - hookPt.ovload = fnRef; // replace normal overlib routine - if (fnHookTo.indexOf('ol_content_') > -1) hookPt.alt[pms[CSSOFF-1-pmStart]]=fnRef; - - } else if (hookType == FBEFORE || hookType == FAFTER) { - var hookPt=(hookType == 1 ? hookPt.before : hookPt.after); - - if (typeof fnRef == 'object') { - hookPt = hookPt.concat(fnRef); - } else { - hookPt[hookPt.length++] = fnRef; - } - - if (optPm) hookPt = reOrder(hookPt, fnRef, optPm); - - } else if (hookType == FALTERNATE) { - if (last=='number') hookPt.alt[pms[optPm-1-pmStart]] = fnRef; - } - - return; - } -} - -// Register a function that will set runtime variables. -function registerRunTimeFunction(fn) { - if (isFunction(fn)) { - if (typeof runTime == 'undefined') runTime = new Array(); - if (typeof fn == 'object') { - runTime = runTime.concat(fn); - } else { - runTime[runTime.length++] = fn; - } - } -} - -// Register a function that will handle command parsing. -function registerCmdLineFunction(fn){ - if (isFunction(fn)) { - if (typeof cmdLine == 'undefined') cmdLine = new Array(); - if (typeof fn == 'object') { - cmdLine = cmdLine.concat(fn); - } else { - cmdLine[cmdLine.length++] = fn; - } - } -} - -// Register a function that does things after command parsing. -function registerPostParseFunction(fn){ - if (isFunction(fn)) { - if (typeof postParse == 'undefined') postParse = new Array(); - if (typeof fn == 'object') { - postParse = postParse.concat(fn); - } else { - postParse[postParse.length++] = fn; - } - } -} - -//////// -// PLUGIN REGISTRATION FUNCTIONS -//////// - -// Runs any hooks registered. -function runHook(fnHookTo, hookType) { - var l = hookPts[fnHookTo], optPm, arS, ar = runHook.arguments; - - if (hookType == FREPLACE) { - arS = argToString(ar, 2); - - if (typeof l == 'undefined' || !(l = l.ovload)) return eval(fnHookTo+'('+arS+')'); - else return eval('l('+arS+')'); - - } else if (hookType == FBEFORE || hookType == FAFTER) { - if (typeof l == 'undefined') return; - l=(hookType == 1 ? l.before : l.after); - - if (!l.length) return; - - arS = argToString(ar, 2); - for (var k = 0; k < l.length; k++) eval('l[k]('+arS+')'); - - } else if (hookType == FALTERNATE) { - optPm = ar[2]; - arS = argToString(ar, 3); - - if (typeof l == 'undefined' || (l = l.alt[pms[optPm-1-pmStart]]) == 'undefined') { - return eval(fnHookTo+'('+arS+')'); - } else { - return eval('l('+arS+')'); - } - } -} - -//////// -// UTILITY FUNCTIONS -//////// - -// Checks if something is a function. -function isFunction(fnRef) { - var rtn = true; - - if (typeof fnRef == 'object') { - for (var i = 0; i < fnRef.length; i++) { - if (typeof fnRef[i]=='function') continue; - rtn = false; - break; - } - } else if (typeof fnRef != 'function') { - rtn = false; - } - - return rtn; -} - -// Converts an array into an argument string for use in eval. -function argToString(array, strtInd, argName) { - var jS = strtInd, aS = '', ar = array; - argName=(argName ? argName : 'ar'); - - if (ar.length > jS) { - for (var k = jS; k < ar.length; k++) aS += argName+'['+k+'], '; - aS = aS.substring(0, aS.length-2); - } - - return aS; -} - -// Places a hook in the correct position in a hook point. -function reOrder(hookPt, fnRef, order) { - if (!order || typeof order == 'undefined' || typeof order == 'number') return; - - var newPt = new Array(), match; - - if (typeof order=='function') { - if (typeof fnRef=='object') { - newPt = newPt.concat(fnRef); - } else { - newPt[newPt.length++]=fnRef; - } - - for (var i = 0; i < hookPt.length; i++) { - match = false; - if (typeof fnRef == 'function' && hookPt[i] == fnRef) { - continue; - } else { - for(var j = 0; j < fnRef.length; j++) if (hookPt[i] == fnRef[j]) { - match = true; - break; - } - } - if (!match) newPt[newPt.length++] = hookPt[i]; - } - - newPt[newPt.length++] = order; - - } else if (typeof order == 'object') { - if (typeof fnRef == 'object') { - newPt = newPt.concat(fnRef); - } else { - newPt[newPt.length++] = fnRef; - } - - for (var j = 0; j < hookPt.length; j++) { - match = false; - if (typeof fnRef == 'function' && hookPt[j] == fnRef) { - continue; - } else { - for (var i = 0; i < fnRef.length; i++) if (hookPt[j] == fnRef[i]) { - match = true; - break; - } - } - if (!match) newPt[newPt.length++]=hookPt[j]; - } - - for (i = 0; i < newPt.length; i++) hookPt[i] = newPt[i]; - newPt.length = 0; - - for (var j = 0; j < hookPt.length; j++) { - match = false; - for (var i = 0; i < order.length; i++) { - if (hookPt[j] == order[i]) { - match = true; - break; - } - } - if (!match) newPt[newPt.length++] = hookPt[j]; - } - newPt = newPt.concat(order); - } - - for(i = 0; i < newPt.length; i++) hookPt[i] = newPt[i]; - - return hookPt; -} - -//////// -// OBJECT CONSTRUCTORS -//////// - -// Object for handling hooks. -function FunctionReference() { - this.ovload = null; - this.before = new Array(); - this.after = new Array(); - this.alt = new Array(); -} - -// Object for simple access to the overLIB version used. -// Examples: simpleversion:351 major:3 minor:5 revision:1 -function Info(version, prerelease) { - this.version = version; - this.prerelease = prerelease; - - this.simpleversion = parseInt(this.version*100); - this.major = parseInt(this.simpleversion / 100); - this.minor = parseInt(this.simpleversion / 10) - this.major * 10; - this.revision = parseInt(this.simpleversion) - this.major * 100 - this.minor * 10; -} - - - -//////// -// STANDARD REGISTRATIONS -//////// -registerHook("ol_content_simple", ol_content_simple, FALTERNATE, CSSOFF); -registerHook("ol_content_caption", ol_content_caption, FALTERNATE, CSSOFF); -registerHook("ol_content_background", ol_content_background, FALTERNATE, CSSOFF); -registerHook("ol_content_simple", ol_content_simple, FALTERNATE, CSSCLASS); -registerHook("ol_content_caption", ol_content_caption, FALTERNATE, CSSCLASS); -registerHook("ol_content_background", ol_content_background, FALTERNATE, CSSCLASS); -registerHook("hideObject", nbspCleanup, FAFTER); - diff --git a/mods/pnATutor/pnincludes/overlib_mini.js b/mods/pnATutor/pnincludes/overlib_mini.js deleted file mode 100644 index 6aa4b8a5e..000000000 --- a/mods/pnATutor/pnincludes/overlib_mini.js +++ /dev/null @@ -1,328 +0,0 @@ -//\///// -//\ overLIB 4.00 - You may not remove or change this notice. -//\ Copyright Erik Bosrup 1998-2004. All rights reserved. -//\ -//\ Contributors are listed on the homepage. -//\ This file might be old, always check for the latest version at: -//\ http://www.bosrup.com/web/overlib/ -//\ -//\ Please read the license agreement (available through the link above) -//\ before using overLIB. Direct any licensing questions to erik@bosrup.com. -//\ -//\ 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 IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL! -var olLoaded=0;var pmStart=10000000; var pmUpper=10001000; var pmCount=pmStart+1; var pms=new Array(); var olInfo=new Info('4.00', 1);var FREPLACE=0; var FBEFORE=1; var FAFTER=2; var FALTERNATE=3;var olHideForm=0;registerCommands('donothing,inarray,caparray,sticky,background,noclose,caption,left,right,center,offsetx,offsety,fgcolor,bgcolor,textcolor,capcolor,closecolor,width,border,cellpad,status,autostatus,autostatuscap,height,closetext,snapx,snapy,fixx,fixy,relx,rely,fgbackground,bgbackground,padx,pady,fullhtml,above,below,capicon,textfont,captionfont,closefont,textsize,captionsize,closesize,timeout,function,delay,hauto,vauto,closeclick,wrap,followmouse,mouseoff,closetitle,cssoff,cssclass,fgclass,bgclass,textfontclass,captionfontclass,closefontclass'); -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_cellpad=='undefined') var ol_cellpad=2;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=RIGHT;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_relx=='undefined') var ol_relx=null;if (typeof ol_rely=='undefined') var ol_rely=null;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=BELOW;if (typeof ol_aboveheight=='undefined') var ol_aboveheight=0;if (typeof ol_capicon=='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=null;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_wrap=='undefined') var ol_wrap=0;if (typeof ol_followmouse=='undefined') var ol_followmouse=1;if (typeof ol_mouseoff=='undefined') var ol_mouseoff=0;if (typeof ol_closetitle=='undefined') var ol_closetitle='Close';if (typeof ol_css=='undefined') var ol_css=CSSOFF;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_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 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_cellpad=2;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_relx=null;var o3_rely=null;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_wrap=0;var o3_followmouse=1;var o3_mouseoff=0;var o3_closetitle='';var o3_css=CSSOFF;var o3_fgclass="";var o3_bgclass="";var o3_textfontclass="";var o3_captionfontclass="";var o3_closefontclass=""; -var o3_x=0;var o3_y=0;var o3_showingsticky=0;var o3_removecounter=0; -var over=null;var fnRef, hoveringSwitch=false; -var isMac=(navigator.userAgent.indexOf("Mac")!=-1);var olOp=(navigator.userAgent.toLowerCase().indexOf('opera 7.')>-1);var olNs4=(navigator.appName=='Netscape'&&parseInt(navigator.appVersion)==4);var olNs6=(document.getElementById)?true:false;var olIe4=(document.all)?true:false;var olIe5=false;var olIe55=false;var docRoot='document.body'; -if (olNs4) {var oW=window.innerWidth;var oH=window.innerHeight;window.onresize=function() { if (oW!=window.innerWidth||oH!=window.innerHeight) location.reload(); } -} -if (olIe4) {var versNum=parseFloat(navigator.userAgent.match(/MSIE (\d\.\d+)\.*/i)[1]);if (versNum>=5){olIe5=true;olIe55=(versNum>=5.5&&!olOp)?true:false;if (olNs6) olNs6=false;} -if (olNs6) olIe4=false;} -if (document.compatMode&&document.compatMode=='CSS1Compat') {docRoot=((olIe4&&!olOp)?'document.documentElement':docRoot);} -if(window.addEventListener) window.addEventListener("load",OLonLoad_handler,true);else if (window.attachEvent) window.attachEvent("onload",OLonLoad_handler);else window.onload=OLonLoad_handler; -var olCheckMouseCapture=true;if ((olNs4||olNs6||olIe4)) {olMouseCapture();} else {overlib=no_overlib;nd=no_overlib;ver3fix=true;} -function overlib() {if (!olLoaded||isExclusive(overlib.arguments)) return true;if (olCheckMouseCapture) olMouseCapture();if (over) cClick(); -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_cellpad=ol_cellpad;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_relx=ol_relx;o3_rely=ol_rely;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_wrap=ol_wrap;o3_followmouse=ol_followmouse;o3_mouseoff=ol_mouseoff;o3_closetitle=ol_closetitle;o3_css=ol_css;o3_fgclass=ol_fgclass;o3_bgclass=ol_bgclass;o3_textfontclass=ol_textfontclass;o3_captionfontclass=ol_captionfontclass;o3_closefontclass=ol_closefontclass; -setRunTimeVariables(); -fnRef=''; -o3_frame=ol_frame; -if (olNs4) {over=o3_frame.document.layers['overDiv'];} else if (document.all) {over=o3_frame.document.all['overDiv'];} else if (document.getElementById) {over=o3_frame.document.getElementById("overDiv");} -parseTokens('o3_', overlib.arguments);if (!postParseChecks()) return false; -if (o3_delay==0) {return runHook("olMain", FREPLACE);} else {o3_delayid=setTimeout("runHook('olMain', FREPLACE)", o3_delay);return false;} -} -function nd(time) {if (olLoaded&&!isExclusive()) {if (time&&!o3_delay) {if (o3_timerid>0) clearTimeout(o3_timerid); -o3_timerid=setTimeout("cClick()",(o3_timeout=time));} -if (o3_removecounter>=1) { o3_showingsticky=0 }; -if (o3_showingsticky==0) {o3_allowmove=0;if (over!=null&&o3_timerid==0) runHook("hideObject", FREPLACE, over);} else {o3_removecounter++;} -} -return true;} -function cClick() {if (olLoaded) {runHook("hideObject", FREPLACE, over);o3_showingsticky=0;} -return false;} -function overlib_pagedefaults() {parseTokens('ol_', overlib_pagedefaults.arguments);} -function olMain() {var layerhtml, styleType;runHook("olMain", FBEFORE); -if (o3_background!=""||o3_fullhtml) { -layerhtml=runHook('ol_content_background', FALTERNATE, o3_css, o3_text, o3_background, o3_fullhtml);} else { -styleType=(pms[o3_css-1-pmStart]=="cssoff"||pms[o3_css-1-pmStart]=="cssclass"); -if (o3_fgbackground!="") o3_fgbackground="background=\""+o3_fgbackground+"\"";if (o3_bgbackground!="") o3_bgbackground=(styleType?"background=\""+o3_bgbackground+"\"":o3_bgbackground); -if (o3_fgcolor!="") o3_fgcolor=(styleType?"bgcolor=\""+o3_fgcolor+"\"":o3_fgcolor);if (o3_bgcolor!="") o3_bgcolor=(styleType?"bgcolor=\""+o3_bgcolor+"\"":o3_bgcolor); -if (o3_height>0) o3_height=(styleType?"height=\""+o3_height+"\"":o3_height);else o3_height=""; -if (o3_cap=="") { -layerhtml=runHook('ol_content_simple', FALTERNATE, o3_css, o3_text);} else { -if (o3_sticky) { -layerhtml=runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, o3_close);} else { -layerhtml=runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, "");} -} -} -if (o3_sticky) {if (o3_timerid>0) {clearTimeout(o3_timerid);o3_timerid=0;} -o3_showingsticky=1;o3_removecounter=0;} -if (!runHook("createPopup", FREPLACE, layerhtml)) return false; -if (o3_autostatus>0) {o3_status=o3_text;if (o3_autostatus>1) o3_status=o3_cap;} -o3_allowmove=0; -if (o3_timeout>0) {if (o3_timerid>0) clearTimeout(o3_timerid);o3_timerid=setTimeout("cClick()", o3_timeout);} -runHook("disp", FREPLACE, o3_status);runHook("olMain", FAFTER); -if (o3_status!='') {return true;} else {return;} -} -function ol_content_simple(text) {txt='
    ':'>')+(o3_textfontclass?'':wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass?'':wrapStr(1,o3_textsize))+'
    '; -set_background("");return txt;} -function ol_content_caption(text,title,close) {var nameId;closing="";closeevent="onmouseover";if (o3_closeclick==1) closeevent=(o3_closetitle?"title='"+o3_closetitle+"'":"")+" onclick";if (o3_capicon!="") {nameId=' hspace=\"5\"'+' align=\"middle\" alt=\"\"';if (typeof o3_dragimg!='undefined'&&o3_dragimg) nameId=' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"';o3_capicon='';} -if (close!="") closing=''+(o3_closefontclass?'':wrapStr(0,o3_closesize,'close'))+close+(o3_closefontclass?'':wrapStr(1,o3_closesize,'close'))+'';txt='
    ':'>')+(o3_captionfontclass?'':''+wrapStr(0,o3_captionsize,'caption'))+o3_capicon+title+(o3_captionfontclass?'':wrapStr(1,o3_captionsize)+'')+''+closing+'
    ' :'>')+(o3_textfontclass?'':wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass?'':wrapStr(1,o3_textsize))+'
    '; -set_background("");return txt;} -function ol_content_background(text,picture,hasfullhtml) {if (hasfullhtml) {txt=text;} else {txt='
    '+wrapStr(0,o3_textsize,'text')+text+wrapStr(1,o3_textsize)+'
    ';} -set_background(picture);return txt;} -function set_background(pic) {if (pic=="") {if (olNs4) {over.background.src=null;} else if (over.style) {over.style.backgroundImage="none";} -} else {if (olNs4) {over.background.src=pic;} else if (over.style) {over.style.backgroundImage="url("+pic+")";} -} -} -function disp(statustext) {runHook("disp", FBEFORE); -if (o3_allowmove==0) {runHook("placeLayer", FREPLACE);runHook("showObject", FREPLACE, over);o3_allowmove=(o3_sticky||o3_followmouse==0)?0:1;} -runHook("disp", FAFTER); -if (statustext!="") self.status=statustext;} -function createPopup(lyrContent){runHook("createPopup", FBEFORE); -if (o3_wrap&&!(olNs4||olOp)) {if (olIe4) {over.style.pixelWidth=0;} else if (olNs6) {repositionTo(over, 0,-over.offsetHeight);} -} -layerWrite(lyrContent); -if (o3_wrap) o3_width=(olNs4?over.clip.width:over.offsetWidth); -runHook("createPopup", FAFTER, lyrContent); -return true;} -function placeLayer() {var placeX, placeY, widthFix=0; -if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientWidth=='number'")&&eval('o3_frame.'+docRoot+'.clientWidth')) {iwidth=eval('o3_frame.'+docRoot+'.clientWidth');} else if (typeof(o3_frame.innerWidth)=='number') {widthFix=Math.ceil(1.2*(o3_frame.outerWidth-o3_frame.innerWidth));iwidth=o3_frame.innerWidth;} -winoffset=(olIe4)?eval('o3_frame.'+docRoot+'.scrollLeft'):o3_frame.pageXOffset;var parsedWidth=parseInt(o3_width); -if (o3_fixx>-1||o3_relx!=null) { -placeX=(o3_relx!=null?( o3_relx<0?winoffset+o3_relx+iwidth-parsedWidth-widthFix:winoffset+o3_relx):o3_fixx);} else { -if (o3_hauto==1) {if ((o3_x-winoffset)>(iwidth/2)) {o3_hpos=LEFT;} else {o3_hpos=RIGHT;} -} -if (o3_hpos==CENTER) {placeX=o3_x+o3_offsetx-(parsedWidth/2); -if (placeX(winoffset+iwidth-widthFix)) {placeX=iwidth+winoffset-parsedWidth-widthFix;if (placeX<0) placeX=0;} -} -if (o3_hpos==LEFT) {placeX=o3_x-o3_offsetx-parsedWidth;if (placeX1) {var snapping=placeX % o3_snapx; -if (o3_hpos==LEFT) {placeX=placeX-(o3_snapx+snapping);} else { -placeX=placeX+(o3_snapx-snapping);} -if (placeX-1||o3_rely!=null) { -placeY=(o3_rely!=null?(o3_rely<0?scrolloffset+o3_rely+iheight-parsedHeight:scrolloffset+o3_rely):o3_fixy);} else { -if (o3_vauto==1) {if ((o3_y-scrolloffset)>(iheight/2)) {o3_vpos=ABOVE;} else {o3_vpos=BELOW;} -} -if (o3_vpos==ABOVE) {if (o3_aboveheight==0) o3_aboveheight=parsedHeight; -placeY=o3_y-(o3_aboveheight+o3_offsety);if (placeY1) {var snapping=placeY % o3_snapy; -if (o3_aboveheight>0&&o3_vpos==ABOVE) {placeY=placeY-(o3_snapy+snapping);} else {placeY=placeY+(o3_snapy-snapping);} -if (placeYpmStart&&ar[i]=pmCount||ar[i]==DONOTHING) { continue; } -if (ar[i]==INARRAY) { fnMark=0; eval(pf+'text=ol_texts['+ar[++i]+'].toString()'); continue; } -if (ar[i]==CAPARRAY) { eval(pf+'cap=ol_caps['+ar[++i]+'].toString()'); continue; } -if (ar[i]==STICKY) { if (pf!='ol_') eval(pf+'sticky=1'); continue; } -if (ar[i]==BACKGROUND) { eval(pf+'background="'+ar[++i]+'"'); continue; } -if (ar[i]==NOCLOSE) { if (pf!='ol_') opt_NOCLOSE(); continue; } -if (ar[i]==CAPTION) { eval(pf+"cap='"+escSglQuote(ar[++i])+"'"); continue; } -if (ar[i]==CENTER||ar[i]==LEFT||ar[i]==RIGHT) { eval(pf+'hpos='+ar[i]); continue; } -if (ar[i]==OFFSETX) { eval(pf+'offsetx='+ar[++i]); continue; } -if (ar[i]==OFFSETY) { eval(pf+'offsety='+ar[++i]); continue; } -if (ar[i]==FGCOLOR) { eval(pf+'fgcolor="'+ar[++i]+'"'); continue; } -if (ar[i]==BGCOLOR) { eval(pf+'bgcolor="'+ar[++i]+'"'); continue; } -if (ar[i]==TEXTCOLOR) { eval(pf+'textcolor="'+ar[++i]+'"'); continue; } -if (ar[i]==CAPCOLOR) { eval(pf+'capcolor="'+ar[++i]+'"'); continue; } -if (ar[i]==CLOSECOLOR) { eval(pf+'closecolor="'+ar[++i]+'"'); continue; } -if (ar[i]==WIDTH) { eval(pf+'width='+ar[++i]); continue; } -if (ar[i]==BORDER) { eval(pf+'border='+ar[++i]); continue; } -if (ar[i]==CELLPAD) { i=opt_MULTIPLEARGS(++i,ar,(pf+'cellpad')); continue; } -if (ar[i]==STATUS) { eval(pf+"status='"+escSglQuote(ar[++i])+"'"); continue; } -if (ar[i]==AUTOSTATUS) { eval(pf+'autostatus=('+pf+'autostatus==1)?0:1'); continue; } -if (ar[i]==AUTOSTATUSCAP) { eval(pf+'autostatus=('+pf+'autostatus==2)?0:2'); continue; } -if (ar[i]==HEIGHT) { eval(pf+'height='+pf+'aboveheight='+ar[++i]); continue; } -if (ar[i]==CLOSETEXT) { eval(pf+"close='"+escSglQuote(ar[++i])+"'"); continue; } -if (ar[i]==SNAPX) { eval(pf+'snapx='+ar[++i]); continue; } -if (ar[i]==SNAPY) { eval(pf+'snapy='+ar[++i]); continue; } -if (ar[i]==FIXX) { eval(pf+'fixx='+ar[++i]); continue; } -if (ar[i]==FIXY) { eval(pf+'fixy='+ar[++i]); continue; } -if (ar[i]==RELX) { eval(pf+'relx='+ar[++i]); continue; } -if (ar[i]==RELY) { eval(pf+'rely='+ar[++i]); continue; } -if (ar[i]==FGBACKGROUND) { eval(pf+'fgbackground="'+ar[++i]+'"'); continue; } -if (ar[i]==BGBACKGROUND) { eval(pf+'bgbackground="'+ar[++i]+'"'); continue; } -if (ar[i]==PADX) { eval(pf+'padxl='+ar[++i]); eval(pf+'padxr='+ar[++i]); continue; } -if (ar[i]==PADY) { eval(pf+'padyt='+ar[++i]); eval(pf+'padyb='+ar[++i]); continue; } -if (ar[i]==FULLHTML) { if (pf!='ol_') eval(pf+'fullhtml=1'); continue; } -if (ar[i]==BELOW||ar[i]==ABOVE) { eval(pf+'vpos='+ar[i]); continue; } -if (ar[i]==CAPICON) { eval(pf+'capicon="'+ar[++i]+'"'); continue; } -if (ar[i]==TEXTFONT) { eval(pf+"textfont='"+escSglQuote(ar[++i])+"'"); continue; } -if (ar[i]==CAPTIONFONT) { eval(pf+"captionfont='"+escSglQuote(ar[++i])+"'"); continue; } -if (ar[i]==CLOSEFONT) { eval(pf+"closefont='"+escSglQuote(ar[++i])+"'"); continue; } -if (ar[i]==TEXTSIZE) { eval(pf+'textsize="'+ar[++i]+'"'); continue; } -if (ar[i]==CAPTIONSIZE) { eval(pf+'captionsize="'+ar[++i]+'"'); continue; } -if (ar[i]==CLOSESIZE) { eval(pf+'closesize="'+ar[++i]+'"'); continue; } -if (ar[i]==TIMEOUT) { eval(pf+'timeout='+ar[++i]); continue; } -if (ar[i]==FUNCTION) { if (pf=='ol_') { if (typeof ar[i+1]!='number') { v=ar[++i]; ol_function=(typeof v=='function'?v:null); }} else {fnMark=0; v=null; if (typeof ar[i+1]!='number') v=ar[++i]; opt_FUNCTION(v); } continue; } -if (ar[i]==DELAY) { eval(pf+'delay='+ar[++i]); continue; } -if (ar[i]==HAUTO) { eval(pf+'hauto=('+pf+'hauto==0)?1:0'); continue; } -if (ar[i]==VAUTO) { eval(pf+'vauto=('+pf+'vauto==0)?1:0'); continue; } -if (ar[i]==CLOSECLICK) { eval(pf+'closeclick=('+pf+'closeclick==0)?1:0'); continue; } -if (ar[i]==WRAP) { eval(pf+'wrap=('+pf+'wrap==0)?1:0'); continue; } -if (ar[i]==FOLLOWMOUSE) { eval(pf+'followmouse=('+pf+'followmouse==1)?0:1'); continue; } -if (ar[i]==MOUSEOFF) { eval(pf+'mouseoff=('+pf+'mouseoff==0)?1:0'); continue; } -if (ar[i]==CLOSETITLE) { eval(pf+"closetitle='"+escSglQuote(ar[++i])+"'"); continue; } -if (ar[i]==CSSOFF||ar[i]==CSSCLASS) { eval(pf+'css='+ar[i]); continue; } -if (ar[i]==FGCLASS) { eval(pf+'fgclass="'+ar[++i]+'"'); continue; } -if (ar[i]==BGCLASS) { eval(pf+'bgclass="'+ar[++i]+'"'); continue; } -if (ar[i]==TEXTFONTCLASS) { eval(pf+'textfontclass="'+ar[++i]+'"'); continue; } -if (ar[i]==CAPTIONFONTCLASS) { eval(pf+'captionfontclass="'+ar[++i]+'"'); continue; } -if (ar[i]==CLOSEFONTCLASS) { eval(pf+'closefontclass="'+ar[++i]+'"'); continue; } -i=parseCmdLine(pf, i, ar);} -} -if (fnMark&&o3_function) o3_text=o3_function(); -if ((pf=='o3_')&&o3_wrap) {o3_width=0; -if (olOp||(olIe4&&isMac)) {var tReg=/<.*\n*>/ig;if (!tReg.test(o3_text)) o3_text=o3_text.replace(/[ ]+/g, ' ');if (!tReg.test(o3_cap))o3_cap=o3_cap.replace(/[ ]+/g, ' ');} -} -if ((pf=='o3_')&&o3_sticky) {if (!o3_close&&(o3_frame!=ol_frame)) o3_close=ol_close;if (o3_mouseoff&&(o3_frame==ol_frame)) opt_NOCLOSE(' ');} -} -function layerWrite(txt) {txt+="\n";if (olNs4) {var lyr=o3_frame.document.overDiv.document -lyr.write(txt) -lyr.close() -} else if (typeof over.innerHTML!='undefined') {if (olIe5&&isMac) over.innerHTML='';over.innerHTML=txt;} else {range=o3_frame.document.createRange();range.setStartAfter(over);domfrag=range.createContextualFragment(txt); -while (over.hasChildNodes()) {over.removeChild(over.lastChild);} -over.appendChild(domfrag);} -} -function showObject(obj) {runHook("showObject", FBEFORE); -var theObj=(olNs4?obj:obj.style);theObj.visibility='visible'; -runHook("showObject", FAFTER);} -function hideObject(obj) {runHook("hideObject", FBEFORE); -var theObj=(olNs4?obj:obj.style);theObj.visibility='hidden'; -if (o3_timerid>0) clearTimeout(o3_timerid);if (o3_delayid>0) clearTimeout(o3_delayid); -o3_timerid=0;o3_delayid=0;self.status=""; -if (over.onmouseout||over.onmouseover) {if (olNs4) over.releaseEvents(Event.MOUSEOUT||Event.MOUSEOVER);over.onmouseout=over.onmouseover=null;} -runHook("hideObject", FAFTER);} -function repositionTo(obj, xL, yL) {var theObj=(olNs4?obj:obj.style);theObj.left=xL+(!olNs4?'px':0);theObj.top=yL+(!olNs4?'px':0);} -function cursorOff() {var left=parseInt(over.style.left);var top=parseInt(over.style.top);var right=left+over.offsetWidth;var bottom=top+over.offsetHeight; -if (o3_xright||o3_ybottom) return true; -return false;} -function opt_FUNCTION(callme) {o3_text=(callme?(typeof callme=='string'?(/.+\(.*\)/.test(callme)?eval(callme):callme):callme()):(o3_function?o3_function():'No Function')); -return 0;} -function opt_NOCLOSE(unused) {if (!unused) o3_close=""; -if (olNs4) {over.captureEvents(Event.MOUSEOUT||Event.MOUSEOVER);over.onmouseover=function () { if (o3_timerid>0) { clearTimeout(o3_timerid); o3_timerid=0; } } -over.onmouseout=cClick;} else {over.onmouseover=function () {hoveringSwitch=true; if (o3_timerid>0) { clearTimeout(o3_timerid); o3_timerid=0; } } -} -return 0;} -function opt_MULTIPLEARGS(i, args, parameter) {var k=i, l, re, pV, str=''; -for(k=i; kpmStart) break;} -if(k>=args.length) l=str.length-1;else {re=eval('/,'+args[k]+'/');l=str.search(re);} -k--;str=str.substring(0, l);pV=(olNs4&&/cellpad/i.test(parameter))?str.split(',')[0]:str;eval(parameter+'="'+pV+'"'); -return k;} -function nbspCleanup() {if (o3_wrap&&(olOp||(olIe4&&isMac))) {o3_text=o3_text.replace(/\ /g, ' ');o3_cap=o3_cap.replace(/\ /g, ' ');} -} -function escSglQuote(str) {return str.toString().replace(/'/g,"\\'");} -function OLonLoad_handler(e) {if (!olLoaded) olLoaded=1; -if (window.removeEventListener) window.removeEventListener("load",OLonLoad_handler,true);else if (window.detachEvent) window.detachEvent("onload",OLonLoad_handler); -if (olNs4) routeEvent(e);} -function wrapStr(endWrap,fontSizeStr,whichString) {var fontStr, fontColor, isClose=((whichString=='close')?1:0), hasDims=/[%\-a-z]+$/.test(fontSizeStr);fontSizeStr=(olNs4)?(!hasDims?fontSizeStr:'1'):fontSizeStr;if (endWrap) return (hasDims&&!olNs4)?(isClose?'':'
    '):'';else {fontStr='o3_'+whichString+'font';fontColor='o3_'+((whichString=='caption')? 'cap':whichString)+'color';return (hasDims&&!olNs4)?(isClose?'':'
    '):'';} -} -function quoteMultiNameFonts(theFont) {var v, pM=theFont.split(',');for (var i=0; i-1) {i=j;break;} -} -} -return i;} -function postParseChecks(){if (typeof postParse!='undefined'&&postParse.length) {for (var k=0; k-1) hookPt.alt[pms[CSSOFF-1-pmStart]]=fnRef; -} else if (hookType==FBEFORE||hookType==FAFTER) {var hookPt=(hookType==1?hookPt.before:hookPt.after); -if (typeof fnRef=='object') {hookPt=hookPt.concat(fnRef);} else {hookPt[hookPt.length++]=fnRef;} -if (optPm) hookPt=reOrder(hookPt, fnRef, optPm); -} else if (hookType==FALTERNATE) {if (last=='number') hookPt.alt[pms[optPm-1-pmStart]]=fnRef;} -return;} -} -function registerRunTimeFunction(fn) {if (isFunction(fn)) {if (typeof runTime=='undefined') runTime=new Array();if (typeof fn=='object') {runTime=runTime.concat(fn);} else {runTime[runTime.length++]=fn;} -} -} -function registerCmdLineFunction(fn){if (isFunction(fn)) {if (typeof cmdLine=='undefined') cmdLine=new Array();if (typeof fn=='object') {cmdLine=cmdLine.concat(fn);} else {cmdLine[cmdLine.length++]=fn;} -} -} -function registerPostParseFunction(fn){if (isFunction(fn)) {if (typeof postParse=='undefined') postParse=new Array();if (typeof fn=='object') {postParse=postParse.concat(fn);} else {postParse[postParse.length++]=fn;} -} -} -function runHook(fnHookTo, hookType) {var l=hookPts[fnHookTo], optPm, arS, ar=runHook.arguments; -if (hookType==FREPLACE) {arS=argToString(ar, 2); -if (typeof l=='undefined'||!(l=l.ovload)) return eval(fnHookTo+'('+arS+')');else return eval('l('+arS+')'); -} else if (hookType==FBEFORE||hookType==FAFTER) {if (typeof l=='undefined') return;l=(hookType==1?l.before:l.after); -if (!l.length) return; -arS=argToString(ar, 2);for (var k=0; kjS) {for (var k=jS; k-GBl{r(wkp#wm4N@adIiMRzweF}NC zRg}7Rro{n+#HrQmyw&6YHfbk@yD^c(3}l?#>hl0efqjRMRFAeninXcFlD*eN zfvSeV-x6`CzuW4U%H%P7s(G~3M4QUU-s|S@_GX&A`uzTT!Q?S?p=YGW2ULm$MS4n! zva`|S7k94-U6s`4@Bv4D08NDiaIHV5+3)uHW3AIRc%>tMw9@MKQirV+Uy|wa_jIAa z0Y!TqMsO5YiFT{Y077`=@%TfJx&&XC1xkMbOo9bRdjMCF21|hM`20wGqXSTfCQWk% zPJ{?jhXg}+e5}eqhOq!gf(BWT07HCpe~bz_X=!8YF?TN3*Z>Y+++U%jg z)p@YcBVdqVv)m|CdKG`T2Tg41ejEjGdkdcy;l$Dm3n31f_g@f3uOawX?G!yuG}*kg0!Q7>_59U}}GCYG991e`;*Z&VNzWk7-fL(AJoI zAqe6jz_q;M=o1qc>=zT`z`_{LQERIhCu(a1`^10q`}RfH7i-uF0>{$)D`trg0(B6{ zK?(tJ9Xlu{vS>6h1d2O}e}u70Lx4>LSMwD9NrS=8%2nB-oN)E1<;s`GE>XNd#|xcz zAs#uLAjQi9C_|*Q@WGU+jwVBTOpqutl1*(2iKS5^lTB6(C>gF{c8s4(ofD|M@$*Do z&_5LaCou5?!UT~PNBrpBTcbsmF$jXDVpH%Dn-ggw*h#ZyD*=)O7B^OdP+PV&C!k?a z*$}}66KkKKx$u@EnzhAz&=JNL23X(&2ON}PK^s`~(1QkJ z${<4m7NF2V6Fh8zqkz@*NY{_uy%5A6XIx>09|iD0VR{2%u?Gh**noo{2bA!D3|lBr zgAFzSzyT3roB;x;PTa7C1uQghfL=!kv4RC(h_Ocjpb9Yn3>6%(!Wn)-m*Xx34vJs} z5-9P41r}K0st-h*#|cFmoblXV*aBdM1LNsc00|H71%L=jK!7c_H7F1S2{q`I#}a!z zq1vB1f>W%42=ncR1}f~e zL>+ZVuonvsyuiS@egKfb9>D?#=)FH4Q9%^|0ANGE5a`iH4@>sp5EMX>(6dH?|`!pGNB9x$)1Uc+AKoJ#_eC`gB z>%{^I=3Ssg<^bY+&KPDBT0;V2V8I0sR|Fs|>U~f&gavu&wfhSj#PRX}72LWDuOAEm z;lK`iQ4oU*@W&rO2EqF=g8&++(?jM{7=XtZ5NS^55|jWQaAA7YyIu$c;gB8#;Rkzx zfd~wDHx8U32pPDWUgmIxAlOYW2dJ6{L@ zAfNyuXh8!8-~hHBumvt?Aqy6OqVI&D0|T&YFJvIX1;p{0=k)6T0H6dV3d~TTHW;7` z2@7S`oM5_54h$R}8EHnWQHE=>LZO{NR z=n@Y+C;%{Ta2sBv06TYxNHG8a diff --git a/mods/pnATutor/pninit.php b/mods/pnATutor/pninit.php deleted file mode 100644 index a2c84281e..000000000 --- a/mods/pnATutor/pninit.php +++ /dev/null @@ -1,79 +0,0 @@ - diff --git a/mods/pnATutor/pnlang/eng/admin.php b/mods/pnATutor/pnlang/eng/admin.php deleted file mode 100644 index 287c168aa..000000000 --- a/mods/pnATutor/pnlang/eng/admin.php +++ /dev/null @@ -1,21 +0,0 @@ - diff --git a/mods/pnATutor/pnlang/eng/courses.php b/mods/pnATutor/pnlang/eng/courses.php deleted file mode 100644 index 2d0083595..000000000 --- a/mods/pnATutor/pnlang/eng/courses.php +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/mods/pnATutor/pntemplates/pnATutor_block_courses.htm b/mods/pnATutor/pntemplates/pnATutor_block_courses.htm deleted file mode 100644 index 2e4e115e8..000000000 --- a/mods/pnATutor/pntemplates/pnATutor_block_courses.htm +++ /dev/null @@ -1,26 +0,0 @@ - - -
    - -
    - - - - - - - -
    - -
    - -
    - - - - - - - - - diff --git a/mods/pnATutor/pntemplates/pnATutor_block_courses_modify.htm b/mods/pnATutor/pntemplates/pnATutor_block_courses_modify.htm deleted file mode 100644 index 02d1896f0..000000000 --- a/mods/pnATutor/pntemplates/pnATutor_block_courses_modify.htm +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mods/pnATutor/pnuser.php b/mods/pnATutor/pnuser.php deleted file mode 100644 index b1ceeb2bf..000000000 --- a/mods/pnATutor/pnuser.php +++ /dev/null @@ -1,147 +0,0 @@ - - - - - "; -echo "function iFrameHeight() {"; -echo " var h = 0;"; -echo " if ( !document.all ) {"; -echo " h = document.getElementById('blockrandom').contentDocument.height;"; -echo " document.getElementById('blockrandom').style.height = h + 60 + 'px';"; -echo " } else if( document.all ) {"; -echo " h = document.frames('blockrandom').document.body.scrollHeight;"; -echo " document.all.blockrandom.style.height = h + 20 + 'px';"; -echo " }"; -echo "}"; -echo ""; -echo ""; -}else{ -echo pnVarPrepHTMLDisplay(_PNSMF_LAUNCHED); -} -include("footer.php"); -return true; - - -} - -?> diff --git a/mods/pnATutor/pnversion.php b/mods/pnATutor/pnversion.php deleted file mode 100644 index 8a6d35a16..000000000 --- a/mods/pnATutor/pnversion.php +++ /dev/null @@ -1,18 +0,0 @@ - '::'); - -?> diff --git a/mods/scorm_packages/delete.php b/mods/scorm_packages/delete.php deleted file mode 100644 index a049cea47..000000000 --- a/mods/scorm_packages/delete.php +++ /dev/null @@ -1,75 +0,0 @@ - 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 .= '
  • ' . $l . '
  • ' . "\n"; - $num++; - } -} - -if ($num == 0) { - $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY'); - header('Location: index.php' ); - exit; -} - -require(AT_INCLUDE_PATH.'header.inc.php'); -?> - -
    -
    -
    -
      - -
    -
    - -
    -
    -
    -
    - - - diff --git a/mods/scorm_packages/import.php b/mods/scorm_packages/import.php deleted file mode 100644 index 7dc8da135..000000000 --- a/mods/scorm_packages/import.php +++ /dev/null @@ -1,111 +0,0 @@ -addError($error); - } - - if(!$msg->containsErrors()){ - if (isset ($_POST['type']) ) { - require ($_POST['type'] . '/import.php'); - } - } -} -require(AT_INCLUDE_PATH.'header.inc.php'); - -$msg->printErrors(); - -?> - -
    -
    -
    - - -
    - -
    - -
    - - -
    - -
    - -
    - - -
    -
    - -
    - -
    - - -
    - -
    - -
    - - - diff --git a/mods/scorm_packages/index.php b/mods/scorm_packages/index.php deleted file mode 100644 index de706b226..000000000 --- a/mods/scorm_packages/index.php +++ /dev/null @@ -1,64 +0,0 @@ - 0) { - array_push ($_pages['mods/scorm_packages/index.php']['children'], - 'mods/scorm_packages/delete.php' - ); - - array_push ($_pages['mods/scorm_packages/index.php']['children'], - 'mods/scorm_packages/settings.php' - ); - - } - -} - - -require(AT_INCLUDE_PATH.'header.inc.php'); -echo '
    '; -if (sizeOf ($pkgs) == 0) { - $msg->addInfo (NO_PACKAGES); - $msg->printAll(); -} else { - echo getScript(); - echo '
      ' . "\n"; - foreach ($pkgs as $pk) { - echo '
    1. ' . $pk . '
    2. ' . "\n"; - } - echo '
    ' . "\n"; -} -echo "
    "; -require (AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/scorm_packages/lib.inc.php b/mods/scorm_packages/lib.inc.php deleted file mode 100644 index 3615a12cc..000000000 --- a/mods/scorm_packages/lib.inc.php +++ /dev/null @@ -1,89 +0,0 @@ -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 " - -"; -} - -?> diff --git a/mods/scorm_packages/module.php b/mods/scorm_packages/module.php deleted file mode 100644 index 3b32d4fba..000000000 --- a/mods/scorm_packages/module.php +++ /dev/null @@ -1,40 +0,0 @@ -getPrivilege()); - -define('AT_PACKAGE_TYPES', 'scorm-1.2'); -define('AT_PACKAGE_URL_BASE', AT_BASE_HREF . 'sco/'); - - -// if this module is to be made available to students on the Home or Main Navigation -$_student_tool = 'mods/scorm_packages/packages/index.php'; - -$this->_pages['mods/scorm_packages/index.php']['title_var'] = 'packages'; -$this->_pages['mods/scorm_packages/index.php']['parent'] = 'tools/index.php'; -$this->_pages['mods/scorm_packages/index.php']['children'] = array('mods/scorm_packages/import.php', 'mods/scorm_packages/delete.php','mods/scorm_packages/settings.php'); -$this->_pages['mods/scorm_packages/index.php']['guide'] = 'instructor/?p=scorm_packages.php'; - - $this->_pages['mods/scorm_packages/import.php']['title_var'] = 'import_package'; - $this->_pages['mods/scorm_packages/import.php']['parent'] = 'mods/scorm_packages/index.php'; - - $this->_pages['mods/scorm_packages/delete.php']['title_var'] = 'delete_package'; - $this->_pages['mods/scorm_packages/delete.php']['parent'] = 'mods/scorm_packages/index.php'; - - $this->_pages['mods/scorm_packages/settings.php']['title_var'] = 'package_settings'; - $this->_pages['mods/scorm_packages/settings.php']['parent'] = 'mods/scorm_packages/index.php'; - - $this->_pages['mods/scorm_packages/scorm-1.2/view.php']['parent'] = 'mods/scorm_packages/index.php'; - -$this->_pages['mods/scorm_packages/packages/index.php']['title_var'] = 'packages'; -$this->_pages['mods/scorm_packages/packages/index.php']['img'] = 'images/content_pkg.gif'; -$this->_pages['mods/scorm_packages/packages/index.php']['children'] = array ('mods/scorm_packages/packages/preferences.php'); -$this->_pages['mods/scorm_packages/packages/index.php']['guide'] = 'general/?p=packages.php'; - - $this->_pages['mods/scorm_packages/packages/preferences.php']['title_var'] = 'preferences'; - $this->_pages['mods/scorm_packages/packages/preferences.php']['parent'] = 'mods/scorm_packages/packages/index.php'; - - $this->_pages['mods/scorm_packages/cmidata.php']['title_var'] = 'cmi_data'; - $this->_pages['mods/scorm_packages/cmidata.php']['parent'] = 'mods/scorm_packages/index.php'; -?> diff --git a/mods/scorm_packages/module.sql b/mods/scorm_packages/module.sql deleted file mode 100644 index 8a479fce6..000000000 --- a/mods/scorm_packages/module.sql +++ /dev/null @@ -1,75 +0,0 @@ - -# SCORM language : some of it is still in svn and should be moved in here. - -INSERT INTO `language_text` VALUES ('en', '_module','scorm_browse','Browse',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','scorm_credit','Credit',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','scorm_credit_mode','Credit Mode:',NOW(),''); -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(),''); -INSERT INTO `language_text` VALUES ('en', '_module','scorm_lesson_mode','Lesson Mode:',NOW(),''); -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(),''); -INSERT INTO `language_text` VALUES ('en', '_module','scorm_normal','Normal',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','scorm_no_credit','No Credit',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','scorm_packages','SCORM Packages',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','scorm_sco_is_running','Running',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','package_scorm_1_2_rte_loading','Loading SCORM-1.2 RTE
    Please be patient ...',NOW(),''); -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(),''); -INSERT INTO `language_text` VALUES ('en', '_module','packages_show_rte_communication','Show RTE Communication',NOW(),''); -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(),''); - -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(),''); -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(),''); -INSERT INTO `language_text` VALUES ('en', '_module','AT_FEEDBACK_SCORM_SETTINGS_SAVED','The package settings have been saved.',NOW(),''); -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(),''); - - -# ---------------- -# SCORM RTE tables - -CREATE TABLE `packages` ( - `package_id` mediumint(8) unsigned NOT NULL auto_increment, - `source` varchar(255) NOT NULL, - `time` datetime NOT NULL, - `course_id` mediumint(8) unsigned NOT NULL, - `ptype` varchar(63) NOT NULL, - PRIMARY KEY (package_id) -) TYPE=MyISAM; - -CREATE TABLE `scorm_1_2_org` ( - `org_id` mediumint(8) unsigned NOT NULL auto_increment, - `package_id` mediumint(8) unsigned NOT NULL, - - `title` varchar(255) NOT NULL, - `credit` varchar(15) not null default 'no-credit', - `lesson_mode` varchar(15) not null default 'browse', - - PRIMARY KEY (org_id), - KEY (package_id) -) TYPE=MyISAM; - -CREATE TABLE `scorm_1_2_item` ( - `item_id` mediumint(8) unsigned NOT NULL auto_increment, - `org_id` mediumint(8) unsigned NOT NULL, - `idx` varchar(15) NOT NULL, - `title` varchar(255), - `href` varchar(255), - `scormtype` varchar(15), - `prerequisites` varchar(255), - `maxtimeallowed` varchar(255), - `timelimitaction` varchar(255), - `datafromlms` varchar(255), - `masteryscore` mediumint(8), - - PRIMARY KEY (item_id), - KEY (org_id) -)TYPE=MyISAM; - - -CREATE TABLE `cmi` ( - `cmi_id` mediumint(8) unsigned NOT NULL auto_increment, - `item_id` mediumint(8) unsigned NOT NULL, - `member_id` mediumint unsigned NOT NULL , - `lvalue` varchar(63) NOT NULL, - `rvalue` blob, - PRIMARY KEY (cmi_id), - UNIQUE KEY (item_id, member_id,lvalue) -)TYPE=MyISAM; diff --git a/mods/scorm_packages/module.xml b/mods/scorm_packages/module.xml deleted file mode 100644 index d177547ea..000000000 --- a/mods/scorm_packages/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - SCORM Packages - Allows instructors to include SCORM packages in a course. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - GPL - - 0.3 - 2010-10-25 - stable - - - \ No newline at end of file diff --git a/mods/scorm_packages/module_install.php b/mods/scorm_packages/module_install.php deleted file mode 100644 index b480d6598..000000000 --- a/mods/scorm_packages/module_install.php +++ /dev/null @@ -1,26 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else { - @chmod($directory, 0666); - if (!is_writable($directory)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); - } -} - -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); -} - -?> \ No newline at end of file diff --git a/mods/scorm_packages/module_uninstall.php b/mods/scorm_packages/module_uninstall.php deleted file mode 100644 index 7604ff748..000000000 --- a/mods/scorm_packages/module_uninstall.php +++ /dev/null @@ -1,35 +0,0 @@ -addError(array('MODULE_UNINSTALL', '
  • '.$directory.' can not be removed. Please manually remove it.
  • ')); -} - -/****** - * the following code checks if there are any errors (generated previously) - * then uses the SqlUtility to run reverted database queries of module.sql, - * ie. "create table" statement in module.sql is run as drop according table. - */ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/scorm_packages/packages/index.php b/mods/scorm_packages/packages/index.php deleted file mode 100644 index 4c07696a8..000000000 --- a/mods/scorm_packages/packages/index.php +++ /dev/null @@ -1,45 +0,0 @@ -'; -$pkgs = getPackagesLearnerLinkList(); - -if (sizeOf ($pkgs) == 0) { - $msg->addInfo (NO_PACKAGES); - $msg->printAll(); -} else { - echo getScript(); - echo '
      ' . "\n"; - foreach ($pkgs as $p) { - echo '
    1. ' . $p . '
    2. ' . "\n"; - } - echo '
    ' . "\n"; -} -echo '
    '; -require (AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/scorm_packages/packages/preferences.php b/mods/scorm_packages/packages/preferences.php deleted file mode 100644 index 35ab27d41..000000000 --- a/mods/scorm_packages/packages/preferences.php +++ /dev/null @@ -1,115 +0,0 @@ -addFeedback (SCORM_SETTINGS_SAVED); - } else { - $msg->addError (SCORM_SETTINGS_SAVE_FAILED); - } -} - -require(AT_INCLUDE_PATH.'header.inc.php'); -?> - -
    -
    - - -

    -

    - /> -

    - -

    -

    - /> -

    - -
    - -
    - -
    -
    - - diff --git a/mods/scorm_packages/possible_module_backup.php b/mods/scorm_packages/possible_module_backup.php deleted file mode 100644 index 3267cd4dc..000000000 --- a/mods/scorm_packages/possible_module_backup.php +++ /dev/null @@ -1,65 +0,0 @@ - \ No newline at end of file diff --git a/mods/scorm_packages/scorm-1.2/images/active.png b/mods/scorm_packages/scorm-1.2/images/active.png deleted file mode 100644 index a672fe60b67dcfb503c88c176b06af912453af1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 499 zcmV^Nj8ip zW_2>OAT;}8hDT#Dh$s1c+t?zT#)k2Pc5JMhg~m@oP&XSa6ylHibmnobvUAVXBTu>R zKuPHa0BLYy;>G4>OcwxNzkTyyeEigSY&;5BH-=^*tt*$CTUoi%cm4(~FMlkRK3DgW p@Zr(yR6bu=Sh(tg|E~*Py55WI_2}l?O3C4u(<-P7&CNRMW4{9Xeq=LG2 zRJy7{cZcH?erjws?`_klX;FmPNp)JEo}Ddzi%2Q0*H1Ezv5Yas5CWj5)QQM^zF_`7 zLWhXQhljrFh>4j(;G!sEjAdCeQ`_zi{ofI9udhwpAR;0X(q18OEMr+l0O-1Q0(&B8z6XD`MepZf0iYrm7+W0Ei$W<0umdb2l?JS2a}=Q9?lgRYd?* zQ`HGXRaGhVDypm^f`kBIZiEB~W)`@ZKwMs3J+IfqLPCfL0B){AM6}&#AO%jNm>UEJN@S5-9*<1mal4>=Dx=bUojaC7_T(2qa;$ji&~ v=k_zD#7uQvpI=;DU*G)KiO0Vg!O{8)`cu9Y*Em*900000NkvXXu0mjfnyF_2DvNpN(XT_f9`K)IFGNF>(FeVy)r^a05Pd5X&j(#|{W%I9+^t z=JgJ}+rb~sl;1ADAus|g4IQ{ntXn}Am*xGh%Jj$k2^P;@%>f_`Kz^Gckbsw~vkB*{ zE?3E**w_+nqbBkZ)v5ulwhGPQ`@vDZJ-FXOdawV5r8&LktHmWKXO75L?|-9 zj&I@{__~Wji$jZRc0653u(&vWNfBB%HSs^4Z&^Nj8ip zW_2>OAT;}8hDT#Dh$s1c+t?zT#)k2Pc5JMhg~m@oP&XSa6ylHibmnobvUAVXBTu>R zKuPHa0BLYy;>G4>OcwxNzkTyyeEigSY&;5BH-=^*tt*$CTUoi%cm4(~FMlkRK3DgW p@Zr(yR6bu=Sh(tg|E~F_2DvNpN(XT_f9`K)IFGNF>(FeVy)r^a05Pd5X&j(#|{W%I9+^t z=JgJ}+rb~sl;1ADAus|g4IQ{ntXn}Am*xGh%Jj$k2^P;@%>f_`Kz^Gckbsw~vkB*{ zE?3E**w_+nqbBkZ)v5ulwhGPQ`@vDZJ-FXOdawV5r8&LktHmWKXO75L?|-9 zj&I@{__~Wji$jZRc0653u(&vWNfBB%HSs^4Z&_!@hljQC0!qCAg>jC6&7I;J!Gca%qf-qx!O8i8iAbW|YuPggyZXR(y zjyIlB2Z2J?o-U3d6?2jk4)C%xMD!@Kcx*CjWAZ$9p<+To2ICAH2C+hhiLHzZrtA({ oHyf=aBvKkon41}yjr}$=F1pKhviDMW7SI?5Pgg&ebxsLQ0G8D^WB>pF diff --git a/mods/scorm_packages/scorm-1.2/images/incomplete.png b/mods/scorm_packages/scorm-1.2/images/incomplete.png deleted file mode 100644 index 0586c28eb9bb92d1ad5358e8daec54d53181ce60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 538 zcmV+#0_FXQP)3_-&itHd zhMCl4C|Igu6WS`?fr7fS7B_;f#EloAs8>*MZBft`LFz4tttcXHyaJ^(Q7TQXNgAuh z&Sd^h=5yn!sZ6Es_Ir7F`FI!+;b77Jby$A+Y_;|-N;X|r9~&L7RL-85yu4?V4X$Xl zHt)~f{q_5k=gG2XmP)4U8qyL)w|Z*oj%9hf`h1W&JA1RSu_C3ghJP$#Nt8ul-``O{!~ow{-R_qhM5?kRp(M_tNQJ$=@27^z z0T%QW1EQ$k3s?@~$XMlDb2SK*6$mL)P3HiTI5Q+?KoVzm;dl;Wdiv6XhaasWWp=qH zH~^Jqy-*n%2Sb|DNX=U;}ys~OMNDc#uE+}YXP-+%VM2*+{G&OSv^Xc(QY z(WSIbNNL;SB#jOao~x?1;9pxtoSuHPtg);ps;1U8ovzb%r~T;R15K4iqpM~AB4RKY z+}sR>njqF{q997Ls3=OKu6K-%VRQ*8Eo)SPxVZQV2mpUGMgT-a#1gSA0nzg(6N8t|mGuYG W57M+fLU$kl0000Ih+L^k;M!Q+=3v?Sf3I<5h%!B;_2(k zewmv`oR4+V549SgkiVykV@SoELMU`3hR<$xJw3dRy?YCggqH(1m-wlqYvD={z}V&Q1m%=jb~ PXf%VTtDnm{r-UW|V}nHS diff --git a/mods/scorm_packages/scorm-1.2/import.php b/mods/scorm_packages/scorm-1.2/import.php deleted file mode 100644 index f07666a46..000000000 --- a/mods/scorm_packages/scorm-1.2/import.php +++ /dev/null @@ -1,489 +0,0 @@ -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 .= '
  • ' . $orgs[$i] . '
  • '; - } - $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/mods/scorm_packages/scorm-1.2/java/ATutorApiAdapterApplet.jar b/mods/scorm_packages/scorm-1.2/java/ATutorApiAdapterApplet.jar deleted file mode 100644 index 0821db893674b7af2278a819251c32ff6e900100..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3574 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 \ No newline at end of file diff --git a/mods/scorm_packages/scorm-1.2/lib.inc.php b/mods/scorm_packages/scorm-1.2/lib.inc.php deleted file mode 100644 index c22ab7bac..000000000 --- a/mods/scorm_packages/scorm-1.2/lib.inc.php +++ /dev/null @@ -1,253 +0,0 @@ -getOrgs ($id); - $rv = Array(); - while ($row = mysql_fetch_assoc($result)) { - array_push ($rv, - '' . ' - ' - - ); - } - return $rv; - } - - function getLearnerItemLinks ($id) { - $result = $this->getOrgs ($id); - $rv = Array(); - while ($row = mysql_fetch_assoc($result)) { - array_push ($rv, '' - . '' - - . ' ' - - ); - } - return $rv; - } - - function getCMILinks ($id) { - $result = $this->getOrgs ($id); - $rv = Array(); - while ($row = mysql_fetch_assoc($result)) { - array_push ($rv, - '' - ); - } - return $rv; - } - - function getSettingsLinks ($id) { - $result = $this->getOrgs ($id); - $rv = Array(); - while ($row = mysql_fetch_assoc($result)) { - array_push ($rv, - '' - ); - } - return $rv; - } - - function getDeleteFormItems ($id, $i) { - $result = $this->getOrgs ($id); - $rv = Array(); - while ($row = mysql_fetch_assoc($result)) { - array_push ($rv, '' - . '' - . '' - - ); - $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/mods/scorm_packages/scorm-1.2/read.php b/mods/scorm_packages/scorm-1.2/read.php deleted file mode 100644 index 97ed220eb..000000000 --- a/mods/scorm_packages/scorm-1.2/read.php +++ /dev/null @@ -1,106 +0,0 @@ - - diff --git a/mods/scorm_packages/scorm-1.2/settings.php b/mods/scorm_packages/scorm-1.2/settings.php deleted file mode 100644 index c32a9ab72..000000000 --- a/mods/scorm_packages/scorm-1.2/settings.php +++ /dev/null @@ -1,121 +0,0 @@ -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['mods/scorm_packages/scorm-1.2/settings.php']['children'] = array(); - $_pages['mods/scorm_packages/scorm-1.2/settings.php']['title'] - = $row['title']; - $cr = $row['credit']; - $lm = $row['lesson_mode']; -} - - -require(AT_INCLUDE_PATH.'header.inc.php'); - -?> -
    -
    - -

    -

    -
    - -

    - -

    -

    -
    - -

    - -
    - -
    - -
    -
    - - - - - diff --git a/mods/scorm_packages/scorm-1.2/view.inc.php b/mods/scorm_packages/scorm-1.2/view.inc.php deleted file mode 100644 index 5be9f49e3..000000000 --- a/mods/scorm_packages/scorm-1.2/view.inc.php +++ /dev/null @@ -1,399 +0,0 @@ -'; -} - -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) - . '' . $ist[$i]
-					. '' - . '' - . $org[$i]['title'] . '' - ); - } else { - array_push ($tree, - implode ($fil) - . '' - . '' - . $org[$i]['title'] . '' - ); - } - } else { - array_push ($tree, - implode ($fil) - . '' . $org[$i]['title'] . '' - ); - } - - $llvl = $lvl; - } - - require(AT_INCLUDE_PATH.'header.inc.php'); - -?> - -
    - - - -' . "\n"; - } -?>" - echo ($prefs['show_rte_communication'] == 1?'true':'false'); - -
    - - - -' . "\n"; - for ($i=$c-1; $i>=0; $i--) { - $p .= $tree[$i] . '
    ' . "\n"; - } - $p .= '' . "\n"; - echo utf8_decode($p); -?> - - diff --git a/mods/scorm_packages/scorm-1.2/view.php b/mods/scorm_packages/scorm-1.2/view.php deleted file mode 100644 index fd9bbd3ce..000000000 --- a/mods/scorm_packages/scorm-1.2/view.php +++ /dev/null @@ -1,426 +0,0 @@ -'; -} - -define('AT_INCLUDE_PATH', '../../../include/'); -require(AT_INCLUDE_PATH.'vitals.inc.php'); -authenticate(AT_PRIV_PACKAGES); -$me = 'mods/scorm_packages/scorm-1.2/view.php'; -$im = 'mods/scorm_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']; - -// check if the org_id belongs to current course - $sql = "SELECT course_id FROM ".TABLE_PREFIX."packages WHERE package_id = '".$pkg."'"; - $result = mysql_query($sql, $db); - $row = mysql_fetch_assoc($result); - if ($row["course_id"] <> $_SESSION['course_id']) - { - $msg->addError('ACCESS_DENIED'); - - $_pages['mods/scorm_packages/scorm-1.2/view.php']['title_var'] = 'scorm_packages'; - require (AT_INCLUDE_PATH.'header.inc.php'); - $msg->printAll(); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; - } - - $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) - . '' . $ist[$i]
-					. '' - . '' - . $org[$i]['title'] . '' - ); - } else { - array_push ($tree, - implode ($fil) - . '' - . '' - . $org[$i]['title'] . '' - ); - } - } else { - array_push ($tree, - implode ($fil) - . '' . $org[$i]['title'] . '' - ); - } - - $llvl = $lvl; - } - - require(AT_INCLUDE_PATH.'header.inc.php'); - -?> - -
    - - - -' . "\n"; - } -?> - -
    - - - -' . "\n"; - for ($i=$c-1; $i>=0; $i--) { - $p .= $tree[$i] . '
    ' . "\n"; - } - $p .= '' . "\n"; - echo utf8_decode($p); -?> - - \ No newline at end of file diff --git a/mods/scorm_packages/scorm-1.2/write.php b/mods/scorm_packages/scorm-1.2/write.php deleted file mode 100644 index d025b7e56..000000000 --- a/mods/scorm_packages/scorm-1.2/write.php +++ /dev/null @@ -1,59 +0,0 @@ - - diff --git a/mods/scorm_packages/settings.php b/mods/scorm_packages/settings.php deleted file mode 100644 index 5d943c6e3..000000000 --- a/mods/scorm_packages/settings.php +++ /dev/null @@ -1,65 +0,0 @@ -'; -$p .= '

      '; -$num = 0; -while ($row = mysql_fetch_assoc($result)) { - foreach ($plug[$row['ptype']]->getSettingsLinks($row['package_id']) as $l) { - $p .= '
    1. ' . $l . '
    2. '; - $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 .= '
    '; -$p .= '

    '; -$p .= ''; - -require(AT_INCLUDE_PATH.'header.inc.php'); -echo $p; -require (AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/social/README b/mods/social/README deleted file mode 100644 index bf0bebc86..000000000 --- a/mods/social/README +++ /dev/null @@ -1,97 +0,0 @@ -MODULE DETAILS: ---------------- -Description: -Putting ATutor into the age of social networking. Allow users to share profiles -and activities, link OpenSocial gadgets and applications into their social -learning environment, and network with others locally, on other ATutor -installations, or on other social networks. - -Version: -0.9 Beta - -License: -GPL/ATutor - -State: -In development. -This version is primarily available for experimentation and feedback, -leading up to a release of a stable version about June 09. Users are encouraged -to make feature suggestions, report bugs, and get involved in developing the -ATutor social network. Discussions can the started in the ATutor community -forums http://www.atutor.ca/forum/16/1.html - -Notes: -Also note that ATutor Social runs with or without the OpenSocial Shindig -server. You may point to your own Shindig server if you have one (download -from: http://incubator.apache.org/shindig/), or use the ATutor social network -server at http://social.atutor.ca/shindig/php. See the Administrator's -Networking Admin panel to setup a link to a Shindig server, and link to other -netowrks and applications, or do not use Shindig to create a self-contained -social network using only your local ATutor installation. - - -INSTALLATION ------------- -1. Login as ATutor admin, install this module. - -2. Setup Shindig if you want to have your own local social container, for a -HOWTO on installing Shindig, please visit the following site: -http://www.chabotc.com/guides/shindig_install/ - -A note on shindig installation, you will need to have the following PHP Extension enabled: -- curl -- openssl - -If you don't want to setup your own Shindig, then you can use ATutor's Shindig server: http://social.atutor.ca/shindig/php -Log in as ATutor admin, click on Networking tab, and type http://social.atutor.ca/shindig/php into the URL text input field. - -3. Done, now you can enjoy e-learning with social networking in your ATutor :) - - -GADGETS: ------------------ -One of the greatest features of Opensocial, gadgets are applications that sits on your social networking page. -Similar to the gadgets on your iGoogle account. - -ATutor social networking module allows users to install any Opensocial gadgets. Such gadgets can be found in: -http://www.google.com/ig/directory?synd=open or http://www.labpixies.com/ - -In order to install a gadget, click on the "Gadgets" link in the side menu, and copy and paste the URL of the gadgets' XML file. -ie. http://www.labpixies.com/campaigns/todo/todo.xml, http://www.labpixies.com/campaigns/horoscope/horoscope.xml -Then click "Add gadget". - - -FEATURES: ------------------- -All Users - - * Search Network: Search for people on a network to display basic information about them. Login to add people as contacts. - -Registered Users - - * My Contacts: Search the network for people you know and add them to your contact list. - * People you Might Know: To help build networks, contacts of your contacts (i.e. friends of friends) are displayed making it easy to add common contacts to your own. Random selections of a few other's contact display each time a page loads. - * Network Activity: Keep track of what other people in your network are doing by following their activities. - * Network Groups: Create interest groups, or join an existing ones. Invite people to join groups you belong to. - * Gadgets: Select from thousands of OpenSocial gadgets available around the internet to customize your social network to your specification. Once a gadget has been used on a system, it becomes available to others on your network to add to their social networking tools. - * Privacy: Select from a range of privacy settings to control who sees what parts of your profile, and control which parts of your profile are searchable by others. - -Instructors - - * Turn off ATutor Social: ATutor Social runs both inside or outside of courses. Instructors may choose to disable social networking in their courses. - -Administrators - - * ShinDig Location: The ShinDig server acts as a hub for a social network. By default social.atutor.ca acts as the central hub for the ATutor social network. Administrators may choose to point to a different ShinDig server to create a private network. - -Developers - - * OpenSocial Standard: Develop your own OpenSocial Gadgets that will plugin to ATutor, or into other OpenSocial container applications. - * Public Source Code: All ATutor Social source code is available for public checkout from the Subversion version control repository. - - -TODO: -------------------- -- OAuth implementation -- Improve UI. -- Allows multiple ATutors to connect to each other, further expand the Social Network. \ No newline at end of file diff --git a/mods/social/activities.php b/mods/social/activities.php deleted file mode 100644 index 411bf628f..000000000 --- a/mods/social/activities.php +++ /dev/null @@ -1,31 +0,0 @@ -display('pubmenu.tmpl.php'); -$savant->assign('activities', $actvity_obj->getFriendsActivities($_SESSION['member_id'], true)); -$savant->display('activities.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/social/admin/delete_applications.php b/mods/social/admin/delete_applications.php deleted file mode 100644 index aaa9637b5..000000000 --- a/mods/social/admin/delete_applications.php +++ /dev/null @@ -1,45 +0,0 @@ -deleteApplications($_POST['apps']); - $msg->addFeedback('GADGET_REMOVED_SUCCESSFULLY'); - } else { - //cannot be empty - $msg->addError('GADGET_DELETED_CANNOT_BE_EMPTY'); - } -} - -//data -$all_apps = $apps->listApplications(); - -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->assign('all_apps', $all_apps); -$savant->display('admin/delete_applications.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/social/applications.php b/mods/social/applications.php deleted file mode 100644 index 53eb8c7ed..000000000 --- a/mods/social/applications.php +++ /dev/null @@ -1,131 +0,0 @@ -printInfos($info); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -//initialization -$app = new Application(); - -// Install gadgets -if (isset($_POST['add_application']) && isset($_POST['app_url'])){ - //check if curl is installed - if (!extension_loaded('curl')){ - $msg->addError('CURL_NOT_INSTALLED'); - header('Location: '. url_rewrite(AT_SOCIAL_BASENAME.'applications.php', AT_PRETTY_URL_IS_HEADER)); - exit; - } - $app_url = $addslashes(trim($_POST['app_url'])); - $gadget = $app->parseModulePrefs($app_url); - $gadget = $gadget[0]; - - if (empty($gadget->errors)){ - //add applicatoin to database - $app->addApplication($gadget); - $msg->addFeedback('GADGET_ADDED_SUCCESSFULLY'); - header('Location: '. url_rewrite(AT_SOCIAL_BASENAME.'applications.php', AT_PRETTY_URL_IS_HEADER)); - exit; - } else { - $msg->addError(array('GADGET_ADDED_FAILURE', implode(', ', $gadget->errors))); - header('Location: '. url_rewrite(AT_SOCIAL_BASENAME.'applications.php', AT_PRETTY_URL_IS_HEADER)); - exit; - } -} - -// Show all gadgets -if (isset($_POST['show_applications'])){ - $list_of_all_apps = $app->listApplications(); -} - -//Display individual application -if (isset($_REQUEST['app_id'])){ - $_REQUEST['app_id'] = intval($_REQUEST['app_id']); - $app = new Application($_REQUEST['app_id']); //testing application 1, 2 - - //Add application - if (isset($_GET['add']) && intval($_GET['add'])==1){ - $app->addMemberApplication($_SESSION['member_id'], $_GET['app_id']); - $msg->addFeedback('GADGET_ADDED_SUCCESSFULLY'); - header('Location: '. url_rewrite(AT_SOCIAL_BASENAME.'applications.php', AT_PRETTY_URL_IS_HEADER)); - exit; - } - - //Delete application - if (isset($_GET['delete']) && intval($_GET['delete']) > 0) { - $app->deleteApplication(); - $msg->addFeedback('GADGET_REMOVED_SUCCESSFULLY'); - header('Location: '. url_rewrite(AT_SOCIAL_BASENAME.'applications.php', AT_PRETTY_URL_IS_HEADER)); - exit; - } - - //Display application settings - if (isset($_GET['settings'])){ - include(AT_INCLUDE_PATH.'header.inc.php'); - $savant->assign('settings', $app->getSettings()); //userPrefs - $savant->assign('user_settings', $app->getApplicationSettings($_SESSION['member_id'])); - $savant->assign('app_id', $app->getId()); //id - $savant->display('application_settings.tmpl.php'); - include(AT_INCLUDE_PATH.'footer.inc.php'); - exit; - } - - //Save settings - if (isset($_POST['app_settings'])){ - foreach ($app->getSettings() as $key=>$value){ - if(isset($_POST[$key])){ - //save values iff it is in the userPrefs serialized string. - //don't save values blindly from the $_POST. - $value = $addslashes($_POST[$key]); - $app->setApplicationSettings($_SESSION['member_id'], $key, $value); - } - } - $msg->addFeedback('GADGET_SETTINGS_SAVED'); - header('Location: '. url_rewrite(AT_SOCIAL_BASENAME.'applications.php', AT_PRETTY_URL_IS_HEADER)); - exit; - } - - //loop through all app and print out the thumbnail - $iframe_url = $app->getIframeUrl($_REQUEST['id'], 'canvas', $_GET['appParams']); - - //display - include(AT_INCLUDE_PATH.'header.inc.php'); - $savant->assign('iframe_url', $iframe_url); - $savant->assign('app', $app); - $savant->display('individual_application.tmpl.php'); - include(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -//list all my applications -$list_of_my_apps = $app->listMyApplications(); - -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('pubmenu.tmpl.php'); -$savant->assign('list_of_my_apps', $list_of_my_apps); -$savant->assign('list_of_all_apps', $list_of_all_apps); -$savant->display('applications.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/social/basic_profile.php b/mods/social/basic_profile.php deleted file mode 100644 index b87589727..000000000 --- a/mods/social/basic_profile.php +++ /dev/null @@ -1,149 +0,0 @@ -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: basic_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 */ -require(AT_INCLUDE_PATH.'header.inc.php'); -include('lib/profile_menu.inc.php'); -$savant->assign('row', $row); -$onload = 'document.form.first_name.focus();'; - -//$savant->display('registration.tmpl.php'); -$savant->display('html/basic_profile.tmpl.php'); -require(AT_INCLUDE_PATH.'footer.inc.php');?> \ No newline at end of file diff --git a/mods/social/connections.php b/mods/social/connections.php deleted file mode 100644 index ea088bd40..000000000 --- a/mods/social/connections.php +++ /dev/null @@ -1,143 +0,0 @@ -printInfos($info); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -// default display my friends -$friends = getFriends($_SESSION['member_id']); -$rand_key = $addslashes($_POST['rand_key']); //should we excape? - -//paginator settings -$page = intval($_GET['p']); -if (!$page) { - $page = 1; -} -$count = (($page-1) * SOCIAL_FRIEND_SEARCH_MAX) + 1; -$offset = ($page-1) * SOCIAL_FRIEND_SEARCH_MAX; - - -//if $_GET['q'] is set, handle Ajax. -if (isset($_GET['q'])){ - $query = $_GET['q']; //don't need to addslashes here cause searchFriends will do it. - - if (isset($_POST['myFriendsOnly'])){ - //retrieve a list of my friends - $search_result = searchFriends($query, true); - } else { - //retrieve a list of friends by the search - $search_result = searchFriends($query); - } - - if (!empty($search_result)){ - echo '
    '._AT('suggestions').':
    '; - $counter = 0; - foreach($search_result as $member_id=>$member_array){ - //display 10 suggestions - if ($counter > 10){ - break; - } - - echo ''.printSocialName($member_id, false).'
    '; - $counter++; - } - echo '
    '; - } - exit; -} - -//safe guard -if (isset($_GET['id'])){ - $id = intval($_GET['id']); - if($id > 0){ - addFriendRequest($id); - $msg->addFeedback('REQUEST_FRIEND_ADDED'); - $sql_notify = "SELECT first_name, last_name, email FROM ".TABLE_PREFIX."members WHERE member_id=$id"; - $result_notify = mysql_query($sql_notify, $db); - $row_notify = mysql_fetch_assoc($result_notify); - - if ($row_notify['email'] != '') { - require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php'); - $body = _AT('notification_new_contact', get_display_name($_SESSION['member_id']), $_base_href.AT_SOCIAL_BASENAME.'index_mystart.php'); - $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('contact_request'); - $mail->Body = $body; - - if(!$mail->Send()) { - $msg->addError('SENDING_ERROR'); - } - unset($mail); - } - - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'connections.php', AT_PRETTY_URL_IS_HEADER)); - exit; - } -} - -//handle search friends request -if(($rand_key!='' && isset($_POST['search_friends_'.$rand_key])) || isset($_GET['search_friends'])){ - if (empty($_POST['search_friends_'.$rand_key]) && !isset($_GET['search_friends'])){ - $msg->addError('CANNOT_BE_EMPTY'); - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'connections.php', AT_PRETTY_URL_IS_HEADER)); - exit; - } - //to adapt paginator GET queries - //don't need to apply addslashes here cause searchFriends will do it. - if($_GET['search_friends']){ - $search_field = $_GET['search_friends']; - } else { - $search_field = $_POST['search_friends_'.$rand_key]; - } - if (isset($_POST['myFriendsOnly'])){ - //retrieve a list of my friends - $friends = searchFriends($search_field, true); - } else { - //retrieve a list of friends by the search - $friends = searchFriends($search_field); //to calculate the total number. TODO: need a better way, wasting runtime. - $num_pages = max(ceil(sizeof($friends) / SOCIAL_FRIEND_SEARCH_MAX), 1); - $friends = searchFriends($search_field, false, $offset); - } -} - -//mark those that are already added -$friends = markFriends($_SESSION['member_id'], $friends); -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('pubmenu.tmpl.php'); -$savant->assign('page', $page); -$savant->assign('num_pages', $num_pages); -$savant->assign('search_field', $search_field); -$savant->assign('friends', $friends); -$savant->assign('rand_key', $rand_key); -$savant->display('connections.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/social/edit_profile.php b/mods/social/edit_profile.php deleted file mode 100644 index 95ba90f48..000000000 --- a/mods/social/edit_profile.php +++ /dev/null @@ -1,236 +0,0 @@ -printInfos($info); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -// Initiates member -$member = new Member($_SESSION['member_id']); - -// Handles social profile -if ($_POST['social_profile']){ - //update database from here - header('Location: sprofile.php'); -} - - -// Handles Saving -if (isset($_POST['submit'])){ - //where was this request sent from - if (isset($_POST['edit'])){ - $id = intval($_POST['id']); - if ($_POST['edit']=='position'){ - $company = $_POST['company']; - $title = $_POST['title']; - $from = $_POST['from']; - $to = $_POST['to']; - $description = $_POST['description']; - $member->updatePosition($id, $company, $title, $from, $to, $description); - } elseif ($_POST['edit']=='education'){ - $university = $_POST['university']; - $country = $_POST['country']; - $province = $_POST['province']; - $degree = $_POST['degree']; - $field = $_POST['field']; - $from = $_POST['from']; - $to = $_POST['to']; - $description = $_POST['description']; - $member->updateEducation($id, $university, $from, $to, $country, $province, $degree, $field, $description); - } elseif ($_POST['edit']=='websites'){ - $url = $_POST['url']; - $site_name = $_POST['site_name']; - $member->updateWebsite($id, $url, $site_name); - } elseif ($_POST['edit']=='interests' || $_POST['edit']=='associations' || $_POST['edit']=='awards' || $_POST['edit']=='expertise' - || $_POST['edit']=='others'){ - $interests = isset($_POST['interests'])&&$_POST['interests']==''? _AT('na'): $_POST['interests']; - $associations = isset($_POST['associations'])&&$_POST['associations']==''? _AT('na'): $_POST['associations']; - $awards = isset($_POST['awards'])&&$_POST['awards']==''? _AT('na'): $addslashes($_POST['awards']); - $expertise = isset($_POST['expertise'])&&$_POST['expertise']==''? _AT('na'): $_POST['expertise']; - $others = isset($_POST['others'])&&$_POST['others']==''? _AT('na'): $_POST['others']; - $member->updateAdditionalInformation($interests, $associations, $awards, $expertise, $others); - } - } - elseif (isset($_POST['add'])) { - if ($_POST['add']=='position'){ - $company = $_POST['company']; - $title = $_POST['title']; - $from = $_POST['from']; - $to = $_POST['to']; - $description = $_POST['description']; - $member->addPosition($company, $title, $from, $to, $description); - } elseif ($_POST['add']=='education'){ - $university = $_POST['university']; - $country = $_POST['country']; - $province = $_POST['province']; - $degree = $_POST['degree']; - $field = $_POST['field']; - $from = $_POST['from']; - $to = $_POST['to']; - $description = $_POST['description']; - $member->addEducation($university, $from, $to, $country, $province, $degree, $field, $description); - } elseif ($_POST['add']=='websites'){ - $url = $_POST['url']; - $site_name = $_POST['site_name']; - $member->addWebsite($url, $site_name); - } elseif ($_POST['add']=='interests'){ - $interests = $_POST['interests']; - $member->addInterests($interests); - } elseif ($_POST['add']=='associations'){ - $associations = $_POST['associations']; - $member->addAssociations($associations); - } elseif ($_POST['add']=='awards'){ - $awards = $_POST['awards']; - $member->addAwards($awards); - } - } -} - - -// Handles Adding -if (isset($_GET['add'])){ - //header starts here. - include(AT_INCLUDE_PATH.'header.inc.php'); - if ($_GET['add']=='position'){ - $savant->display('edit_profile/edit_position.tmpl.php'); - } elseif ($_GET['add']=='education'){ - $savant->display('edit_profile/edit_education.tmpl.php'); - } elseif ($_GET['add']=='websites'){ - $savant->display('edit_profile/edit_websites.tmpl.php'); - } elseif ($_GET['add']=='interests' || $_GET['add']=='associations' || $_GET['add']=='awards'){ - $savant->assign('title', $_GET['add']); - $savant->display('edit_profile/edit_additional.tmpl.php'); - } - //footer - include(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -// Handles Editing -if (isset($_GET['edit']) && isset($_GET['id']) && (intval($_GET['id']) > 0)){ - $id = intval($_GET['id']); - - //header starts here. - include(AT_INCLUDE_PATH.'header.inc.php'); - $savant->assign('id', $id); - if ($_GET['edit']=='position'){ - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_member_position WHERE id='.$id; - $rs = mysql_query($sql, $db); - $row = mysql_fetch_assoc($rs); - - //Template - $savant->assign('company', $row['company']); - $savant->assign('profile_title', $row['title']); - $savant->assign('from', $row['from']); - $savant->assign('to', $row['to']); - $savant->assign('description', $row['description']); - $savant->display('edit_profile/edit_position.tmpl.php'); - } elseif ($_GET['edit']=='education'){ - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_member_education WHERE id='.$id; - $rs = mysql_query($sql, $db); - $row = mysql_fetch_assoc($rs); - - //Template - $savant->assign('university', $row['university']); - $savant->assign('country', $row['country']); - $savant->assign('province', $row['province']); - $savant->assign('degree', $row['degree']); - $savant->assign('field', $row['field']); - $savant->assign('from', $row['from']); - $savant->assign('to', $row['to']); - $savant->assign('description', $row['description']); - $savant->display('edit_profile/edit_education.tmpl.php'); - } elseif ($_GET['edit']=='websites'){ - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_member_websites WHERE id='.$id; - $rs = mysql_query($sql, $db); - $row = mysql_fetch_assoc($rs); - - //Template - $savant->assign('url', $row['url']); - $savant->assign('site_name', $row['site_name']); - $savant->display('edit_profile/edit_websites.tmpl.php'); - - } elseif ($_GET['edit']=='interests'){ - $sql = 'SELECT interests FROM '.TABLE_PREFIX.'social_member_additional_information WHERE member_id='.$_SESSION['member_id']; - $rs = mysql_query($sql, $db); - $row = mysql_fetch_assoc($rs); - - //Template - $savant->assign('interests', $row['interests']); - $savant->assign('title', 'interests'); - $savant->display('edit_profile/edit_additional.tmpl.php'); - } elseif ($_GET['edit']=='associations'){ - $sql = 'SELECT associations FROM '.TABLE_PREFIX.'social_member_additional_information WHERE member_id='.$_SESSION['member_id']; - $rs = mysql_query($sql, $db); - $row = mysql_fetch_assoc($rs); - - //Template - $savant->assign('associations', $row['associations']); - $savant->assign('title', 'associations'); - $savant->display('edit_profile/edit_additional.tmpl.php'); - } elseif ($_GET['edit']=='awards'){ - $sql = 'SELECT awards FROM '.TABLE_PREFIX.'social_member_additional_information WHERE member_id='.$_SESSION['member_id']; - $rs = mysql_query($sql, $db); - $row = mysql_fetch_assoc($rs); - - //Template - $savant->assign('awards', $row['awards']); - $savant->assign('title', 'awards'); - $savant->display('edit_profile/edit_additional.tmpl.php'); - } - //footer - include(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - - -// Handles Deleting -if (isset($_GET['delete'])){ - $id = intval($_GET['id']); - if ($_GET['delete']=='position'){ - $member->deletePosition($id); - } elseif ($_GET['delete']=='education'){ - $member->deleteEducation($id); - } elseif ($_GET['delete']=='websites'){ - $member->deleteWebsite($id); - } elseif ($_GET['delete']=='interests'){ - $member->deleteInterests($id); - } elseif ($_GET['delete']=='associations'){ - $member->deleteAssociations($id); - } elseif ($_GET['delete']=='awards'){ - $member->deleteAwards($id); - } -} - - -// Member object -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('pubmenu.tmpl.php'); -$savant->assign('profile', $member->getDetails()); -$savant->assign('position', $member->getPosition()); -$savant->assign('education', $member->getEducation()); -$savant->assign('websites', $member->getWebsites()); -$savant->display('edit_profile.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/social/groups/create.php b/mods/social/groups/create.php deleted file mode 100644 index c9c7d153a..000000000 --- a/mods/social/groups/create.php +++ /dev/null @@ -1,177 +0,0 @@ -printInfos('FEATURE_NOT_AVAILABLE'); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; - } - - // check if this is a supported file type - $filename = $stripslashes($_FILES['logo']['name']); - $path_parts = pathinfo($filename); - $extension = strtolower($path_parts['extension']); - $image_attributes = getimagesize($_FILES['logo']['tmp_name']); - - if ($extension == 'jpeg') { - $extension = 'jpg'; - } - - if (!in_array($extension, $supported_images)) { - $msg->addError(array('FILE_ILLEGAL', $extension)); - header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id); - exit; - } else if ($image_attributes[2] > IMAGETYPE_PNG) { - $msg->addError(array('FILE_ILLEGAL', $extension)); - header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id); - exit; - } - - // make sure under max file size - if ($_FILES['logo']['size'] > $_config['prof_pic_max_file_size']) { - $msg->addError('FILE_MAX_SIZE'); - header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id); - exit; - } - - // delete the old images (if any) - foreach ($supported_images as $ext) { - if (file_exists(AT_CONTENT_DIR.'social/'. $id.'.'.$ext)) { - unlink(AT_CONTENT_DIR.'social/'. $id.'.'.$ext); - } - } - - $new_filename = 'no_id'. '.' . $extension; - $original_img = AT_CONTENT_DIR.'social/temp_'. $new_filename; - $thumbnail_img= AT_CONTENT_DIR.'social/'. $new_filename; - - // only want the resized logo. (for now) - if (!move_uploaded_file($_FILES['logo']['tmp_name'], $original_img)) { - $msg->addError('CANNOT_OVERWRITE_FILE'); - header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id); - exit; - } - - // resize the original and save it at $thumbnail_file - $width = $image_attributes[0]; - $height = $image_attributes[1]; - - if ($width > $height && $width>100) { - $thumbnail_height = intval(100 * $height / $width); - $thumbnail_width = 100; - - resize_image($original_img, $thumbnail_img, $height, $width, $thumbnail_height, $thumbnail_width, $extension); - } else if ($width <= $height && $height > 100) { - $thumbnail_height= 100; - $thumbnail_width = intval(100 * $width / $height); - resize_image($original_img, $thumbnail_img, $height, $width, $thumbnail_height, $thumbnail_width, $extension); - } else { - // no resizing, just copy the image. - // it's too small to resize. - copy($original_img, $thumbnail_img); - } - // clean the original - unlink($original_img); - } - - //check if fields are empty - if ($_POST['group_name']==''){ - $missing_fields[] = _AT('group_name'); - } elseif (intval($_POST['group_type'])<=0){ - $missing_fields[] = _('group_type'); - } - if ($missing_fields) { - $missing_fields = implode(', ', $missing_fields); - $msg->addError(array('EMPTY_FIELDS', $missing_fields)); - } else { - $group_id = $social_groups->addGroup($_POST['group_type'], $_POST['group_name'], $_POST['description'], $_POST['group_privacy']); - if($group_id){ - //Add the logo in now that we have the group id. And rename the old one. - if ($thumbnail_img!=''){ - $new_group = new SocialGroup($group_id); - $new_group->updateGroupLogo($group_id . '.' . $extension); - $new_location = AT_CONTENT_DIR.'social/'. $group_id . '.' . $extension; - copy($thumbnail_img, $new_location); - unlink($thumbnail_img); - } - $msg->addFeedback('GROUP_CREATED'); - header('Location: index.php'); - exit; - } else { - //Something went bad in the backend, contact admin? - $msg->addError('GROUP_CREATION_FAILED'); - } - } -} - -//Display -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('pubmenu.tmpl.php'); -$savant->assign('group_types', $social_groups->getAllGroupType()); -$savant->display('sgroup_edit.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/social/groups/delete.php b/mods/social/groups/delete.php deleted file mode 100644 index df4509803..000000000 --- a/mods/social/groups/delete.php +++ /dev/null @@ -1,53 +0,0 @@ -getUser() != $_SESSION['member_id']){ - $msg->addError('CANT_DELETE_GROUP'); - header('Location: index.php'); - exit; -} - -//delete group -$msg->addFeedback('GROUP_DELETED'); -$sgs->removeGroup($id); -header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'groups/index.php', AT_PRETTY_URL_HEADER)); -exit; - -//Display -/* -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->assign('group_obj', $group); -$savant->assign('group_types', $social_groups->getAllGroupType()); -$savant->display('sgroup_edit.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -*/ -?> \ No newline at end of file diff --git a/mods/social/groups/delete_message.php b/mods/social/groups/delete_message.php deleted file mode 100644 index 4341bd4c5..000000000 --- a/mods/social/groups/delete_message.php +++ /dev/null @@ -1,56 +0,0 @@ - 0 && $mid > 0){ - $group = new SocialGroup($gid); - if ($_POST['submit_yes']){ - $result = $group->removeMessage($mid, $_SESSION['member_id']); - if($result){ - $msg->addFeedback('MESSAGE_DELETE_SUCCESSFULLY'); - } else { - $msg->addError('CANT_DELETE_MESSAGE'); - } - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'groups/view.php?id='.$gid, AT_PRETTY_URL_HEADER)); - exit; - } elseif ($_POST['submit_no']){ - $msg->addFeedback('CANCELLED'); - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'groups/view.php?id='.$gid, AT_PRETTY_URL_HEADER)); - exit; - } - $hidden_vars['gid'] = $gid; - $hidden_vars['delete'] = $mid; - $message = $group->getMessage($mid, $_SESSION['member_id']); - if ($message==false){ - $msg->addError('INVALID'); //users tries to delete message that aren't theirs. - } else { - $msg->addConfirm(array('DELETE', $group->getMessage($mid, $_SESSION['member_id'])), $hidden_vars); - } -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$msg->printConfirm(); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/social/groups/edit.php b/mods/social/groups/edit.php deleted file mode 100644 index f96891a3a..000000000 --- a/mods/social/groups/edit.php +++ /dev/null @@ -1,197 +0,0 @@ -getUser() != $_SESSION['member_id']){ - $msg->addError('CANT_EDIT_GROUP'); - header('Location: index.php'); - exit; -} - -//TODO -//validate the group_admin is indeed a group member - -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); - } - - imagecopyresampled($thumbnail_img, $source, 0, 0, 0, 0, $dest_w, $dest_h, $src_w, $src_h); - - if ($type == 'gif') { - imagegif($thumbnail_img, $dest); - } else if ($type == 'jpg') { - imagejpeg($thumbnail_img, $dest, 75); - } else { - imagepng($thumbnail_img, $dest, 7); - } -} - -// check if GD is installed -if (!extension_loaded('gd')) { - require(AT_INCLUDE_PATH.'header.inc.php'); - $msg->printInfos('FEATURE_NOT_AVAILABLE'); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - - -// Update group -if (isset($_POST['save'])){ - //handles group logo - if ($_FILES['logo']['name']!=''){ - $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'; - } - - if (!$supported_images) { - require(AT_INCLUDE_PATH.'header.inc.php'); - $msg->printInfos('FEATURE_NOT_AVAILABLE'); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; - } - - // check if this is a supported file type - $filename = $stripslashes($_FILES['logo']['name']); - $path_parts = pathinfo($filename); - $extension = strtolower($path_parts['extension']); - $image_attributes = getimagesize($_FILES['logo']['tmp_name']); - - if ($extension == 'jpeg') { - $extension = 'jpg'; - } - - if (!in_array($extension, $supported_images)) { - $msg->addError(array('FILE_ILLEGAL', $extension)); - header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id); - exit; - } else if ($image_attributes[2] > IMAGETYPE_PNG) { - $msg->addError(array('FILE_ILLEGAL', $extension)); - header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id); - exit; - } - - // make sure under max file size - if ($_FILES['logo']['size'] > $_config['prof_pic_max_file_size']) { - $msg->addError('FILE_MAX_SIZE'); - header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id); - exit; - } - - // delete the old images (if any) - foreach ($supported_images as $ext) { - if (file_exists(AT_CONTENT_DIR.'social/'. $id.'.'.$ext)) { - unlink(AT_CONTENT_DIR.'social/'. $id.'.'.$ext); - } - } - - $new_filename = $id . '.' . $extension; - $original_img = AT_CONTENT_DIR.'social/temp_'. $new_filename; - $thumbnail_img= AT_CONTENT_DIR.'social/'. $new_filename; - - // only want the resized logo. (for now) - if (!move_uploaded_file($_FILES['logo']['tmp_name'], $original_img)) { - $msg->addError('CANNOT_OVERWRITE_FILE'); - header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id); - exit; - } - - // resize the original and save it at $thumbnail_file - $width = $image_attributes[0]; - $height = $image_attributes[1]; - - if ($width > $height && $width>100) { - $thumbnail_height = intval(100 * $height / $width); - $thumbnail_width = 100; - - resize_image($original_img, $thumbnail_img, $height, $width, $thumbnail_height, $thumbnail_width, $extension); - } else if ($width <= $height && $height > 100) { - $thumbnail_height= 100; - $thumbnail_width = intval(100 * $width / $height); - resize_image($original_img, $thumbnail_img, $height, $width, $thumbnail_height, $thumbnail_width, $extension); - } else { - // no resizing, just copy the image. - // it's too small to resize. - copy($original_img, $thumbnail_img); - } - // clean the original - unlink($original_img); - } - - - //check if fields are empty - if ($_POST['group_name']==''){ - $missing_fields[] = _AT('group_name'); - } elseif (intval($_POST['group_type'])<=0){ - $missing_fields[] = _('group_type'); - } - if ($missing_fields) { - $missing_fields = implode(', ', $missing_fields); - $msg->addError(array('EMPTY_FIELDS', $missing_fields)); - } else { - $isSucceded = $social_groups->updateGroup($id, $_POST['group_admin'], $_POST['group_type'], $_POST['group_name'], $_POST['description'], $new_filename, $_POST['group_privacy']); - - if($isSucceded){ - $msg->addFeedback('SOCIAL_GROUP_UPDATED'); - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'groups/index.php', AT_PRETTY_URL_HEADER)); - exit; - } else { - //Something went bad in the backend, contact admin? - $msg->addError('GROUP_EDIT_FAILED'); - } - } -} elseif (isset($_POST['cancel'])){ - $msg->addFeedback('CANCELLED'); - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'groups/index.php', AT_PRETTY_URL_HEADER)); - exit; -} - -//Display -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('pubmenu.tmpl.php'); -$savant->assign('group_obj', $group); -$savant->assign('group_types', $social_groups->getAllGroupType()); -$savant->display('sgroup_edit.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/social/groups/get_sgroup_logo.php b/mods/social/groups/get_sgroup_logo.php deleted file mode 100644 index 0314d1caa..000000000 --- a/mods/social/groups/get_sgroup_logo.php +++ /dev/null @@ -1,70 +0,0 @@ - \ No newline at end of file diff --git a/mods/social/groups/index.php b/mods/social/groups/index.php deleted file mode 100644 index e128c76be..000000000 --- a/mods/social/groups/index.php +++ /dev/null @@ -1,57 +0,0 @@ -printInfos($info); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -//paginator settings -$page = intval($_GET['p']); -if (!$page) { - $page = 1; -} -$count = (($page-1) * SOCIAL_GROUP_MAX) + 1; -$offset = ($page-1) * SOCIAL_GROUP_MAX; - -// Get activities -$act_obj = new Activity(); -$activities = $act_obj->getActivities($id); - -// Get social group class -$social_group = new SocialGroups(); -$my_groups = $social_group->getMemberGroups($_SESSION['member_id']); //to get the size -$num_pages = sizeof($my_groups)/SOCIAL_GROUP_MAX; -$my_groups = $social_group->getMemberGroups($_SESSION['member_id'], $offset); - -//Display -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('pubmenu.tmpl.php'); -print_paginator($page, $num_pages, '', 1); -$savant->assign('my_groups', $my_groups); -$savant->display('sgroups.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/social/groups/invitation_handler.php b/mods/social/groups/invitation_handler.php deleted file mode 100644 index 10acd34fa..000000000 --- a/mods/social/groups/invitation_handler.php +++ /dev/null @@ -1,132 +0,0 @@ - 0){ - //handle invitations - if ($_GET['invitation']=='accept'){ - - $sql = "SELECT sender_id from ".TABLE_PREFIX."social_groups_invitations WHERE member_id = '$_SESSION[member_id]' AND group_id = '$id'"; - - $result_sender = mysql_query($sql, $db); - $sender = mysql_fetch_array($result_sender); - - require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php'); - foreach ($sender as $sid){ - - $sql_notify = "SELECT first_name, last_name, email FROM ".TABLE_PREFIX."members WHERE member_id=$sid"; - $result_notify = mysql_query($sql_notify, $db); - $row_notify = mysql_fetch_assoc($result_notify); - //require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php'); - if ($row_notify['email'] != '') { - //require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php'); - $body = _AT('notification_group_invite_accepted', get_display_name($_SESSION['member_id']),$group_obj->getName() , $_base_href.AT_SOCIAL_BASENAME.'index_mystart.php'); - $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('group_invitation_accepted'); - $mail->Body = $body; - - if(!$mail->Send()) { - $msg->addError('SENDING_ERROR'); - } - unset($mail); - } - } - - acceptGroupInvitation($id); - $status = 1; - } elseif ($_GET['invitation']=='reject'){ - rejectGroupInvitation($id); - $status = 2; - } - - //handle requests (requests to join a group from some member) - if ($sender_id > 0){ - if ($_GET['request']=='accept'){ - - $sql = "SELECT sender_id from ".TABLE_PREFIX."social_groups_requests WHERE member_id = '$_SESSION[member_id]' AND group_id = '$id'"; - - $result_sender = mysql_query($sql, $db); - $sender = mysql_fetch_array($result_sender); - - require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php'); - foreach ($sender as $sid){ - - $sql_notify = "SELECT first_name, last_name, email FROM ".TABLE_PREFIX."members WHERE member_id=$sid"; - $result_notify = mysql_query($sql_notify, $db); - $row_notify = mysql_fetch_assoc($result_notify); - - if ($row_notify['email'] != '') { - $body = _AT('notification_group_request_accepted', $group_obj->getName() , $_base_href.AT_SOCIAL_BASENAME.'index_mystart.php'); - $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('group_request_accepted'); - $mail->Body = $body; - - if(!$mail->Send()) { - $msg->addError('SENDING_ERROR'); - } - unset($mail); - } - } - acceptGroupRequest($id, $sender_id); - $status = 3; - } elseif ($_GET['request']=='reject'){ - rejectGroupRequest($id, $sender_id); - $status = 4; - } - } - } - - switch($status){ - case 1: - $msg->addFeedback('ACCEPT_GROUP_INVITATION'); - break; - case 2: - $msg->addFeedback('REJECT_GROUP_INVITATION'); - break; - case 3: - $msg->addFeedback('ACCEPT_GROUP_REQUEST'); - break; - case 4: - $msg->addFeedback('REJECT_GROUP_REQUEST'); - break; - default: - break; - } - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'groups/view.php?id='.$id, AT_PRETTY_URL_HEADER)); - exit; -} - -header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'groups/index.php', AT_PRETTY_URL_HEADER)); -exit; -?> \ No newline at end of file diff --git a/mods/social/groups/invite.php b/mods/social/groups/invite.php deleted file mode 100644 index 2ff673253..000000000 --- a/mods/social/groups/invite.php +++ /dev/null @@ -1,68 +0,0 @@ -$v){ - $k = intval($k); - if ($gid != ''){ - $sql_notify = "SELECT first_name, last_name, email FROM ".TABLE_PREFIX."members WHERE member_id=$k"; - $result_notify = mysql_query($sql_notify, $db); - $row_notify = mysql_fetch_assoc($result_notify); - - if ($row_notify['email'] != '') { - require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php'); - $body = _AT('notification_group_invite', get_display_name($_SESSION['member_id']),$group_obj->getName() , $_base_href.AT_SOCIAL_BASENAME.'index_mystart.php'); - $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('group_invitation'); - $mail->Body = $body; - - if(!$mail->Send()) { - $msg->addError('SENDING_ERROR'); - } - unset($mail); - } - //TODO, move the following function from friends.inc.php to the SocialGroup.class object - addGroupInvitation($k, $gid); - } - } - $msg->addFeedback('INVITATION_SENT'); -} - -//Display -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('pubmenu.tmpl.php'); -$savant->assign('group_obj', $group_obj); -$savant->display('sgroup_invite.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/social/groups/join.php b/mods/social/groups/join.php deleted file mode 100644 index 9f187e364..000000000 --- a/mods/social/groups/join.php +++ /dev/null @@ -1,80 +0,0 @@ -getPrivacy()==0){ - /*public*/ - $result = $group_obj->addMember($_SESSION['member_id']); //adding "myself" into the group - if($result){ - $msg->addFeedback('GROUP_JOINED'); - } else { - $msg->addError('JOIN_REQUEST_FAILED'); - } -} else { - /*private*/ - $result = $group_obj->addRequest(); - if ($result){ - $sql = "SELECT member_id from ".TABLE_PREFIX."social_groups WHERE id = '$gid'"; - - $result_sender = mysql_query($sql, $db); - $grpadmins = mysql_fetch_row($result_sender); - $grpadmin = $grpadmins['0']; - - require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php'); - $sql_notify = "SELECT first_name, last_name, email FROM ".TABLE_PREFIX."members WHERE member_id=$grpadmin"; - $result_notify = mysql_query($sql_notify, $db); - $row_notify = mysql_fetch_assoc($result_notify); - - if ($row_notify['email'] != '') { - $body = _AT('notification_group_request', $group_obj->getName() , $_base_href.AT_SOCIAL_BASENAME.'index_mystart.php'); - $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('group_request'); - $mail->Body = $body; - - if(!$mail->Send()) { - $msg->addError('SENDING_ERROR'); - } - unset($mail); - } - - $msg->addFeedback('JOIN_REQUEST_SENT'); - } else { - $msg->addError('JOIN_REQUEST_FAILED'); - } -} - - - -//Display -header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'groups/index.php', AT_PRETTY_URL_HEADER)); -exit; -?> \ No newline at end of file diff --git a/mods/social/groups/list.php b/mods/social/groups/list.php deleted file mode 100644 index 86bfe40c8..000000000 --- a/mods/social/groups/list.php +++ /dev/null @@ -1,91 +0,0 @@ -getGroupMembers(); - -$rand_key = $addslashes($_POST['rand_key']); //should we excape? - -//if $_GET['q'] is set, handle Ajax. -if (isset($_GET['q'])){ - $query = $addslashes($_GET['q']); - $search_result = $grp_obj->searchMembers($query); - - if (!empty($search_result)){ - echo '
    '._AT('suggestions').':
    '; - $counter = 0; - foreach($search_result as $member_id=>$member_obj){ - //display 10 suggestions - if ($counter > 10){ - break; - } - echo ''.printSocialName($member_obj->getID(), false).'
    '; - $counter++; - } - echo '
    '; - } - exit; -} - -//handle search friends request -if($rand_key!='' && isset($_POST['search_friends_'.$rand_key])){ - if (empty($_POST['search_friends_'.$rand_key])){ - $msg->addError('CANNOT_BE_EMPTY'); - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'groups/list.php?id='.$id, AT_PRETTY_URL_IS_HEADER)); - exit; - } - $search_field = $addslashes($_POST['search_friends_'.$rand_key]); - $grp_members = $grp_obj->searchMembers($search_field); -} - - -//handle delete friends request -if (isset($_GET['remove']) && isset($_GET['member_id'])){ - //saveguard - $member_id = $_GET['member_id']; - - //validate if this is the creator of group - if($_SESSION['member_id']==$grp_obj->getUser()){ - $grp_obj->removeMember($member_id); - $msg->addFeedback('GRUOP_MEMBER_REMOVED'); - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'groups/list.php?id='.$id, AT_PRETTY_URL_IS_HEADER)); - exit; - } -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('pubmenu.tmpl.php'); -$savant->assign('grp_obj', $grp_obj); -$savant->assign('grp_members', $grp_members); -$savant->assign('rand_key', $rand_key); -$savant->display('sgroup_list.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/social/groups/search.php b/mods/social/groups/search.php deleted file mode 100644 index 74409dec2..000000000 --- a/mods/social/groups/search.php +++ /dev/null @@ -1,77 +0,0 @@ -printInfos($info); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -//social groups init -$social_groups = new SocialGroups(); -$rand_key = $addslashes($_POST['rand_key']); //should we excape? - -//if $_GET['q'] is set, handle Ajax. -if (isset($_GET['q'])){ - $query = $addslashes($_GET['q']); - $search_result = $social_groups->search($query); - if (!empty($search_result)){ - echo '
    Suggestion:
    '; - $counter = 0; - foreach($search_result as $group_id=>$group_array){ - //display 10 suggestions - if ($counter > 10){ - break; - } - - $group_obj = $group_array['obj']; - /* A bit of a hack here - * Escape XSS for the ajax search. Problem: the ' and " is changed to its entities. - * - * @Apr 2, 2009 - Harris - */ - echo ''.$group_obj->getName().'
    '; - $counter++; - } - echo '
    '; - } - exit; -} - -// handle post request -if ($rand_key!='' && isset($_POST['search_groups_'.$rand_key]) && !empty($_POST['search_groups_'.$rand_key])){ - $query = $addslashes($_POST['search_groups_'.$rand_key]); - $search_result = $social_groups->search($query); -} elseif(empty($_POST['search_groups_'.$rand_key])) { - $msg->addError('CANNOT_BE_EMPTY'); -} - -//Display -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('pubmenu.tmpl.php'); -$savant->assign('rand_key', $rand_key); -$savant->assign('search_result', $search_result); -$savant->display('sgroup_search.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> diff --git a/mods/social/groups/view.php b/mods/social/groups/view.php deleted file mode 100644 index e6f378c18..000000000 --- a/mods/social/groups/view.php +++ /dev/null @@ -1,76 +0,0 @@ -isValid()){ - $msg->addError('GROUP_HAS_BEEN_REMOVED'); - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'groups/index.php', AT_PRETTY_URL_HEADER)); - exit; -} - -//remove group member -if (isset($_GET['remove']) && $_GET['remove']==1){ - $group_obj->removeMember($_SESSION['member_id']); - $msg->addFeedback('LEFT_GROUP_SUCCESSFULLY'); - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'groups/index.php', AT_PRETTY_URL_HEADER)); - exit; -} - -//submit message -if (isset($_POST['submit'])){ - $body = $_POST['msg_body']; - if ($body!=''){ - $group_obj->addMessage($body); - } -} - -// delete group -if($_GET['delete'] == "confirm"){ - //$msg->addConfirm('DELETE_GROUP', $group_obj->getName()); - //$msg->addConfirm('DELETE_GROUP', ); - $hidden_vars['id'] = $gid; - $msg->addConfirm(array('DELETE_GROUP', $group_obj->getName()), $hidden_vars); - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME."groups/view.php?id=".$gid, AT_PRETTY_URL_HEADER)); - exit; - -}else if($_POST['submit_yes']){ - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME."groups/delete.php?id=".$gid, AT_PRETTY_URL_HEADER)); - exit; -}else if($_POST['submit_no']){ - $msg->addFeedback('CANCELLED'); - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME."groups/view.php?id=".$gid, AT_PRETTY_URL_HEADER)); - exit; -} - -//Display -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('pubmenu.tmpl.php'); -$savant->assign('group_invitations',getGroupInvitations()); -$savant->assign('group_obj', $group_obj); -$savant->display('sgroup_view.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/social/html/activities.tmpl.php b/mods/social/html/activities.tmpl.php deleted file mode 100644 index 26ab32e28..000000000 --- a/mods/social/html/activities.tmpl.php +++ /dev/null @@ -1,34 +0,0 @@ - -
    -
    -
    - getVisitors(); - echo _AT('visitor_counts').': '.$count['total']; - ?> -
    -

    -
    - - -
    - activities)): ?> -
      - activities as $id=>$array): ?> -
    • - -
    - activities)==SOCIAL_FRIEND_ACTIVITIES_MAX): ?> - - - - - -

    -
    \ No newline at end of file diff --git a/mods/social/html/admin/delete_applications.tmpl.php b/mods/social/html/admin/delete_applications.tmpl.php deleted file mode 100644 index 8d66997a0..000000000 --- a/mods/social/html/admin/delete_applications.tmpl.php +++ /dev/null @@ -1,40 +0,0 @@ -
    -
    -

    - -
    -all_apps)): ?> -all_apps as $id=>$app_obj): - //skip the ones that are installed already - if ($this->list_of_my_apps[$id]!=null){ - continue; - } - $author = ($app_obj->getAuthor()!='')?$app_obj->getAuthor():_AT('unknown'); -?> -
    - getAppLink($app_obj->getTitle(), $id); ?>
    - getAppLink('', $id); ?>
    - - getAuthorEmail()!=''): ?> - - - -
    - -
    - - -
    -
    - getDescription(); ?>

    - getUrl(); ?>
    -
    -
    - - - - -
    -
    - \ No newline at end of file diff --git a/mods/social/html/application_settings.tmpl.php b/mods/social/html/application_settings.tmpl.php deleted file mode 100644 index ad6c97965..000000000 --- a/mods/social/html/application_settings.tmpl.php +++ /dev/null @@ -1,63 +0,0 @@ -
    -settings)) { - $settings = $this->settings; - foreach ($settings as $key => $setting) { - $name = ! empty($setting->displayName) ? $setting->displayName : $key; - $default = isset($setting->default) ? $setting->default : ''; -// $value = isset($vars['application']['user_prefs'][$key]) ? $vars['application']['user_prefs'][$key] : $default; - $html .= "
    $name
    "; - switch ($setting->type) { - case 'ENUM': - $html .= "\n"; - break; - case 'STRING': - if (isset($this->user_settings[$key]) && $this->user_settings[$key]!=''){ - $default=$this->user_settings[$key]; - } - $html .= "\n"; - break; - case 'HIDDEN': - //hide these for now so that they don't get saved? - //echo "\n"; - $html = ''; //do not display anything - break; - case 'BOOL': - //TODO add radio boxes here, should they be yes / no? - $yes = ''; - $no = ''; - if ($default=='true'){ - $yes = ' checked="checked"'; - } else { - $no = ' checked="checked"'; - } - $html .= ''; - $html .= ''; - $html .= ''; - $html .= ''; - break; - case 'LIST': - //TODO not sure what to do with this one yet - break; - case 'NUMBER': - $html .= "\n"; - break; - } - } - } - if ($html != '') : - echo $html . "
    "; - ?> - - - - - - -
    \ No newline at end of file diff --git a/mods/social/html/applications.tmpl.php b/mods/social/html/applications.tmpl.php deleted file mode 100644 index abeea3a64..000000000 --- a/mods/social/html/applications.tmpl.php +++ /dev/null @@ -1,103 +0,0 @@ - - - - - -
    -

    -
    -
    "> - - - - -
    - -
    "> - list_of_all_apps)): ?> - - - - - -
    -
    -
    - -list_of_all_apps) && !empty($this->list_of_all_apps)): ?> -
    -

    -list_of_all_apps as $id=>$app_obj): - //skip the ones that are installed already - if ($this->list_of_my_apps[$id]!=null){ - continue; - } - $author = ($app_obj->getAuthor()!='')?$app_obj->getAuthor():_AT('unknown'); -?> -
    -
    - getAppLink($app_obj->getTitle(), $id); ?>
    - getAppLink('', $id); ?>
    - - getAuthorEmail()!=''): ?> - - - -
    - -
    - - <?php echo _AT('add_to_mygadgets');?> -
    -
    - getDescription(); ?>

    - getUrl(); ?>
    -
    -
    -
    - -
    - - -
    -

    -list_of_my_apps as $id=>$app_obj): - $author = ($app_obj->getAuthor()!='')?$app_obj->getAuthor():_AT('unknown'); -?> -
    -
    - getAppLink($app_obj->getTitle(), $id); ?>
    - getAppLink('', $id); ?>
    - - getAuthorEmail()!=''): ?> - - - -
    - -
    - <?php echo _AT('settings');?> - - <?php echo _AT('delete');?> -
    -
    - getDescription(); ?>

    - getUrl(); ?>
    -
    - -
    - -
    -'; -echo _AT('no_gadgets_installed'); -echo '
    '; -} -?> - diff --git a/mods/social/html/basic_profile.tmpl.php b/mods/social/html/basic_profile.tmpl.php deleted file mode 100644 index 512222c3a..000000000 --- a/mods/social/html/basic_profile.tmpl.php +++ /dev/null @@ -1,128 +0,0 @@ -
    - -
    -
    -
    -

    -
    - -
    -
    - - - -
    -
    -
    - - /> -
    -
    -
    *

    - -
    - -
    -
    - -
    - -
    -
    *

    - -
    - - - -
    -
    *

    - - /> - - /> - - - /> - - /> - - -
    - -
    -
    -
    -

    -
    - - -
    -
    -
    -
    -
    -
    -
    -
    - - -
    -
    - -
    - -
    -
    - /> /> /> -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    - -
    -
    - -
    -
    -
    - - -
    -
    -
    diff --git a/mods/social/html/connections.tmpl.php b/mods/social/html/connections.tmpl.php deleted file mode 100644 index aa200f618..000000000 --- a/mods/social/html/connections.tmpl.php +++ /dev/null @@ -1,107 +0,0 @@ - -rand_key != ''){ - $last_search = $_POST['search_friends_'.$this->rand_key]; - } elseif(isset($_GET['search_friends'])) { - $last_search = htmlentities_utf8($_GET['search_friends']); - } else { - $last_search = $_POST['search_friends_'.$rand]; - } - //take out double quotes until there is a way to escape XSS from the ajax script. - $last_search = preg_replace('/\"/', '', $last_search); -?> -page, $this->num_pages, 'search_friends='.$this->search_field, 1); ?> -
    -
    -

    -
    - - - - -
    /> -
    - - -
    -
    -
    -
    -
    -

    -
    - friends)): - $privacy_controller = new PrivacyController(); - echo "

    "._AT('there_are_entries', sizeof($this->friends))."

    "; - foreach ($this->friends as $id=>$person): - $privacy_obj = $privacy_controller->getPrivacyObject($id); -// debug($privacy_obj->getSearch(), 'search'.$id); - $relationship = $privacy_controller->getRelationship($id); - - if ((!isset($person['added']) || $person['added']!=1) && !PrivacyController::validatePrivacy(AT_SOCIAL_SEARCH_VISIBILITY, $relationship, $privacy_obj->getSearch())){ - //if this user doesn't want to be searched. - continue; - } - ?> -
    - - <?php echo _AT('delete'); ?> -
    -
    -
    - getAddress(); - echo printSocialName($id) . '
    '; - echo $address['province'] . ' ' . $address['country'] . '
    '; - ?> -
    -

    -
    - - - - -
    - -
    <?php echo _AT('add_to_friends'); ?>
    - -
    -
    -
    - getAddress(); - echo printSocialName($id) . '
    '; - echo $address['country'] . ' ' . $address['province'] . '
    '; - ?> -
    -

    -
    - - - -
    - -
    - -
    -
    -page, $this->num_pages, 'search_friends='.$this->search_field, 1); ?> \ No newline at end of file diff --git a/mods/social/html/edit_profile.tmpl.php b/mods/social/html/edit_profile.tmpl.php deleted file mode 100644 index e4c4cf133..000000000 --- a/mods/social/html/edit_profile.tmpl.php +++ /dev/null @@ -1,99 +0,0 @@ -

    profile['first_name'].' '.$this->profile['last_name']; ?>

    - - - - -
      -
    • -
      -
      - position)): - //note: $id is just a array holder, it does not represent $row[id] - foreach ($this->position as $id=>$row): ?> -
      -
      <?php echo _AT('edit'); ?> <?php echo _AT('remove'); ?> ?>
      -
      -
      -
      -
      -
      -
      - -

      -
      -
    • -
    • -
      - education)): - foreach ($this->education as $id=>$row): ?> -
      -
      <?php echo _AT('edit'); ?> <?php echo _AT('remove'); ?> ?>
      -
      -
      -
      -
      -
      -
      -
      -
      - -

      -
    • -
    • -
      - websites)): - foreach ($this->websites as $id=>$row): ?> -
      -
      <?php echo _AT('edit'); ?> <?php echo _AT('remove'); ?> ?>
      -
      -
      -
      - -

      -
    • - -
    • -
      - profile['interests'])): ?> -
      -
      <?php echo _AT('edit'); ?> <?php echo _AT('remove'); ?> ?>
      -
      profile['interests']); ?>
      -
      - -

      - -
    • - -
    • -
      - profile['associations'])): ?> -
      -
      <?php echo _AT('edit'); ?> <?php echo _AT('remove'); ?> ?>
      -
      profile['associations']); ?>
      -
      - -

      - -
    • - -
    • -
      - profile['awards'])): ?> -
      -
      <?php echo _AT('edit'); ?> <?php echo _AT('remove'); ?> ?>
      -
      profile['awards']); ?>
      -
      - -

      - -
    • -
    diff --git a/mods/social/html/edit_profile/edit_additional.tmpl.php b/mods/social/html/edit_profile/edit_additional.tmpl.php deleted file mode 100644 index ebab07e8a..000000000 --- a/mods/social/html/edit_profile/edit_additional.tmpl.php +++ /dev/null @@ -1,26 +0,0 @@ -title); - $interests = htmlentities_utf8($this->interests, false); - $associations = htmlentities_utf8($this->associations, false); - $awards = htmlentities_utf8($this->awards, false); -?> -
    -
    - - -
    - -
    - - id)): ?> - - - - - - - -
    -
    \ No newline at end of file diff --git a/mods/social/html/edit_profile/edit_education.tmpl.php b/mods/social/html/edit_profile/edit_education.tmpl.php deleted file mode 100644 index 52e6f27b6..000000000 --- a/mods/social/html/edit_profile/edit_education.tmpl.php +++ /dev/null @@ -1,56 +0,0 @@ -university); - $country = htmlentities_utf8($this->country); - $province = htmlentities_utf8($this->province); - $degree = htmlentities_utf8($this->degree); - $field = htmlentities_utf8($this->field); - $from = htmlentities_utf8($this->from); - $to = htmlentities_utf8($this->to); - $description = htmlentities_utf8($this->description, false); -?> - -

    -
    -
    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    - - - - - - - - - - -
    -
    - \ No newline at end of file diff --git a/mods/social/html/edit_profile/edit_position.tmpl.php b/mods/social/html/edit_profile/edit_position.tmpl.php deleted file mode 100644 index 24c9715fc..000000000 --- a/mods/social/html/edit_profile/edit_position.tmpl.php +++ /dev/null @@ -1,44 +0,0 @@ -company); - $title = htmlentities_utf8($this->profile_title); - $description = htmlentities_utf8($this->description, false); - $from = htmlentities_utf8($this->from); - $to = htmlentities_utf8($this->to); -?> - -

    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    - - - - - - - - - - - -
    - \ No newline at end of file diff --git a/mods/social/html/edit_profile/edit_websites.tmpl.php b/mods/social/html/edit_profile/edit_websites.tmpl.php deleted file mode 100644 index d4045f046..000000000 --- a/mods/social/html/edit_profile/edit_websites.tmpl.php +++ /dev/null @@ -1,29 +0,0 @@ -url); - $site_name = htmlentities_utf8($this->site_name); -?> -

    -
    -
    -
    -
    -
    - -
    -
    - - - - - - - - - - -
    -
    - \ No newline at end of file diff --git a/mods/social/html/friend_list.tmpl.php b/mods/social/html/friend_list.tmpl.php deleted file mode 100644 index 946268e80..000000000 --- a/mods/social/html/friend_list.tmpl.php +++ /dev/null @@ -1,35 +0,0 @@ -
    - -
    -
    -
    -

    -
    - friends)): ?> - friends as $id=>$m_obj): - if (is_array($m_obj) && $m_obj['added']!=1){ - //skip over members that are not "my" friends - continue; - } ?> -
    - -
    -
    - -
    -
    - -
    - - - -
    -
    diff --git a/mods/social/html/index_public.tmpl.php b/mods/social/html/index_public.tmpl.php deleted file mode 100644 index fae614b36..000000000 --- a/mods/social/html/index_public.tmpl.php +++ /dev/null @@ -1,71 +0,0 @@ - -rand_key != ''){ - $last_search = $_POST['search_friends_'.$this->rand_key]; - } else { - $last_search = $_POST['search_friends_'.$rand]; - } -?> -page, $this->num_pages, 'search_friends='.$this->search_field, 1); ?> -
    -
    -

    -
    - - - - - -
    -
    -
    -
    -
    -

    -
    - friends)): - $privacy_controller = new PrivacyController(); - echo "

    "._AT('there_are_entries', sizeof($this->friends))."

    "; - foreach ($this->friends as $id=>$person): - $privacy_obj = $privacy_controller->getPrivacyObject($id); -// debug($privacy_obj->getSearch(), 'search'.$id); - $relationship = $privacy_controller->getRelationship($id); - - if ((!isset($person['added']) || $person['added']!=1) && !PrivacyController::validatePrivacy(AT_SOCIAL_SEARCH_VISIBILITY, $relationship, $privacy_obj->getSearch())){ - //if this user doesn't want to be searched. - continue; - } - ?> -
    -
    -
    -
    - getAddress(); - echo printSocialName($id) . '
    '; - echo $profile['country'] . ' ' . $profile['province'] . '
    '; - ?> -
    -

    -
    -
    - -
    - -
    -
    -page, $this->num_pages, 'search_friends='.$this->search_field, 1); ?> diff --git a/mods/social/html/individual_application.tmpl.php b/mods/social/html/individual_application.tmpl.php deleted file mode 100644 index 55db833ce..000000000 --- a/mods/social/html/individual_application.tmpl.php +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - -

    app->getTitle(); ?>

    -
    - \ No newline at end of file diff --git a/mods/social/html/notifications.tmpl.php b/mods/social/html/notifications.tmpl.php deleted file mode 100644 index 6fcd2aae9..000000000 --- a/mods/social/html/notifications.tmpl.php +++ /dev/null @@ -1,78 +0,0 @@ -pending_requests)): -?> - -

    -
    -pending_requests as $id=>$r_obj): -?> - -
    -
    <?php echo _AT('accept_request'); ?> <?php echo _AT('reject_request'); ?> -
    -
      -
    • -
    • -
    -

    - - -

    - - -group_invitations)): -?> - -

    -group_invitations as $id=>$sender_ids): - $gobj = new SocialGroup($id); - $name = ''; - foreach($sender_ids as $index=>$sender_id){ - $name .= printSocialName($sender_id).', '; - } - $name = substr($name, 0, -2); -?> -
    -
    <?php echo _AT('accept_request'); ?> <?php echo _AT('reject_request'); ?>
    -
      -
    • getID(), $gobj->getName()); ?>
    • - -
    -
    -
    - - - -group_requests)): -?> - -

    -
    - -group_requests as $id=>$senders): - $gobj = new SocialGroup($id); - foreach($senders as $index=>$sender_id): - $name = printSocialName($sender_id); -?> -
    -
    - <?php echo _AT('accept_request'); ?> <?php echo _AT('reject_request'); ?> -
    -
      -
    • getName()); ?>
    • - -
    - -
    - -

    - - \ No newline at end of file diff --git a/mods/social/html/profile_picture.html.php b/mods/social/html/profile_picture.html.php deleted file mode 100644 index f840c4529..000000000 --- a/mods/social/html/profile_picture.html.php +++ /dev/null @@ -1,213 +0,0 @@ - 0 || $src_y > 0){ - imagecopyresized($thumbnail_img, $source, 0, 0, $src_x, $src_y, $dest_w, $dest_h, $src_w, $src_h); - } else { - imagecopyresampled($thumbnail_img, $source, $src_x, $src_y, 0, 0, $dest_w, $dest_h, $src_w, $src_h); - } - - if ($type == 'gif') { - imagegif($thumbnail_img, $dest); - } else if ($type == 'jpg') { - imagejpeg($thumbnail_img, $dest, 75); - } else { - imagepng($thumbnail_img, $dest, 7); - } -} - -// check if GD is installed -if (!extension_loaded('gd')) { - require(AT_INCLUDE_PATH.'header.inc.php'); - $msg->printInfos('FEATURE_NOT_AVAILABLE'); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -// check if folder exists, if not, create it -if (!is_dir(AT_CONTENT_DIR.'/profile_pictures/profile')) { - mkdir(AT_CONTENT_DIR.'/profile_pictures/profile'); -} - -$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'; -} - -if (!$supported_images) { - require(AT_INCLUDE_PATH.'header.inc.php'); - $msg->printInfos('FEATURE_NOT_AVAILABLE'); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -if (isset($_POST['cancel'])) { - $msg->addFeedback('CANCELLED'); - header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id); - exit; -} else if (isset($_POST['submit'])) { - if (isset($_POST['delete']) && !$_FILES['file']['size']) { - profile_image_delete($member_id); - - $msg->addFeedback('PROFILE_UPDATED'); - - header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id); - exit; - } else if ($_FILES['file']['error'] == UPLOAD_ERR_FORM_SIZE) { - $msg->addError(array('FILE_MAX_SIZE', $_config['prof_pic_max_file_size'] . ' ' . _AT('bytes'))); - header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id); - exit; - } else if (!$_FILES['file']['size']) { - header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id); - exit; - } - - // check if this is a supported file type - $filename = $stripslashes($_FILES['file']['name']); - $path_parts = pathinfo($filename); - $extension = strtolower($path_parts['extension']); - $image_attributes = getimagesize($_FILES['file']['tmp_name']); - - if ($extension == 'jpeg') { - $extension = 'jpg'; - } - - if (!in_array($extension, $supported_images)) { - $msg->addError(array('FILE_ILLEGAL', $extension)); - header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id); - exit; - } else if ($image_attributes[2] > IMAGETYPE_PNG) { - $msg->addError(array('FILE_ILLEGAL', $extension)); - header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id); - exit; - } - - // make sure under max file size - if ($_FILES['file']['size'] > $_config['prof_pic_max_file_size']) { - $msg->addError('FILE_MAX_SIZE'); - header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id); - exit; - } - - // delete the old images (if any) - profile_image_delete($member_id); - - $new_filename = $member_id . '.' . $extension; - $original_img = AT_CONTENT_DIR.'profile_pictures/originals/'. $new_filename; - $profile_img = AT_CONTENT_DIR.'profile_pictures/profile/'. $new_filename; - $thumbnail_img = AT_CONTENT_DIR.'profile_pictures/thumbs/'. $new_filename; - - // save original - if (!move_uploaded_file($_FILES['file']['tmp_name'], $original_img)) { - $msg->addError('CANNOT_OVERWRITE_FILE'); - header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id); - exit; - } - - // resize the original and save it at $thumbnail_file - $width = $image_attributes[0]; - $height = $image_attributes[1]; - - $thumbnail_fixed_height = 60; - $thumbnail_fixed_width = 60; - - if ($width > $height && $height > $thumbnail_fixed_height) { - $thumbnail_height= $thumbnail_fixed_height; - $thumbnail_width = intval($thumbnail_fixed_height * $width / $height); - resize_image($original_img, $thumbnail_img, $height, $width, $thumbnail_height, $thumbnail_width, $extension); - //cropping - resize_image($thumbnail_img, $thumbnail_img, $thumbnail_fixed_height, $thumbnail_fixed_width, $thumbnail_fixed_height, $thumbnail_fixed_width, $extension, ($thumbnail_width-$thumbnail_fixed_width)/2); - } else if ($width <= $height && $width>$thumbnail_fixed_width) { - $thumbnail_height = intval($thumbnail_fixed_width * $height / $width); - $thumbnail_width = $thumbnail_fixed_width; - resize_image($original_img, $thumbnail_img, $height, $width, $thumbnail_height, $thumbnail_width, $extension); - //cropping - resize_image($thumbnail_img, $thumbnail_img, $thumbnail_fixed_height, $thumbnail_fixed_width, $thumbnail_fixed_height, $thumbnail_fixed_width, $extension, 0, ($thumbnail_height-$thumbnail_fixed_height)/2); - } else { - // no resizing, just copy the image. - // it's too small to resize. - copy($original_img, $thumbnail_img); - } - - // resize the original and save it to profile - $profile_fixed_height = 320; - $profile_fixed_width = 240; - if ($width > $height && $height>$profile_fixed_height) { - $profile_width = intval($profile_fixed_height * $width / $height); - $profile_height = $profile_fixed_height; - resize_image($original_img, $profile_img, $height, $width, $profile_height, $profile_width, $extension); - //cropping - resize_image($profile_img, $profile_img, $profile_fixed_height, $profile_fixed_width, $profile_fixed_height, $profile_fixed_width, $extension, ($profile_width-$profile_fixed_width)/2); - } else if ($width <= $height && $width > $profile_fixed_width) { - $profile_width = $profile_fixed_width; - $profile_height = intval($profile_fixed_width * $height / $width); - resize_image($original_img, $profile_img, $height, $width, $profile_height, $profile_width, $extension); - //cropping - resize_image($profile_img, $profile_img, $profile_fixed_height, $profile_fixed_width, $profile_fixed_height, $profile_fixed_width, $extension, 0, ($profile_height-$profile_fixed_height)/2); - } else { - // no resizing, just copy the image. - // it's too small to resize. - copy($original_img, $profile_img); - } - - $msg->addFeedback('PROFILE_UPDATED'); - - header('Location: '.$_SERVER['PHP_SELF'].'?member_id='.$member_id); - exit; -} - -require(AT_INCLUDE_PATH.'header.inc.php'); - -?> - -
    - -
    - -
    - - -
    - -
    -

    - ()
    - -
    - - -
    -
    -
    - - \ No newline at end of file diff --git a/mods/social/html/pubmenu.tmpl.php b/mods/social/html/pubmenu.tmpl.php deleted file mode 100644 index eaade657b..000000000 --- a/mods/social/html/pubmenu.tmpl.php +++ /dev/null @@ -1,12 +0,0 @@ - - -
    - \ No newline at end of file diff --git a/mods/social/html/settings/account_settings.tmpl.php b/mods/social/html/settings/account_settings.tmpl.php deleted file mode 100644 index 7e16ea81b..000000000 --- a/mods/social/html/settings/account_settings.tmpl.php +++ /dev/null @@ -1,10 +0,0 @@ -
    -
    -

    -
    -
    - - -
    -
    -
    \ No newline at end of file diff --git a/mods/social/html/settings/application_settings.tmpl.php b/mods/social/html/settings/application_settings.tmpl.php deleted file mode 100644 index d7a2f4dcc..000000000 --- a/mods/social/html/settings/application_settings.tmpl.php +++ /dev/null @@ -1,26 +0,0 @@ -my_apps)): - echo _AT('no_gadgets_installed'); -else: ?> -
    -
    -

    -
    - my_apps as $id=>$app_obj): ?> -
    -
    getTitle(); ?>
    -
    - - home_display[$id]))? $checked = ' checked="checked"': $checked = ''; ?> - /> -
    -

    -
    - -
    - - -
    -
    -
    - diff --git a/mods/social/html/settings/privacy_settings.tmpl.php b/mods/social/html/settings/privacy_settings.tmpl.php deleted file mode 100644 index 23bf8f365..000000000 --- a/mods/social/html/settings/privacy_settings.tmpl.php +++ /dev/null @@ -1,144 +0,0 @@ -
    -
    -

    -
    -
    -
    - -
    - controller->getPermissionLevels() as $control_id=>$control_string): - (isset($this->profile_prefs[AT_SOCIAL_PROFILE_BASIC][$control_id]))?$checked=' checked="checked"':$checked=''; ?> - - > - -
    -
    -
    - -
    - controller->getPermissionLevels() as $control_id=>$control_string): - (isset($this->profile_prefs[AT_SOCIAL_PROFILE_PROFILE][$control_id]))?$checked=' checked="checked"':$checked=''; ?> - - > - -
    -
    -
    - -
    - controller->getPermissionLevels() as $control_id=>$control_string): - (isset($this->profile_prefs[AT_SOCIAL_PROFILE_STATUS_UPDATE][$control_id]))?$checked=' checked="checked"':$checked=''; ?> - - > - -
    -
    - -
    - -
    - controller->getPermissionLevels() as $control_id=>$control_string): - (isset($this->profile_prefs[AT_SOCIAL_PROFILE_CONNECTION][$control_id]))?$checked=' checked="checked"':$checked=''; ?> - - > - -
    -
    -
    - -
    - controller->getPermissionLevels() as $control_id=>$control_string): - (isset($this->profile_prefs[AT_SOCIAL_PROFILE_EDUCATION][$control_id]))?$checked=' checked="checked"':$checked=''; ?> - - > - -
    -
    -
    - -
    - controller->getPermissionLevels() as $control_id=>$control_string): - (isset($this->profile_prefs[AT_SOCIAL_PROFILE_POSITION][$control_id]))?$checked=' checked="checked"':$checked=''; ?> - - > - -
    -
    -
    - -
    Search Control -
    - -
    - controller->getPermissionLevels() as $control_id=>$control_string): - (isset($this->search_prefs[AT_SOCIAL_SEARCH_VISIBILITY][$control_id]))?$checked=' checked="checked"':$checked=''; ?> - - > - -
    -
    - -
    - - -
    - - -
    -
    -
    \ No newline at end of file diff --git a/mods/social/html/settings/settings_menu.tmpl.php b/mods/social/html/settings/settings_menu.tmpl.php deleted file mode 100644 index 117d2773d..000000000 --- a/mods/social/html/settings/settings_menu.tmpl.php +++ /dev/null @@ -1,6 +0,0 @@ - - \ No newline at end of file diff --git a/mods/social/html/sgroup_create.tmpl.php b/mods/social/html/sgroup_create.tmpl.php deleted file mode 100644 index 817a65bd9..000000000 --- a/mods/social/html/sgroup_create.tmpl.php +++ /dev/null @@ -1,38 +0,0 @@ - - -
    -
    -
    - - -
    - -
    - - -
    - -
    - - -
    - -
    - - -
    - -
    - -
    -
    -
    \ No newline at end of file diff --git a/mods/social/html/sgroup_edit.tmpl.php b/mods/social/html/sgroup_edit.tmpl.php deleted file mode 100644 index 594374ec1..000000000 --- a/mods/social/html/sgroup_edit.tmpl.php +++ /dev/null @@ -1,93 +0,0 @@ -group_obj)){ - //edit - $form_url = AT_SOCIAL_BASENAME.'groups/edit.php'; - $button_name = 'save'; - $name = $this->group_obj->getName(); - $logo = $this->group_obj->getLogo(); - $privacy = $this->group_obj->getPrivacy(); - $description = $this->group_obj->getDescription(false); - $id = $this->group_obj->getID(); -} else { - //create new one - $form_url = AT_SOCIAL_BASENAME.'groups/create.php'; - $button_name = 'create'; -} -?> - -
    -
    -
    - - -
    - - group_obj)): ?> -
    - - -
    - - -
    - - -
    - -
    - -
    - /> -
    - /> - -
    - -
    - - - -
    - -
    - - -
    - -
    - - - -
    -
    -
    \ No newline at end of file diff --git a/mods/social/html/sgroup_invite.tmpl.php b/mods/social/html/sgroup_invite.tmpl.php deleted file mode 100644 index cc3ee5208..000000000 --- a/mods/social/html/sgroup_invite.tmpl.php +++ /dev/null @@ -1,47 +0,0 @@ -group_obj); ?> -
    -
    -
    -

    -
    -
      - group_obj->getGroupMembers() as $k=>$person_obj): ?> -
    • getID()); ?>
    • - -
    -
    -
    -
    -
    -
    -

    -
    - -
    - $member_id): - if(in_array(new Member($member_id), $this->group_obj->getGroupMembers())){ - $extra = ' disabled="disabled"'; - } else { - $extra = ''; - } - - if(isset($_POST['new_members'][$member_id])){ - $extra .= ' checked="checked"'; - } - ?> - /> -
    - -
    - - - -
    -
    \ No newline at end of file diff --git a/mods/social/html/sgroup_list.tmpl.php b/mods/social/html/sgroup_list.tmpl.php deleted file mode 100644 index bed3e3901..000000000 --- a/mods/social/html/sgroup_list.tmpl.php +++ /dev/null @@ -1,61 +0,0 @@ - -rand_key != ''){ - $last_search = $_POST['search_friends_'.$this->rand_key]; - } else { - $last_search = $_POST['search_friends_'.$rand]; - } -?> - -
    -
    -

    -
    - - - - - -
    -
    -
    -
    -
    -

    -
    - grp_members)): - echo "

    "._AT('there_are_entries', sizeof($this->grp_members))."

    "; - foreach ($this->grp_members as $id=>$person_obj): - ?> -
    - grp_obj->getUser()): ?> -
    <?php echo _AT('remove_group_member'); ?>
    - -
    -
    getID()); ?>
    -
    - getDetails(); - echo printSocialName($person_obj->getID()) . '
    '; - echo $profile['country'] . ' ' . $profile['province'] . '
    '; - ?> -
    -

    -
    -
    - -
    - -
    - diff --git a/mods/social/html/sgroup_search.tmpl.php b/mods/social/html/sgroup_search.tmpl.php deleted file mode 100644 index f8eb9a4c2..000000000 --- a/mods/social/html/sgroup_search.tmpl.php +++ /dev/null @@ -1,51 +0,0 @@ - -rand_key != ''){ - $last_search = $_POST['search_groups_'.$this->rand_key]; - } else { - $last_search = $_POST['search_groups_'.$rand]; - } - //take out double quotes until there is a way to escape XSS from the ajax script. - $last_search = preg_replace('/\"/', '', $last_search); -?> -
    -

    -
    -
    - - - - -
    -
    -
    -
    -
    - -

    -
    - search_result)): - foreach($this->search_result as $group_id=>$group_array): - $grp_obj = $group_array['obj']; - ?> -
    -
    - getLogo(); ?> - -
    -
    -

    getName(); ?>


    - getGroupType();?>
    - '. $grp_obj->getDescription();?>
    -
    -
    -
    - -
    - -
    \ No newline at end of file diff --git a/mods/social/html/sgroup_view.tmpl.php b/mods/social/html/sgroup_view.tmpl.php deleted file mode 100644 index e08e3b360..000000000 --- a/mods/social/html/sgroup_view.tmpl.php +++ /dev/null @@ -1,136 +0,0 @@ -printConfirm(); ?> -
    - - group_obj->group_members)): ?> - | | - - - group_obj->getUser() == $_SESSION['member_id']): ?> - | - | - - - | - - - - - | - - - - | - - -
    -
    - group_obj->getGroupActivities() as $activity_id=>$activity_title){ - echo $activity_title; - } - ?> -
    - - -group_obj->group_members)): ?> -
    -
    -

    -
    -
    - -
    - -

    - - - - - -
    -
    - group_obj->getMessages() as $id=>$message_array): ?> -
    - - group_obj->getUser()==$_SESSION['member_id']){ - echo ''._AT('remove').''; - } - ?> -

    -
    - -
    -
    - << - >> -
    -
    -
    -
    - - -
    -

    -
    -
    group_obj->getLogo();?>
    -
    -
    -
    group_obj->getName();?>
    - -
    -
    group_obj->getGroupType();?>
    - -
    -
    group_obj->getPrivacy()?_AT('private'):_AT('public'))?>
    - -
    -
    group_obj->getUser());?>
    - -
    -
    group_obj->getCreatedDate(), AT_DATE_MYSQL_DATETIME);?>
    - -
    -
    group_obj->getLastUpdated(), AT_DATE_MYSQL_DATETIME);?>
    - -
    -
    group_obj->group_members);?>
    -
    -

    -
    \ No newline at end of file diff --git a/mods/social/html/sgroups.tmpl.php b/mods/social/html/sgroups.tmpl.php deleted file mode 100644 index 1f3f79a02..000000000 --- a/mods/social/html/sgroups.tmpl.php +++ /dev/null @@ -1,37 +0,0 @@ - -rand_key != ''){ - $last_search = $_POST['search_groups_'.$this->rand_key]; - } else { - $last_search = $_POST['search_groups_'.$rand]; - } -?> -
    - -
    -
    -
    -
    -

    -
    -
    - - - - -
    -
    -
    -
    -
    -
    -
    -
    -

    -

    -
    -
    -
    - diff --git a/mods/social/html/sprofile.tmpl.php b/mods/social/html/sprofile.tmpl.php deleted file mode 100644 index 5358f3d6c..000000000 --- a/mods/social/html/sprofile.tmpl.php +++ /dev/null @@ -1,214 +0,0 @@ - - -
    -

    profile['member_id'], false); ?>

    -
    -
    -
    -
    -
    - scope=='owner'): ?> -
    - "><?php echo _AT('edit_profile'); ?> -
    - - profile['member_id'], 2, false); ?> -

    -
    - profile['occupation']){ ?> -
    -
    profile['occupation']; ?>
    - - profile['expertise']){ ?> -
    -
    profile['expertise']; ?>
    - - relationship==AT_SOCIAL_FRIENDS_VISIBILITY || $this->relationship==AT_SOCIAL_OWNER_VISIBILITY): ?> - profile['email']): ?> -
    -
    profile['email']; ?>
    - - - profile['gender']){ ?> -
    -
    profile['gender']; ?>
    - - profile['dob']){ ?> -
    -
    profile['dob']; ?>
    - - profile['phone']){ ?> -
    -
    profile['phone']; ?>
    - - profile['country']){ ?> -
    -
    profile['country']; ?>
    - - profile['postal']){ ?> -
    -
    profile['postal']; ?>
    - - profile['interests']){ ?> -
    -
    profile['interests']; ?>
    - - profile['associations']){ ?> -
    -
    profile['associations']; ?>
    - - profile['awards']){ ?> -
    -
    profile['awards']; ?>
    - - profile['others']){ ?> -
    -
    profile['others']; ?>
    - -
    -
    -
    - -
    - relationship, $this->prefs)): ?> - education)){ ?> -
    -
    -
    - - - - - - - - education as $edu){ - echo ''; - echo ''; - echo ''; - } - ?> - -
    '.$edu['university'].''.$edu['degree'].'/'.$edu['field'].'/'.$edu['field'].''.$edu['from'].'-'.$edu['to'].'
    -
    -

    - - - - relationship, $this->prefs)): ?> - - position)){ ?> -
    -
    -
    - - - - - - - - position as $pos){ - echo ''; - echo ''; - echo ''; - } - ?> - -
    '.$pos['company'].''.$pos['title'].''.$pos['from'].'-'.$pos['to'].'
    -

    - - - - relationship, $this->prefs)): ?> -
    - websites)): ?> -
    -
    - - - - - - - websites as $sites){ - echo ''; - echo ''; - } - ?> - -
    '.$sites['site_name'].''.$sites['url'].'
    -

    - -
    - - - relationship, $this->prefs)): ?> -
    -
    -
    - activities)): ?> -
      - activities as $id=>$activity): - /* - * harris @may 26, 2009 - * Would be nice to use this, but we will have to change "has" to "have" for _AT('you') - * - if ($_SESSION['member_id']== $this->profile['member_id']){ - echo '
    • '._AT('you'); - echo ' '.$activity.' '; - echo ''._AT('remove').'
    • '; - } else { - echo '
    • '.printSocialName($this->profile['member_id']).' '.$activity.'
    • '; - } - */ - ?> -
    • - -
    - - - -

    - - - relationship, $this->prefs)): ?> -
    -
    -
    -
    - friends)>0): - foreach($this->friends as $friend_id): ?> -
    -
    - -
    - -

    - - mutual_friends)): ?> -
    -
    -
    -
    - mutual_friends as $friend_id): ?> -
    -
    - -
    - -
    - mutual_friends != empty ?> - -
    -
    - diff --git a/mods/social/html/tiny_applications.tmpl.php b/mods/social/html/tiny_applications.tmpl.php deleted file mode 100644 index 8867ac2a5..000000000 --- a/mods/social/html/tiny_applications.tmpl.php +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - -list_of_my_apps as $id=>$app_obj): -?> -
    -
    -
    - <?php echo _AT('delete'); ?> - - <?php echo _AT('settings');?> -
    -

    getAppLink($app_obj->getTitle(), $id); ?>

    -
    -
    - - -

    - \ No newline at end of file diff --git a/mods/social/html/tiny_sgroups.tmpl.php b/mods/social/html/tiny_sgroups.tmpl.php deleted file mode 100644 index 36653c21c..000000000 --- a/mods/social/html/tiny_sgroups.tmpl.php +++ /dev/null @@ -1,36 +0,0 @@ -

    -
    - my_groups as $i=>$grp): - $grp_obj = new SocialGroup($grp); - - ?> -
    - getUser() == $_SESSION['member_id']): ?> -
    <?php echo _AT('settings'); ?>
    - - getUser() != $_SESSION['member_id']): ?> -
    <?php echo _AT('delete'); ?>
    - - - - -
    -
    - getLogo(); ?> - -
    -
    -

    getName(); ?>


    - getGroupType();?>
    - getPrivacy()?_AT('private'):_AT('public'))?>
    - '. $grp_obj->getDescription();?>
    -
    -
    -

    -
    - - -
    diff --git a/mods/social/images/b_drop.png b/mods/social/images/b_drop.png deleted file mode 100644 index 6fc4d3b2030ecf772fae856411c7b0968d99005b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 311 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLli5Jei0#Y0$L4LviA%Njt^WI31l&6bhNX4zB1b1cz#v=#L9XQ1BeB*}A z%q#-T*4)b4(o?t>F*0#zoIb=Q$oTmtkhx|Ks|wRYkOCL`0G3nf>>LU!8g&ecZvf@i zF{v>LIB*y*Py(9O5Wuep(t6;`5vIViTuKZ~9gTA(-x+M+aA06$eNbb-z@e}}OvNsM m(}BTo!EZ5z1_KrbCLV@_U2LV?JKcpq4)=8Rb6Mw<&;$Tia9maZ diff --git a/mods/social/images/check_icon.gif b/mods/social/images/check_icon.gif deleted file mode 100644 index 734af92062816eae1b0aea5f4c086ffdb0b3c1c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 564 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 diff --git a/mods/social/images/edit_profile.gif b/mods/social/images/edit_profile.gif deleted file mode 100644 index e74c4ddff797fb2ab499e962b2471f6632355895..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 232 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 QPyhe`07*qoM6N<$f-fNoZ2$lO diff --git a/mods/social/images/plus_icon.gif b/mods/social/images/plus_icon.gif deleted file mode 100644 index 95d00c964047a6785f04ee92adf61fc98ef75b53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 997 zcmZ?wbhEHb6*jul_l<%q3NHg<(<#$TgV!aFBp`sA5bI{ zSS%k{A{J225M0h1Sj7@jE*)Af8BuH#RjL;me4Po-{o38F*$FZ zc-^dk&IJ+e^GeFs3U(|^Xj*ODzQVU@qw<8+G0i(Pns%x;?=b4zX5P2OwPT0jgw5g8 zHe~i}ckb9}-Lc!Mf452RKDC~G<{bykdJdS+*csP-SgH50>a5+teFq(;?sx1v=rrYk z>x=_#v-if#*dH?OVA#xqeiM#5PCM)}~1dk2}sk96IB; z^R(lhlTX^uI_5R=xcBsvF4Imq&OYHe^OWthGiD1;`7Ak>G3%V`k`pPjF1Rf`8@2pQ z)T&c;i?6t^I-k1aa^S+tQL8T$tiF`G{&M>ATY<}Odu_a#zV2SyribBMALi|RP`2w) z(Sau|`(ET6dQpAsRonkjK=%+({3qyKl$uzQnxasiS(2gP?&%xAp!k!8k&EF!gAM}_ zfHDdL$6AK}oPWMQZfarWO5%z6@xFDIW5a`%1d9m_(zYRgSQcn}Xqlp3yv8A-;xTgr zhs2$RgTn4DZOobp4Ih+V_|LcXIrZSgVf71>Sok(9xhZ(WQ&czi+82Y*Y_4n?zWYQh zg^qRbDJD03aBw)(E^C;6A?4)7)^k&=JhTdC99ZDOF6p^rLZqPsL$@TiufWYkM_O6? l{>$;~Olo#xJ|MT~&cxtmrUX%G9ubL)OdFooGcqz*0|2cHgGT@W diff --git a/mods/social/images/plus_icon.jpg b/mods/social/images/plus_icon.jpg deleted file mode 100644 index 558191e1b6c85501ab403f2c192fe356ffcdf6cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 458 zcmex=g`_5!kNXkA|ChW4RC?LU@i!ln;QbzxlP_V z2OuKcqIggLG zjv!B%piRxpEi7&A&e%IRIyt+!dw63Q6 z=j1-g%P%M_diI=NQCU^}qNcH_xuvzOy`ytraA^4L$h-HWpFU4bf0_9@J2$_~Tv=WF zvA)6D{N(}x;J;Wq>tC?HxkPqcTo4Et!u!hw;tJiFU=axS9xWbGV+^lLpqR4ub*T99 z#4K6^A6y5!B;gv=&o8N>`)Tj;FWPU}e+Rqqf64w0`;TiB5CnsEk_Q$6P{8`8YIY>Q zY7XKt7bTxicy`QP^21coAr&$iCHu9^5ZgIzTJJ``C{MQF0Q>_F)rN?a7a8-7naw?w zlrI{Fjw*o)jSZe3INA(8exkaU0OD zX^~zUMwUpw!P1x@nAzfbvOe4UWgBd9>1>T{9k2|^$Be4>JaM#jpdzhGEyu^y&xYLG zkV^XFb!L1p>CafFXSXMoq1FS`b%A%T*@Az$gX%)u!@^zr>Ie>7_%Y1BtqCSHyxrVPm51=z-JHBJxtSYJzV^~X?8>>A5d+* z0ksKaQE@_5B}TE1Fz_3fq_zz-=^;B!D60@>tmg4i*1V+lPxz*TLg>;WgYY(q$>^fn z$!9Y;Kqh#t%#AxX=X9n9-Fun#jx_jiZq4wcJp)?;E1nE}{9yGZRjuBzL=Kz;_t@G!cY@7D3CRqn{MZ214Wx&3^ zn4icWD9S?;bn{B$<~)WzG3+9GX~efH7X2$8Uh>59e9<@jGCbEtBd#Gws~&wEGP*4V z;Q(DWK`7+cxLDC!@yEcCK)nPidN`UELAz(-{h4Tk%&6X}yvagqvwdqu$e@bsl$c}7 z?d9z&=8jX3CxyaoSA+f-4v|8P$$VvVvn6=4$l}nx40@avo!DC{>(?moB5kR_729oI z-w?3;)V{xeXgs^%X{mQFz1_C2=C1IRgK>NN97aaXuPvk{o1z{qjzI&SAJ`11iU8J} zT;UcJ&Pp#U@X?|6t+e3Qfh z9#vrWeE6ghkXuDjRRMkG-~AM+7_;`q`=jB&+4kMS)x?6elHxB3qwHyTM6Awa=E>=+ zx9oF&PFGx0+4@$ewmI^|BL^Wy%8^3XD9DAW3?`ONy@~R1-3_(Fcy<%F)vQB)uX);`e>al2n z9)H|A!RrlrP;pA(g{Ry%J z)vr-3GV_51JC8&!u9ZBv^12r>)%$I{IW%vMEtT4O)2~k;b|lK*G0BXof99y zG&LN}{Fzhg^=f6j(=|$^VMPSe3PcmdJF@C4OX1fWbw7;XK` zw${7TBC-G%PHQXwX7uI)eZVa?#VSS2^40Y?Wis!YUSZ;blR>aa0%@k}o1mrH&!orx zn7%mXM5c2HR`N`O#EJ?W2Ci4k{UPznT(>-ORnb@KdlBxU z(boNd_N~s?p-|h%`vY|H?J|Y(Oz}ql89fEd5zE1u*DvpPRYip!y_g}~m`ksTW)8@u zDn;nPLi`92ciERmahheWB=y=Si?!P|ADp|NH8w{s^i58(=~$9?!_oOW62}>*#H@bY z2@{k8$V=LC+n>hE`j2%x((xWaBSGqghHX5ijKYNt{^11a$=hb4>af|O!`xQprrr_> z@?@&(q|%1@7MsLMo9NwsKDOaDUWh;Bx+$44ia%H;BBL_h9wt{s-IDG-k94gSyM*?| z?|MilF2T%mYzlJ96^aSYop0H7?K4+G!zVU5fKE?b{PrVfzKds<1NPKtwa>UQ6~-^Z z6UZca*D{|JxOHVEh8$7n`z#fAQYP0e3M;J{9y};7%g`4#PS@{W{P;s^nErujl7aRO z#k=0M^0SwESu-e8ujSvwm7kN?(dIX_qAQ@7!vUaUxOf3~6kf}JlEM1nm9e-$S<{j} zA1VC!2^6RYgk7A;zCZJPc{sp>CHBil)@5CJV;j~O4sgpdJpP##1RHhm`3!<(!G_oC z#uuDUe{=KI=W*uvcR8nQog+!d4wtk9)9kj7j+BI%OZg9vjY#KooolI#d$f^DQwyo< zE_9Krcvvg)WprintInfos($info); - require(AT_INCLUDE_PATH.'footer.inc.php'); - exit; -} - -//Handles search queries from side menu -if (isset($_GET['searchFriends']) && $_GET['friendsName']!=''){ - $wanted = $addslashes($_GET['friendsName']); - $friends = searchFriends($wanted, true); -} - -//Handles remove request -if (isset($_GET['remove'])){ - $id = intval($_GET['id']); -// if (isset($_GET['confirm_remove'])){ - removeFriend($id); - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'index.php', AT_PRETTY_URL_IS_HEADER)); - exit; -// } -// $msg->addConfirm("are_you_sure?"); -// header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'index.php?remove=yes'.SEP.'id='.$id.SEP.'confirm_remove=yes')); -} - -//Handles request approval, and rejection -if (isset($_GET['approval'])){ - $id = intval($_GET['id']); - if ($_GET['approval'] == 'y'){ - approveFriendRequest($id); - $sql_notify = "SELECT first_name, last_name, email FROM ".TABLE_PREFIX."members WHERE member_id=$id"; - $result_notify = mysql_query($sql_notify, $db); - $row_notify = mysql_fetch_assoc($result_notify); - - if ($row_notify['email'] != '') { - require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php'); - $body = _AT('notification_accept_contact', get_display_name($_SESSION['member_id']), $_base_href.AT_SOCIAL_BASENAME.'index_mystart.php'); - $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('contact_accepted'); - $mail->Body = $body; - - if(!$mail->Send()) { - $msg->addError('SENDING_ERROR'); - } - unset($mail); - } - - } elseif ($_GET['approval'] == 'n'){ - rejectFriendRequest($id); - } - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'index.php', AT_PRETTY_URL_IS_HEADER)); - exit; -} - -include (AT_INCLUDE_PATH.'header.inc.php'); -$savant->display('pubmenu.tmpl.php'); ?> -
    - assign('activities', $actvity_obj->getFriendsActivities($_SESSION['member_id'])); - $savant->display('activities.tmpl.php'); - - //applications/gagdets - $applications_obj = new Applications(); - $savant->assign('list_of_my_apps', $applications_obj->listMyApplications(true)); - $savant->display('tiny_applications.tmpl.php'); -// echo '
    '; -// echo '
    Applications
    '; -// echo '
    TODO: GADGETS/Applications
    '; -// echo '
    '; - ?> -
    - -
    - assign('friends', $friends); - } else { - $savant->assign('friends', getFriends($_SESSION['member_id'], SOCIAL_FRIEND_HOMEPAGE_MAX)); - } - $savant->assign('group_invitations', getGroupInvitations()); - $savant->assign('group_requests', getGroupRequests()); - $savant->assign('pending_requests', getPendingRequests()); - $savant->display('friend_list.tmpl.php'); - ?> -
    - - - -
    - -
    -

    -
    -
    - $id): ?> -
    -
    - - - <?php echo _AT('add_to_friends'); ?> -
    -
    - -
    -
    - - -

    - getMemberGroups($_SESSION['member_id']); - $random_groups = array(); - for ($i=0; (sizeof($random_groups)assign('my_groups', $random_groups); - $savant->assign('randomize_groups', true); - $savant->display('tiny_sgroups.tmpl.php'); - ?> -
    - - - diff --git a/mods/social/index_admin.php b/mods/social/index_admin.php deleted file mode 100644 index 4b138d29d..000000000 --- a/mods/social/index_admin.php +++ /dev/null @@ -1,49 +0,0 @@ -addFeedback('SOCIAL_SETTINGS_SAVED'); - }else{ - $msg->addError('SOCIAL_SETTINGS_NOT_SAVED'); - } - header("Location: ".$_SERVER['PHP_SELF']); - exit; -} - -require (AT_INCLUDE_PATH.'header.inc.php'); -?> - - -

    -
    -
    -

    -
    -
    -
    -
    - - -
    - \ No newline at end of file diff --git a/mods/social/index_instructor.php b/mods/social/index_instructor.php deleted file mode 100644 index 606a84cb5..000000000 --- a/mods/social/index_instructor.php +++ /dev/null @@ -1,23 +0,0 @@ - - -Hello Instructor!! :) - - \ No newline at end of file diff --git a/mods/social/index_mystart.php b/mods/social/index_mystart.php deleted file mode 100644 index 309fc9ef2..000000000 --- a/mods/social/index_mystart.php +++ /dev/null @@ -1,19 +0,0 @@ - \ No newline at end of file diff --git a/mods/social/index_public.php b/mods/social/index_public.php deleted file mode 100644 index 9e6527e76..000000000 --- a/mods/social/index_public.php +++ /dev/null @@ -1,127 +0,0 @@ -'._AT('suggestions').':
    '; - $counter = 0; - foreach($search_result as $member_id=>$member_array){ - //display 10 suggestions - if ($counter > 10){ - break; - } - - echo ''.printSocialName($member_id, false).'
    '; - $counter++; - } - echo ''; - } - exit; -} - -//safe guard -//No friend request on index_public.. need login -/* -if (isset($_GET['id'])){ - $id = intval($_GET['id']); - if($id > 0){ - addFriendRequest($id); - $msg->addFeedback('REQUEST_FRIEND_ADDED'); - $sql_notify = "SELECT first_name, last_name, email FROM ".TABLE_PREFIX."members WHERE member_id=$id"; - $result_notify = mysql_query($sql_notify, $db); - $row_notify = mysql_fetch_assoc($result_notify); - - if ($row_notify['email'] != '') { - require(AT_INCLUDE_PATH . 'classes/phpmailer/atutormailer.class.php'); - $body = _AT('notification_new_contact', get_display_name($_SESSION['member_id']), $_base_href.AT_SOCIAL_BASENAME.'index_mystart.php'); - $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('contact_request'); - $mail->Body = $body; - - if(!$mail->Send()) { - $msg->addError('SENDING_ERROR'); - } - unset($mail); - } - - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'connections.php', AT_PRETTY_URL_IS_HEADER)); - exit; - } -} -*/ - -//handle search friends request -if(($rand_key!='' && isset($_POST['search_friends_'.$rand_key])) || isset($_GET['search_friends'])){ - if (empty($_POST['search_friends_'.$rand_key]) && !isset($_GET['search_friends'])){ - $msg->addError('CANNOT_BE_EMPTY'); - header('Location: '.url_rewrite(AT_SOCIAL_BASENAME.'index_public.php', AT_PRETTY_URL_IS_HEADER)); - exit; - } - //to adapt paginator GET queries - if($_GET['search_friends']){ - $search_field = $addslashes($_GET['search_friends']); - } else { - $search_field = $addslashes($_POST['search_friends_'.$rand_key]); - } - if (isset($_POST['myFriendsOnly'])){ - //retrieve a list of my friends - $friends = searchFriends($search_field, true); - } else { - //retrieve a list of friends by the search - $friends = searchFriends($search_field); //to calculate the total number. TODO: need a better way, wasting runtime. - $num_pages = max(ceil(sizeof($friends) / SOCIAL_FRIEND_SEARCH_MAX), 1); - $friends = searchFriends($search_field, false, $offset); - } -} - -include(AT_INCLUDE_PATH.'header.inc.php'); -$savant->assign('page', $page); -$savant->assign('num_pages', $num_pages); -$savant->assign('search_field', $search_field); -$savant->assign('friends', $friends); -$savant->assign('rand_key', $rand_key); -$savant->display('index_public.tmpl.php'); -include(AT_INCLUDE_PATH.'footer.inc.php'); -?> \ No newline at end of file diff --git a/mods/social/lib/BasicBlobCrypter.php b/mods/social/lib/BasicBlobCrypter.php deleted file mode 100644 index b9a3ee215..000000000 --- a/mods/social/lib/BasicBlobCrypter.php +++ /dev/null @@ -1,130 +0,0 @@ -cipherKey = 'INSECURE_DEFAULT_KEY'; - $this->hmacKey = 'INSECURE_DEFAULT_KEY'; - $this->allowPlaintextToken = true; - } - - /** - * {@inheritDoc} - */ - public function wrap(Array $in) { - $encoded = $this->serializeAndTimestamp($in); - if (! function_exists('mcrypt_module_open') && $this->allowPlaintextToken) { - $cipherText = base64_encode($encoded); - } else { - $cipherText = Crypto::aes128cbcEncrypt($this->cipherKey, $encoded); - } - $hmac = Crypto::hmacSha1($this->hmacKey, $cipherText); - $b64 = base64_encode($cipherText . $hmac); - return $b64; - } - - private function serializeAndTimestamp(Array $in) { - $encoded = ""; - foreach ($in as $key => $val) { - $encoded .= urlencode($key) . "=" . urlencode($val) . "&"; - } - $encoded .= $this->TIMESTAMP_KEY . "=" . time(); - return $encoded; - } - - /** - * {@inheritDoc} - */ - public function unwrap($in, $maxAgeSec) { - //TODO remove this once we have a better way to generate a fake token in the example files - if ($this->allowPlaintextToken && count(explode(':', $in)) == 6) { - $data = explode(":", $in); - $out = array(); - $out['o'] = $data[0]; - $out['v'] = $data[1]; - $out['a'] = $data[2]; - $out['d'] = $data[3]; - $out['u'] = $data[4]; - $out['m'] = $data[5]; - } else { - $bin = base64_decode($in); - $cipherText = substr($bin, 0, strlen($bin) - Crypto::$HMAC_SHA1_LEN); - $hmac = substr($bin, strlen($cipherText)); - Crypto::hmacSha1Verify($this->hmacKey, $cipherText, $hmac); - if (! function_exists('mcrypt_module_open') && $this->allowPlaintextToken) { - $plain = base64_decode($cipherText); - } else { - $plain = Crypto::aes128cbcDecrypt($this->cipherKey, $cipherText); - } - $out = $this->deserialize($plain); - $this->checkTimestamp($out, $maxAgeSec); - } - return $out; - } - - private function deserialize($plain) { - $map = array(); - $items = split("[&=]", $plain); - for ($i = 0; $i < count($items);) { - $key = urldecode($items[$i ++]); - $value = urldecode($items[$i ++]); - $map[$key] = $value; - } - return $map; - } - - private function checkTimestamp(Array $out, $maxAge) { - $minTime = (int)$out[$this->TIMESTAMP_KEY] - $this->CLOCK_SKEW_ALLOWANCE; - $maxTime = (int)$out[$this->TIMESTAMP_KEY] + $maxAge + $this->CLOCK_SKEW_ALLOWANCE; - $now = time(); - if (! ($minTime < $now && $now < $maxTime)) { - throw new BlobExpiredException("Security token expired"); - } - } -} diff --git a/mods/social/lib/BasicSecurityToken.php b/mods/social/lib/BasicSecurityToken.php deleted file mode 100644 index 858af438b..000000000 --- a/mods/social/lib/BasicSecurityToken.php +++ /dev/null @@ -1,160 +0,0 @@ -token); - } - - /** - * Generates a token from an input string - * @param token String form of token - * @param maxAge max age of the token (in seconds) - * @throws BlobCrypterException - */ - static public function createFromToken($token, $maxAge) { - return new BasicSecurityToken($token, $maxAge, null, null, null, null, null, null); - } - - /** - * Generates a token from an input array of values - * @param owner owner of this gadget - * @param viewer viewer of this gadget - * @param app application id - * @param domain domain of the container - * @param appUrl url where the application lives - * @param moduleId module id of this gadget - * @throws BlobCrypterException - */ - static public function createFromValues($owner, $viewer, $app, $domain, $appUrl, $moduleId) { - return new BasicSecurityToken(null, null, $owner, $viewer, $app, $domain, $appUrl, $moduleId); - } - - public function __construct($token, $maxAge, $owner, $viewer, $app, $domain, $appUrl, $moduleId) { - $this->crypter = $this->getCrypter(); - if (! empty($token)) { - $this->token = $token; - $this->tokenData = $this->crypter->unwrap($token, $maxAge); - } else { - $this->tokenData = array(); - $this->tokenData[$this->OWNER_KEY] = $owner; - $this->tokenData[$this->VIEWER_KEY] = $viewer; - $this->tokenData[$this->APP_KEY] = $app; - $this->tokenData[$this->DOMAIN_KEY] = $domain; - $this->tokenData[$this->APPURL_KEY] = $appUrl; - $this->tokenData[$this->MODULE_KEY] = $moduleId; - $this->token = $this->crypter->wrap($this->tokenData); - } -// debug($this->tokenData); - } - - protected function getCrypter() { - return new BasicBlobCrypter(); - } - - public function isAnonymous() { - return ($this->tokenData[$this->OWNER_KEY] === 0 && $this->tokenData[$this->VIEWER_KEY] === 0); - } - - /** - * {@inheritDoc} - */ - public function getAppId() { - if ($this->isAnonymous()) { - throw new Exception("Can't get appId from an anonymous token"); - } - return $this->tokenData[$this->APP_KEY]; - } - - /** - * {@inheritDoc} - */ - public function getDomain() { - if ($this->isAnonymous()) { - throw new Exception("Can't get domain from an anonymous token"); - } - return $this->tokenData[$this->DOMAIN_KEY]; - } - - /** - * {@inheritDoc} - */ - public function getOwnerId() { - if ($this->isAnonymous()) { - throw new Exception("Can't get ownerId from an anonymous token"); - } - return $this->tokenData[$this->OWNER_KEY]; - } - - /** - * {@inheritDoc} - */ - public function getViewerId() { - if ($this->isAnonymous()) { - throw new Exception("Can't get viewerId from an anonymous token"); - } - return $this->tokenData[$this->VIEWER_KEY]; - } - - /** - * {@inheritDoc} - */ - public function getAppUrl() { - if ($this->isAnonymous()) { - throw new Exception("Can't get appUrl from an anonymous token"); - } - return $this->tokenData[$this->APPURL_KEY]; - } - - /** - * {@inheritDoc} - */ - public function getModuleId() { - if ($this->isAnonymous()) { - throw new Exception("Can't get moduleId from an anonymous token"); - } - if (! is_numeric($this->tokenData[$this->MODULE_KEY])) { - throw new Exception("Module ID should be an integer"); - } - return $this->tokenData[$this->MODULE_KEY]; - } -} diff --git a/mods/social/lib/BlobCrypter.php b/mods/social/lib/BlobCrypter.php deleted file mode 100644 index b6801ee6d..000000000 --- a/mods/social/lib/BlobCrypter.php +++ /dev/null @@ -1,53 +0,0 @@ - $blocksize) { - $key = pack('H*', $hashfunc($key)); - } - $key = str_pad($key, $blocksize, chr(0x00)); - $ipad = str_repeat(chr(0x36), $blocksize); - $opad = str_repeat(chr(0x5c), $blocksize); - $hmac = pack('H*', $hashfunc(($key ^ $opad) . pack('H*', $hashfunc(($key ^ $ipad) . $data)))); - return $hmac; - } -} diff --git a/mods/social/lib/SecurityToken.php b/mods/social/lib/SecurityToken.php deleted file mode 100644 index 7e6ac3db0..000000000 --- a/mods/social/lib/SecurityToken.php +++ /dev/null @@ -1,70 +0,0 @@ -getActivities($userId, $groupId, $appdId, null, null, null, null, 0, 20, $fields, array($activityId), $token); - if ($activities instanceof RestFulCollection) { - $activities = $activities->getEntry(); - foreach ($activities as $activity) { - if ($activity->getId() == $activityId) { - return $activity; - } - } - } - throw new SocialSpiException("Activity not found", ResponseError::$NOT_FOUND); - } - - // public function getActivities($userIds, $groupId, $appId, $sortBy, $filterBy, $filterOp, $filterValue, $startIndex, $count, $fields, $activityIds, $token) { - public function getActivities($userIds, $groupId, $appId, $sortBy, $filterBy, $filterOp, $filterValue, $startIndex, $count, $fields, $token) { - $ids = $this->getIdSet($userIds, $groupId, $token); -// $activities = ATutorDbFetcher::get()->getActivities($ids, $appId, $sortBy, $filterBy, $filterOp, $filterValue, $startIndex, $count, $fields, $activityIds); - $activities = ATutorDbFetcher::get()->getActivities($ids, $appId, $sortBy, $filterBy, $filterOp, $filterValue, $startIndex, $count, $fields); - if ($activities) { - $totalResults = $activities['totalResults']; - $startIndex = $activities['startIndex']; - $count = $activities['count']; - unset($activities['totalResults']); - unset($activities['startIndex']); - unset($activities['count']); - $ret = new RestfulCollection($activities, $startIndex, $totalResults); - $ret->setItemsPerPage($count); - return $ret; - } else { - throw new SocialSpiException("Invalid activity specified", ResponseError::$NOT_FOUND); - } - } - - public function createActivity($userId, $groupId, $appId, $fields, $activity, SecurityToken $token) { - try { - print_r($token); - print_r($token->getOwnerId()); - print_r($token->getViewerId()); - if ($token->getOwnerId() != $token->getViewerId()) { - throw new SocialSpiException("unauthorized: Create activity permission denied.", ResponseError::$UNAUTHORIZED); - } - ATutorDbFetcher::get()->createActivity($userId->getUserId($token), $activity, $token->getAppId()); - } catch (SocialSpiException $e) { - throw $e; - } catch (Exception $e) { - throw new SocialSpiException("Invalid create activity request: " . $e->getMessage(), ResponseError::$INTERNAL_ERROR); - } - } - - public function deleteActivities($userId, $groupId, $appId, $activityIds, SecurityToken $token) { - $ids = $this->getIdSet($userId, $groupId, $token); - if (count($ids) < 1 || count($ids) > 1) { - throw new SocialSpiException("Invalid user id or count", ResponseError::$BAD_REQUEST); - } - if (! ATutorDbFetcher::get()->deleteActivities($ids[0], $appId, $activityIds)) { - throw new SocialSpiException("Invalid activity id(s)", ResponseError::$NOT_FOUND); - } - } -} -?> \ No newline at end of file diff --git a/mods/social/lib/Shindig/ATutorAppDataService.php b/mods/social/lib/Shindig/ATutorAppDataService.php deleted file mode 100644 index 35f6b0aa2..000000000 --- a/mods/social/lib/Shindig/ATutorAppDataService.php +++ /dev/null @@ -1,74 +0,0 @@ -getIdSet($userId, $groupId, $token); - if (count($ids) < 1) { - throw new InvalidArgumentException("No userId specified"); - } elseif (count($ids) > 1) { - throw new InvalidArgumentException("Multiple userIds not supported"); - } - $userId = $ids[0]; - $appId = $token->getAppId(); - if ($fields == null) { - if (! ATutorDbFetcher::get()->deleteAppData($userId, '*', $appId)) { - throw new SocialSpiException("Internal server error", ResponseError::$INTERNAL_ERROR); - } - } else { - foreach ($fields as $key) { - if (! self::isValidKey($key) && $key != '*') { - throw new SocialSpiException("The person app data key had invalid characters", ResponseError::$BAD_REQUEST); - } - } - foreach ($fields as $key) { - if (! ATutorDbFetcher::get()->deleteAppData($userId, $key, $appId)) { - throw new SocialSpiException("Internal server error", ResponseError::$INTERNAL_ERROR); - } - } - } - } - - public function getPersonData($userId, GroupId $groupId, $appId, $fields, SecurityToken $token) { - $ids = $this->getIdSet($userId, $groupId, $token); - $data = ATutorDbFetcher::get()->getAppData($ids, $fields, $appId); - // If the data array is empty, return empty DataCollection. - return new DataCollection($data); - } - - public function updatePersonData(UserId $userId, GroupId $groupId, $appId, $fields, $values, SecurityToken $token) { - if ($userId->getUserId($token) == null) { - throw new SocialSpiException("Unknown person id.", ResponseError::$NOT_FOUND); - } - foreach ($fields as $key) { - if (! self::isValidKey($key)) { - throw new SocialSpiException("The person app data key had invalid characters", ResponseError::$BAD_REQUEST); - } - } - switch ($groupId->getType()) { - case 'self': - foreach ($fields as $key) { - $value = isset($values[$key]) ? $values[$key] : null; - if (! ATutorDbFetcher::get()->setAppData($userId->getUserId($token), $key, $value, $token->getAppId())) { - throw new SocialSpiException("Internal server error", ResponseError::$INTERNAL_ERROR); - } - } - break; - default: - throw new SocialSpiException("We don't support updating data in batches yet", ResponseError::$NOT_IMPLEMENTED); - break; - } - } -} -?> \ No newline at end of file diff --git a/mods/social/lib/Shindig/ATutorDbFetcher.php b/mods/social/lib/Shindig/ATutorDbFetcher.php deleted file mode 100644 index 6633e9c2d..000000000 --- a/mods/social/lib/Shindig/ATutorDbFetcher.php +++ /dev/null @@ -1,812 +0,0 @@ -'; - if ($title) { - echo '

    '.$title.'

    '; - } - - ob_start(); - print_r($var); - $str = ob_get_contents(); - ob_end_clean(); - - $str = str_replace('<', '<', $str); - - $str = str_replace('[', '[', $str); - $str = str_replace(']', ']', $str); - $str = str_replace('=>', '=>', $str); - $str = str_replace('Array', 'Array', $str); - echo $str; - echo '
    '; -} - - /** - * Get the set of user id's from a user or collection of users, and group - */ - protected function getIdSet($user, GroupId $group, SecurityToken $token) { - $ids = array(); - if ($user instanceof UserId) { - $userId = $user->getUserId($token); - if ($group == null) { - return array($userId); - } - switch ($group->getType()) { - case 'all': - case 'friends': - case 'groupId': - $friendIds = ATutorDbFetcher::get()->getFriendIds($userId); - if (is_array($friendIds) && count($friendIds)) { - $ids = $friendIds; - } - break; - case 'self': - $ids[] = $userId; - break; - } - } elseif (is_array($user)) { - $ids = array(); - foreach ($user as $id) { - $ids = array_merge($ids, $this->getIdSet($id, $group, $token)); - } - } - return $ids; - } - - /** - * Determines whether the input is a valid key. Valid keys match the regular - * expression [\w\-\.]+. - * - * @param key the key to validate. - * @return true if the key is a valid appdata key, false otherwise. - */ - public static function isValidKey($key) { - if (empty($key)) { - return false; - } - for ($i = 0; $i < strlen($key); ++ $i) { - $c = substr($key, $i, 1); - if (($c >= 'a' && $c <= 'z') || ($c >= 'A' && $c <= 'Z') || ($c >= '0' && $c <= '9') || ($c == '-') || ($c == '_') || ($c == '.')) { - continue; - } - return false; - } - return true; - } - - protected function sortPersonResults(&$people, $options) { - if (! $options->getSortBy()) { - return true; // trivially sorted - } - // for now, ATutor can only sort by displayName, which also demonstrates returning sorted: false - if ($options->getSortBy() != 'displayName') { - return false; - } - usort($people, array($this, 'comparator')); - if ($options->getSortOrder() != CollectionOptions::SORT_ORDER_ASCENDING) { - $people = array_reverse($people); - } - return true; - } - - protected function comparator($person, $person1) { - $name = ($person instanceof Person ? $person->getDisplayName() : $person['displayName']); - $name1 = ($person1 instanceof Person ? $person1->getDisplayName() : $person1['displayName']); - return strnatcasecmp($name, $name1); - } -} diff --git a/mods/social/lib/Shindig/README b/mods/social/lib/Shindig/README deleted file mode 100644 index 1f170e3ff..000000000 --- a/mods/social/lib/Shindig/README +++ /dev/null @@ -1,4 +0,0 @@ -ATutor Service Provider Interface, SPI. -In simplicity, these files provide services for the gadgets. - -Check shindig/php/src/social/spi/*Service.php for more Details diff --git a/mods/social/lib/classes/Activity.class.php b/mods/social/lib/classes/Activity.class.php deleted file mode 100644 index 48a86942e..000000000 --- a/mods/social/lib/classes/Activity.class.php +++ /dev/null @@ -1,151 +0,0 @@ - 0){ - $app_string = ", application_id=$app_id"; - //overwrite title with an automated message - $title = $this->generateApplicationTitle($app_id); - } - - if ($id > 0 && $title!=''){ - $sql = 'INSERT INTO '.TABLE_PREFIX."social_activities SET member_id=$id, title='$title'".$app_string; - mysql_query($sql, $db); - } - } - - - /** - * Retrieve this user's activity - * - * @param int user id. - * @param boolean set TRUE to display all entry - * @return The array of description of all the activities from the given user. - */ - function getActivities($id, $displayAll=false){ - global $db; - $activities = array(); - $id = intval($id); - if ($id > 0){ - $sql = 'SELECT * FROM '.TABLE_PREFIX."social_activities WHERE member_id=$id ORDER BY created_date DESC"; - if (!$displayAll){ - $sql .= ' LIMIT '.SOCIAL_FRIEND_ACTIVITIES_MAX; - } - $result = mysql_query($sql, $db); - if ($result){ - while($row = mysql_fetch_assoc($result)){ - $activities[$row['id']]['member_id'] = $row['member_id']; - $activities[$row['id']]['title'] = $row['title']; - $activities[$row['id']]['created_date'] = $row['created_date']; - } - } - return $activities; - } - return; - } - - - /** - * Remove an activity - * - * @param int user id - * @return true if activity is deleted. - */ - function deleteActivity($id){ - global $db; - - $id = intval($id); - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_activities WHERE member_id='.$_SESSION['member_id'].' AND id='.$id; - mysql_query($sql, $db); - if (mysql_affected_rows() > 0){ - return true; - } else { - return false; - } - } - - - /** - * Retrieve friends' recent activities - * - * @param int user id - * @param boolean set TRUE to display all entry - * @return The array of description of all the activities of the given user's friends. - */ - function getFriendsActivities($id, $displayAll=false){ - global $db; - $activities = array(); - - $friends = getFriends($id); - $friends_ids = implode(', ', array_keys($friends)); - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_activities WHERE member_id IN ('.$friends_ids.') ORDER BY created_date DESC'; - if (!$displayAll){ - $sql .= ' LIMIT '.SOCIAL_FRIEND_ACTIVITIES_MAX; - } - $result = mysql_query($sql, $db); - - if ($result){ - while($row = mysql_fetch_assoc($result)){ - $activities[$row['id']]['member_id'] = $row['member_id']; - $activities[$row['id']]['title'] = $row['title']; - $activities[$row['id']]['created_date'] = $row['created_date']; - } - } - return $activities; - } - - - /** - * Generate the title string for application. - * - * @param int application id - * @return the title string that has a hyperlink to the application itself. - */ - function generateApplicationTitle($app_id){ - global $db; - $app_id = intval($app_id); - - //This here, it is actually better to use $url instead of app_id. - //$url is the primary key. $id is also a key, but it is not guranteed that it will be unique - $sql = 'SELECT title FROM '.TABLE_PREFIX."social_applications WHERE id=$app_id"; - $result = mysql_query($sql, $db); - $row = mysql_fetch_assoc($result); - - $msg = _AT("has_added_app", url_rewrite(AT_SOCIAL_BASENAME.'applications.php?app_id='.$app_id), - htmlentities_utf8($row['title'])); - return $msg; - } -} -?> diff --git a/mods/social/lib/classes/Application.class.php b/mods/social/lib/classes/Application.class.php deleted file mode 100644 index 2121c2658..000000000 --- a/mods/social/lib/classes/Application.class.php +++ /dev/null @@ -1,398 +0,0 @@ -id = $id; - $this->getApplicationPrefs(); - } - } - - /* - * Add application by URL - * @param object gadget object retrieved from JSON + cURL - */ - function addApplication($gadget_obj){ - global $db, $addslashes; - - //TODO: Many more fields to add -// $id = $gadget_obj['moduleId']; //after i change the URL to the key. - $author = $addslashes($gadget_obj->author); - $author_email = $addslashes($gadget_obj->authorEmail); - $description = $addslashes($gadget_obj->description); - $screenshot = $addslashes($gadget_obj->screenshot); - $thumbnail = $addslashes($gadget_obj->thumbnail); - $title = $addslashes($gadget_obj->title); - $height = intval($gadget_obj->height); - $module_id = intval($gadget_obj->module_id); - $url = $addslashes($gadget_obj->url); - $userPrefs = $addslashes(serialize($gadget_obj->userPrefs)); - $views = $addslashes(serialize($gadget_obj->views)); - - //determine next id - $sql = 'SELECT MAX(id) AS max_id FROM '.TABLE_PREFIX.'social_applications'; - $result = mysql_query($sql, $db); - if ($result){ - $row = mysql_fetch_assoc($result); - $id = $row['max_id'] + 1; - } else { - $id = 1; - } - $member_id = $_SESSION['member_id']; - - $sql = 'INSERT INTO '.TABLE_PREFIX."social_applications (id, url, title, height, screenshot, thumbnail, author, author_email, description, settings, views, last_updated) VALUES ($id, '$url', '$title', $height, '$screenshot', '$thumbnail', '$author', '$author_email', '$description', '$userPrefs', '$views', NOW())"; - $result = mysql_query($sql, $db); - - //This application is already in the database, get its ID out - if (!$result){ - $sql = 'SELECT id, UNIX_TIMESTAMP(last_updated) AS last_updated FROM '.TABLE_PREFIX."social_applications WHERE url='$url'"; - $result = mysql_query($sql, $db); - $row = mysql_fetch_assoc($result); - $id = $row['id']; - - //Update the gadget - //TODO: Needs some sort of comparing instead of blinding updating everytime. Version(can't find any)? Date(need another field in db?) - //Use TIMESTAMP for now, but i perfer version #. - //If the gadget is SOCIAL_APPLICATION_UPDATE_SCHEDULE days old, update it - if (abs($row['last_updated']) < strtotime('-'.SOCIAL_APPLICATION_UPDATE_SCHEDULE.' day')){ - $sql = 'UPDATE '.TABLE_PREFIX."social_applications SET title='$title', height=$height, screenshot='$screenshot', thumbnail='$thumbnail', author='$author', author_email='$author_email', description='$description', settings='$userPrefs', views='$views', last_updated=NOW() WHERE url='$url'"; - $result = mysql_query($sql, $db); - //echo $sql; - } - } - - //Add a record into application_member table for mapping - $this->addMemberApplication($member_id, $id); - } - - - /** - * Add this application to the member's application list - * @param int member_id - * @param int application_id - */ - function addMemberApplication($member_id, $app_id){ - global $db; - - $member_id = intval($member_id); - $app_id = intval($app_id); - - $sql = 'INSERT INTO '.TABLE_PREFIX."social_members_applications (member_id, application_id) VALUES ($member_id, $app_id)"; - $result = mysql_query($sql, $db); - - if ($result){ - //Add this to the home page - $home_settings = $this->getHomeDisplaySettings(); - $home_settings[$app_id] = 1; //manually set this application - $this->setHomeDisplaySettings($home_settings); - - $act = new Activity(); - $act->addActivity($_SESSION['member_id'], '', $app_id); - unset($act); - } - } - - - /** - * Parse application details - * @return array of the attributes - * - */ - function parseModulePrefs($app_url){ - //parse all the attributes of the tag - //and save everything in the object. - $gadget = $this->fetch_gadget_metadata($app_url); - return $gadget->gadgets; - } - - - // Restful - JSON CURL data transfer - private function fetch_gadget_metadata($app_url) { - $request = json_encode(array( - 'context' => array('country' => 'US', 'language' => 'en', 'view' => 'default', - 'container' => 'atutor'), - 'gadgets' => array(array('url' => $app_url, 'moduleId' => '1')))); - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, AT_SHINDIG_URL.'/gadgets/metadata'); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_AUTOREFERER, 1); - curl_setopt($ch, CURLOPT_MAXREDIRS, 10); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 4); - curl_setopt($ch, CURLOPT_TIMEOUT, 20); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, 'request=' . urlencode($request)); - $content = @curl_exec($ch); - return json_decode($content); - } - - - /** - * Add application perferences into the table. - * @param int member id - * @param string hash's key, usually the name of the application - * @param string hash's value, contains key, value, and st. - * @return true(1) if the perference has been updated, false(0) otherwise. - */ - function setApplicationSettings($member_id, $key, $value){ - global $addslashes, $db; - - $app_id = $this->id; - $member_id = intval($member_id); - $key = $addslashes($key); - $value = $addslashes($value); - - $sql = 'INSERT INTO '.TABLE_PREFIX."social_application_settings (application_id, member_id, name, value) VALUES ($app_id, $member_id, '$key', '$value') ON DUPLICATE KEY UPDATE value='$value'"; - $result = mysql_query($sql, $db); - - //TODO: Might want to add something here to throw appropriate exceptions - return $result; - } - - - /** - * Get member's applications - * @param int the member id - */ - function getMemberApplications($member_id){ - global $db; - $result = array(); - - $member_id = intval($member_id); - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_members_applications WHERE member_id='.$member_id; - $rs = mysql_query($sql, $db); - if ($rs){ - while($row = mysql_fetch_assoc($rs)){ - $result[] = $row['app_id']; - } - } - return $result; - } - - - /** - * Get user perferences for this application - * @return array - */ - function getApplicationSettings($member_id){ - global $db; - $result = array(); - $member_id = intval($member_id); - - $sql = 'SELECT * FROM '.TABLE_PREFIX."social_application_settings WHERE member_id=$member_id AND application_id=".$this->id; - $rs = mysql_query($sql); - if ($rs){ - //loop cause an application can have multiple pairs of key=>value - while ($row = mysql_fetch_assoc($rs)){ - $result[$row['name']] = $row['value']; - } - } - return $result; - } - - function getId(){ - return $this->id; - } - - function getUrl(){ - return $this->url; - } - - function getTitle(){ - return $this->title; - } - - function getModuleId(){ - return intval($this->module_id); - } - - function getHeight(){ - if ($this->height==0){ - return 600; - } - return $this->height; - } - - function getScreenshot(){ - return $this->screenshot; - } - - function getThumbnail(){ - //check if this thumbnail link is a relative link - $url = parse_url($this->thumbnail); - if (!isset($url['scheme']) && !isset($url['host'])){ - $orig_url = parse_url($this->getUrl()); - return $orig_url['scheme'].'://'.$orig_url['host'].$this->thumbnail; - } - return $this->thumbnail; - } - - function getAuthor(){ - return $this->author; - } - - function getAuthorEmail(){ - return $this->author_email; - } - - function getDescription(){ - return $this->description; - } - - function getSettings(){ - return unserialize($this->settings); - } - - function getViews(){ - return unserialize($this->views); - } - - /** - * Return iframe URL based on the given parameters - * @param int owner id - * @param string avaiable options are 'profile', 'canvas' - * http://code.google.com/apis/orkut/docs/orkutdevguide/orkutdevguide-0.8.html#ops_mode - * @param string extra application parameters - * @return iframe url - */ - function getIframeUrl($oid, $view='profile', $appParams=''){ - //let view=profile as default option - if ($view!='profile' && $view!='canvas'){ - $view = 'profile'; - } - - $app_settings = $this->getSettings(); - $user_settings = $this->getApplicationSettings($_SESSION['member_id']); - - //retrieve user preferences - foreach ($app_settings as $key => $setting) { - if (! empty($key)) { - $value = isset($user_settings[$key]) ? $user_settings[$key] : (isset($setting->default) ? $setting->default : null); - if (isset($user_settings[$key])) { - unset($user_settings[$key]); - } - //shindig doesn't like ';', it only takes '&' as of Apr 6th, 2009 - //$prefs .= SEP.'up_' . urlencode($key) . '=' . urlencode($value); - $prefs .= '&up_' . urlencode($key) . '=' . urlencode($value); - } - } - foreach ($user_settings as $name => $value) { - // if some keys _are_ set in the db, but not in the gadget metadata, we still parse them on the url - // (the above loop unsets the entries that matched - if (! empty($value) && ! isset($appParams[$name])) { - //shindig doesn't like ';', it only takes '&' as of Apr 6th, 2009 - //$prefs .= SEP.'up_' . urlencode($name) . '=' . urlencode($value); - $prefs .= '&up_' . urlencode($name) . '=' . urlencode($value); - } - } - - //generate security token - $securityToken = BasicSecurityToken::createFromValues(($oid > 0?$oid:$_SESSION['member_id']), // owner - $_SESSION['member_id'], // viewer - $this->getId(), // app id - 'default', // domain key, shindig will check for php/config/.php for container specific configuration - urlencode($this->getUrl()), // app url - $this->getModuleId());// mod id -//debug($securityToken); - $url = AT_SHINDIG_URL.'/gadgets/ifr?' - . "synd=default" - . "&container=default" - . "&viewer=". $_SESSION['member_id'] - . "&owner=" . $oid - . "&aid=" . $this->getId() //application id - . "&mid=" . $this->getModuleId() //not sure what mod_id is - . "&country=US" - . "&lang=en" - . "&view=" . $view //canvas for this big thing, should be a variable - . "&parent=" . urlencode("http://" . $_SERVER['HTTP_HOST']) . $prefs . (isset($appParams) ? '&view-params=' . urlencode($appParams) : '') - . "&st=" . urlencode(base64_encode($securityToken->toSerialForm())) - . "&v=" . $this->getVersion() - . "&url=" . urlencode($this->getUrl()) . "#rpctoken=" . rand(0, getrandmax()); - return $url; - } - - //TO BE IMPLEMENTED - function getVersion(){ - return '0.1'; - } - - - /** - * Retrieve all information about this gadget and save it in the object - * @private - */ - function getApplicationPrefs(){ - global $db; - - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_applications WHERE id='.$this->id; - $rs = mysql_query($sql); - - if ($rs){ - $row = mysql_fetch_assoc($rs); - //assign values - $this->url = $row['url']; - $this->title = $row['title']; - $this->height = $row['height']; - $this->screenshot = $row['screenshot']; - $this->thumbnail = $row['thumbnail']; - $this->author = $row['author']; - $this->author_email = $row['author_email']; - $this->description = $row['description']; - $this->settings = $row['settings']; - $this->views = $row['views']; - $this->last_updated = $row['last_updated']; - } - } - - /** - * Delete an application - */ - function deleteApplication(){ - global $db; - - //delete application mapping - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_members_applications WHERE application_id='.$this->id.' AND member_id='.$_SESSION['member_id']; - $rs = mysql_query($sql); - - //delete application data? - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_application_settings WHERE application_id='.$this->id.' AND member_id='.$_SESSION['member_id']; - $rs = mysql_query($sql); - - //delete application settings - $home_settings = $this->getHomeDisplaySettings(); - if (isset($home_settings[$this->id])){ - unset($home_settings[$this->id]); - $this->setHomeDisplaySettings($home_settings); - } - - return $rs; - } -} -?> \ No newline at end of file diff --git a/mods/social/lib/classes/Applications.class.php b/mods/social/lib/classes/Applications.class.php deleted file mode 100644 index 613a19f06..000000000 --- a/mods/social/lib/classes/Applications.class.php +++ /dev/null @@ -1,120 +0,0 @@ -app obj - */ - function listMyApplications($use_settings=false){ - global $db; - $hash = array(); - - $sql = 'SELECT id, title FROM '.TABLE_PREFIX.'social_applications a, (SELECT application_id FROM '.TABLE_PREFIX.'social_members_applications WHERE member_id='.$_SESSION['member_id'].') AS apps WHERE a.id=apps.application_id'; - $result = mysql_query($sql, $db); - $home_settings = $this->getHomeDisplaySettings(); - if ($result){ - while($row = mysql_fetch_assoc($result)){ - $app = new Application($row['id']); - if($use_settings){ - if(!isset($home_settings[$row['id']])){ - continue; - } - } - $hash[$row['id']] = $app; - } - } - return $hash; - } - - /** - * Retrieve a list of all installed applications - */ - function listApplications(){ - global $db; - $hash = array(); - - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_applications'; - $result = mysql_query($sql, $db); - - while ($row = mysql_fetch_assoc($result)){ - $hash[$row['id']] = new Application($row['id']); - } - return $hash; - } - - - /** - * Delete applications - * @param array array of application_id to be deleted. - */ - function deleteApplications($ids){ - global $db; - $id_list = implode(', ', $ids); - $sql = 'DELETE FROM '.TABLE_PREFIX."social_applications WHERE id IN ($id_list)"; - mysql_query($sql, $db); - } - - /** - * To determine which application to show on the home tab - * Save the settings in serialized format. - * @param mixed settings array. [note: upgrade this to an object if needed later on] - */ - function setHomeDisplaySettings($settings){ - global $db, $addslashes; - $settings = $addslashes(serialize($settings)); - $sql = 'REPLACE INTO '.TABLE_PREFIX."social_user_settings SET app_settings='".$settings."', member_id=".$_SESSION['member_id']; - $result = mysql_query($sql, $db); - } - - - /** - * Return the link of an application by the given id. - * @param string the title/name of this application - * @param int application id - * @return THe tag link of the requested application. - */ - function getAppLink($title, $id){ - return '' . $title . ''; - } - - - /** - * Get the home display setting - * @return array of settings that define which gadget to be displayed on the social home page. - */ - function getHomeDisplaySettings(){ - global $db; - $sql = 'SELECT app_settings FROM '.TABLE_PREFIX.'social_user_settings WHERE member_id='.$_SESSION['member_id']; - $rs = mysql_query($sql, $db); - if ($rs){ - list($settings) = mysql_fetch_array($rs); - } - return unserialize($settings); - } - -} -?> \ No newline at end of file diff --git a/mods/social/lib/classes/Member.class.php b/mods/social/lib/classes/Member.class.php deleted file mode 100644 index 5db83fc55..000000000 --- a/mods/social/lib/classes/Member.class.php +++ /dev/null @@ -1,478 +0,0 @@ -id = intval($id); - } - - - /** - * Add a new job position - * @param string Name of the company, in full. - * @param string Title of this position - * @param int Started date for this position, in the format of yyyymm - * @param int Position ended on this date, in the format of yyyymm, or 'NOW'. - * 'NOW' means it is still on going. - * @param string Description of what the position was about - */ - function addPosition($company, $title, $from, $to, $description){ - global $addslashes, $db; - $member_id = $this->id; - $company = $addslashes($company); - $title = $addslashes($title); - $from = $addslashes($from); - $to = $addslashes($to); - $description = $addslashes($description); - - $sql = 'INSERT INTO '.TABLE_PREFIX."social_member_position (member_id, company, title, `from`, `to`, description) VALUES ($member_id, '$company', '$title', '$from', '$to', '$description')"; - mysql_query($sql, $db); - } - - - /** - * Add a new education - * TODO: University names can be generated from another table. - * - * @param string Name of the University, in full. Might need to pull from another table. - * @param int This education begins on this date, yyyymm - * @param int This education ends on this date, yyyymm, or can be 'NOW' - * @param string The full name of the country this University is in, ie. Canada - * @param string The full name of the province this University is in, ie. Ontario - * @param string The name of the degree, ie. B.Sc. - * @param string The field of study, ie. Computer Science - * @param string The description of this education. - */ - function addEducation($university, $from, $to, $country, - $province, $degree, $field, $description){ - global $addslashes, $db; - $member_id = $this->id; - $university = $addslashes($university); - $from = $addslashes($from); - $to = $addslashes($to); - $country = $addslashes($country); - $province = $addslashes($province); - $degree = $addslashes($degree); - $field = $addslashes($field); - $description = $addslashes($description); - - $sql = 'INSERT INTO '.TABLE_PREFIX."social_member_education (member_id, university, `from`, `to`, country, province, degree, field, description) VALUES ($member_id, '$university', '$from', '$to', '$country', '$province', '$degree', '$field', '$description')"; - mysql_query($sql, $db); - } - - - /** - * Add a new website associated with this member, can be blog, work, portfolio, etc. - * @param string Unique URL of the website - * @param string A name for the website. - */ - function addWebsite($url, $site_name){ - global $addslashes, $db; - $member_id = $this->id; - $url = urlencode($url); - $site_name = $addslashes($site_name); - - $sql = 'INSERT INTO '. TABLE_PREFIX ."social_member_websites (member_id, url, site_name) VALUES ($member_id, '$url', '$site_name')"; - mysql_query($sql, $db); - } - - - /** - * Add new interest for this member, in CSV format - * @param string interest - */ - function addInterests($interests){ - $this->updateAdditionalInformation($interests); - } - - - /** - * Add new interest for this member, in CSV format - * @param string interest - */ - function addAssociations($associations){ - $this->updateAdditionalInformation('', $associations); - } - - - /** - * Add new interest for this member, in CSV format - * @param string interest - */ - function addAwards($awards){ - $this->updateAdditionalInformation('', '', $awards); - } - - - /** - * Add additional information, including interest, awards, associations. - * @param string CSV format of interests, ie. camping, biking, etc - * @param string CSV format of associations, clubs, groups, ie. IEEE - * @param string CSV format of awards, honors - * @param string expterise, occupation - * @param string any extra information - */ - function addAdditionalInformation($interests, $associations, $awards, $expertise, $others){ - global $addslashes, $db; - $member_id = $this->id; - $interests = $addslashes($interests); - $associations = $addslashes($associations); - $awards = $addslashes($awards); - $expertise = $addslashes($expertise); - $others = $addslashes($others); - $sql = 'INSERT INTO ' . TABLE_PREFIX . "social_member_additional_information (member_id, interests, associations, awards, expertise, others) VALUES ($member_id, '$interests', '$associations', '$awards', '$expertise', '$others')"; - mysql_query($sql, $db); - } - - - /** - * Add visitor - * @param int visitor id - */ - function addVisitor($visitor_id){ - global $db; - $visitor_id = intval($visitor_id); - $sql = 'INSERT INTO '.TABLE_PREFIX."social_member_track (`member_id`, `visitor_id`, `timestamp`) VALUES (".$this->getID().", $visitor_id, NOW())"; - mysql_query($sql, $db); - } - - - /** - * Update a new job position - * @param int The id of this entry - * @param string Name of the company, in full. - * @param string Tht title of this position - * @param int Started date for this position, in the format of yyyymm - * @param int Position ended on this date, in the format of yyyymm, or 'NOW'. - * 'NOW' means it is still on going. - * @param string Description of the position - */ - function updatePosition($id, $company, $title, $from, $to, $description){ - global $addslashes, $db; - $id = intval($id); - $company = $addslashes($company); - $title = $addslashes($title); - $form = $addslashes($form); - $to = $addslashes($to); - $description = $addslashes($description); - - $sql = 'UPDATE '.TABLE_PREFIX."social_member_position SET company='$company', title='$title', `from`='$from', `to`='$to', description='$description' WHERE id=$id"; - mysql_query($sql, $db); - } - - - /** - * Update a new education - * TODO: University names can be generated from another table. - * - * @param int ID of this entry - * @param string Name of the University, in full. Might need to pull from another table. - * @param int This education begins on this date, yyyymm - * @param int This education ends on this date, yyyymm, or can be 'NOW' - * @param string The full name of the country this University is in, ie. Canada - * @param string The full name of the province this University is in, ie. Ontario - * @param string The name of the degree, ie. B.Sc. - * @param string The field of study, ie. Computer Science - * @param string The description of this education. - */ - function updateEducation($id, $university, $from, $to, $country, $province, $degree, $field, $description){ - global $addslashes, $db; - $id = intval($id); - $university = $addslashes($university); - $from = $addslashes($from); - $to = $addslashes($to); - $country = $addslashes($country); - $province = $addslashes($province); - $degree = $addslashes($degree); - $field = $addslashes($field); - $description = $addslashes($description); - - $sql = 'UPDATE '.TABLE_PREFIX."social_member_education SET university='$university', `from`='$from', `to`='$to', country='$country', province='$province', degree='$degree', field='$field', description='$description' WHERE id=$id"; - mysql_query($sql, $db); - } - - - /** - * Updates a new website associated with this member, can be blog, work, portfolio, etc. - * @param int ID of this entry - * @param string Unique URL of the website - * @param string A name for the website. - */ - function updateWebsite($id, $url, $site_name){ - global $addslashes, $db; - $id = intval($id); - $url = $addslashes($url); - $site_name = $addslashes($site_name); - - $sql = 'UPDATE '.TABLE_PREFIX."social_member_websites SET url='$url', site_name='$site_name' WHERE id=$id"; - mysql_query($sql, $db); - } - - - /** - * Update additional information, including interest, awards, associations. - * @param string CSV format of interests, ie. camping, biking, etc - * @param string CSV format of associations, clubs, groups, ie. IEEE - * @param string CSV format of awards, honors - * @param string expterise, occupation - * @param string any extra information - */ - function updateAdditionalInformation($interests='', $associations='', $awards='', $expertise='', $others=''){ - global $addslashes, $db; - $interests = $addslashes($interests); - $associations = $addslashes($associations); - $awards = $addslashes($awards); - $expertise = $addslashes($expertise); - $others = $addslashes($others); - - $sql = ''; - //tricky, not all fields get updated at once. Update only the ones that has entries. - if ($interests!=''){ - $sql .= "interests='$interests', "; - } - if ($associations!=''){ - $sql .= " associations='$associations', "; - } - if ($awards!=''){ - $sql .= "awards='$awards', "; - } - if ($expertise!=''){ - $sql .= "expertise='$expertise', "; - } - if ($others!=''){ - $sql .= "others='$others', "; - } - if ($sql!=''){ - $sql = substr($sql, 0, -2); - } - - $sql2 = 'INSERT INTO '.TABLE_PREFIX."social_member_additional_information SET ".$sql.", member_id=".$_SESSION['member_id'] . " ON DUPLICATE KEY UPDATE ".$sql; - mysql_query($sql2, $db); - } - - - /** - * Get member info - * This method tends to be have a negative impact on system run time. - */ - function getDetails(){ - global $db; - $sql = 'SELECT core.*, T.interests, T.associations, T.awards, T.expertise, T.others FROM '. - '(SELECT * FROM '.TABLE_PREFIX.'members WHERE member_id='.$this->id.') AS core '. - 'LEFT JOIN '. - TABLE_PREFIX.'social_member_additional_information T ON core.member_id=T.member_id'; - $result = mysql_query($sql, $db); - if ($result){ - $row = mysql_fetch_assoc($result); - $this->profile = $row; - } - return $this->profile; - } - - - /** - * Get member address - */ - function getAddress(){ - global $db; - $sql = 'SELECT address, postal, city, province, country FROM '.TABLE_PREFIX.'members WHERE member_id='.$this->id; - $result = mysql_query($sql, $db); - if ($result){ - $row = mysql_fetch_assoc($result); - } - return $row; - } - - - /** - * Get position info - * @return the array of job/position - */ - function getPosition(){ - global $db; - $position = array(); - - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_member_position WHERE member_id='.$this->id; - $result = mysql_query($sql, $db); - if ($result){ - while($row = mysql_fetch_assoc($result)){ - $position[] = $row; - } - } - return $position; - } - - - /** - * Get education info - * can be 1+ - * @return the array of education details - */ - function getEducation(){ - global $db; - $education = array(); - - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_member_education WHERE member_id='.$this->id; - $result = mysql_query($sql, $db); - if ($result){ - while($row = mysql_fetch_assoc($result)){ - $education[] = $row; - } - } - return $education; - } - - - /** - * Get websites. can be 1+ - * @return the array of website details. - */ - function getWebsites(){ - global $db; - $websites = array(); - - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_member_websites WHERE member_id='.$this->id; - $result = mysql_query($sql, $db); - if ($result){ - while($row = mysql_fetch_assoc($result)){ - $websites[] = $row; - } - } - return $websites; - } - - - /** - * Get visitor counts within a month, the resultant array contains a daily, weekly, monthly, and a total count. - * @return the count of all visitors on this page, within a month. - */ - function getVisitors(){ - global $db; - $count = array('month'=>0, 'week'=>0, 'day'=>0, 'total'=>0); - //Time offsets - $month = time() - 60*60*24*30; //month, within 30days. - $week = time() - 60*60*24*7; //week, within 7 days. - $day = time() - 60*60*24; //day, within 24 hours. - - $sql = 'SELECT visitor_id, UNIX_TIMESTAMP(timestamp) AS `current_time` FROM '.TABLE_PREFIX.'social_member_track WHERE member_id='.$this->id; - $result = mysql_query($sql, $db); - if ($result){ - while ($row = mysql_fetch_assoc($result)){ - if($row['current_time'] >= $month && $row['current_time'] <= $week){ - $count['month']++; - } elseif ($row['current_time'] > $week && $row['current_time'] <= $day){ - $count['week']++; - } elseif ($row['current_time'] > $day){ - $count['day']++; - } else { - continue; - } - $count['total']++; - } - } - - //clean up table randomly, 1% - if (rand(1,100) == 1){ - $sql = 'DELETE FROM '.TABLE_PREFIX."social_member_track WHERE UNIX_TIMESTAMP(`timestamp`) < $month"; - mysql_query($sql, $db); - } - - return $count; - } - - - /** - * Delete position - * @param int position id - */ - function deletePosition($id){ - global $db; - - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_member_position WHERE id='.$id; - $result = mysql_query($sql, $db); - } - - - /** - * Delete education - * @param int education id - */ - function deleteEducation($id){ - global $db; - - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_member_education WHERE id='.$id; - $result = mysql_query($sql, $db); - } - - - /** - * Delete websites - * @param int websites id - */ - function deleteWebsite($id){ - global $db; - - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_member_websites WHERE id='.$id; - $result = mysql_query($sql, $db); - } - - - /** - * Delete interest - */ - function deleteInterests(){ - global $db; - - $sql = 'UPDATE '.TABLE_PREFIX."social_member_additional_information SET interests='' WHERE member_id=".$this->getID(); - $result = mysql_query($sql, $db); - } - - - /** - * Delete associations - */ - function deleteAssociations(){ - global $db; - - $sql = 'UPDATE '.TABLE_PREFIX."social_member_additional_information SET associations='' WHERE member_id=".$this->getID(); - $result = mysql_query($sql, $db); - } - - - /** - * Delete awards - */ - function deleteAwards(){ - global $db; - - $sql = 'UPDATE '.TABLE_PREFIX."social_member_additional_information SET awards='' WHERE member_id=".$this->getID(); - $result = mysql_query($sql, $db); - } - - - /** - * Get the ID of this member - */ - function getID(){ - return $this->id; - } -} -?> \ No newline at end of file diff --git a/mods/social/lib/classes/PrivacyControl/PrivacyController.class.php b/mods/social/lib/classes/PrivacyControl/PrivacyController.class.php deleted file mode 100644 index 1b08f577a..000000000 --- a/mods/social/lib/classes/PrivacyControl/PrivacyController.class.php +++ /dev/null @@ -1,162 +0,0 @@ -preference[profile, basic_profile, photo, ...]) - * @return boolean True if access granted, false otherwise. - */ - function validatePrivacy($field_id, $relationship, $pref){ - //if this is the owner, return true without question - if ($relationship==AT_SOCIAL_OWNER_VISIBILITY){ - return true; - } - - $pref_string = $pref[$field_id]; -// debug($pref_string, $field_id); - -//I have take this out so that in the settings, "Eveyerone" permission has to be switched on for everyone to see - //if AT_SOCIAL_EVERYONE_VISIBILITY is set, relationship flag will no longer matters. -// if ($relationship==AT_SOCIAL_EVERYONE_VISIBILITY){ -// return true; -// } - - //all values are 1 or 0, match the key to the field_id - if (is_array($pref_string) && !empty($pref_string)){ - return (isset($pref_string[$relationship]) && $pref_string[$relationship]==1); - } else { - return false; - } - } - - /** - * Get the relationship between Session[member_id] and the given id. - * Relationship can be friends, friends of friends, network, family, aquaintance, etc. - * TODO: Confirm that the order of checks is not important. Draw a control flow diagram to check this. - * For now, Friends of friends > Groups - * @param int the member that we want to find the relationship to the session[member] - * @return relationship status - */ - function getRelationship($id){ - global $db; - - //if id = self, always true (cause i should be able to see my own profile) - if ($id == $_SESSION['member_id']){ - return AT_SOCIAL_OWNER_VISIBILITY; - } - - //is friend of friend? - if (isFriendOfFriend($id, $_SESSION['member_id'])==true){ - return AT_SOCIAL_FRIENDS_OF_FRIENDS_VISIBILITY; - } - - //is in some of the groups together? - $social_groups = new SocialGroups(); - $my_group = $social_groups->getMemberGroups($_SESSION['member_id']); - $person_group = $social_groups->getMemberGroups($id); - $groups_intersection = array_intersect($my_group, $person_group); //groups intersection - - //If it is not empty or not null, then these 2 people share a group - if (!empty($groups_intersection) > 0){ - return AT_SOCIAL_GROUPS_VISIBILITY; - } - - $sql = 'SELECT relationship FROM '.TABLE_PREFIX."social_friends WHERE (member_id=$id AND friend_id=$_SESSION[member_id]) OR (member_id=$_SESSION[member_id] AND friend_id=$id)"; - $result = mysql_query($sql, $db); -// echo $sql; - if ($result){ - list($relationship) = mysql_fetch_row($result); - } - - //If the relationship is not set, this implies that it's not in the table, - //implying that the user has never set its privacy settings, meaning a default is needed - if (!isset($relationship)){ - return AT_SOCIAL_NETWORK_VISIBILITY; - } - - return $relationship; - } - - /** - * Get user privacy perference - * @param int user id - * @Precondition: include('PrivacyObject.class.php'); - */ - function getPrivacyObject($member_id){ - global $db; - $member_id = intval($member_id); - - //TODO: Check if this object exists in _SESSION, if so, don't pull it from db again - $sql = 'SELECT preferences FROM '.TABLE_PREFIX.'social_privacy_preferences WHERE member_id='.$member_id; - $result = mysql_query($sql, $db); - if (mysql_numrows($result) > 0){ - list($prefs) = mysql_fetch_row($result); - $privacy_obj = unserialize($prefs); - - //Should we checked if this is an actual object before returning it? - return($privacy_obj); - } - //No such person - return new PrivacyObject(); - } - - /** - * Update privacy preference for a single user - * - * @param int user id - * @param mixed preferences object - * @return true if update was successful, false otherwise - */ - function updatePrivacyPreference($member_id, $prefs){ - global $db, $addslashes; - - $member_id = intval($member_id); - $prefs = $addslashes(serialize($prefs)); - - //TODO: Change it back to update - $sql = 'REPLACE '.TABLE_PREFIX."social_privacy_preferences SET member_id=$member_id, preferences='$prefs'"; -// echo $sql; - $result = mysql_query($sql, $db); - return $result; - } - - /** - * Returns an array of the user permission levels - * Check constants.inc.php - */ - function getPermissionLevels(){ - return array ( - //checkboxes don't need to have none and everyone -// -1 => _AT('none'), - AT_SOCIAL_EVERYONE_VISIBILITY => _AT('world_network'), - AT_SOCIAL_FRIENDS_VISIBILITY => _AT('friends'), - AT_SOCIAL_FRIENDS_OF_FRIENDS_VISIBILITY => _AT('friends_of_friends'), - AT_SOCIAL_NETWORK_VISIBILITY => _AT('local_network'), - AT_SOCIAL_GROUPS_VISIBILITY => _AT('groups') - ); - } -} -?> diff --git a/mods/social/lib/classes/PrivacyControl/PrivacyObject.class.php b/mods/social/lib/classes/PrivacyControl/PrivacyObject.class.php deleted file mode 100644 index 97581868e..000000000 --- a/mods/social/lib/classes/PrivacyControl/PrivacyObject.class.php +++ /dev/null @@ -1,92 +0,0 @@ -0, - AT_SOCIAL_FRIENDS_VISIBILITY=>1, - AT_SOCIAL_FRIENDS_OF_FRIENDS_VISIBILITY=>1, - AT_SOCIAL_NETWORK_VISIBILITY=>1, - AT_SOCIAL_GROUP_VISIBILITY=>1 - ); - - $profile_prefs = array( - AT_SOCIAL_PROFILE_BASIC => $demo, - AT_SOCIAL_PROFILE_PROFILE => $demo, - AT_SOCIAL_PROFILE_STATUS_UPDATE => $demo, - AT_SOCIAL_PROFILE_MEDIA => $demo, - AT_SOCIAL_PROFILE_CONNECTION => $demo, - AT_SOCIAL_PROFILE_EDUCATION => $demo, - AT_SOCIAL_PROFILE_POSITION => $demo - ); - - $search_prefs = array( - AT_SOCIAL_SEARCH_VISIBILITY => array(AT_SOCIAL_EVERYONE_VISIBILITY=>0, AT_SOCIAL_FRIENDS_VISIBILITY=>1, - AT_SOCIAL_FRIENDS_OF_FRIENDS_VISIBILITY=>1, AT_SOCIAL_NETWORK_VISIBILITY=>1, - AT_SOCIAL_GROUP_VISIBILITY=>1), - AT_SOCIAL_SEARCH_PROFILE => array(AT_SOCIAL_EVERYONE_VISIBILITY=>1, AT_SOCIAL_FRIENDS_VISIBILITY=>1), - AT_SOCIAL_SEARCH_CONNECTION => array(AT_SOCIAL_EVERYONE_VISIBILITY=>1, AT_SOCIAL_FRIENDS_VISIBILITY=>1), - AT_SOCIAL_SEARCH_EDUCATION => array(AT_SOCIAL_EVERYONE_VISIBILITY=>1, AT_SOCIAL_FRIENDS_VISIBILITY=>1), - AT_SOCIAL_SEARCH_POSITION => array(AT_SOCIAL_EVERYONE_VISIBILITY=>1, AT_SOCIAL_FRIENDS_VISIBILITY=>1) - ); - - //set them - $this->setProfile($profile_prefs); - $this->setSearch($search_prefs); - } - - - //Return bitwise representation of the profile privacy settings - function getProfile(){ - return $this->profile_prefs; - } - - //Return bitwise representation of the search privacy settings - function getSearch(){ - return $this->search_prefs; - } - - //Return bitwise representation of the activity privacy settings - function getActivity(){ - return $this->activity_prefs; - } - - /* Set - * @param mixed array of profile preferences array - */ - function setProfile($prefs){ - $this->profile_prefs = $prefs; - } - - /* - * @param mixed array of prefs arrays - */ - function setSearch($prefs){ - $this->search_prefs = $prefs; - } - - function setActivity($prefs){ - $this->activities_prefs = $prefs; - } -} -?> \ No newline at end of file diff --git a/mods/social/lib/classes/PrivacyControl/SetPrivacyControl.php b/mods/social/lib/classes/PrivacyControl/SetPrivacyControl.php deleted file mode 100644 index d0aad1fbb..000000000 --- a/mods/social/lib/classes/PrivacyControl/SetPrivacyControl.php +++ /dev/null @@ -1,60 +0,0 @@ -'; - -//search_prefs -$search_prefs = array(); - -//activity prefs -$activity_prefs = array(); - -//Updates -$po = new PrivacyObject(); -$po->setProfile($profile_prefs); -$po->setSearch($search_prefs); -$po->setActivity($activity_prefs); - -//update privacy preference -PrivacyController::updatePrivacyPreference($user_id, $po); -?> \ No newline at end of file diff --git a/mods/social/lib/classes/SocialGroups/SocialGroup.class.php b/mods/social/lib/classes/SocialGroups/SocialGroup.class.php deleted file mode 100644 index 2b3f10e18..000000000 --- a/mods/social/lib/classes/SocialGroups/SocialGroup.class.php +++ /dev/null @@ -1,485 +0,0 @@ -group_id = intval($group_id); - - if ($this->group_id > 0){ - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_groups WHERE id='.$this->group_id; - $result = mysql_query($sql, $db); - if (mysql_num_rows($result) > 0){ - $row = mysql_fetch_assoc($result); - $this->user_id = $row['member_id']; - $this->logo = $row['logo']; - $this->name = $row['name']; - $this->type_id = $row['type_id']; - $this->privacy = $row['privacy']; - $this->description = $row['description']; - $this->created_date = $row['created_date']; - $this->last_updated = $row['last_updated']; - $this->group_members = $this->getGroupMembers(); - $this->group_activities = $this->getGroupActivities(); - $this->is_valid = true; - } else { - //group does not exist, most likely deleted - $this->is_valid = false; - } - } - } - - - /** - * Retrieve a list of group members - * @param int group id - * @return mixed array of members object - */ - function getGroupMembers(){ - global $db; - if (!empty($this->group_members)){ - return $this->group_members; - } - $members = array(); - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_groups_members WHERE group_id='.$this->group_id; - $result = mysql_query($sql, $db); - if ($result){ - while ($row = mysql_fetch_assoc($result)){ - $members[] = new Member($row['member_id']); - } - } - - //TODO Return empty array or should i return error? - return $members; - } - - - /** - * Get the group activities, all the activities that happens in this group. - * @param int group id - * @return mixed array of activities - */ - function getGroupActivities(){ - global $db; - if (!empty($this->group_activities)){ - return $this->group_activities; - } - $activities = array(); - $sql = 'SELECT a,id AS id, a.title AS title FROM '.TABLE_PREFIX.'social_groups_activities g LEFT JOIN '.TABLE_PREFIX.'social_activities a ON g.activity_id=a.id WHERE g.group_id='.$this->group_id; - $result = mysql_query($sql, $db); - if ($result){ - while($row = mysql_fetch_assoc($result)){ - $activities[$row['id']] = $row['title']; - } - } - return $activities; - } - - /** - * Get a specific mesage from the given user. - * @param int the message id. - * @param int the member id, the member who created this message, or the moderator. - * @return the text of the message - */ - function getMessage($id, $member_id){ - global $db; - $id = intval($id); - $member_id = intval($member_id); - - $sql = 'SELECT body FROM '.TABLE_PREFIX.'social_groups_board WHERE group_id='.$this->getID().' AND id='.$id; - - //if not moderator - if($member_id!=$this->user_id){ - $sql .= ' AND member_id='.$member_id; - } - - $rs = mysql_query($sql, $db); - if($rs){ - list($body) = mysql_fetch_array($rs); - return htmlentities_utf8($body); - } - return false; - } - - /** - * Get message boards message, return a list sorted by date, in descending order - */ - function getMessages(){ - global $db; - $result = array(); - - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_groups_board WHERE group_id='.$this->getID().' ORDER BY created_date DESC'; - $rs = mysql_query($sql, $db); - - if ($rs){ - while ($row = mysql_fetch_assoc($rs)){ - $row['body'] = htmlentities_utf8($row['body']); //escape xss attack - $result [$row['id']] = $row; - } - } - return $result; - } - - - /** - * Get the group information - */ - function getID(){ - return $this->group_id; - } - function getUser(){ - return $this->user_id; - } - function getGroupType(){ - global $db; - //or maybe print out the exact type name - $sql = 'SELECT title FROM '.TABLE_PREFIX.'social_groups_types WHERE type_id='.$this->type_id; - $result = mysql_query($sql, $db); - list($type_name) = mysql_fetch_row($result); - return _AT($type_name); - } - function getLogo() { - if (!empty($this->logo)) { - $str = ''.$this->getName().''; - } else { - $str = ''._AT('placelogo').''; - } - - return $str; - } - function getName() { - return htmlentities_utf8($this->name); - } - //@param boolean change all carrier returns to
    if true. - function getDescription($use_nl2br=true){ - return htmlentities_utf8($this->description, $use_nl2br); - } - function getCreatedDate(){ - return $this->created_date; - } - function getPrivacy(){ - //0 for public, 1 for private - return $this->privacy; - } - function getLastUpdated(){ - return $this->last_updated; - } - function isValid(){ - return $this->is_valid; - } - - /** - * Add a member to the group - * @param int member id - * @return boolean true if succeded, false otherwise. - */ - function addMember($member_id){ - global $db; - $member_id = intval($member_id); - - $sql = 'INSERT INTO '.TABLE_PREFIX.'social_groups_members (group_id, member_id) VALUES ('.$this->group_id.", $member_id)"; - $result = mysql_query($sql, $db); - if ($result){ - //add a record to the activities - $act = new Activity(); - $str1 = printSocialName($friend_id).' has joined the group, '.htmlentities_utf8($this->getName()).''; - $act->addActivity($member_id, $str1); - unset($act); - return true; - } - return false; - } - - - /** - * Sends an invitation to a member - * @param int member_id - */ - function addInvitation($member_id) { - global $db; - $member_id = intval($member_id); - - $sql = 'INSERT INTO '.TABLE_PREFIX.'social_groups_invitations (sender_id, member_id, group_id) VALUES (' - .$_SESSION['member_id'].', '.$member_id.', '.$this->getID().')'; - $result = mysql_query($sql, $db); - } - - - /** - * Sends a request to the group creator - * @param int member_id - */ - function addRequest(){ - global $db; - - $sql = 'INSERT INTO '.TABLE_PREFIX.'social_groups_requests (sender_id, member_id, group_id) VALUES (' - .$_SESSION['member_id'].', '.$this->getUser().', '.$this->getID().')'; - $result = mysql_query($sql, $db); - return $result; - } - - /** - * Add message to the message board - * @param string the message body - */ - function addMessage($body) { - global $db, $addslashes; - $body = $addslashes($body); - $member_id = $_SESSION['member_id']; - $group_id = $this->getID(); - - $sql = 'INSERT INTO '.TABLE_PREFIX."social_groups_board (member_id, group_id, body, created_date) VALUES ($member_id, $group_id, '$body', NOW())"; - $result = mysql_query($sql, $db); - return $result; - } - - - /** - * Update group logo - * @param string filename of the logo. - */ - function updateGroupLogo($logo) { - global $db, $addslashes; - $logo = $addslashes($logo); - $sql = 'UPDATE '.TABLE_PREFIX."social_groups SET logo='$logo' WHERE id=".$this->getID(); - $result = mysql_query($sql, $db); - return $result; - } - - - /** - * Edit message - * @param int the id of the message - * @param string message body - */ - function updateMessage($id, $body){ - global $db, $addslashes; - $id = intval($id); - $body = $addslashes($body); - if ($id <= 0){ - return false; - } - - $sql = 'UPDATE '.TABLE_PREFIX."social_groups_board SET body='$body' WHERE id=$id"; - $result = mysql_query($sql, $db); - return $result; - } - - - /** - * Remove a member from the group - * @param int member_id - * @retrun boolean troe successful and false otherwise. - */ - function removeMember($member_id){ - global $db; - $member_id = intval($member_id); - - //quit if member_id = creator id - if ($member_id == $this->getUser()){ - return false; - } - - $sql = 'DELETE FROM '.TABLE_PREFIX."social_groups_members WHERE member_id=$member_id AND group_id=".$this->group_id; - $result = mysql_query($sql, $db); - if ($result){ - return true; - } - return false; - } - - /** - * Remove logo from content/social folder - */ - function removeGroupLogo(){ - if ($this->logo!=''){ - unlink(AT_CONTENT_DIR.'social/'. $this->logo); - } - return file_exists(AT_CONTENT_DIR.'social/'. $this->logo); - } - - - - /** - * Delete all group activities - * ToDo: Delete just one? - */ - function removeGroupActivities(){ - global $db; - - $act_obj = new Activity(); - - //First remove groups activities from activity table - $allActs = $this->group_activities; - foreach ($allActs as $id=>$garbage) { - $act_obj->deleteActivity($id); - } - - //Then remove the associations from social_groups_activities - $sql = 'DELETE FROM '.TABLE_PREFIX."social_groups_activities WHERE group_id=".$this->group_id; - $result = mysql_query($sql, $db); - if ($result){ - return true; - } - return false; - } - - - /** - * Delete all group forums - */ - function removeGroupForums(){ - global $db; - include(AT_INCLUDE_PATH.'lib/forums.inc.php'); - - //delete all forums for this social group - $sql = 'SELECT forum_id FROM '.TABLE_PREFIX.'social_groups_forums WHERE group_id='.$this->group_id; - $result = mysql_query($sql, $db); - if ($result){ - while ($row = mysql_fetch_assoc($result)){ - delete_forum($row['forum_id']); - } - } - - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_groups_forums WHERE group_id='.$this->group_id; - $result = mysql_query($sql, $db); - if ($result){ - return true; - } - return false; - } - - - /** - * Delete all group members - */ - function removeGroupMembers(){ - global $db; - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_groups_members WHERE group_id='.$this->group_id; - $result = mysql_query($sql, $db); - if ($result){ - return true; - } - return false; - } - - - /** - * Delete all requests inside this group - */ - function removeGroupRequests(){ - global $db; - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_groups_requests WHERE group_id='.$this->group_id; - $result = mysql_query($sql, $db); - if ($result){ - return true; - } - return false; - } - - - /** - * Delete all invitations inside this group - */ - function removeGroupInvitations(){ - global $db; - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_groups_invitations WHERE group_id='.$this->group_id; - $result = mysql_query($sql, $db); - if ($result){ - return true; - } - return false; - } - - /** - * Delete a message from the board - * @param int member_id - */ - function removeMessage($id, $member_id){ - global $db; - $id = intval ($id); - $member_id = intval($member_id); - $sql = 'DELETE FROM '.TABLE_PREFIX."social_groups_board WHERE id=$id "; - - //if not moderator. - if ($member_id != $this->user_id){ - $sql .= " AND member_id=$member_id"; - } - $result = mysql_query($sql, $db); - return $result; - } - - - /** - * Delete all the messages from the board - */ - function removeAllMessages(){ - global $db; - - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_groups_board WHERE group_id='.$this->getID(); - $result = mysql_query($sql, $db); - return $result; - } - - - /** - * Search members - * TODO: Maybe to make a general search($string, $member_obj_array) that takess any member obj array. - * This can be used for friends search as well. Optimize the code and structure a bit. - * @param string member name - * @return array of Members Object - */ - function searchMembers($name){ - global $db, $addslashes; - - //break the names by space, then accumulate the query - $name = $addslashes($name); - $sub_names = explode(' ', $name); - foreach($sub_names as $piece){ - $query .= "(first_name LIKE '%$piece%' OR second_name LIKE '%$piece%' OR last_name LIKE '%$piece%' OR email LIKE '$piece') AND "; - } - //trim back the extra "AND " - $query = substr($query, 0, -4); - - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_groups_members g LEFT JOIN '.TABLE_PREFIX.'members m ON g.member_id=m.member_id WHERE g.group_id='.$this->getID().' AND '.$query; - $rs = mysql_query($sql, $db); - - while ($row=mysql_fetch_assoc($rs)) { - $result[$row['member_id']] = new Member($row['member_id']); - } - return $result; - } -} -?> \ No newline at end of file diff --git a/mods/social/lib/classes/SocialGroups/SocialGroups.class.php b/mods/social/lib/classes/SocialGroups/SocialGroups.class.php deleted file mode 100644 index af341621e..000000000 --- a/mods/social/lib/classes/SocialGroups/SocialGroups.class.php +++ /dev/null @@ -1,250 +0,0 @@ -'.htmlentities_utf8($name).''; - $act->addActivity($member_id, $str1); - unset($act); - } - return $group_id; - } - return false; - } - - /** - * Removing a group, invovles removing everything related to this group. - * @param int the group id - */ - function removeGroup($id){ - global $db; - $social_group = new SocialGroup($id); - - //remove group activities - $status = $social_group->removeGroupActivities(); - - //remove group forums - $status &= $social_group->removeGroupForums(); - - //remove group members - $status &= $social_group->removeGroupMembers(); - - //remove group requests - $status &= $social_group->removeGroupRequests(); - - //remove group invitations - $status &= $social_group->removeGroupInvitations(); - - //remove message board - $status &= $social_group->removeAllMessages(); - - //remove group logo - $status &= $social_group->removeGroupLogo(); - - //remove groups - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_groups WHERE id='.$id; - $status &= mysql_query($sql, $db); - } - - - /** - * Update a group - * @param int group id - * @param int member_id, to update the owner of this group - * @param int the group type specified in the table, social_groups_type - * @param string name of the group - * @param string description of the group - * @param string the filename of the logo - * @param string group privacy, private for 1, public for 0 - */ - function updateGroup($group_id, $member_id, $type_id, $name, $description, $logo, $privacy){ - global $db, $addslashes; - - $group_id = intval($group_id); - $member_id = intval($member_id); - $type_id = intval($type_id); - $name = $addslashes($name); - $description = $addslashes($description); - $logo = $addslashes($logo); - $privacy = ($privacy=='private')?1:0; - //only include logo sql iff it is not empty, otherwise the old entry will be erased. - if ($logo!=''){ - $logo_sql = "`logo`='$logo', "; - } else { - $logo_sql = ''; - } - - $sql = 'UPDATE '.TABLE_PREFIX."social_groups SET `member_id`=$member_id, `type_id`=$type_id, ".$logo_sql."`name`='$name', `privacy`=$privacy, `description`='$description', `last_updated`=NOW() WHERE id=$group_id"; - $result = mysql_query($sql, $db); - if ($result){ - $act = new Activity(); - $str1 = ' has updated the group, '.htmlentities_utf8($name).''; - $act->addActivity($member_id, $str1); - unset($act); - return true; - } - return false; - } - - - /** - * Get all the group types - * @return list of group types - */ - function getAllGroupType(){ - global $db, $addslashes; - $group_types = array(); - - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_groups_types'; - $result = mysql_query($sql, $db); - if ($result){ - while($row = mysql_fetch_assoc($result)){ - $group_types[$row['type_id']] = $row['title']; - } - } - return $group_types; - } - - - /** - * Get the group infromation from the sql - * @param int group id - * @return mixed SocialGroup obj - */ - function getGroup($group_id){ - $socialGroup = new SocialGroup($group_id); - return $socialGroup; - } - - - /** - * Get ALL of a person's groups - * @param int the groups that this member is in. - * @param int the index of which the entry to get - */ - function getMemberGroups($member_id, $offset=-1){ - global $db; - $my_groups = array(); - - $sql = 'SELECT group_id FROM '.TABLE_PREFIX.'social_groups_members WHERE member_id='.$member_id; - if ($offset >= 0){ - $sql .= " LIMIT $offset, ".SOCIAL_GROUP_MAX; - } - $result = mysql_query($sql, $db); - if ($result){ - while($row = mysql_fetch_assoc($result)){ - $my_groups[] = $row['group_id']; - } - } - return $my_groups; - } - - - /** - * Search - * @param string query string for the search - * @param string filters - */ - function search($query, $filters=''){ - /* Perform a simple search for now - * That searches only the title? - * Use Joel's search idea? Point based system search? The Google's idea? - * - * Idea: - * 1. Get all results that matches the query separtated by space - * 2. Give points to the result that has more match, or whatever our "point system" is - * 3. Sort it in the order of most points to the least points. - */ - global $db, $addslashes; - - if ($query=='') return array(); //quit if search query is empty - - $search_result = array(); - $query = $addslashes(trim($query)); - $words = explode(' ', $query); - foreach($words as $piece){ - $extra .= "`name` LIKE '%$piece%' OR "; - $extra .= "`description` LIKE '%$piece%' OR "; - } - $extra = substr($extra, 0, -3); - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_groups WHERE '.$extra; - $result = mysql_query($sql, $db); - if ($result){ - while ($row = mysql_fetch_assoc($result)){ - $search_result[$row['id']]['obj'] = new SocialGroup($row['id']); - $search_result[$row['id']]['weight'] = $this->inQuery($words, $row['name']); - } - } - uasort($search_result, array($this, 'search_cmp')); - return array_reverse($search_result); - } - - - /** - * Return the counts of word appeareance in the given string. - * @param array the string that hte user typed in to search for - * @param string the name of the group - */ - function inQuery($words, $str){ - $count = 0; - foreach ($words as $index=>$word){ - if (trim($word)=='') continue; - $count += substr_count($str, strtolower($word)); - } - return $count; - } - - - function search_cmp($row1, $row2){ - if ($row1['weight'] == $row2['weight']) return 0; - return ($row1['weight'] < $row2['weight']) ? -1 : 1; - } -} -?> \ No newline at end of file diff --git a/mods/social/lib/constants.inc.php b/mods/social/lib/constants.inc.php deleted file mode 100644 index 2b5808959..000000000 --- a/mods/social/lib/constants.inc.php +++ /dev/null @@ -1,64 +0,0 @@ - \ No newline at end of file diff --git a/mods/social/lib/friends.inc.php b/mods/social/lib/friends.inc.php deleted file mode 100644 index ad03183bd..000000000 --- a/mods/social/lib/friends.inc.php +++ /dev/null @@ -1,656 +0,0 @@ -url should retrieve the member's profile link. - * - * @param int the person who we want to get friends from - * @param int the max number of friends to be returned - * - * TODO: Need optimization, too slow. - */ -function getFriends($member_id, $limit=0){ - global $db, $addslashes; - $friends = array(); - - //All member_id = member_id, and All friend_id = member_id - $sql = 'SELECT F.member_id AS member_id, F.friend_id AS friend_id FROM '.TABLE_PREFIX.'social_friends F LEFT JOIN '.TABLE_PREFIX.'members M ON F.friend_id=M.member_id WHERE (F.member_id='.$member_id.' OR F.friend_id='.$member_id.')'; - if ($limit > 0){ - $sql .= ' ORDER BY RAND() LIMIT '.$limit; - } - $result = mysql_query($sql, $db); - - if ($result){ - while ($row = mysql_fetch_assoc($result)){ - if ($row['member_id']==$member_id){ - //member_id=member_id case - $friends[$row['friend_id']] = $row['friend_id']; - // $friends[$row['member_id']]['first_name'] = $row['first_name']; - // $friends[$row['member_id']]['last_name'] = $row['last_name']; - } else { - //friend_id = member_id - $friends[$row['member_id']] = $row['member_id']; - // $friends[$row['friend_id']]['first_name'] = $row['first_name']; - // $friends[$row['friend_id']]['last_name'] = $row['last_name']; - } - } - } -/* - //All friend_id = member_id - $sql = 'SELECT F.member_id AS member_id, F.friend_id AS friend_id FROM '.TABLE_PREFIX.'social_friends F LEFT JOIN '.TABLE_PREFIX.'members M ON F.friend_id=M.member_id WHERE F.friend_id='.$member_id; - $result = mysql_query($sql, $db); - while ($row = mysql_fetch_assoc($result)){ - $friends[$row['member_id']] = new Member($row['member_id']); -// $friends[$row['friend_id']]['first_name'] = $row['first_name']; -// $friends[$row['friend_id']]['last_name'] = $row['last_name']; - } -*/ - return $friends; -} - - -/** - * Decide rather these two people are strictly friend of friend. If they are already friends, return false. - * - * @param int person A's member_id - * @param int person B's member_id - * @return true if they are friend of friend. - */ -function isFriendOfFriend($member_a, $member_b){ - $member_a = intval($member_a); - $member_b = intval($member_b); - $friends_of_a = getFriends($member_a); - - //if these two are already friends - if(isset($friends_of_a[$member_b])){ - return false; - } - - $friends_of_b = getFriends($member_b); - $fof = array_intersect($friends_of_a, $friends_of_b); //friends of friends - - //If it is not empty or not null, then they have friends - if (!empty($fof) > 0){ - return true; - } - return false; -} - - -/** - * Get a list of people you may know - */ -function getPeopleYouMayKnow(){ - global $db; - $counter = 0; - $people_you_may_know = array(); - $pending_requests = getPendingRequests(true); - - $sql = 'SELECT MAX(member_id) FROM '.TABLE_PREFIX.'members'; - $result = mysql_query($sql, $db); - if ($result){ - list($max_id) = mysql_fetch_array($result); - } else { - return null; - } - - //if we ran out of people, quit; - while($counter++ < $max_id){ - //if we get enough people we might know, quit; - if (sizeof($people_you_may_know) >= SOCIAL_NUMBER_OF_PEOPLE_YOU_MAY_KNOW){ - break; - } - //get new random member - $random_member = rand(1, $max_id); //seed is generated automatically since php 4.2.0 - - //if this person is myself, next - if ($random_member==$_SESSION['member_id']){ - continue; - } - - //if this person is already on pending, next. - if (isset($pending_requests[$random_member])){ - continue; - } - - - //if we have added this random number before, next. - if (in_array($random_member, $people_you_may_know)){ - continue; - } - - if (isFriendOfFriend($_SESSION['member_id'], $random_member)){ - $people_you_may_know[] = $random_member; - } - } - return $people_you_may_know; -} - - -/** - * Returns a list of friend requests to me/by me depends on the flag - * @param flag, true for requests made by me, false for requests made to me. DEFAULT: false - * @return array of friend requests - */ -function getPendingRequests($request_by_me=false){ - global $db; - /* NOTE: This table is not bilinear, unlike the friends table. - * In this table, please do not be confused, member_id is the one who requests - * friend_id is the member that needs to approve/reject. Thus, when we want to retrieve - * pending requests, we need to pull entries from friend_id. - */ - $requests = array(); - - if ($request_by_me==true) { - $sql = 'SELECT friend_id AS id FROM '.TABLE_PREFIX.'social_friend_requests WHERE member_id='.$_SESSION['member_id']; - } else { - $sql = 'SELECT member_id AS id FROM '.TABLE_PREFIX.'social_friend_requests WHERE friend_id='.$_SESSION['member_id']; - } - $rs = mysql_query($sql, $db); - - //myself=> pending objs - while($row = mysql_fetch_assoc($rs)){ - $requests[$row['id']] = new Member($row['id']); - } - return $requests; -} - - -/** - * This function adds a friend to the database, remove the equivalent friend request. - * - * @param int the member being approved, not "MYSELF" - */ -function approveFriendRequest($friend_id){ - global $db; - $friend_id = intval($friend_id); - - if ($friend_id < 1){ - return; - } - //TODO: hardcoded relationship = 1 - $sql = "INSERT INTO ".TABLE_PREFIX."social_friends SET member_id=$_SESSION[member_id], friend_id=$friend_id, relationship=1"; - $is_succeeded = mysql_query($sql, $db); - //remove the equivalent friend request - if ($is_succeeded){ - $is_succeeded = removeFriendRequest($friend_id, $_SESSION['member_id']); - } - - //add to activities log - if ($is_succeeded){ - $act = new Activity(); - $str1 = _AT('now_friends1', printSocialName($friend_id)); - $act->addActivity($_SESSION['member_id'], $str1); - $str2 = _AT('now_friends2', printSocialName($_SESSION['member_id'])); - $act->addActivity($friend_id, $str2); - unset($act); - } -} - - -/** - * Reject friend request - * - * @param int the member being rejected, not "MYSELF" - */ -function rejectFriendRequest($friend_id){ - global $db; - return removeFriendRequest($friend_id, $_SESSION['member_id']); -} - - -/** - * Remove Friend request - * @param member_id the one who make this request - * @param friend_id the member that decide approval/reject on this request - */ -function removeFriendRequest($member_id, $friend_id){ - global $db; - $sql = 'DELETE FROM '.TABLE_PREFIX."social_friend_requests WHERE member_id=$member_id AND friend_id=$friend_id"; - $is_succeeded = mysql_query($sql, $db); - return $is_succeeded; -} - - -/** - * This function adds a friend request to the database - * - * @param friend_id the member_id of the friend - */ -function addFriendRequest($friend_id){ - global $db; - $friend_id = intval($friend_id); - - if ($friend_id < 1){ - return; - } - - $sql = "INSERT INTO ".TABLE_PREFIX."social_friend_requests SET member_id=$_SESSION[member_id], friend_id=$friend_id"; - mysql_query($sql, $db); - } - - -/** - * This function removes a friend from the the user. - * - * @param int user id - */ -function removeFriend($friend_id){ - global $db; - $friend_id = intval($friend_id); - - $sql = 'DELETE FROM '.TABLE_PREFIX.'social_friends WHERE (member_id='.$_SESSION['member_id'].' AND '.'friend_id='.$friend_id.') OR (friend_id='.$_SESSION['member_id'].' AND '.'member_id='.$friend_id.')'; - mysql_query($sql, $db); -} - - -/** - * This function will return a list of people from the network with the given name. - * @param string to be searched in the members table, can have space. - * @param [OPTIONAL] boolean if true, will search only within this member. - * @return array of friends of this member; id=>[first name, last name, profile picture] - * - * TODO: search needs work. Order by the most matches to the least matches - */ -function searchFriends($name, $searchMyFriends = false, $offset=-1){ - global $db, $addslashes; - $result = array(); - $my_friends = array(); - $exact_match = false; - - //break the names by space, then accumulate the query - if (preg_match("/^\\\\?\"(.*)\\\\?\"$/", $name, $matches)){ - $exact_match = true; - $name = $matches[1]; - } - $name = $addslashes($name); - $sub_names = explode(' ', $name); - foreach($sub_names as $piece){ - if ($piece == ''){ - continue; - } - - //if there are 2 double quotes around a search phrase, then search it as if it's "first_name last_name". - //else, match any contact in the search phrase. - if ($exact_match){ - $match_piece = "= '$piece' "; - } else { - $match_piece = "LIKE '%$piece%' "; - } - $query .= "(first_name $match_piece OR second_name $match_piece OR last_name $match_piece OR email LIKE '$piece') AND "; - } - //trim back the extra "AND " - $query = substr($query, 0, -4); - - //Check if this is a search on all people - if ($searchMyFriends == true){ - //If searchMyFriend is true, return the "my friends" array - //If the member_id is empty, (this happens when we are doing a search without logging in) then get all members? - //else, use "my friends" array to distinguish which of these are already in my connection - if(!isset($_SESSION['member_id'])){ - $sql = 'SELECT member_id FROM '.TABLE_PREFIX.'members WHERE '; - } else { - $sql = 'SELECT F.* FROM '.TABLE_PREFIX.'social_friends F LEFT JOIN '.TABLE_PREFIX.'members M ON F.friend_id=M.member_id WHERE (F.member_id='.$_SESSION['member_id'].') AND '; - $sql .= $query; - $sql .= ' UNION '; - $sql .= 'SELECT F.* FROM '.TABLE_PREFIX.'social_friends F LEFT JOIN '.TABLE_PREFIX.'members M ON F.member_id=M.member_id WHERE (F.friend_id='.$_SESSION['member_id'].') AND '; - } - $sql .= $query; - - $rs = mysql_query($sql, $db); - if ($rs){ - while ($row = mysql_fetch_assoc($rs)){ - if ($row['member_id']==$_SESSION['member_id']){ - $this_id = $row['friend_id']; - } else { - $this_id = $row['member_id']; - } - $temp =& $my_friends[$this_id]; - $temp['obj'] = new Member($this_id); - if ($searchMyFriends){ - $temp['added'] = 1; - } - } - } - unset($this_id); //don't want the following statements to reuse this - return $my_friends; - } else { - /* - * Harris' note: - * IF the 'search my friend' is off, then it should search all members inside that table - * don't know why i did the search inside [friends x members] - * Also this query is gonna pull out all members cept 'myself' - * raised a small problem for public use, cause there is no member_id - * end note; - */ - //$sql = 'SELECT * FROM '.TABLE_PREFIX.'social_friends F LEFT JOIN '.TABLE_PREFIX.'members M ON F.friend_id=M.member_id WHERE '; - $sql = 'SELECT * FROM '.TABLE_PREFIX.'members M WHERE '; - if (isset($_SESSION['member_id'])){ - $sql .= 'member_id!='.$_SESSION['member_id'].' AND '; - } - } - $sql = $sql . $query; - if ($offset >= 0){ - $sql .= " LIMIT $offset, ". SOCIAL_FRIEND_SEARCH_MAX; - } - $rs = mysql_query($sql, $db); - - //Get all members out - while($row = mysql_fetch_assoc($rs)){ -// if ($row['member_id']==$_SESSION['member_id']){ -// $this_id = $row['friend_id']; -// } else { - $this_id = $row['member_id']; -// } - - //skip empty entry, don't know why there would be empty entry. - //TODO: Trace this. could be a bug in query - if ($this_id == ''){ - continue; - } - - $temp =& $result[$this_id]; - $temp['id'] = $this_id; -// $temp['first_name'] = $row['first_name']; -// $temp['last_name'] = $row['last_name']; - - //if this person exists in "my friends" list, mark it. - if (isset($my_friends[$this_id])){ - $temp['added'] = 1; - } - } - return $result; -} - - -/** - * Given an array list of friends, this function will add an attribute 'added' into the array if this person is already connected to the user. - * @param int the user id - * @param array the given array of friends - * @return marked array - */ - function markFriends($id, $connections){ - //get all friends - $my_friends = getFriends($id); - $pending_requests = getPendingRequests(true); - - foreach($my_friends as $friends){ - //if it is in the connection, set the attribute - if($connections[$friends] != null){ - $connections[$friends]['added'] = 1; - } - } - - foreach ($pending_requests as $friends=>$garbage){ - //if it is already added, set pending =1 - if ($connections[$friends] != null){ - $connections[$friends]['pending'] = 1; - } - } - return $connections; - } - - -/** - * Invite other members - * @param int The member that we are going to invite - * @param int The group id in which we are inviting the person to. - */ - function addGroupInvitation($member_id, $group_id){ - global $db; - - $sql = 'INSERT INTO '.TABLE_PREFIX."social_groups_invitations (sender_id, group_id, member_id) VALUES ($_SESSION[member_id], $group_id, $member_id)"; -// echo $sql; - $result = mysql_query($sql, $db); - if($result){ - return true; - } - return false; - } - - -/** - * Get invitation from "ME", which is the logged in person - * @return list of groups id + sender_id - */ - function getGroupInvitations(){ - global $db; - $inv = array(); - - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_groups_invitations WHERE member_id='.$_SESSION['member_id']; - - $result = mysql_query($sql, $db); - if ($result){ - while ($row = mysql_fetch_assoc($result)){ - $inv[$row['group_id']][] = $row['sender_id']; - } - } - - return $inv; - } - - - /** - * Get group requests for "ME", which is the logged in person. - * @return list of groups id + sender_id - */ - function getGroupRequests(){ - global $db; - $requests = array(); - - $sql = 'SELECT * FROM '.TABLE_PREFIX.'social_groups_requests WHERE member_id='.$_SESSION['member_id']; - - $result = mysql_query($sql, $db); - if ($result){ - while ($row = mysql_fetch_assoc($result)){ - $requests[$row['group_id']][] = $row['sender_id']; - } - } - - return $requests; - } - - - /** - * Accept "my" group invitation - * @param int group id - * @param int sender's member_id - */ -function acceptGroupInvitation($group_id){ - global $db; - - //will only add member if the group_id is valid. - if ($group_id <= 0){ - return; - } - - $sg = new SocialGroup($group_id); - $isSucceeded = $sg->addMember($_SESSION['member_id']); - - if ($isSucceeded){ - removeGroupInvitation($group_id); - } -} - - - /** - * Reject "my" group invitation - */ - function rejectGroupInvitation($group_id){ - return removeGroupInvitation($group_id); - } - - - - /** - * Remove "my" group invitation - * @param int group id - */ - function removeGroupInvitation($group_id){ - global $db; - $group_id = intval($group_id); - - //delete invitation based on 3 primary keys -// $sql = 'DELETE FROM '.TABLE_PREFIX."social_groups_invitations WHERE group_id=$group_id AND sender_id=$sender_id AND member_id=$member_id"; - //doesn't need sender_id cause we want to remove all anyway. - $sql = 'DELETE FROM '.TABLE_PREFIX."social_groups_invitations WHERE group_id=$group_id AND member_id=$_SESSION[member_id]"; - $result = mysql_query($sql, $db); - if ($result){ - return true; - } - return false; - } - - - /** - * Accept the group request - * @param int group id - * @param int member that made this request - */ - function acceptGroupRequest($group_id, $sender_id){ - global $db; - - //will only add member if the group_id is valid. - if ($group_id <= 0){ - return; - } - - $sg = new SocialGroup($group_id); - $isSucceeded = $sg->addMember($sender_id); - - if ($isSucceeded){ - removeGroupRequest($group_id, $sender_id); - } - } - - - /** - * Reject the group request - * @param int group id - * @param int member that made this request - */ - function rejectGroupRequest($group_id, $sender_id) { - return removeGroupRequest($group_id, $sender_id); - } - - - - /** - * Remove group requests - * @param int group id - * @param int member that made this request - */ - function removeGroupRequest($group_id, $sender_id){ - global $db; - $group_id = intval($group_id); - $sender_id = intval($sender_id); - - $sql = 'DELETE FROM '.TABLE_PREFIX."social_groups_requests WHERE group_id=$group_id AND member_id=$_SESSION[member_id] AND sender_id=$sender_id"; - - $result = mysql_query($sql, $db); - if ($result){ - return true; - } - return false; - } - - -/** - * Print social name, with AT_print and profile link - * @param int member id - * @param link will return a hyperlink when set to true - * return the name to be printed. - */ -function printSocialName($id, $link=true){ - $str .= AT_print(get_display_name($id), 'members.full_name'); - if ($link) { - return getProfileLink($id, $str); - } - return $str; -} - - -/** - * Mimic vital's print_profile_img function, but with a more customized image definition - * @param int the member id - * @param 1 for thumbnail, 2 for profile - * @param true will return a href link to the profile page, false otherwise - * @return the profile image link - */ -function printSocialProfileImg($id, $type=1, $link=true) { - global $moduleFactory; - $str = ''; - $mod = $moduleFactory->getModule('_standard/profile_pictures'); - if ($mod->isEnabled() === FALSE) { - return; - } - if (profile_image_exists($id)) { - if ($type==1){ - $str = ''; - } elseif ($type==2){ - $str = ''; - } - } else { - $str = ''; - } - if (!$link){ - return $str; - } - return getProfileLink($id, $str); -} - - -/** - * Generate the a href link to the designated profile - * For now, it's to sprofile, but in the future, we want ATutor + Opensocial to have only 1 profile, which should - * point to the default atutor profile page. - * - * @private - * @param int member id - * @param string Image tag, or any string - * @return the hyperlink to the profile - */ -function getProfileLink($id, $str){ - $link = ''; - $link .= $str; - $link .= ''; - return $link; -} - -/** - * Convert all input to htmlentities output, in UTF-8. - * @param string input to be convert - * @param boolean true if we wish to change all carrier returns to a
    tag, false otherwise. - */ -function htmlentities_utf8($str, $use_nl2br=true){ - $return = htmlentities($str, ENT_QUOTES, 'UTF-8'); - if ($use_nl2br){ - return nl2br($return); - } - return $return; -} - -/** - * This function will return a list of the member's activities - * @param member_id The id of the member we wish to get the activities from. - */ -function getMemberActivities($member_id){ -} - -?> \ No newline at end of file diff --git a/mods/social/lib/js/container.js b/mods/social/lib/js/container.js deleted file mode 100644 index 18572cc34..000000000 --- a/mods/social/lib/js/container.js +++ /dev/null @@ -1,89 +0,0 @@ -var Container = Class.create(); -Container.prototype = { - maxHeight: 4096, - - initialize: function() { - // rpc services our container supports - gadgets.rpc.register('resize_iframe', this.setHeight); - gadgets.rpc.register('set_pref', this.setUserPref); - gadgets.rpc.register('set_title', this.setTitle); - gadgets.rpc.register('requestNavigateTo', this.requestNavigateTo); - }, - - setHeight: function(height) { - if ($(this.f) != undefined) { - // compensate for margin/padding offsets in some browsers (ugly hack but functional) - height += 28; - // change the height of the gadget iframe, limit to maxHeight height - if (height > gadgets.container.maxHeight) { - height = gadgets.container.maxHeight; - } - Element.setStyle($(this.f), {'height':height+'px'}); - } - }, - - _parseIframeUrl: function(url) { - // parse the iframe url to extract the key = value pairs from it - var ret = new Object(); - var hashParams = url.replace(/#.*$/, '').split('&'); - var param = key = val = ''; - for (i = 0 ; i < hashParams.length; i++) { - param = hashParams[i]; - key = param.substr(0, param.indexOf('=')); - val = param.substr(param.indexOf('=') + 1); - ret[key] = val; - } - return ret; - }, - - setUserPref: function(editToken, name, value) { - // we use the security token to tell our backend who this is (app/mod/viewer) - // since it's the only fail safe way of doing so - if ($(this.f) != undefined) { - var params = gadgets.container._parseIframeUrl($(this.f).src); - //TODO use params.st to make the store request, it holds the owner / viewer / app id / mod id required - new Ajax.Request('./mods/social/set_prefs.php', {method: 'get', parameters: { name: name, value: value, st: params.st }}); - } - }, - - setTitle: function(title) { - var element = $(this.f+'_title'); - if (element != undefined) { - // update the title, and make sure we don't break it's html - element.update(title.replace(/&/g, '&').replace(/)[^>]*$|^#([\w-]+)$/, - // Is it a simple selector - isSimple = /^.[^:#\[\.,]*$/; - -jQuery.fn = jQuery.prototype = { - init: function( selector, context ) { - // Make sure that a selection was provided - selector = selector || document; - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this[0] = selector; - this.length = 1; - this.context = selector; - return this; - } - // Handle HTML strings - if ( typeof selector === "string" ) { - // Are we dealing with HTML string or an ID? - var match = quickExpr.exec( selector ); - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) - selector = jQuery.clean( [ match[1] ], context ); - - // HANDLE: $("#id") - else { - var elem = document.getElementById( match[3] ); - - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem && elem.id != match[3] ) - return jQuery().find( selector ); - - // Otherwise, we inject the element directly into the jQuery object - var ret = jQuery( elem || [] ); - ret.context = document; - ret.selector = selector; - return ret; - } - - // HANDLE: $(expr, [context]) - // (which is just equivalent to: $(content).find(expr) - } else - return jQuery( context ).find( selector ); - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) - return jQuery( document ).ready( selector ); - - // Make sure that old selector state is passed along - if ( selector.selector && selector.context ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return this.setArray(jQuery.isArray( selector ) ? - selector : - jQuery.makeArray(selector)); - }, - - // Start with an empty selector - selector: "", - - // The current version of jQuery being used - jquery: "1.3.2", - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num === undefined ? - - // Return a 'clean' array - Array.prototype.slice.call( this ) : - - // Return just the object - this[ num ]; - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems, name, selector ) { - // Build a new jQuery matched element set - var ret = jQuery( elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - ret.context = this.context; - - if ( name === "find" ) - ret.selector = this.selector + (this.selector ? " " : "") + selector; - else if ( name ) - ret.selector = this.selector + "." + name + "(" + selector + ")"; - - // Return the newly-formed element set - return ret; - }, - - // Force the current matched set of elements to become - // the specified array of elements (destroying the stack in the process) - // You should use pushStack() in order to do this, but maintain the stack - setArray: function( elems ) { - // Resetting the length to 0, then using the native Array push - // is a super-fast way to populate an object with array-like properties - this.length = 0; - Array.prototype.push.apply( this, elems ); - - return this; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem && elem.jquery ? elem[0] : elem - , this ); - }, - - attr: function( name, value, type ) { - var options = name; - - // Look for the case where we're accessing a style value - if ( typeof name === "string" ) - if ( value === undefined ) - return this[0] && jQuery[ type || "attr" ]( this[0], name ); - - else { - options = {}; - options[ name ] = value; - } - - // Check to see if we're setting style values - return this.each(function(i){ - // Set all the styles - for ( name in options ) - jQuery.attr( - type ? - this.style : - this, - name, jQuery.prop( this, options[ name ], type, i, name ) - ); - }); - }, - - css: function( key, value ) { - // ignore negative width and height values - 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] ) { - // The elements to wrap the target around - var wrap = jQuery( html, this[0].ownerDocument ).clone(); - - if ( this[0].parentNode ) - wrap.insertBefore( this[0] ); - - wrap.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, function(elem){ - if (this.nodeType == 1) - this.appendChild( elem ); - }); - }, - - prepend: function() { - return this.domManip(arguments, true, function(elem){ - if (this.nodeType == 1) - this.insertBefore( elem, this.firstChild ); - }); - }, - - before: function() { - return this.domManip(arguments, false, function(elem){ - this.parentNode.insertBefore( elem, this ); - }); - }, - - after: function() { - return this.domManip(arguments, false, function(elem){ - this.parentNode.insertBefore( elem, this.nextSibling ); - }); - }, - - end: function() { - return this.prevObject || jQuery( [] ); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: [].push, - sort: [].sort, - splice: [].splice, - - find: function( selector ) { - if ( this.length === 1 ) { - var ret = this.pushStack( [], "find", selector ); - ret.length = 0; - jQuery.find( selector, this[0], ret ); - return ret; - } else { - return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){ - return jQuery.find( selector, elem ); - })), "find", selector ); - } - }, - - clone: function( events ) { - // Do the clone - var ret = this.map(function(){ - if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) { - // IE copies events bound via attachEvent when - // using cloneNode. Calling detachEvent on the - // clone will also remove the events from the orignal - // In order to get around this, we use innerHTML. - // Unfortunately, this means some modifications to - // attributes in IE that are actually only stored - // as properties will not be copied (such as the - // the name attribute on an input). - var html = this.outerHTML; - if ( !html ) { - var div = this.ownerDocument.createElement("div"); - div.appendChild( this.cloneNode(true) ); - html = div.innerHTML; - } - - return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0]; - } else - return this.cloneNode(true); - }); - - // Copy the events from the original to the clone - if ( events === true ) { - var orig = this.find("*").andSelf(), i = 0; - - ret.find("*").andSelf().each(function(){ - if ( this.nodeName !== orig[i].nodeName ) - return; - - var events = jQuery.data( orig[i], "events" ); - - for ( var type in events ) { - for ( var handler in events[ type ] ) { - jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); - } - } - - i++; - }); - } - - // Return the cloned set - 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, jQuery.grep(this, function(elem){ - return elem.nodeType === 1; - }) ), "filter", selector ); - }, - - closest: function( selector ) { - var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null, - closer = 0; - - return this.map(function(){ - var cur = this; - while ( cur && cur.ownerDocument ) { - if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) { - jQuery.data(cur, "closest", closer); - return cur; - } - cur = cur.parentNode; - closer++; - } - }); - }, - - not: function( selector ) { - if ( typeof selector === "string" ) - // test special case where just one selector is passed in - if ( isSimple.test( selector ) ) - return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector ); - 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 this.pushStack( jQuery.unique( jQuery.merge( - this.get(), - typeof selector === "string" ? - jQuery( selector ) : - jQuery.makeArray( selector ) - ))); - }, - - is: function( selector ) { - return !!selector && jQuery.multiFilter( selector, this ).length > 0; - }, - - hasClass: function( selector ) { - return !!selector && this.is( "." + selector ); - }, - - val: function( value ) { - if ( value === undefined ) { - var elem = this[0]; - - if ( elem ) { - if( jQuery.nodeName( elem, 'option' ) ) - return (elem.attributes.value || {}).specified ? elem.value : elem.text; - - // We need to handle select boxes special - if ( jQuery.nodeName( elem, "select" ) ) { - var index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type == "select-one"; - - // Nothing was selected - if ( index < 0 ) - return null; - - // Loop through all the selected options - for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { - var option = options[ i ]; - - if ( option.selected ) { - // Get the specifc value for the option - value = jQuery(option).val(); - - // We don't need an array for one selects - if ( one ) - return value; - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - } - - // Everything else, we just grab the value - return (elem.value || "").replace(/\r/g, ""); - - } - - return undefined; - } - - if ( typeof value === "number" ) - value += ''; - - return this.each(function(){ - if ( this.nodeType != 1 ) - return; - - if ( jQuery.isArray(value) && /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 = jQuery.makeArray(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[0] ? - this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") : - 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 ), - "slice", Array.prototype.slice.call(arguments).join(",") ); - }, - - 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 ); - }, - - domManip: function( args, table, callback ) { - if ( this[0] ) { - var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(), - scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ), - first = fragment.firstChild; - - if ( first ) - for ( var i = 0, l = this.length; i < l; i++ ) - callback.call( root(this[i], first), this.length > 1 || i > 0 ? - fragment.cloneNode(true) : fragment ); - - if ( scripts ) - jQuery.each( scripts, evalScript ); - } - - return this; - - function root( elem, cur ) { - return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ? - (elem.getElementsByTagName("tbody")[0] || - elem.appendChild(elem.ownerDocument.createElement("tbody"))) : - elem; - } - } -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -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 ); -} - -function now(){ - return +new Date; -} - -jQuery.extend = jQuery.fn.extend = function() { - // copy reference to target object - var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) - target = {}; - - // extend jQuery itself if only one argument is passed - if ( length == i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) - // Extend the base object - for ( var name in options ) { - var src = target[ name ], copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) - continue; - - // Recurse if we're merging object values - if ( deep && copy && typeof copy === "object" && !copy.nodeType ) - target[ name ] = jQuery.extend( deep, - // Never move original objects, clone them - src || ( copy.length != null ? [ ] : { } ) - , copy ); - - // Don't bring in undefined values - else if ( copy !== undefined ) - target[ name ] = copy; - - } - - // Return the modified object - return target; -}; - -// exclude the following css properties to add px -var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i, - // cache defaultView - defaultView = document.defaultView || {}, - toString = Object.prototype.toString; - -jQuery.extend({ - noConflict: function( deep ) { - window.$ = _$; - - if ( deep ) - window.jQuery = _jQuery; - - return jQuery; - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return toString.call(obj) === "[object Function]"; - }, - - isArray: function( obj ) { - return toString.call(obj) === "[object Array]"; - }, - - // check if an element is in a (or is an) XML document - isXMLDoc: function( elem ) { - return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || - !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument ); - }, - - // Evalulates a script in a global context - globalEval: function( data ) { - if ( data && /\S/.test(data) ) { - // Inspired by code by Andrea Giammarchi - // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html - var head = document.getElementsByTagName("head")[0] || document.documentElement, - script = document.createElement("script"); - - script.type = "text/javascript"; - if ( jQuery.support.scriptEval ) - script.appendChild( document.createTextNode( data ) ); - else - script.text = data; - - // Use insertBefore instead of appendChild to circumvent an IE6 bug. - // This arises when a base node is used (#2709). - head.insertBefore( script, head.firstChild ); - head.removeChild( script ); - } - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); - }, - - // args is for internal usage only - each: function( object, callback, args ) { - var name, i = 0, length = object.length; - - if ( args ) { - if ( length === undefined ) { - for ( name in object ) - if ( callback.apply( object[ name ], args ) === false ) - break; - } else - for ( ; i < length; ) - if ( callback.apply( object[ i++ ], args ) === false ) - break; - - // A special, fast, case for the most common use of each - } else { - if ( length === undefined ) { - for ( name in object ) - if ( callback.call( object[ name ], name, object[ name ] ) === false ) - break; - } else - for ( var value = object[0]; - i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} - } - - return object; - }, - - prop: function( elem, value, type, i, name ) { - // Handle executable functions - if ( jQuery.isFunction( value ) ) - value = value.call( elem, i ); - - // Handle passing in a number to a CSS property - return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ? - value + "px" : - value; - }, - - className: { - // internal only, use addClass("class") - 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; - }); - }, - - // internal only, use removeClass("class") - 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(" ") : - ""; - }, - - // internal only, use hasClass("class") - has: function( elem, className ) { - return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; - } - }, - - // A method for quickly swapping in/out CSS properties to get correct calculations - swap: function( elem, options, callback ) { - var old = {}; - // Remember the old values, and insert the new ones - for ( var name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - callback.call( elem ); - - // Revert the old values - for ( var name in options ) - elem.style[ name ] = old[ name ]; - }, - - css: function( elem, name, force, extra ) { - 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; - - if ( extra === "border" ) - return; - - jQuery.each( which, function() { - if ( !extra ) - val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; - if ( extra === "margin" ) - val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0; - else - val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; - }); - } - - if ( elem.offsetWidth !== 0 ) - getWH(); - else - jQuery.swap( elem, props, getWH ); - - return Math.max(0, Math.round(val)); - } - - return jQuery.curCSS( elem, name, force ); - }, - - curCSS: function( elem, name, force ) { - var ret, style = elem.style; - - // We need to handle opacity special in IE - if ( name == "opacity" && !jQuery.support.opacity ) { - ret = jQuery.attr( style, "opacity" ); - - return ret == "" ? - "1" : - ret; - } - - // Make sure we're using the right name for getting the float value - if ( name.match( /float/i ) ) - name = styleFloat; - - if ( !force && style && style[ name ] ) - ret = style[ name ]; - - else if ( defaultView.getComputedStyle ) { - - // Only "float" is needed here - if ( name.match( /float/i ) ) - name = "float"; - - name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); - - var computedStyle = defaultView.getComputedStyle( elem, null ); - - if ( computedStyle ) - ret = computedStyle.getPropertyValue( name ); - - // We should always get a number back from opacity - 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 ]; - - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { - // Remember the original values - var left = style.left, rsLeft = elem.runtimeStyle.left; - - // Put in the new values to get a computed value out - elem.runtimeStyle.left = elem.currentStyle.left; - style.left = ret || 0; - ret = style.pixelLeft + "px"; - - // Revert the changed values - style.left = left; - elem.runtimeStyle.left = rsLeft; - } - } - - return ret; - }, - - clean: function( elems, context, fragment ) { - context = context || document; - - // !context.createElement fails in IE with an error but returns typeof 'object' - if ( typeof context.createElement === "undefined" ) - context = context.ownerDocument || context[0] && context[0].ownerDocument || document; - - // If a single string is passed in and it's a single tag - // just do a createElement and skip the rest - if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) { - var match = /^<(\w+)\s*\/?>$/.exec(elems[0]); - if ( match ) - return [ context.createElement( match[1] ) ]; - } - - var ret = [], scripts = [], div = context.createElement("div"); - - jQuery.each(elems, function(i, elem){ - if ( typeof elem === "number" ) - elem += ''; - - if ( !elem ) - return; - - // Convert html string into DOM nodes - if ( typeof elem === "string" ) { - // Fix "XHTML"-style tags in all browsers - 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 + ">"; - }); - - // Trim whitespace, otherwise indexOf won't work as expected - var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase(); - - var wrap = - // option or optgroup - !tags.indexOf("", "" ] || - - !tags.indexOf("", "" ] || - - tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && - [ 1, "", "
    " ] || - - !tags.indexOf("", "" ] || - - // matched above - (!tags.indexOf("", "" ] || - - !tags.indexOf("", "" ] || - - // IE can't serialize and - - - \ No newline at end of file diff --git a/mods/userplane/index_admin.php b/mods/userplane/index_admin.php deleted file mode 100644 index f4920a5b7..000000000 --- a/mods/userplane/index_admin.php +++ /dev/null @@ -1,67 +0,0 @@ -addError('USERPLANE_ID_ADD_EMPTY'); - } - - if (!$msg->containsErrors()) { - $_POST['uri'] = $addslashes($_POST['uri']); - $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('userplane', '$_POST[uri]')"; - mysql_query($sql, $db); - $msg->addFeedback('USERPLANE_ID_SAVED'); - - header('Location: '.$_SERVER['PHP_SELF']); - exit; - } -} - -require (AT_INCLUDE_PATH.'header.inc.php'); - -?> - - -
    -
    -

    -
    -
    - -
    -
    -

    -
    -
    - - -
    -
    -
    -

    - - -
    -
    - -
    -
    -
    - -
    - -
    - - - \ No newline at end of file diff --git a/mods/userplane/module.css b/mods/userplane/module.css deleted file mode 100644 index ee33529e2..000000000 --- a/mods/userplane/module.css +++ /dev/null @@ -1,12 +0,0 @@ -div#userplane { - border: 1px solid #ccc; - padding: 10px; - width: 60%; - margin-right: auto; - margin-left: auto; - background-color: #efefef; - color: #444; - margin-top: 30px; - margin-bottom: 30px; - text-align: center; -} \ No newline at end of file diff --git a/mods/userplane/module.php b/mods/userplane/module.php deleted file mode 100644 index 96373bb67..000000000 --- a/mods/userplane/module.php +++ /dev/null @@ -1,47 +0,0 @@ -getAdminPrivilege()); - -/******* - * create a side menu box/stack. - */ -$this->_stacks['userplane'] = array('title_var'=>'userplane', 'file'=>AT_INCLUDE_PATH.'../mods/userplane/side_menu.inc.php'); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_student_tool = 'mods/userplane/index.php'; - -/******* - * add the admin page so the Userplane ID can be managed - */ - -if (admin_authenticate(AT_ADMIN_PRIV_USERPLANE, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages[AT_NAV_ADMIN] = array('mods/userplane/index_admin.php'); - $this->_pages['mods/userplane/index_admin.php']['title_var'] = 'userplane'; - $this->_pages['mods/userplane/index_admin.php']['parent'] = AT_NAV_ADMIN; -} - -/******* - * student page. - */ -$this->_pages['mods/userplane/index.php']['title_var'] = 'userplane'; -$this->_pages['mods/userplane/index.php']['img'] = 'mods/userplane/userplane.jpg'; - -// You may use the ATutor community ID (e2405db9bcd4f802ffed98a4d1a15ac3) but you should register your own -// at http://www.userplane.com/buy/index.cfm - -?> \ No newline at end of file diff --git a/mods/userplane/module.sql b/mods/userplane/module.sql deleted file mode 100644 index 2b70bb870..000000000 --- a/mods/userplane/module.sql +++ /dev/null @@ -1,10 +0,0 @@ -# sql file for Userplane module - -INSERT INTO `language_text` VALUES ('en', '_module','userplane','UserPlane',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','userplane_id','UserPlane ID',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','userplane_text','Your Userplane ID is displayed in the box below. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','userplane_missing_id','Create a Userplane account at http://www.userplane.com/buy/index.cfm. Enter the ID you are assigned into the box below. ',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_module','userplane_howto','Use Userplane Web Chat to communicate with other ATutor users using voice and video. Requires Javascript and Flash. Enter a screen name then press Login, or choose Sign Up to create a user profile.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_FEEDBACK_USERPLANE_ID_SAVED','UserPlane ID was successfully saved.',NOW(),''); -INSERT INTO `language_text` VALUES ('en', '_msgs','AT_ERROR_USERPLANE_ID_ADD_EMPTY','UserPlane ID cannot be empty.',NOW(),''); - diff --git a/mods/userplane/module.xml b/mods/userplane/module.xml deleted file mode 100644 index e09153712..000000000 --- a/mods/userplane/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - UserPlane - This modules links the Userplane Web Chat into ATutor - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.4 - 2010-10-25 - stable - You will need to create a Userplane account at http://www.userplane.com/buy/index.cfm, then through the administrator's UserPlane manager, enter that ID into the UserPlane ID field. - - \ No newline at end of file diff --git a/mods/userplane/module_install.php b/mods/userplane/module_install.php deleted file mode 100644 index ed40a602b..000000000 --- a/mods/userplane/module_install.php +++ /dev/null @@ -1,30 +0,0 @@ -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); -} - -?> \ No newline at end of file diff --git a/mods/userplane/module_uninstall.php b/mods/userplane/module_uninstall.php deleted file mode 100644 index 60ce25da8..000000000 --- a/mods/userplane/module_uninstall.php +++ /dev/null @@ -1,26 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/userplane/side_menu.inc.php b/mods/userplane/side_menu.inc.php deleted file mode 100644 index 13a647466..000000000 --- a/mods/userplane/side_menu.inc.php +++ /dev/null @@ -1,14 +0,0 @@ - - - - -assign('dropdown_contents', ob_get_contents()); -ob_end_clean(); - -$savant->assign('title', _AT('userplane')); // the box title -$savant->display('include/box.tmpl.php'); -?> \ No newline at end of file diff --git a/mods/userplane/userplane.jpg b/mods/userplane/userplane.jpg deleted file mode 100644 index ee301c5c43dd1f8a459d6175436dfca6ae7b0a94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1804 zcmb7Ac`)0F9{>F$k*G5gsWV8`S&E6eq9JvZx0X6WMYoQ&TB=lS)uJtmSB(;FLLEV< zy245w5w_^z=vM1$yN-|)ZKZXrvRK+|-p+e7`|taFXTCGv`CKz!@o!=Qpyc7|?h1e) z2pp9RAf5t_05Av?3WdNV3kHKp!{rcg2^3{zW#o{G%F0MZBoc+u+>1i1t00l8x~l40 zTH4y$sJ%En99B;gtBw6n2q>|_rQr$)gaQ_gL}UMNh1(Ak>P#8kOS}6e_1R@22!4Ut|fPfSP3PUREN?U}&Q8=e#Xv?sRG!={< z$;Yo^WS?(yzQm>h0w7HCfqwv$gh)f-64C@IX_TCB*#887XCh%1%DTs-QD_xhXtSkH zSZXgxJPF82YNe16BtQf+2fp%`?-nqXV`Z~xZ4citFf#g9-4zB=j%YoymX$nr*8i#Trzh;ee**Fj&{QR)W zY=8dZj9-GH?Q5>_kt$@K%EG_Sw<^)HSwj(T^O^_QTJYC0-&O?L&SrEe?=uR6R*pM_ z!gY$e*W%H-7-7}wwoZjVy(yt}sQZI)_yn7kf1h(g6n=j6$-xBR$^ccMEPVTn`bA^z zo`3Xm^}Ao6QNl|yWrEf5ctON`!-c^!T&8Lr!-H)aO<8;Q=DKud%wP!qGCVTt7Skqs zI&y^PfX9?>`QP5Oq8?024;smL?*U!v4-WI$n*&CaLZijo_XsmbZHcDzl>X#%m$(Bv zDQ)Z_*10G1!_zOWGFQHO#-4B)nI=AM{3Bgh37?LsH~x(M%zSjGox^Ub z;HiJZ#nhYjEQ&OCcJ-nX>bi7@f>2`BwP){hqj*;ZVnEnE`pbp*_M&BNW( zE-^e-2AdSO5nReJlM1sfQ51b#!fWa)%?;eyJs}EuZpZoE(;vD}Y~#B6IeE4I(eM(! zjkgtP$T}rgKmMVwH!~~EQeZ15QtM}WS(3XWx@`L}pI)>UxN#Wzec@3-?+MS{H9jAT zd6m4azjK=LVedp>js4~Pg zRH)WQ#u<_f)tHiDY*O`Z582D&l5D#=u=Y`f54rY~U{Fw(aQchzL|NyS@?}~Hrih4K zBjY0mQoNbVgR`Ba(S|keNEctPhs60de9ks5aHH?N;KB{#!zWR4ga_2>zyoE{ExjJFC2xnbrU6~3?Y~{VF znTn^Scj(O7Z%{;UO{VMi-OahaFPdjIf48*EcH!|@atM*$E@OU}W6JZG!L&{`#R|UI`$27W#-ID?>;!@`ZE5@@H_VXI;iV65Bt@M1A(Q<= z=GE9rMg(?vsnDjp;g$F7lGBy8m19q>k-qroY@4ZS!_=3w@$LMMt9+N8%meD8BM<@MwY>rEPsS;d~wO!pKOrgDGk&^fnUJQ$D+o@Lhk9N_01 z*t?A1HZg5pya33CmXDZfp46I>fwq`8jIxFs9-MV|w0U?FAEU#e82k z5r* z$#b(1c&0Tb=PRZqm-b~(5IL%JH_O4nW1{QcY(h~H1GinK+h2J0m6e^~D*AS&g|E-! z#nKM5=?1eh7VmYIyUzOjx9wfi48C7LMsr_EpmyU)lY1co^+cnj$@ib=Q`|ED@txEt zG2rb>Zn5IZ_sH6OB=hO4vwax%F+xdx1u@q2nn*S*D=j*H^pjE=sUW<<)ebF`OF<>Q z{V`~KyxF&(Wzz%NKVV(b+G8uXs&vI;dYPf?;)8bVm)LxC>|3?DsLDdz@7YWw*9 z3Y<%CrI2T1GD|*Qz+FfPdeagj&+yIz_;+sI - -
    - Hello Student!! :) -
    - - \ No newline at end of file diff --git a/mods/utf8conv/index_admin.php b/mods/utf8conv/index_admin.php deleted file mode 100644 index 46a36201b..000000000 --- a/mods/utf8conv/index_admin.php +++ /dev/null @@ -1,21 +0,0 @@ - diff --git a/mods/utf8conv/index_instructor.php b/mods/utf8conv/index_instructor.php deleted file mode 100644 index 77b6eadc1..000000000 --- a/mods/utf8conv/index_instructor.php +++ /dev/null @@ -1,21 +0,0 @@ - diff --git a/mods/utf8conv/module.php b/mods/utf8conv/module.php deleted file mode 100644 index e59f0d2ab..000000000 --- a/mods/utf8conv/module.php +++ /dev/null @@ -1,37 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_UTF8CONV', $this->getAdminPrivilege()); - -/******* - * add the admin pages when needed. - */ -if (admin_authenticate(AT_ADMIN_PRIV_UTF8CONV, TRUE) || admin_authenticate(AT_ADMIN_PRIV_ADMIN, TRUE)) { - $this->_pages['admin/courses.php']['children'] = array('mods/utf8conv/index_admin.php'); - $this->_pages['mods/utf8conv/index_admin.php']['title_var'] = 'utf8conv'; - $this->_pages['mods/utf8conv/index_admin.php']['parent'] = 'admin/courses.php'; -} - -/******* - * instructor Manage section: - */ -$this->_pages['tools/content/index.php']['children'] = array('mods/utf8conv/index_instructor.php'); -$this->_pages['mods/utf8conv/index_instructor.php']['title_var'] = 'utf8conv'; -$this->_pages['mods/utf8conv/index_instructor.php']['parent'] = 'tools/content/index.php'; - -function utf8conv_get_group_url($group_id) { - return 'mods/utf8conv/index.php'; -} -?> \ No newline at end of file diff --git a/mods/utf8conv/module.sql b/mods/utf8conv/module.sql deleted file mode 100644 index 7f81a971f..000000000 --- a/mods/utf8conv/module.sql +++ /dev/null @@ -1,4 +0,0 @@ -# sql file for hello world module - - -INSERT INTO `language_text` VALUES ('en', '_module','utf8conv','UTF8 Conversion',NOW(),''); diff --git a/mods/utf8conv/module.xml b/mods/utf8conv/module.xml deleted file mode 100644 index 953716f2b..000000000 --- a/mods/utf8conv/module.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - UTF8 Content Conversion Utility - This is a utility to convert character sets to UTF-8. - The conversion includes: - 1. replaces the charset strings defined in html "meta" tag and "charset" tag in xml files to "UTF-8"; - 2. convert files from old character set to UTF-8. - - Requirement - This module requires PHP ICONV module to be installed and enabled. - - File types to convert - html, xml, csv, txt, sql - - Usage - 1. Upload the zip file that contains all the files needed to be converted, Click "Convert" button; - 2. The module searchs through all html and xml files to find "charset" defined in html "meta" tag and "charset" defined in xml files. - If: - (1) Only 1 character set found: - The module converts the files with file types to convert from found charset to UTF-8. - (2) More than 1 character set found: - The module displays a drop-down listbox with all found character sets. User selects one and clicks "Go" button. The module will do the conversion from the selcted character set to UTF-8. - (3) No character set found: - The module displays a drop-down listbox with default character sets. User selects one and clicks "Go" button. The module will do the conversion from the selcted character set to UTF-8. - - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - BSD - - 0.2 - 2010-10-25 - Beta - This module requires PHP ICONV module to be installed and enabled. - - \ No newline at end of file diff --git a/mods/utf8conv/module_install.php b/mods/utf8conv/module_install.php deleted file mode 100644 index d319de129..000000000 --- a/mods/utf8conv/module_install.php +++ /dev/null @@ -1,67 +0,0 @@ -addError(array('MODULE_INSTALL', '
  • '.$directory.' does not exist. Please create it.
  • ')); -} else if (!is_writable($directory) && @chmod($directory, 0666)) { - $msg->addError(array('MODULE_INSTALL', '
  • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
  • ')); -} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/utf8conv/module_uninstall.php b/mods/utf8conv/module_uninstall.php deleted file mode 100644 index 52d8f8129..000000000 --- a/mods/utf8conv/module_uninstall.php +++ /dev/null @@ -1,31 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/utf8conv/readDir.php b/mods/utf8conv/readDir.php deleted file mode 100644 index c84026709..000000000 --- a/mods/utf8conv/readDir.php +++ /dev/null @@ -1,148 +0,0 @@ -recursive = false; - $this->errcount = 0; - $this->events = array('readDir_dir', 'readDir_file'); - $this->handlers = array(); - } - - /*** Set the directory to read* @param string full directory path*/ - function setPath( $path ) - { - if (!is_dir($path)) - { - $this->_error('The supplied argument, '.$path.', is not a valid directory path!'); - return false; - } - - $this->path = $path; - return true; - } - - /*** Set and event handler* @param string event name* @param string event handler function name*/ - function setEvent( $event, $handler ) - { - if (in_array($event, $this->events) !== false) - { - $this->handlers[$event] = $handler; - } - else - { - $this->_error('Event Type specified does not exist.'); - return false; - } - return true; - } - - /*** Set if we want to read through sub folders recursively* @param bool TRUE or FALSE*/ - function readRecursive( $bool = true ) - { - $this->recurse = $bool; - } - - /*** Read the directory*/ - function read() - { - if ( !is_dir($this->path) ) - { - $this->_error('Directory to read from is invalid.'.'Please use setPath() to defind a valid directory.'); - return false; - } - - // all set, start reading - return $this->_read($this->path); - } - - function _read($dir) - { - if ($dh = opendir($dir)) - { - $i = 0; - while ($el = readdir($dh)) - { $path = $dir.'/'.$el; - - if (is_dir($path) && $el != '.' && $el != '..') - { - if ($this->_trigger('readDir_dir', $path, $el) == -1) - { - closedir($dh); - return true; - } - - if ($this->recurse) - { - // read sub directories recursively - $this->_read($path); - } - } - elseif (is_file($path)) - { - if ($this->_trigger('readDir_file', $path, $el) == -1) - { - closedir($dh); - return true; - } - } - - $i++; - } - - closedir($dh); - return true; - } - - else - { - $this->_error('Could not open the directory, '.$path); - } - return false; - } - - function _trigger($event, $path, $el) - { - if ($this->handlers[$event]) - { - if (!function_exists($this->handlers[$event])) - { - $this->_error('User Function, '.$this->handlers[$event].', defined for the event, '.$event.', does not exist'); - return false; - } - - return call_user_func($this->handlers[$event], $path, $el); - } - } - - function _error($txt) - { - $this->errcount++; - $this->errtxt = $txt; - } - - /*** View the last error logged*/ - function error() - { - return $this->errtxt; - } - - /*** View the last error number*/ - function errorCount() - { - return $this->errcount; - } -} - -?> diff --git a/mods/utf8conv/utf8conv.php b/mods/utf8conv/utf8conv.php deleted file mode 100644 index e4c5b1e8d..000000000 --- a/mods/utf8conv/utf8conv.php +++ /dev/null @@ -1,442 +0,0 @@ -(.*)#i", file_get_contents($filename), $matches)) - { - $charset = strtoupper(trim($matches[1])); - } - } - - return $charset; -} - -/** -* This function finds all charsets defined in all html & xml files in the given zip -* and save the charsets in global variable $charsets -* @access public -* @param string $path The full path and name of the files to find charset definition -* output of readDir -* @author Cindy Qi Li -*/ -function find_all_charsets($path, $filename) -{ - global $charsets; - - $charset = find_charset($path); - - if (strlen($charset) > 0 && !in_array($charset, $charsets)) - { - array_push($charsets, $charset); - } -} - -/** -* This function: -* 1. replaces the charset strings defined in html "meta" tag and "charset" tag in xml files to "UTF-8"; -* 2. convert files from old character set to UTF-8. -* @access public -* @param string $path The full path and name of the files to find charset definition -* output of readDir -* @author Cindy Qi Li -*/ -function convert($path, $filename) -{ - global $charset_from, $charset_to; - global $filetypes; - global $charsets; - - // 1. html & xml files: - // if charset is defined, convert from defined charset, - // otherwise, convert from $charset_from - // 2. Other files with defined file type - // convert from $charset_from - if ((in_array('html', $filetypes) && preg_match("/\.html$/i", $path)) || - (in_array('xml', $filetypes) && preg_match("/\.xml$/i", $path))) - { - $charset_in = find_charset($path); - - $content = file_get_contents($path); - // convert file - if (strlen($charset_in) > 0) - { - // replace old charset in tag to new charset - $content = str_ireplace($charset_in,$charset_to,$content); - - // convert file from old charset to new charset - $content = iconv($charset_in, $charset_to. '//IGNORE', $content); - } - else - { - $content = iconv($charset_from, $charset_to. '//IGNORE', $content); - } // end inner if - - $fp = fopen($path,'w'); - fwrite($fp,$content); - fclose($fp); - } - elseif (in_array(strtolower(substr($path, (strrpos($path, '.')+1))),$filetypes)) - { - $content = file_get_contents($path); - $content = iconv($charset_from, $charset_to. '//IGNORE', $content); - - $fp = fopen($path,'w'); - fwrite($fp,$content); - fclose($fp); - } -} - -/** -* This function displays all values in $charsets_array in a drop-down box -* @access public -* @param array $charsets_array The options to display -* @author Cindy Qi Li -*/ -function display_options($charsets_array) -{ -?> - -extract(PCLZIP_OPT_PATH, $module_content_folder) == 0) - { - clear_dir($module_content_folder); - die("Cannot unzip file " . $_FILES['userfile']['tmp_name'] . "
    Error : ".$archive->errorInfo(true)); - } -} - -if (isset($_POST['Convert']) || $_POST['Go']) -{ - // 2. Read content folder recursively to convert. - include_once("readDir.php"); - - $dir = new readDir(); - // set the directory to read - if (!$dir->setPath( $module_content_folder )) - { - clear_dir($module_content_folder); - die($dir->error()); - } - - // set recursive reading of sub folders - $dir->readRecursive(true); - - // set a function to call when a new file is read - if (!$dir->setEvent( 'readDir_file', 'find_all_charsets' )) - { - clear_dir($module_content_folder); - die($dir->error()); - } - - // read the dir - if ( !$dir->read() ) - { - clear_dir($module_content_folder); - die($dir->error()); - } - - // If only one character set is found in all html & xml files - if ((count($charsets) == 1 && $_POST['Convert']) || - (count($charsets) != 1 && $_POST['Go'])) - { - if (count($charsets) == 1 && $_POST['Convert']) - $charset_from = $charsets[0]; - elseif (count($charsets) != 1 && $_POST['Go']) - $charset_from = $_POST['charfrom']; - - // Real conversion - $dir = new readDir(); - $dir->setPath( $module_content_folder ); - $dir->readRecursive(true); - $dir->setEvent( 'readDir_file', 'convert' ); - $dir->read(); - - // 3. ZIP converted files - if ($_POST['Convert']) $orig_filename=$_FILES['userfile']['name']; - elseif ($_POST['Go']) $orig_filename=$_POST['filename']; - - $zip_filename = AT_CONTENT_DIR . "/" . str_replace('.zip','_'.$charset_to . '.zip', $orig_filename); - - $archive = new PclZip($zip_filename); - - if ($archive->add($module_content_folder, PCLZIP_OPT_REMOVE_PATH, $module_content_folder) == 0) { - clear_dir($module_content_folder); - die("Cannot zip converted files.
    Error : ".$archive->errorInfo(true)); - } - - // 4. force zipped converted file to download - ob_end_clean(); - - header('Content-Type: application/x-zip'); - header('Content-transfer-encoding: binary'); - header('Content-Disposition: attachment; filename="'.htmlspecialchars(basename($zip_filename)) . '"'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Pragma: public'); - - readfile($zip_filename); - - // 5. clear all temp files - unlink($zip_filename); - clear_dir($module_content_folder); - } -} -// End of main convert process - -include_once (AT_INCLUDE_PATH.'header.inc.php'); - -// Check ICONV library is installed and enabled -if (!extension_loaded('iconv') || !function_exists('iconv')) -{ - die ('Warning: This utility is not available as PHP ICONV module is not installed or not enabled.'); -} -?> - - - - - - -
    - -
    - -
    - Upload a zip file to convert the character set to UTF-8: -
    - -
    - - -
    - -
    - - -
    - - 1) - { -?> -
    - Multiple character sets are found, please select one to convert from: -
    - -
    - No character set found in zip file, please choose one character set to convert from: -
    - - -
    - -
    - - -
    - -
    -
    - - - - - - diff --git a/mods/wiki/LICENSE b/mods/wiki/LICENSE deleted file mode 100644 index 8d85d0b89..000000000 --- a/mods/wiki/LICENSE +++ /dev/null @@ -1,36 +0,0 @@ - -Public Domain -------------- - -The ewiki+ distribution for the most part is Public Domain. This means -that you can absolutely freely use, modify and redistribute it and any -parts of it. No rules, no restrictions, not even attribution enforced. - -That's why you could apply your license of choice (be it the GNU GPL, -LGPL, BSD or MIT/X11, MPL, QPL, PHP, Perl, CDDL, Artistic, MSFT EULA, -AGPL, SISSL, IBM CPL, Apache, ASDL or so) to it and distribute and use -it further under that's conditions. The Public Domain status of this -original package doesn't affect or hinder you in any way thereby. - - -Exceptions ----------- - -Parts of the distributed tarball however fall under different licenses, -namely: - -+------------------------+--------------------------------------------+ -| plugins/auth-liveuser/ | GNU Lesser General Public License, 2.1+, | -| | a PEAR class library, http://pear.php.net/ | -+------------------------+--------------------------------------------+ -| tools/whiptail | GNU Library General Public License, 2.0+?, | -| | originally from Debian project, just see | -| | http://google.com/search?q=whiptail | -+------------------------+--------------------------------------------+ -| plugins/lib/js.php | only FreeWare, but PDification planned, | -| | http://phpjs.berlios.de/ | -+------------------------+--------------------------------------------+ - -Our "extra tarball", btw, also contains source code from different -projects and regularily under different licenses. - diff --git a/mods/wiki/README_ATUTOR_MODULE b/mods/wiki/README_ATUTOR_MODULE deleted file mode 100644 index 825c6a6fd..000000000 --- a/mods/wiki/README_ATUTOR_MODULE +++ /dev/null @@ -1,30 +0,0 @@ -README ATutor Module -This version of the ewiki module for ATutor is available in English, as well as some limited Spanish and German. Languages are automatically available based in the perferred language set in the users browser. See the translation section in the ewiki.php file if you wish to start a new language - -Installing EWiki for ATutor - -1. Download the appropriate version of the module from the ATutor modules site. - -ATutor Modules -http://www.atutor.ca/atutor/modules.php - -2. Delete any previously installed wiki/ directory if you are upgrading. NOTE: Wiki files will be preserved in the course content/ directories. - -3. Extract/Unzip the downloaded file into the mods/ directory of your ATutor installation. This will create a directory called wiki/. (you may wish to modify the config.php file to enable/disable EWiki plugins) - -On Linux ->tar xzvf atutor_ewiki-R1.02b.tar.gz - -Windows -left or right click the file to unzip it into the mods/ directory -(you might use Winzip or Winrar to extract the file) - -4. Login to ATutor as the administrator - -5. Choose the Modules Tab, then choose Install Modules. - -6. Select EWiki from list of uninstalled modules, then press Install Confirm by clicking the Yes button to complete the installation. - -7. From the Module Manager select the Wiki module then press Enable to make EWiki available to users on the system. - - diff --git a/mods/wiki/config.php b/mods/wiki/config.php deleted file mode 100644 index b7e091c03..000000000 --- a/mods/wiki/config.php +++ /dev/null @@ -1,123 +0,0 @@ - array("edit", "delete", "control", "admin")); -} - -define("EWIKI_PROTECTED_MODE", 1); - - if($_SESSION['is_admin'] ==1){ - define("EWIKI_AUTH_DEFAULT_RING", 0); - }else if ($_SESSION['enroll'] ==0){ - define("EWIKI_AUTH_DEFAULT_RING", 3); - }else{ - define("EWIKI_AUTH_DEFAULT_RING", 2); - } - // setlocale(LC_TIME, "nl"); - -#-- helper scripts for broken/outdated PHP configurations -include_once("plugins/lib/fix.php"); -include_once("plugins/lib/upgrade.php"); - - -#-- load plugins, before core script ewiki.php -/* Load admin plugins id ATutor user is_admin or privileged*/ -if($_SESSION['is_admin'] ==1 || authenticate(AT_PRIV_WIKI, AT_PRIV_RETURN)){ - include_once("plugins/admin/control.php"); -} - -include_once("plugins/init.php"); -//include_once("plugins/page/README.php"); -include_once("plugins/pluginloader.php"); - -include_once("plugins/action/rss.php"); - -include_once("plugins/appearance/title_calendar.php"); -include_once("plugins/appearance/listpages_ul.php"); - -include_once("plugins/auth/auth_perm_ring.php"); -include_once("plugins/auth/userdb_userregistry.php"); -include_once("plugins/auth/auth_method_http.php"); - -include_once("plugins/aview/linktree.php"); -include_once("plugins/aview/toc.php"); - -include_once("plugins/edit/templates.php"); - -include_once("plugins/interwiki/intermap.php"); - -include_once("plugins/lib/feed.php"); -include_once("plugins/lib/mime_magic.php"); - -include_once("plugins/markup/css.php"); -#enable for page footnotes (footnote anchors are broken however) -#include_once("plugins/markup/footnotes.php"); -include_once("plugins/markup/rescuehtml.php"); -#enable for full html support (to allow students to create homepages, for instance) -#include_once("plugins/markup/rendering_null.php"); -include_once("plugins/markup/naturallists.php"); -//include_once("plugins/markup/fix_source_mangling.php"); -include_once("plugins/markup/braceabbr.php"); -include_once("plugins/markup/table_rowspan.php"); - -include_once("plugins/meta/meta.php"); - -include_once("plugins/module/downloads.php"); -include_once("plugins/module/calendar.php"); -include_once("plugins/module/tour.php"); - -include_once("plugins/mpi/mpi.php"); - -include_once("plugins/notify.php"); - -include_once("plugins/page/powersearch.php"); -include_once("plugins/page/ewikilog.php"); -include_once("plugins/page/wordindex.php"); -include_once("plugins/page/imagegallery.php"); -include_once("plugins/page/orphanedpages.php"); -include_once("plugins/page/textupload.php"); -include_once("plugins/page/wantedpages.php"); -include_once("plugins/page/wikidump.php"); -include_once("plugins/page/wikinews.php"); -include_once("plugins/page/hitcounter.php"); -include_once("plugins/page/scandisk.php"); -include_once("plugins/page/recentchanges.php"); -include_once("plugins/linking/link_icons.php"); - -include_once("ewiki.php"); -?> diff --git a/mods/wiki/doc/Acronyms b/mods/wiki/doc/Acronyms deleted file mode 100644 index 266d50abb..000000000 --- a/mods/wiki/doc/Acronyms +++ /dev/null @@ -1,112 +0,0 @@ -Use this file as template page for the markup/abbr plugin. Most -terms herein are computing/technics related (except a few runaways). - -|ABI|Application Binary Interface| -|API|Application Programming Interface| -|BCD|binary coded decimal| -|BIOS|Basic Input/Output System| -|BNC|Bayonet Nut Connector| -|CET|Central European Time| -|CGI|Common Gateway Interface| -|CISC|Complex Instruction Set Computer| -|CLI|Command Line Interpreter| -|CMOS|Complementary Metal Oxide Semiconductors| -|CMYK|Cyan, Magenta, Yellow, Black| -|CNC|Computer Numeric Control| -|CPU|Central Processing Unit| -|CRC|cyclic redundancy checking| -|CSS|cascading style sheets| -|DMA|Direct Memory Access| -|DNS|Domain Name System| -|DOS|Disk Operating System| -|DTD|Document Type Definition| -|EOF|end of file| -|EOT|end of tape| -|FAQ|Frequently Asked Questions| -|FAT|File Allocation Table| -|FOAF|Friend Of A Friend| -|FTP|File Transfer Protocol| -|GMT|Greenwhich Mean Time| -|GPL|(GNU projects) General Public License| -|HTML|HyperText Markup Language| -|HTTP|HyperText Transfer Protocol| -|IRC|Internet Relay Chat| -|ISDN|Integrated Services Digital Network| -|ISP|Internet Service Provider| -|JIT|Just-in-time| -|KISS|"Keep It Simple, Stupid" principle| -|LAN|local area network| -|LCD|Liquid Crystal Display| -|LED|light-emitting diode| -|LID|Light-Weight Identity| -|LSB|least significant bit| -|MBR|Mmaster Boot Record| -|MSB|most significant bit| -|MSIE|Microsoft Intranet Exploder| -|OCR|Optical Character Recognition| -|PHP|PHP Hypertext Processor language| -|PNG|Portable Network Graphics| -|RDF|Resource Description Framework| -|RFC|Request For Comments| -|RGB|Red, Green, Blue| -|ROM|Read-Only Memory| -|RPG|Report Program Generator| -|SCSI|small computer system interface| -|USB|Universal Serial Bus| -|UTC|Universal Time Code| -|WAN|wide area network| -|WLAN|wireless local area network| -|WWW|World Wide Web| -|XML|Extensible Markup Language| -|XUL|XML User-interface Language| -|XUP|XML User Profiles| -|EULA|End User Licence Agreement| -|NDA|Non-Disclosure Agreement| -|TCO|Total Cost of Ownership| -|CEO|Chief Executive Officer| -|CIO|Chief Information Officer| -|CRM|Customer Relationship Management| -|FOSS|Free and Open Source Software| -|FUD|Fear, Uncertainty and Doubt| -|MBA|Master of Business Administration| -|SLA|Service Level Agreement| -|ATM|Automated Teller Machine| -|BBQ|barbecue| -|ISBN|International Standard Book Number| -|MTB|mountain bike| -|PVC|polyvinyl chloride| -|SOS|Save Our Souls| -|SPF|Sun Protection Factor| -|UFO|unidentified flying object| -|VCR|Video Cassette Recorder| -|BBC|British Broadcasting Company| -|BBS|Bulletin Board System| -|BSD|Berkeley System Distribution (Unix derivate, and a license)| -|CCC|Chaos Computer Club| -|CIA|Central Intelligence Agency| -|ECB|European Central Bank| -|ECMA|European Computer Manufacturers Association| -|ESA|European Space Agency| -|FBI|Federal Bureau of Investigation| -|FSF|Free Software Foundation| -|IBM|International Business Machines Corp.| -|IETF|Internet Engineering Task Force| -|IRTF|Internet Research Task Force| -|NBC|National Broadcasting Company| -|UNICEF|United Nations Children's Fund| -|UNO|United Nations| -|USA|United States of America| -|WIPO|World Intellectual Property Organization| -|WTO|World Trade Organization| -|HIV|Human Immuno-deficiency Virus| -|AFAIK|as far as I know| -|AKA|also known as| -|BTW|by the way| -|BWQ|buzzword quotient| -|DIY|do it yourself| -|FYI|for your information| -|IANAL|I am not a lawyer| -|IIRC|if I recall/remember correctly| -|IMHO|in my humble (honest) opinion| -|RTFM|Read the fine (fucking) manual!| - diff --git a/mods/wiki/doc/AdminTasksSql b/mods/wiki/doc/AdminTasksSql deleted file mode 100644 index f25ee1b7a..000000000 --- a/mods/wiki/doc/AdminTasksSql +++ /dev/null @@ -1,114 +0,0 @@ - -Administrative tasks with SQL ------------------------------ - -If you run your Wiki with one of the SQL backends, you can leverage -the advanced functions of your database server in some cases. It is -not necessary to create a complicated or slow script to clean things -up then. - -Suddenly many settings in ewiki pages are encoded into the {meta} -field, which isn't accessible from SQL queries. But the most basic -page flags always remain accessible, so you can utilize it within -queries. - -A few examples for common tasks follow. It is recommended that you -always perform a SELECT, before you start an unrecoverable DELETE -or UPDATE or something else. -Enter the given SQL commands into PhpMySqlAdmin or your commandline -'mysql' program, if you have a direct or shell/ssh access to the -Web server near your Wikis database. The examples here are wrapped -across multiple lines to make them more readable, but you should -enter them without any newline in between, and append the ; -semicolon always at the end. - - - -deleting old binary entries ---------------------------- - -If your users upload lots of images and data -files, and you want to get rid of them, this -recipie may be for you. - - The {flags} field is an integer, with basic page settings encoded - bit wise. Of course you can utilize this in SQL with the bit - operations that every database supports. You however first need - to look up the page flag values in the core script (ewiki.php). - - The EWIKI_DB_F_BINARY flag for example corresponds to the 2 (two, - decimal). - - You also have a {lastmodified} field with every page / file entry - in your ewiki database, which you can query for. You however need - to calculate your wanted time frame into seconds, because all time - fields in the ewiki database use Unix timestamps (seconds since - 01-01-1970 00:00). - Once day has 24 hours, 60 minutes, a 60 seconds. So for 120 days - you would multiply 24*60*60 with *120 and get 10368000 seconds, - which we could use in the SQL query (we however simply embed the - formula here): - - SELECT pagename, version - FROM ewiki - WHERE (lastmodified + 120*24*60*60 < unix_timestamp()) - AND (flags & 2) ; - - And after testing it, to really delete the old binary entries - then: - - DELETE - FROM ewiki - WHERE (lastmod ... - AND (flags ... - - - -deleting similarily named but redundant pages ---------------------------------------------- - -If some spammer pestered you with almost same- -named pages (by using a script or so), you can -easily get rid of it. - - Regular expression provide a powerful means to select multiple - database entries at once. Allthough you could do the same with - the 'ewikictl' utility or a similar of our database tools/ - collection, the according SQL query may help you too. - - You probably know *.* from old DOS days, Windows UIs or the Linux - commandline - regular expressions are almost the same, only that - you write ".+" to say "one or more random characters". There are - other things like "[0-9]" or "[a-z]" supported in regular - expressions, but you should better read a real reference on this; - perlre(1) or regex(3) are a good start. - - But just the example, assuming you wanted to delete a bunch of - pages called "SsSs..." (with some numbers at the end) from your - Wiki database: - - DELETE FROM ewiki - WHERE (pagename REGEXP '^SsSs.+') ; - - Or for PostgreSQL: - - DELETE FROM ewiki - WHERE (pagename ~ '^SsSs.+') ; - - - -delete non-existent _BINARY + _DISABLED entries ------------------------------------------------ - - Referenced images, that ewiki couldn't find on a remote web server, - and therefore didn't cache as internal:// entry remain in the DB - as empty entries. You may want to delete them (allthough they don't - occupy much space). - - DELETE FROM ewiki - WHERE (flags & (2+4)) - AND (pagename REGEXP 'http://') - - - - diff --git a/mods/wiki/doc/CHANGES b/mods/wiki/doc/CHANGES deleted file mode 100644 index 0b63fe25f..000000000 --- a/mods/wiki/doc/CHANGES +++ /dev/null @@ -1,464 +0,0 @@ - -ToDoLog -¯¯¯¯¯¯¯ - -R1.03a -- CoreSplit and cutting a few older features -- GetText support/emulation replaces ewiki_t() -- full security review (htmlentities on bare $action and page $titles) -- getting rid of JavaScript for image uploads -- ... - - -ChangeLog -¯¯¯¯¯¯¯¯¯ - -R1.02b - 10-06-2005 -* parts of the documentation have been moved into the new doc/ directory and - new information snippets have been added: AdminTasksSql, LinkSpammers, - MagicFields, SetupTool, Acronyms, ... -* all regular plugins are now accompanied by .meta description files for - more efficient management, dependency resolution and other purposes, a - description of the simplistic format is in [doc/PluginMetaData] -* three plugins (downloads, subpage) had to be renamed for filename uniquenes -* the older SetupWizard has been adapted -* a new console setup tool has been added, for faster config.php creation - and monsterwiki plugin melting -* the "ewiki.ini" scheme has been introduced for simpler configuration -* many syntax and typo fixes -* new fragments/ (printhint, head/core) -* clickableimages patch documented and fixed, -* new plugins: ini, diff_gnu_safemode (Menno Lodder), manpage export, - userdb_xprofile, ext_multi (database-multiplex), ext_subwiki (database - fragmentation and API level), debug/xerror, helptext, msg, limitlinks, - anacron, captcha, feedparse, xml, http, http_cache, sync, libxprofile, - webdav, upgrade.php (PHP5 compatibility/emulation), a_nofollow, - new_nofollow, link targets, tabel_colspan (Marc Schiffbauer), AddComment, - InlineFrame, FarInclude, RegisterSpam mpi, Syndicate (uses new feedparse - backend), antibot_captcha, anitbot_checkbox and other anti-spam triggers, - arrowadmin (Menno Lodder), pluginmetadata -* new _ARCHIVE flag introduced (yet unused) -* fixes in plugins: userdb_sql, toc, tex (Francois), email_protect (multi- - engaging now prevented) -* SqlQuery and BrainFuck mpi plugins are disabled again, escaping and - back-conversion were added in the mpi core -* multiple fixes to "db/any" for Postgres compatibility (a.o. Josh More/ - AllianceT) -* flat_files database backend had a non-critical fixed (redundant content:) -* introduction of _config[ua] string and X-Server response header -* the cron scripts have been extended and partly fixed -* t_revert was corrected -* introduced InterWiki plugins for neighbor pages, near links, sisterpages - (all using the metadb data file) -* completed first minimal WebDAV interface -* splitting of the ewiki.php core script (future ver) has been prepared -* internal changes: $title can be overriden from _interwiki() link tweak - plugins, interxhtml URL checking fixed, _script_url() has been tweaked - again (jbw), format bock 0x0040 flag handling fixed (Marc Schiffbauer), - fix for random {flags} clearing in _PROTECTED_MODE, slightly larger - default for "edit_box_size", WikiRegex underscore fix, image extension - URL check, fix in ewiki_db::GETALL, ewiki_stripentities(), ewiki_form(), -* patch for userdb_ldap and method_http authentication methods (AllianceT) - - -R1.02a - 27-08-2004 -* the database interface was overhauled (much cOOler now) -* new CSS class names fragment the final pages more precisely -* some typecasting was introduced to work around PHP5s changed array_merge() -additions: -* introduced general html head includes in fragments/ -** "meta.php" inserts tags from entries of {meta}{meta} box -** "core.php" adds NOINDEX to robots meta tags for old page ?versions= -* added "z.php" script as general dispatcher for application interfaces - like WikiToXmlRpc and OpenSearch, a general XML-RPC lib now is included -* OpenSearch interface for cross-site scanning was added (MySQL only) -* BannedLinks (defacing unwanted URLs) and BlockedLinks against vandalism, - optionally with future-proof whois lookups against commercial spammers -* spellcheck plugins were moved, and a new aspell variant was added -* QuickDiff action -* rss action plugin and general RSS/Atom feed output support (with TCN) -* aview/aedit_ plugins were moved into their own edit/ directory -* blog support via multiple plugins or as mpi_ extension as contributed - by Wojciech Jan Kalka -* edit/ plugin for setting the AuthorName on the fly, one to set certain - page flags (_MINOR or _HIDDEN) and one to set changelog entries -* lock and warn plugins for concurrect edits -* link-validating RefererLog and PingBack plugins -* TimeStampMarkup, Short|Wiki links, support for for abbreviations in braces, - a plugin for TeX markup (uses MimeTeX and inserts .gif images) -* XFN plugin (XHTML Friends Network) -* mpi_honeypot, mpi_addlink, enhanced mpi_insert -* MiniDump, WikiDump2 -* DocBook filter added for TextUpload plugin -* refreshed administration tools/ suite, which also introduced WikiCommander - (a NC-lookalike database control tool), an ewikictl web-based frontend, - and advent of the tools/cron.d/ scripts -changes: -* renewed init-pages/ and default (index) page name is now "FrontPage" -* PATH_INFO is enabled per default again for Apache servers -* added User-Agent logging -* {meta} info is now displayed more verbose on info/ pages -* commonly used ...&action=view URLs can now be enabled more easily -* produces more XHTML like tags (at least
    and ) -* _DB_F_HTML flag is now preserved on changes -* new page rendering block flag 0x0400 to decode < and > again -* logging of failed auth calls -* CommunityWiki: and WikiFeatures: are now in the default interwiki list -* introduction of obscured (=numeric) error message numbers for security - leak misconfigurations -* Image resize plugins are now called regardless of filesize to allow for - resizing by width and height; a more advanced variant was added -* spages/ now holds AbandonedPages, HitCounter, LeastPopular, LinkLessPages, - OrphanedPages, PageLinks, PageRefs, PageSize, WantedPages and WordIndex, - but the "PageIndex" is now a core feature -* SetupWizard moved into tools/ -* spages now tries to serve binary files (images) -internals: -* new _DB_F_MINOR page flag (respected on RecentChanges) -* ewiki_script_url() now works as enhanced alias to ewiki_script() -* _list_pages() got new list call parameter format -* extended ewiki_interwiki() for non-hyperlink uses (XML meta data, XFN) -* ewiki_author_html() deciphers the {author} field now -fixes: -* fixed [noinlineimage.png#] support, ewikictl --rm pattern matching, - search_highlight to not downcase found words, serious bug in StaticPages - plugin, reworked link_regex to not break at question mark, sub-links and - fixed chunking on info/ page, removed dependency on mysql_ping, core - script made slightly more E_NOTICE clean, fixed action pages for emptied - page versions (not showing up on info/ and info/ now coming up instead of - edit/ box), and fixes for auth/ and in auth-liveuser/ plugins - - -R1.01e - 20-05-2004 -* default page is now called "FrontPage" (previously just "ErfurtWiki") -* added Dutch page translations, as contributed by Koen Roggemans -* the new flat file database plugin 'dzf2' is quicker, stores compressed - files and is plattform intercompatible -* new, general and user interface plugins were added: markup/abbr, db/zip, - aedit_pageimage, aedit_templates, fpage_copyright, fpage_logo (Andy), - imgfile_naming (orig file names instead of md5md5md5-internal://), - subwiki (database fragmentation), instanturls, instanturl_find, - input_trimming, - meta (new plugin framework) and builtincategories, f_title; -* also a usemod/moinmoin-lookalike RecentChanges page plugin together with - a plugin to specify a {meta} log entry; -* the new "raw" action plugin allows to retrieve the plain Wiki page source -* added markup plugins include: naturallists, table_rowspan, update_format -* mpi plugin framework was overhauled, new additions include: mpi_brainfuck, - mpi_embed, mpi_settitle, mpi_sqlquery, mpi_survey (for user polls) -* overhauled liveuser authentication plugin framework -* initial [.SubPage] linking support (suggested by Timm) -* init plugin now overrides builtin database INIT, email protection plugin - now mostly disables itself if human validated -* fixed licensing issues, GPL plugins now separate -* code fixes include: _script_url() web server port patch (Christian Buck), - fixes for PHPs incomplete session.trans_sid feature, _protected_mode and - security fixes, image linking fixed, and table markup is more forgiving - now (allows spaces after the trailing | dash, but not for the first row), - fileupload javascript error, corrected _preview newline handling, - space indentation closing and

    code changed, _format() block splitting, - edit_box_size setting (missed $e_config), removal of all pass-by-reference - calls -* internal/API changes: _UP_PARENTID for image uploads, ewiki_lowercase() - is now a core function (moved from PowerSearch), normalized
    output - from ["edit_form_append"], new ewiki_new_data() to create empty page $data - hashes, CSS page (class) names are mangled for more standards compliance, - internal "create" action for auth plugins, introduction of _HIDDEN flag -* allowed for enumerated lists with html tag type="" attribute -* provide a RSS feed for UpdatedPages -* edit/ page and for CSS class and - style instructions with the new "@@" markup -* plugins/markup_css_singleat allows for CSS divs with a single @ -* added plugins/patchsave to support concurrent page changes (GNU diff+patch) -* all www accessible tools/ have been renamed, the backup and the restore - tools are now wrappers around ewikictl -* new plugins: aview_imgappend, spages (read static pages from a directory), - title_calendar (Andy), action_extracttodo (Andy), - admin/control (for renaming pages and flag changing), - admin/page_searchcache (creates db text entries from dynamic pages) -* notify plugin is now language aware -* fix for ewiki_control_links() to honor the $action param (Andy), the - senseless tag was removed (Culley), the {meta} field now gets - saved correctly for _TEXT database entries (Andy) -* introduction of $ewiki_config[] which strips some data things from the - $ewiki_plugins[] array, and will further replace some of the constants -* added plugin hooks ["list_transform"], ["page_final"] -* renaming of _page_title to _split_title, and _print_title to _add_title, - added _make_title() to return a html string with optional link per cfg. -* moved and renamed multiple plugins into plugins/contrib/, and also made - all mpi stuff go into plugins/mpi/ -* added the GNU GPL with a note to the plugins/contrib/ directory -* extended email_protect plugin to hide addresses for diff/ and info/ also -* ewiki_page_view() now contains the printing code for ordinary wiki pages -* {meta} is now automatically un/serialized() in the database layer -* rendering_pre was replaced by markup_code -* most example layouts went into examples/, re-added examples/yourthemes.php -* php-patches/array_merge for PHP5 beta2 support (with lots of error messages) - - -R1.01a - 04-08-2003 -* markup changes: -** typewriter like fonts will be used for text enclosed in == - (previously spaces to the left were used for that) -** text is now right aligned with ">>" to the left -** added markup for preformatted text:

     at the very beginning of a line
    -   starts a paragraph and a 
    (also lowercase) ends it again - (the empty lines markup has been removed during development) -** added SPACEs/TAB indentation support (CSS only) -** anchors are now defined placing the hash sign before the square brackets - #[anchornane], and that anchor can then be jumped to using [#anchorname] -* fixed/removed define() from default config.php which prevented binary uploads -* fixed internal://md5sum filename generation for uploaded binary/image files -* new plugins are: aview_backlinks, link_target_blank, page_wantedpages, - page_interwikimap, aview_linktree (which shows path from current to index - page), page_wikiuserlogin (to add an author name for page savers), - markup_paragraphs, imgresize_magick, fun_wella, spellcheck2 (AndyFundinger), - aview_control2, link_css, link_icons, binary_store (keeps uploaded files - separate from real database), pluginloader (for action and page plugins) -* renamed plugins/downloads_view.php to aview_downloads.php -* added mpi_phpwiki, which emulates AllPages, AllUsers -* changed all EWIKI_T_ constants into an array, which can now be accessed - via the more flexible "ewiki_t()" function -* finished read only access with plugins/db_phpwiki13.php, guessworking - write access is now also available, but disabled per default -* the ewiki_log() function is now used for debug messages -* InterWiki:Links are working again (seems they got broken previously) -* changed _binary_save_image() to handle binary and image files different -* extracted the squirrel image from example-1.php, so it works in '97 browsers -* the new example-1 wiki wrapper has support for an editable MainMenu -* implemented core ewiki_auth() using permission levels in _PROTECTED_MODE, - added plugins: auth_user_array, auth_method_http, auth_perm_ring and - auth_perm_old for compatibility -* added/activated fragments/strike_register_globals.php -* the plugin task "url_link" has been renamed to "link_url" to follow the - new and more consistent naming scheme -* the admin interface scripts (tools/) are now access restricted per default -* added Last-Modified: HTTP header (edit date of current page) -* email_protect &version= bug fixed, cookie is now set once access is granted -* introduced reliable global $ewiki_id -* fixed some "&" page name problems -* fixed MySQL database action "SEARCH" -* ewiki_script() unifies URL generation from $action,$id,EWIKI_SCRIPT and - also allows to work around some design flaws and unreliabilities -* fixed Refresh: HTTP header, which lead IE to reload constantly after save -* plugins/calendar.php localized to en_ (APF) -* the meaning of the EWIKI_LOGLEVEL setting has changed - - -R1.00f - 20-05-2003 -* USE_PATH_INFO now defaults to off, due to the many broken Apache versions -* added str_rot17 to make email_protect links valid for one session only -* fixed string conversion bug in _p_ordered_list once more (Carsten) -* added initial db_phpwiki13.php plugin (read-only) -* added page_since_updates.php (Carsten) -* renaming of plugins/fancy_indexing.php to listpages_tbl.php -* added listpages_br.php, listpages_ul.php (previously part of core ewiki.php) -* allowed for ~PhpWiki13 ~WikiWordEscaping -* new markup for [http://link "entitling"], because dashes hurt table markup -* international characters` html entities (Ӓ) are now reconverted -* added page version holes support in db_flat_files -* added DELETE and SQL subfunctions in db interface (for tools/) -* db field 'meta' is now a serialized() array with http headers / bonus data -* added plugins/downloads.php, which allows files to be saved and retrieved -* added plugins/mime_magic.php (GPL code) -* changes in default distribution: index.php removed, config.php added, and - example-1.php is now set as DirectoryIndex in .htaccess and .nwaccess -* added otherwise unused EWIKI_VERSION constant (as requested by Beate ;) -* merged db_fast_files into db_flat_files (both formats can be used together) -* added plugins/page_aboutplugins.php -* now allows for wiki page title splitting (as seen in other WikiWare) -* extended download plugin to support page attachments -* renamed plugins/pagediff.php to diff.php -* added plugins/downloads_view.php to show attachments below a page -* added plugins/page_scandisk.php -* fixed the missing email_protection of the edit box -* added redirection after edit/save -* added plugins/notify.php which can send a mail whenever a page gets edited -* added page diff plugin which is powered by the GNU diff util (more reliable) -* added page anchor support (define [#anchor] and link [WikiPage#anchor]) -* added tools/ewikictl -* added plugins/fancy_list_dict.php to enhance WordIndex and PageIndex -* renamed most ["page"] plugins to plugins/page_*.php -* reworked _binary_save_image() and moved _resize_image_gd() into a plugin -* added image width= and height= support in _link_regex_callback() and - the database plugins for mysql and adodb (dba and dbff are unsupported) -* images can now be rescaled by appending "?x=..&y=.." to [url] references -* fixed a _scan_wikiwords / pre parsing bug with colons - - -R1.00e - 06-04-2003 -* db_fast_files for serialized()/gzencoded() files contributed by Carsten Senf -* added error output for database initialization -* added edit mode cancel link -* added edit-textarea resizing JavaScript link -* added small README.de -* fixed bug with repeatedly reconcatenated $ewiki_author string -* fixed fputs() bug in db_flat_files, which lead to PHP4.1 incompatibility - (reported by Beate Paland) -* workaround for PATH_INFO bug of Apache+CGI_PHP -* added page plugin: RandomPage -* added spellcheck plugin, which is accessible with the [preview] button - (it uses the ispell/aspell programs or PHP's pspell extension) -* added diff plugin, which shows changed parts between two page versions -* added markup emulation plugin for parts of BBcode (from phpBB) -* fixed Win32 filenames bug in db_flat_files / db_fast_files (Carsten) -* added dba/dbm database plugin -* added plugins/calendar.php (Carsten) -* made uploading of binary files now possible by config constant -* added email address protection plugin (against automated spambots) -* fixed ?edit=1&forced_version= bug -* added (markup) for image alignment -* added support for ^Oldwikilink markup - - -R1.00d - 20-03-2003 -* added plugins: PageIndex, ImageGallery, PowerSearch -* added plugins to emulate markup of PhpWiki, sfWiki, miki -* added mpi_multimedia plugin to reference non-image files -* added markup plugin for generating footnotes -* added tools/ewiki_backdown.php (for inserting backup/initial pages) -* added shared tools/ewiki_tools_config.php (database activation) -* added Content-Disposition (2183) HTTP header output for easier page saving -* HTTP "From:" request header gets now saved if $ewiki_author is unset -* made "/cgi/request.php?WikiPageName" possible (ISINDEX method) -* fixed double "FIND" database query, now the arrays to be queried for are - merged rather than the resulting arrays of the db query - speed improvement -* tools/ewiki_backup.php now can save in different formats -* lowercased all generated HTML -* renamed complex tables plugin -* added more pages in .de lang -* urlencoding and decoding now configurable (for PATH_INFO usage) -* added http authentication include script -* the format core now searches and renders email-addresses in the text - - -R1.00c - 06-03-2003 -* wikimarkup for tables now included -* added interWiki links (simple variant) -* allowed chars in WikiPageNames now configurable (for l10n purposes) -* rudimentary but general pluginterface for various tasks -* unified $internal_pages and $page_actions into the pluginterface -* plugin for LikePages (as in WardsWiki:) -* db_flat_files is now a plugin -* fancy lists plugin (
      replacement for internal/generated pages) -* plugin for "mpi" markup/inline plugins from Hans B Pufal -* mpi plugins: calendar, insert, environment, page_flags, plugins-list -* complex tables plugin (code from Hans B Pufal) -* error_reporting(0) now in the ewiki.php source code -* bugfix in the SEARCH action of the MySQL database interface -* fixed bug to reallow markup with | -* bugs fixed which hurt the rescue_html code, now also faster -* ADDPARAMDELIM now attaches the more correct & -* demo and download site moved to http://erfurtwiki.sourceforge.net/ - - -R1.00b - 02-03-2003 -* db_flat_files for saving wiki contents in plain text files, where - no database is available (saves it in message/rfc822 style) -* example private homepage wrapper script (authenticated wiki) -* time to fix lots of bugs in the README, as there were none in ewiki ;-P -* caching of images now possible -* some of the config constants were renamed -* rescaling of uploaded images added (may be buggy for palette images) -* new wikimarkup for small text (µµ) -* wikimarkup for definition lists -* more changes in ewiki_format() for speed purposes -* configurable HTML preserving (allows only very simple tags) - - -R1.00a - initial version - 25-02-2003 -* ewiki_database() -* ewiki_localization() -* ewiki_format() -* ewiki_page(), ewiki_page_...() -* ewiki_binary() with support for easy image uploads -* README, examples, phpnuke integration module -* tools/ for backup and flag modification - diff --git a/mods/wiki/doc/CREDITS b/mods/wiki/doc/CREDITS deleted file mode 100644 index 648767ffe..000000000 --- a/mods/wiki/doc/CREDITS +++ /dev/null @@ -1,107 +0,0 @@ -Who worked on ErfurtWiki -======================== -(please note that all mail addresses are 'beautified') - - -Mario Salzer [http://mario.erphesfurt.de/] -- original author, current maintainer - - -Andy Fundinger [http://www.burgiss.com/] -- compatibility fixes for PHP.A/W32, notify: address protection for info/ -- markup_css_singleat, action_extracttodo -- spellcheck2, phplib_auth, title_calendar -- navbar, aview_posts -- LiveUser authentication / permission framework plugin - - -Carsten Senf (from Erfurt) -- db_flat_files.php bugfixes for Win32 systems -- calendar.php, db_fast_files.php` code -- page_since_updates.php - - -Jochen Schuh <> -- fixed and advanced the filter/search_highlight plugin -- helped with the markup/toc plugin - - -Henner Kollmann -- extended the notify plugin with "GlobalNotify" page supported, - and fixed long-time diff utility call bug -- provied intertwingled versions of auth/method_form and userregistry - - -Alex Wan [http://www.burgiss.com/] -- LiveUser framework auth plugin, - log viewing plugin - - -Jeremy Mikola [http://www.burgiss.com/] -- aview_piclogocntl, the Burgiss Groups` LiveUser framework auth plugin - - -Koen Roggemans -- provided dutch translations of the init-pages/ - - -Culley Harrelson -- fixes for html code generation bugs, - various feature requests - - -Michael Schneider -- translations, fixe for tools/t_remove - - -Hans B. Pufal [http://www.aconit.org/] -- various enhancements, bugfixes -- mpi_calendar -- mpi_environment -- mpi_plugins -- mpi_page_flags -- markup_complextbl - - -Vladimir Támara -- Spanish translation of core messages and - the basic init-pages/ - - -Frank 'Sigi' Luithle -- contributed the wiki_format.inc (reduced rendering core) - - -Beate Paland [http://www.paland.tv/] -- bug notices and many helpful suggestions - (constantly demanded for
       support)
      -- phpCMS integration, see http://www.paland.tv/...
      -
      -
      -Timm Zwickel  [http://massenmensch.de/]
      -- re-suggestion and initial implementation of
      -  easier [.SubPage] linking
      -
      -
      -Marc Schiffbauer 
      -- fix core _block code, 0x0400 flag
      -- plugins/markup/table_colspan
      -
      -
      -Wojciech Jan Kalka
      -- wrote the mpi_blog extension
      -
      -
      -Christian Buck 
      -- server port patch (EWIKI_SCRIPT_URL)
      -
      -
      -Markus Ackermann  [http://www.symlink.ch/]
      -- bug reports, improvement suggestions
      -
      -
      -Dominik Eckardt 
      -- suggested the TAB indentation
      -  (while now SPACEs are supported)
      -
      -
      diff --git a/mods/wiki/doc/ConfigSettings b/mods/wiki/doc/ConfigSettings
      deleted file mode 100644
      index b84784fe8..000000000
      --- a/mods/wiki/doc/ConfigSettings
      +++ /dev/null
      @@ -1,851 +0,0 @@
      -
      -ewiki configuration constants and variables
      -===========================================
      -
      -
      -README.config
      -¯¯¯¯¯¯¯¯¯¯¯¯¯
      -In this part of the documentation the core configuration settings/constants
      -will be described. There is a long list of EWIKI_ constants and a smaller
      -fraction of setup variables in the $ewiki_config[] array, which can tweak
      -behaviour.
      -
      -Some other run-time variables are described in the [README.programming],
      -which also talks about other internals.
      -
      -
      -
      -  -------------------------------------------------------------------- 3 --
      -                  
      -
      -
      -EWIKI_ constants
      -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
      -This chapter explains some of the constants and how you can utilize
      -them to tweak some of ewiki's behaviour.
      -
      -The recommended way to change settings is to copy the define() commands
      -from "ewiki.php" into "yoursite.php" (see our example "config.php"). This
      -is a good idea, because then your settings won't get lost if you upgrade
      -to a newer version by overwriting your tweaked "ewiki.php".
      -
      -                   [Note: constants in PHP can be defined() once only, so
      -                   pre-defining them in "yoursite.php" or a "config.php"
      -                   script is nearly like a 'configuration']
      -
      -To define() some of those constants in 'yoursite.php' is especially a good
      -thing, because some of them are more used like state variables and it may
      -be more senseful to set them depending on informations only available in
      -the scripts of yoursite.php (for example if yourscripts provide a way to
      -authenticate and login a user you could give him additional rights within
      -ewiki by pre-defining one of the following constants).
      -
      -
      - EWIKI_SCRIPT
      -     This is the most important setting. It is used by ewiki.php
      -     to generate links to other WikiPages.
      -
      -     It needs the name of yourscript.php which itself includes
      -     ewiki.php.
      -     The name of the linked WikiPage is just appended to the string
      -     defined here, so you must ensure that it either ends in "/"
      -     or "?id=" or "?name=" or "?page=" so it constructs a valid
      -     URL after concatenation (or %s replaced) with the WikiPageName.
      -
      -     If you utilize mod_rewrite on your server, you may wish to
      -     make it blank when all requests to http://wiki.example.com/
      -     are redirected to the correct script by your WebServer.
      -
      -     If your wrapper script for example is called 'index.php' then you
      -     can just set EWIKI_SCRIPT to "?page=" (which then refers to the
      -     index.php of the current directory).
      -     You should preferrably set it absolute to the servers DocumentRoot,
      -     which gets a requirement if you'd like to give page names and actions
      -     via PATH_INFO "/wiki.php/WikiPage" and not as QUERY_STRING "?id=".
      -
      -     Update: this constant will stay, but the core script now utilizes
      -     the ewiki_script() function (which itself additionally respects
      -     the $ewiki_config["script"] config variable in favour).
      -
      -     ewiki_script() introduces use of the "%s" placeholder inside
      -     EWIKI_SCRIPT, which will be replaced by pagename and action, when
      -     URLs are generated.
      -
      - EWIKI_SCRIPT_URL
      -     Some parts of ewiki require the absolute URL of the ewiki wrapper
      -     script. So in contrast to the (often) short EWIKI_SCRIPT, this
      -     constant MUST contain the protocol and server name, like:
      -     "http://www.example.com/wiki/index.php?id="
      -     If you do not set this constant, it will be guessed by the
      -     ewiki_script_url() funciton, what often works but may be suboptimal
      -     and could also lead to security problems.
      -      
      -
      - EWIKI_DB_TABLE_NAME
      -     Sets the name of the MySQL database table name to be created
      -     and used to store all WikiPages.
      - EWIKI_DBQUERY_BUFFER
      -     When set to a value>0 then SQL database buffering will be enabled
      -     for SEARCH and GETALL queries. This is mostly like the old (R1.00)
      -     behaviour (memory exhaustive), but instead is limited to the size
      -     defined by this configuration constant (for example 384K).
      - EWIKI_DBFILES_DIRECTORY
      -     Defines where db_flat_files puts the database (made up of files).
      -     There is a separate paragraph about this,
      - EWIKI_DBFILES_ENCODE
      -     If set to 1 will generate urlencoded() filenames even on UNIX
      -     systems, so the dbff database 'files' get exchangeable across
      -     DOS/Win and UNIX filesystems. Not recommended, and will make
      -     ewiki run bogus, if you switch it after there already entries
      -     in the database.
      -     It may however be useful to enable this per default, if you want to
      -     "backup" (this is the wrong way) from a Unix server to a Win box via
      -     an ordinary FTP program (more professional tools could however handle
      -     this more easily).
      - EWIKI_DBFILES_NLR
      -     Used by flat files backends to encode newline characters.
      - EWIKI_DBFILES_GZLEVEL
      -     Compression level for fast flat files and dba backend.
      - EWIKI_DBA
      -     File name of .db3 data file, if the dba/dbx backend was used.
      - EWIKI_INIT_PAGES
      -     Names the directory from which the basic pages should be read and
      -     then written into the database, when ewiki is run the very first
      -     time (or the FrontPage - EWIKI_PAGE_INDEX) is still empty.
      -     Btw, you could use the 'ewikictl' utility to export all your Wiki
      -     pages into this directory as auto-reinit-backup.
      -
      -
      - EWIKI_NAME
      -     Defines the name of your Wiki. (This is not used currently, but
      -     is required, as _PAGE_INDEX is often just set to "FrontPage".)
      - EWIKI_PAGE_INDEX
      -     This defines the name of the WikiPage which shall be displayed
      -     when no value is received within the URL. Often this is called
      -     the "FrontPage" of the Wiki.
      -     The mysql error message "Table 'ewiki' already exists" will appear
      -     until you create (and fill) the page specified herein.
      -     If you'd like to have a wiki without FrontPage, you can set this
      -     constant to 0 or "" - you must then however ensure, that the ewiki
      -     script is never activated without a page name!
      - EWIKI_PAGE_NEWEST
      -     This defined the name of the virtual (internally generated) page
      -     containing a list of the lately added WikiPages.
      - EWIKI_PAGE_SEARCH
      -     Holds the WikiPageName for the search function.
      - EWIKI_PAGE_LIST
      -     List of all pages.
      - EWIKI_PAGE_HITS
      -     Pages ordered by most hits.
      - EWIKI_PAGE_VERSIONS
      -     Page list sorted by number of changes/revisions.
      - EWIKI_PAGE_UPDATES
      -     "UpdatedPages" 
      -
      -
      - EWIKI_CONTROL_LINE
      -     Pre-define this with 0 before including("ewiki.php") if you
      -     don't want that "
      EditThisPage ..." to be shown - at the bottom of each page. - You must then generate the EditThisPage link yourself somewhere - else on yoursite.php - It is often easier to simply edit the - ewiki_control_links() function to match the layout/design of yoursite. - EWIKI_LIST_LIMIT - Number of pages to show up in search queries (and other generated - pages). - EWIKI_PRINT_TITLE - If set to 0 will prevent the page title from being shown on many - pages (generated and database content ones). - EWIKI_SPLIT_TITLE - If changed to 1 will separate WikiPages titles into its different - word parts (only on top of each page). - - - EWIKI_DEFAULT_ACTION - EWIKI_AUTO_EDIT - If set to 1 (default) will automatically bring up the edit box - for non-existent pages. Else a page in between will appear ("please - edit me!") like in PhpWiki. - EWIKI_EDIT_REDIRECT - EWIKI_RESOLVE_DNS - EWIKI_HTTP_HEADERS - Allows ewiki to throw HTTP headers, where appropriate. You should keep - it enabled, as it allows for things like RedirectionAfterEdit (when - a page gets saved), and many other useful things. - headers() can often only be sent, if your wiki/yoursite.php is binary - safe, or uses PHPs output buffering (less reliable). - EWIKI_HTTP_HEADERS - Instructs browsers not to cache delivered pages at all. This is often - a good thing, because otherwise unclever caches will prevent the most - recent wikipage version to get seen by users. - EWIKI_NO_CACHE - Sends appropriate header to effectively prevent caching of pages - (since they change quickly). - - - EWIKI_CASE_INSENSITIVE - Was only recently implemented, but ewiki is fully configurable now in - regards to WikiLink case. It is enabled per default, and thus allows - referencing any "WikiPage" using strings like "WiKipAgE". This is - believed to be more user-friendly than case-dependency. - Reverting to "binary" page name matching is not fully complete now (our - database scheme was designed for case-insensitivity from the very start - and thus the DB code first needs tweaking before links in ewiki really - get case-dependent. (case-insensitivity in ewiki.php means, that - everything is converted into lowercase characters for comparisions) - EWIKI_HIT_COUNTING - Enable counting of page views. - - - EWIKI_URLENCODE - EWIKI_URLDECODE - You shouldn't disable both unless you know, you don't need to encode - WikiPageNames (else almost always necessary for sanity and security - reasons). - EWIKI_USE_PATH_INFO - If you have a broken Webserver (like many Apache versions), you may - wish to disable the use of PATH_INFO. If you ever happen to see - "Edit page '/wiki/example-1.php'", you probably need to disable it. - EWIKI_USE_ACTION_PARAM - Allows the page action command to be given as '&action=...' within - an URL (else only "action/WikiPage" allowed). You want to leave that - enabled. - If you set this constant to 2, ewiki will default to actively create - such URLs (instead of using the "edit/PageName" prefix). If set so you - should then disable EWIKI_ACTION_TAKE_ASIS, and you probably want to - edit EWIKI_SCRIPT to make ewiki emit _PATH_INFO style URLs as seen in - other WikiWare. - EWIKI_ACTION_SEP_CHAR - Defines the character that separates the page name from the action - name in generated URLs. Per default this is the slash, but you - could use something else (like the ":" colon), which however may - have a few drawbacks somewhere else. - EWIKI_ACTION_TAKE_ASIS - If kept enabled, ewiki will always take anything before a slash - in the given ?id= as action. If set to 0, it will however check - if such an action exists (or is enabled) at all, thus making it - easier to retrieve ?id=With/Slashes in it (without ewiki suddenly - treating the first part as $action string). - EWIKI_SUBPAGE_LONGTITLE - EWIKI_SUBPAGE_START - EWIKI_SUBPAGE_CHARS - Character classes used to decipher SubPages (an optional extension). - - - EWIKI_ESCAPE_AT - Encodes the "@" sign into a html entities, which in the past helped - a little bit against address rippers. But please check out the new - plugins/email_protect.php, which is more effective against email - harvesters. - EWIKI_ALLOW_HTML - Usually you do not want that users are able to add tags - inside the WikiPages as this allows for corruption of your page - layout or creation of harmful JavaScript areas. - - This is however one of the few constants which could be set by - yoursite.php for logged-in users. If it is set while a user - saves a changed page, then the special EWIKI_DB_F_HTML will - be set for the newly created version, so won't be - garbaged by ewiki_format() if another (not logged-in) user - requests the WikiPage next time. - - You must start a line with a "|" to actually make the HTML - work within a WikiPage. - - If a not logged-in user however re-saves the page this flag - won't be set anymore, so you should be careful about that. - {{edit ewiki.php and define(_DB_F_HTML with 8+16) to change}} - EWIKI_RESCUE_HTML - Was replaced by "plugins/markup_rescuehtml.php", which now allows - for certain 'safe' HTML tags within the wiki source to be used. - EWIKI_HTML_CHARS - If set the rendering function will backconvert html entities which - represent non-latin characters, like ႊ or Ԭ - - - EWIKI_DB_F_* - Page flags are associated to every page and can be used to effectively - tweak access restrictions and behaviour of individual text pieces. - There are various tools/ to tweak them in a running database. - EWIKI_DB_F_TEXT - This flag is set for every WikiPage inside the database. Usually - the only flag set on creation of a new page. - Starting from R1.00b previous flags will be copied after applying - EWIKI_DB_F_COPYMASK. - EWIKI_DB_F_BINARY - Used for cached/uploaded images. Prevents a page from getting - shown. - EWIKI_DB_F_DISABLED - If set will prevent the page from being shown. Not useful. - You could more easily unset the TEXT flag to disable page view. - EWIKI_DB_F_HTML - Special flag to allow the current version to include - tags regardless of the global EWIKI_ALLOW_HTML setting. - EWIKI_DB_F_READONLY - Prevents a new version to be saved, and thus disallows - editing of the WikiPage. - EWIKI_DB_F_WRITEABLE - Is the reversal of READONLY but only useful if you crippled - ewiki by setting EWIKI_EDIT_AUTHENTICATE, as this flag is only - intended to reallow editing of a page if you disallowed it before - with _EDIT_AUTH (which denies access to _all_ pages). - EWIKI_DB_F_APPENDONLY - Gets implemented by the plugins/append*.php, and allows to lock - a page, in that users can only append to edit (or edit parts of - it). See the plugin description for more details. - EWIKI_DB_F_SYSTEM - Is used to mark internally used data holders (usually serialized() - variables). - EWIKI_DB_F_PART - Denotes a page that first must be merged with others (only one piece - of a larger group of pages). - EWIKI_DB_F_MINOR - Signalizes hiding that revision on RecentChanges and UpatedPages. - EWIKI_DB_F_HIDDEN - Page shouldn't show up on any of the automatically generated page - lists (like RecentChanges and SearchPages). Links on pages will still - be rendered normally, unless the deadlyhidden plugin was loaded. - EWIKI_DB_F_ARCHIVE - Excludes a page/version from automated deletion (cron scripts). - EWIKI_DB_F_EXEC - Marks a system page containing executable (PHP) code. Not a core - feature, only used by xpi plugins to date. - EWIKI_DB_F_TYPE - Used internally to separate TEXT, BINARY, DISABLED and SYSTEM entries. - EWIKI_DB_F_ACCESS - Is a mask to check for READONLY, WRITEABLE and APPENDONLY flags. - EWIKI_DB_F_COPYMASK - When a new page is created, the flags of the previous version - are ANDed with this value to strip off some unsafe settings. - Note, that the _HTML and a few other feature flags are now copied - as well, so you may want to set a page _READONLY once you enabled - "unsafe" options. - Always keep in mind, that flags could be reimported from previous versions - as well - it hasn't been verified, but that could happen. - - - EWIKI_PROTECTED_MODE - Is an operation mode of ewiki, which activates ewiki_auth() function, - that is utilized from many places to require a permission level (from - authenticated users). Set this constant to 1 to enable this mode. - You'll also need some plugins from plugins/auth/ to make this useful. - - If this constant is set to 2, then you don't need a permission plugin, - but can control access to the edit/ function, by setting $ewiki_ring - to 2 (to allow) from within yoursite.php scripts. This setting is also - sometimes referred to as the "ClassicProtectedMode". - EWIKI_FLAT_REAL_MODE - Not a configuration directive, but the opposite to _PROTECTED_MODE ;) - EWIKI_AUTH_DEFAULT_RING - Is the permission level which is to be set, if no user is logged in - currently (defaults to 3 - which means "browsing only"). - EWIKI_AUTO_LOGIN - If this is enabled, then ewiki_page() automatically requests for - (re-)presenting the login
      on startup, if current authentication - isn't sufficient to go any further. Leave this enabled, it helps around - some problems. - EWIKI_EDIT_AUTHENTICATE - EWIKI_ALLOW_OVERWRITE - Outdated (were present in older ewiki versions). See - 'plugins/auth/auth_perm_old.php' to get them back. - EWIKI_PROTECTED_MODE_HIDING - Hides links to pages that weren't viewable with current auth status. - - EWIKI_ADMIN_PW - Is used occasionally by some plugins as lightweight alternative to - the ProtectedMode. - - - - EWIKI_SCRIPT_BINARY - This requires the REAL absolute address of the ewiki.php - library script (but the database must already be opened). - Needed for the function for cached/uploaded images. - You can set it to almost the same value as EWIKI_SCRIPT if it - is ensured that there is yet no output made, and the headers() - are not already sent. - - Usually just "?binary=" works fine (if you use the index.php - way of including ewiki.php). - - If you don't want ewiki to use image caching and uploading - functions you would define this to "" or 0, because this disables - the redirection through ewiki_binary(). You should then - also disable the following two constants: - EWIKI_ENGANGE_BINARY - If you pre-define this to zero, the _binary() part of ewiki won't - come up automatically as soon as you include the ewiki.php script. - EWIKI_CACHE_IMAGES - Allow caching of images. - To disable all the image functions (uploading, caching) set this to 0, - as well as EWIKI_SCRIPT_BINARY and: - EWIKI_IMAGE_MAXSIZE - ewiki will scale down images until they get smaller than - the absolute size (bytes) given here. This is true for cached - and uploaded images. - Your database may grow really fast, if you set it too high! - (even if .BMP and .XWD files are discarded normally ;-) - EWIKI_IMAGE_MAXALLOC - Maximum size of image while uploading and resizing it (memory - limits). - EWIKI_IMAGE_RESIZE - Enables the internal resizing functions. - EWIKI_IMAGE_MAXWIDTH - EWIKI_IMAGE_MAXHEIGHT - Maximum height and width for uploaded images. Else resizing will - engage. - EWIKI_IMAGE_ACCEPT - All acceptable MIME types for uploading. - EWIKI_IDF_INTERNAL - Is used to identify uploaded images and data files. Usually you do - not want to change it, especially if there are already uploaded - files; however "chrome://" or "file://localhost/tmp/" could be - funny alternatives to the default "internal://". - - Note that the renderer relies only on some unique string to detect - binary references, but the database functions in fact depend upon - "://" to return image sizes on "FIND" calls. - EWIKI_ACCEPT_BINARY - Allows users to upload arbitrary binary files through the image upload - function. You should now rather use the downloads plugin, which adds - a lot of functionality missing better suited for such purposes. - This feature depends on the image upload and cache function. - - - EWIKI_SERVER - Name of the web server domain. (auto) - EWIKI_BASE_URL - URL to access the current installation. (auto) - EWIKI_ADDPARAMDELIM - Automatically defined, holds either "?" or "&" depending on what - is in EWIKI_SCRIPT. You shouldn't change this unless you know what - you are doing. (auto) - EWIKI_CHARS_U - EWIKI_CHARS_L - Allowed chars in WikiPageNames (uppercase and lowercase chars). Use - this to localize your wiki (standard Wikis only allow A-Z, think of - that when it comes to InterWiki). - EWIKI_TMP - Tells ewiki which directory to use for temporary files. The default - value is "/tmp" or whatever the environment variable $TEMP or %TEMP - tells (often "C:\\Windoze\\Temp" or "C:\\Trashcan" on DOS systems). - EWIKI_LOGLEVEL - Log messages are internally separated into four categories: - 0=evil errors, 1=warnings, 2=notices, 3=annoying debug stuff. - If you do not want a log at all, just set this constant - to -1 or 357. If you set it to 1 for example, you will see - error and warning messages in EWIKI_LOGFILE. - - - EWIKI_UP_* - URL parameters. Changing these may only be necessary, if one is already - evaluated within yoursite.php for other purposes (incompatibilities). - You could also change these just to make some of the generated URLs - look a bit nicer ;) - EWIKI_UP_BINARY - EWIKI_UP_UPLOAD - EWIKI_UP_PARENTID - EWIKI_UP_LISTLIM - - - EWIKI_T_* - These text string constants were replaced by the $ewiki_t[] array and - ewiki_t() function. - EWIKI_DEFAULT_LANG - This value is used by a few plugins, that must guess the desired - language of visitors, or the language of a pages content. - EWIKI_CHARSET - ewiki currently only supports the Latin-1 charset, but UTF-8 - support is underway. So you should only specify "ISO-8859-1" - or "UTF-8" herein (while most other "ISO-8859-*" are believed - to work too). - - - UNIX_MILLENNIUM - Just a constant. Used for verification of timestamps (ony range 1*UM - till 2*UM accepted). - EWIKI_VERSION - Is not used at all. It is just placed on top of every ewiki.php to tell - you, which version you are running currently. - Major releases have a version number like 'R1.00a', while testing and - unstable releases have another number appended 'R1.00a7'. - - - - -$ewiki_config array -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -As it turned out not all configuration settings are as everlasting that -they can be constants (this mainly applies to "look&feel"-settings). So -some of the above mentioned EWIKI_ constants can now be overridden by -settings in the more flexible $ewiki_config[] array. - -Usually this array contains index=>value pairs with simple boolean -meanings, but often there are more complex entries and some of its contents -are data/behaviour entries (that were previously/falsely in $ewiki_plugins). - - $ewiki_config["name"] = "setting..."; - -Would overwrite/override a default setting by that name. You can put -this assignment even above loading the ewiki.php script (or after doing -so), because the built-in defaults won't overwrite single existing -values. - - -general, links --------------- - - ["script"] - Replaced EWIKI_SCRIPT, and is used to define the path/URL of the ewiki - wrapper script (yoursite.php, which at least included the ewiki.php - script and runs the ewiki_page() function). - - ["script_url"] - Should contain an absolute URL to the ewiki wrapper script. (replaces - EWIKI_SCRIPT_URL) - - ["script_binary"] - same as EWIKI_SCRIPT_BINARY - - -appearance ----------- - - ["print_title"] - replaces EWIKI_PRINT_TITLE, but also allows finer grained control: - a 1 says that titles should be added at top of pages - a 2 states that titles should also link for internal and generated - pages - a 3 will make linked titles even for pages, that should normally not - have them - - ["split_title"] - replaces EWIKI_SPLIT_TITLE, defines if pages` titles WikiWords should - be separated by spaces when displayed in pages - - ["qmark_links"] - Defines how links to not-existing pages shall look. Usually links to - such pages would be bold words with a QuestionMarkLink behind it. But - you can fully customize it: - - "0b?" would produce the default QuestionMarkLink? - "0u+" became UnderLined+ - "?b0" became ?StrongText - "*u0" became *UnderLined - "[i]" would show as [ItalicTitle] - - So the innermost letter will make the HTML tag, which encloses the - title of the linked page (you can only use one-letter tags, like - or , or even ). While the characters besides control, if - (the "0" suppresses it on either side) and how the link to the - not-existent page will appear. - That way you can have the HyperQuestionMark on both or only one of - the sides, and you can choose an arbitrary symbol for it ("*" and - often "+" make good replacements for the question mark). - - If you want to enclose the title of the linked (but not existing) - page in another html tag (not one-letter), then you can set this - configuration variable with an array containing 3 elements (which - correspond to the flags/chars in the string variant): - - $ewiki_config["qmark_links"] = array(0, "tt", "?"); - - (You could for example use a "" instead of the - usual textual question mark here.) - - If you set ["qmark_links"] to simply 0 or -1, then you will get - a very ordinary link, that should later be styled via CSS. Links to - not-existent pages are always enclosed in . - - Adv: a fourth character (like "0b?E") in the pattern would force - linking to the edit/ action of that page. - - ["control_links_enclose"] - Is typically empty, but if you want to style the action links below - every page via real CSS, you could turn them into a list using: - - $ewiki_config["control_links_enclose"] = array( - "
        ", "
      • ", "
      • ", "
      " - ); - - So you can put arbitrary html/text into the 4 array elements, into - which the single control/action links will later be enclosed. - - -access controls ---------------- - - ["action_links"][$ACTION1][$ACTION2] - Holds title for $ACTION2 when shown on a page activated with $ACTION1 - (only "view" and "info" get other actions` titles associated - currently). This is used for the _control_links() for example to - entitle/show action links. - - ["idf"][$TYPE] - Associates arrays with identification (search) strings into classes - (we have "url" and "img", "obj" for example associated with proto:// - prefixes or filename extension lists). - - ["interwiki"][$PREFX] - Connects other Wikis` script URLs to WikiLinkPrefixes. - - -formatting / rendering control ------------------------------- - - ["format_params"][] - Contains the default $params, the ewiki_format() function will assume, - if they weren't overridden by the second paramater given to it. - - ["wm_..."] - WikiMarkup definitions. See the [README] section on tweaking for some - examples on how to define your own markup. - - -you probably don't want/need to change at all ---------------------------------------------- - - ["wiki_pre_scan_regex"] - Is the regular expression used to separate out links from a pages` - content to query the database for existence of all mentioned WikiPages. - - ["wiki_link_regex"] - Is the actual link search regular expression. It is responsible for - finding WikiWords and things in square brackets and ordinary http:// - or internal:// WWW-links and even email addresses. - - ["htmlentities"] - Used by ewiki_format() to pre-escape in wikipages (later some - of the escaped html is often reactivated). - - ["format_block"][$BTYPE] - Defines "block" types, which are scanned for in WikiPages (using the - given search strings), and then handled by specialized ["format_block"] - plugins (instead of the core ewiki_format() function code). - - -informational -------------- - ["ua"] - Contains an User-Agent/X-Server string build from the ewiki version - number and some major extension plugins. - - - -PLUGIN_ constants in short overview -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Plugins provide additional configuration settings, that sometimes (=rarely) -need to be tweaked: - - - EWIKI_PAGE_EMAIL - "ProtectedEmail" virtual page for hiding mail addresses from bots - EWIKI_EMAILPROT_UNLOCK - automatically disables the email_protection rewrites, once a user - is authenticated as a real person - EWIKI_UP_ENCEMAIL - EWIKI_UP_NOSPAMBOT - EWIKI_UP_REQUESTLV - EWIKI_UP_REDIRECT_COUNT - prevents endless loops for redirection across Wikis - EWIKI_FAKE_EMAIL_LOOP - how many faked email addresses to generate - STR_ROT17 - used for simple reversable string ciphering (= making text unreadable) - - EWIKI_JUMP_HTTP - allow [jump:...] markup to redirect even to an http:// URL - - EWIKI_NOTIFY_WITH_DIFF - (integer) include a diff of the change in notify: mails, but only if - the diff is larger than the given size of bytes (e.g. set this to 300) - EWIKI_NOTIFY_SENDER - sender email address to use for page content change notify: messages - - EWIKI_BIN_DIFF - (eventually full) path name to GNU diff utility - EWIKI_BIN_PATCH - path name of GNU patch utility - - EWIKI_SPAGES_DIR - standard directory name for StaticPages, usually set to "spages/" - EWIKI_SPAGES_BIN - allow/try serving of image files from the spages/ directory, by - circumventing any ewiki_page() output - - EWIKI_DB_F_MODERATORFLAGS - - EWIKI_NAME_SEP - CALENDAR_NAME_SEP - seperator character for identifying subpages of certain types - - CALENDAR_PAGE_TITLE_REGEX - CALENDAR_PAGE_DATE_PARSE_REGEX - - EWIKI_AUTH_QUERY_SAFE - constant which states if the current auth [request] backend is - binary clean - that is, it can be activated even in POST requests - EWIKI_USERDB_SYSTEMGROUPS - page name for authentication purposes, stores group names - EWIKI_PERM_UNIX_UMASK - EWIKI_PERM_UNIX_SHAREHOLDERS - EWIKI_PERM_USERSET_FREE - EWIKI_USERDB_GROUPDELIMS - EWIKI_PHPLIB_ALLUSERS_PERM - EWIKI_AUTH_ANONYMOUS_RING - EWIKI_AUTH_ANONYMOUS_VERIFY - EWIKI_USERDB_SYSTEMPASSWD - EWIKI_PAGE_USERREGISTRY - EWIKI_USERDB_USERREGISTRY - EWIKI_REGISTERED_LEVEL - EWIKI_LDAP_SERVER - EWIKI_LDAP_RDN - EWIKI_LDAP_FILTER - EWIKI_LDAP_RING - YOUR_PASSWORD - YOUR_LEVEL - EWIKI_LOGGEDIN_RING - EWIKI_MIN_DICT_WORD_LENGTH - EWIKI_PASS_DICT_PATH - EWIKI_PASSWORD_COMPLEXITY - EWIKI_LIVEUSER_LOGIN_SHUTDOWN_DELAY - EWIKI_PASSWD_LIFETIME - EWIKI_NOT_LOGGEDIN_RING - ALERT_RECIPIENTS - ALERT_SUBJECT - LEVENSTIEN_MIN - LW_PREFIX - LW_PASSWORD_LEN_MIN - LW_PASSWORD_LEN_MAX - LU_GUI_USER_SUBGROUPS - EWIKI_LOGGEDIN_RING - EWIKI_NOT_LOGGEDIN_RING - - EWIKI_LINKTREE_UL - DEFAULT_LOGO - EWIKI_POSTID_PARSE_REGEX - EWIKI_DBFF_ACCURATE - DZF2_HIT_COUNTING - EWIKI_DB_UTF8 - EWIKI_DB_STORE_DIRECTORY - EWIKI_DB_STORE_MINSIZE - EWIKI_DB_STORE_MAXSIZE - EWIKI_DB_STORE_URL - EWIKI_DB_ZIP - EWIKI_DB_FAST_FILES - EWIKI_DB_FAST_FILES - EWIKI_DBFF_ACCURATE - PHPWIKI13_WRITEACCESS - EWIKI_APPENDONLY_COMMENTSPART - EWIKI_APPENDWRITE_AUTOLOCK - EWIKI_DB_F_APPENDWRITE - EWIKI_IMGRESIZE_WIN - EWIKI_IMGRESIZE_WIN - EWIKI_IMAGE_MAX_PIXELS - EWIKI_IMAGE_TOLERANCE - EWIKI_WORK_AREA - EWIKI_IMAGE_MAX_X - EWIKI_IMAGE_MIN_X - EWIKI_IMAGE_MAX_Y - EWIKI_IMAGE_RATIO - - XPI_DB - XPI_EVERYBODY_JPI - EWIKI_ACTION_USE_PARAM - EWIKI_REFERER_NOISE - EWIKI_XHTML - EWIKI_UP_SCREAMOMATIC - EWIKI_BINARY_DATA_SAFE_AUTH - EWIKI_CACHE_FULL - EWIKI_CACHE_ALL - EWIKI_CACHE_VTIME - EWIKI_CACHE_DIR - EWIKI_CACHE_DB - EWIKI_NAVBAR_SELECTALL_DEPTH - EWIKI_NAVBAR_ACTIVATEPARENTS - EWIKI_NAVBAR_ACTIVATECHILDREN - EWIKI_NAVBAR_ACTION - EWIKI_DESC - EWIKI_COPY - EWIKI_CATEGORY - EWIKI_LOGO_URL - EWIKI_USERVARS_PAGENAME_PREFIX - EWIKI_USERVARS_PAGENAME_PREFIX - EWIKI_AUTOLINKING_CACHE - EWIKI_LINK_ICONS_DIR - EWIKI_LINK_ICONS_LOOKUP_DIR - EWIKI_LINK_ICONS_LOOKUP_SIZE - EWIKI_LINK_ICONS_DEFAULT_SIZE - EWIKI_AUTO_CHOOSE - EWIKI_UP_FORCE_LANG - ZERO_PAGERANK - EWIKI_PAGE_BANNED - EWIKI_CSS_BLOCK - EWIKI_CSS_INLINE - EWIKI_CSS_CLASSPREP - EWIKI_CSS_LOWER - EWIKI_CSS_FIX - SMILIES_DIR - SMILIES_BASE_HREF - MIMETEX_BIN - MIMETEX_DIR - MIMETEX_PATH - MIMETEX_INLINE - EWIKI_ACTION_CALENDAR - EWIKI_PAGE_CALENDAR - EWIKI_PAGE_YEAR_CALENDAR - EWIKI_CALENDAR_WIDTH - EWIKI_NAME_SEP - CALENDAR_NAME_SEP - CALENDAR_PAGE_TITLE_REGEX - EWIKI_UPLOAD_MAXSIZE - EWIKI_PAGE_UPLOAD - EWIKI_PAGE_DOWNLOAD - EWIKI_ACTION_ATTACHMENTS - EWIKI_MPI_DEMANDLOAD - EWIKI_MPI_AUTOLOAD_DIR - EWIKI_MPI_FILE_PREFIX - EWIKI_MPI_FILE_POSTFIX - EWIKI_MPI_MARKUP_REGEX - EWIKI_MPI_INSERT_TBL - EWIKI_UP_SURVEY - EWIKI_MPI_SYNDICATE_INVALIDATE - EWIKI_GALLERY_WIDTH - EWIKI_PAGE_IMAGEGALLERY - EWIKI_PAGE_ORPHANEDPAGES - EWIKI_PAGE_POWERSEARCH - EWIKI_PAGE_RANDOMPAGE - EWIKI_PAGE_SINCEUPDATES - EWIKI_UNTAR - EWIKI_UNZIP - EWIKI_DEV_STDOUT - EWIKI_PAGE_WORDINDEX - EWIKI_PAGE_RECENTCHANGES - EWIKI_PAGE_EXALL - EWIKI_PAGE_SITEMAP - EWIKI_SITEMAP_DEPTH - EWIKI_WIKIDUMP_ARCNAME - EWIKI_WIKIDUMP_DEFAULTTYPE - EWIKI_WIKIDUMP_MAXLEVEL - EWIKI_DUMP_FILENAME_REGEX - NUM_LINKS - ZERO_LEVEL - NESTED_LEVEL - EWIKI_UP_AUTHOR_NAME - EWIKI_UP_CHANGELOG - EWIKI_PAGE_LOGOCNTRL_GALLERY - ZERO_PAGERANK - EWIKI_PAGE_BANNED - EWIKI_PAGE_BLOCKED - EWIKI_BULTINCAT_METAID - EWIKI_UP_SET_CATEGORY - EWIKI_UP_METABOX - EWIKI_UP_PAGENUM - EWIKI_UP_PAGEEND - EWIKI_UP_PAGE_LENGTH - EWIKI_USERNAME_LENGTH - EWIKI_GROUPNAME_LENGTH - EWIKI_PASSWORD_LENGTH - EWIKI_FIELDNAME_LENGTH - - diff --git a/mods/wiki/doc/FAQ b/mods/wiki/doc/FAQ deleted file mode 100644 index b708730e3..000000000 --- a/mods/wiki/doc/FAQ +++ /dev/null @@ -1,116 +0,0 @@ -This is a list of rather often asked questions, together with answers of -course. It has been compiled from our MailingList, SupportForum and years -of experience with user frustration. :) - - -When I edit a page, ugly BACKSLASHES \ \\ appear before quotation marks. ------------------------------------------------------------------------- - -This is not a bug in ewiki+, but a misconfiguration of the PHP interpreter. -Older versions still have the dumb "magic_quotes_gpc" setting enabled in the -"php.ini". Ask your provider to change this (disabled per default since PHP -version 4.2). - -As workaround it is recommended to ALWAYS load the "plugins/lib/fix.php" -script. This will remove the backslashes from the mangled input, and won't -hurt otherwise. - - -Where can I switch the LANGUAGE for the »!ErfurtWiki«? ------------------------------------------------------- - -NoWhere! It depends on the settings of your browser. Every browser sends -a list of preferred languages with every request. ewiki+ automatically -checks for this and chooses the most appropriate translations. (Of course -it is possible to hard-wire a certain language.) - -You could use the plugin "linking/tcn" to let it automatically switch -between pages in a multi-lingual Wiki. - - -TABLES and link TITLES ----------------------- - -The dash syntax for giving titles to links, of course clashes with the -markup for tables. - -To work around this, and also because it looks nicer, you can use the -alternative syntax with quotation marks: - - ["quotes around the title" ExtendedWikiMarkup] - - -The default LAYOUT doesn't look so nice ---------------------------------------- - -All the example layouts distributed with the main ewiki tarball aren't -quite good-looking. There is always too little time to spend it on that, -and then this is also to encourage people to use their own layouts. - -You can go to http://oswd.org/ and get ideas or templates from there. Or -download our ewiki extra tarball or the layouts from the WebInstaller on -http://ewiki.berlios.de/installer/layouts/ - - -I want side PANELS and an editable MENU ---------------------------------------- - -Only few of the default/example layouts come with portal-script like -features. But you can have a look into fragments/blocks/ if you are -looking for some fancy feature. - -ewiki doesn't care too much about your site layout, it only emits the -inner body part (with the Wiki page and controls). What else you want to -have on your pages is hardly controlled by it - that's the major design -constraint and conceptual shortcoming here. - - -Spammers! Spammers! Spammers! I need help, quick! -------------------------------------------------- - -Please read the doc/LinkSpammers file. We have prepared lots of -countermeasures. - - -Have authors listed with a name/page in addition to the IP address ------------------------------------------------------------------- - -This is the domain of the "$ewiki_author" variable. If you want your users -to set their names themselves (so your scripts don't need to do that), you -can use the "plugins/edit/authorname" plugin for example. The ProtectedMode -plugins provide similar functionatility (though that's overkill here). -There is even a WikiUserLogin page plugin. - - - - - -old ---- - -! Remove - -__Q:__ What for are the settings in "default settings are good settings - sometimes"? - -__A:__ please see the README file, most configuration constants are explained there, -ask the author if something is unmentioned and unclear or annoying. -As ewiki.php can be included() in very different environments these -settings may allow you to integrate it more sane and nicely. However -usually the distributed settings are very __ok__. - - - -! no errors, but nothing happens - -__Q:__ There is no database-mistake, but I can't see or edit all files. -what's the reason? - -__A:__ In the current release: go to ewiki.php and make a "echo mysql_error();" -in function "ewiki_database" before "return;". This might help to localise -the problems :-) -Reasons can be very different, so feel free to contact the author for support (icq95596825, mail: mario@erphesfurt.de). - - - - - diff --git a/mods/wiki/doc/INSTALL b/mods/wiki/doc/INSTALL deleted file mode 100644 index dedffa807..000000000 --- a/mods/wiki/doc/INSTALL +++ /dev/null @@ -1,28 +0,0 @@ -Information on how to install and use ErfurtWiki can be found in the -README, this file only contains notes for the impatient: - -Quick Test Installation -======================= - -- just move this newly extracted directory into your webservers docroot: - mv ewiki-R1.02i /var/www/wiki - -- then edit the "config.php" file, you may need to set the correct - parameters to access your MySQL database server (db user name and - password, and select a database different from "test") - -- if you don't have MySQL, then ewiki will simply fall back to use a - flat file backend that stores its pages in "/tmp" until you configure - something real (constant EWIKI_DBFILES_DIRECTORY) - -- just go to http://localhost/wiki/ - (or whereever you did put the files) - - -Real Setup -========== - -If you don't want to go through the [README] files to find out about all -possible features, then the 'setup.php' wizard script will help you to -generate a custom 'config.php' script. - diff --git a/mods/wiki/doc/INTERNALS b/mods/wiki/doc/INTERNALS deleted file mode 100644 index 072791e5d..000000000 --- a/mods/wiki/doc/INTERNALS +++ /dev/null @@ -1,1135 +0,0 @@ - -ewiki internals and extension howto -=================================== - -This part of the [README] series describes a bit of the internals of -the ewiki script and its plugin system. It lists variables, coding -guidelines and a few recommendations. -These informations are useful if you'd like to change some of the -hardcoded behaviour, fix annoying bugs you've found or to write your -own extensions. You do not need to read this, if you just want to -setup and use a Wiki. - - -README.programming -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - 1 ewiki_ functions() - 2 $GLOBALS pollution ($ewiki_ variables) - 3 internal coding explained - 3.1 how ewiki operates - 3.2 used variables - 4 Extension HowTo - 4.1 the PlugInterface - 4.2 plugin tasks - 4.2.1 mpi plugins - 4.2.2 authentication/permission plugins - 4.3 writing your own plugin - 4.4 format_* / rendering plugins - 4.4.1 ewiki_format() internals - 4.4.2 the format_ plugin hooks - 4.4.3 $iii[] and $ooo[] block flags - 4.4.4 your own block markup plugin - 4.5 xpi plugin system - 5 mysql database structure - 6 Just using the wiki source transformation - - - - - -------------------------------------------------------------------- 1 -- - - - - - -ewiki_ functions() -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Some of the core functions of ewiki.php can be used separate from the -others and some of them were designed to be replaced by different -implementations. -Btw, all the functions, constants and variables start with "ewiki_" -to make it easier to mix it into other projects (reduces function name -conflicts and similar problems, that usually arise if you join two -or more scripts into one program). - - - ewiki_page($id) - --------------- - This is the main function which fetches the selected WikiPage - (or the one given with $id) via ewiki_database to transform - with ewiki_format(). - If the requested page does not exist it returns the edit - screen. - It also includes some virtual pages (InfoAboutThisPage, - NewestPages, SearchPage, ReferencesToThisPage, ...). - - - ewiki_page_...() - ---------------- - These functions were separated out from the main ewiki_page() - to make it more readable. - Most of them contain code to generate the few special/internal - WikiPages (Search, Newest, Info, and the Edit , ...) - - - ewiki_control_links($id, $data) - ------------------------------- - Prints the line with the EditThisPage and PageInfo, ... links. - - - ewiki_format($wiki_source, $params) - ---------------------------------------------------------- - This returns the formatted (HTML) output for the given WikiSource - (with all the WikiMarkup in it). - - The second param is an array with various config overrides. An entry - of "scan_links"=>1 for example tells ewiki_format to lookup the - referenced WikiPages in the database (see ewiki_scan_wikiwords) for - filling up $ewiki_links. Another $params entry is "html"=>0, which - controls interpetation of the ... page content blocks. - - - ewiki_render_wiki_links(&$o) - ---------------------------- - Transforms WikiLinks and square brackets in a page into html links. - - - ewiki_scan_wikiwords(&$wiki_source, &$ewiki_links) - -------------------------------------------------- - work with regex on the wiki source text, to find valid WikiWords, - the $ewiki_links will be filled with informations if the found page - names exist in the DB. - - - ewiki_link_regex_callback() - --------------------------- - Called from ewiki_format(). To separate the ewiki_format() from - the database this function will utilize the global $ewiki_links - (generated on demand by ewiki_format) to output either a normal - link or a question-mark after the WikiPageName to signal a - non-existent page. - - - ewiki_script() - -------------- - Builds the complete URL needed to access the given resource. This - function replaces/enhances the static EWIKI_SCRIPT constant and - unifies the generated URLs (less bugs). It also helps around - various design flaws (like nice looking URL strings), that made - some parts of ewiki a bit weird and unreliable in the past. Btw, - now the base URL is stored in $ewiki_config["script"]. - - - ewiki_script_binary() - --------------------- - Is just a ewiki_script() wrapper, but can additionally distinguish - between binary download and upload URLs, which could be utilized by - (database external) plain file storages (see plugins/binary_store). - - - ewiki_binary() - -------------- - Gets called automatically for requests with the ?binary= trailer - which is used to reference cached and uploaded images (or not - yet cached ones). - - - ewiki_author() - -------------- - returns a string with REMOTE_ADDR and the $ewiki_author or a default - string incorporated - - - ewiki_auth() - ------------ - Is a simple interface to a probably large collection of plugins, - which should to actual user and permission management. Support for - this in the core is however still sporadic. - - - ewiki_auth_user() - ----------------- - Queries all registered user databases, and is usually itself called - from within an auth_method/auth_query plugin. - - - ewiki_t() - --------- - Fetches a text string from the $ewiki_t[] array and additionally adds - some text pieces into it (given as second param). It can retrieve - translations for registered abbreviations, or searches for complete - text fragment replacements. It also understands _{...} to recursively - translate a text snippet inside of larger text blocks. - This is probably a bit slower and less readable than the previous usage - of EWIKI_T_ constants, but it saves some memory and allows to extend - translations or additional text constants (of plugins) a lot more - easier (previously one had to edit inside a function, which is almost - impossible to do from outside / per configuration). - - - ewiki_make_title() - ------------------ - Returns a string enclosing (the generated) page title (as link) into - the html title markup "

      ". The $class parameter actually tells from - which plugin sort it was called, and this decides if a link will be - generated or the title will be unclickable plain text (the setting in - $ewiki_config["print_title"] is used to determine that). $go_action tells - which action to link the title to. - - - ewiki_chunked_page(...) - ----------------------- - Is a helper function to split large results into multiple click-through - pages, and is used by info/ and some search functions/plugins. It only - produces the click-through links for inclusion on other dynamic pages, - allows overlapping of page chunk ranges. - - - ewiki_in_array($value, &$array, $dn=0) - -------------------------------------- - Case-insensitive variant of PHPs` in_array(), returns the $value if - found. The $array will be all-lowercased afterwards (except when $dn - was set). - - - ewiki_array($array, $index=false, $am=1) - ---------------------------------------- - Returns input-array lowercased (indices), or just the entry for the - $index if searched for. The $am decides if multiple entries should be - merged together (uppercase+lowercase merging produces overlaps). - - - ewiki_db:: - ---------- - This static class provides the interface to the database backends. - It abstracts the database as a simple flat store for named entries - (file or page names). Therefore it is that easy to switch from a - SQL backend to a flat file based data store. - Actually, this rude form of "database abstraction" has the drawback, - that it knows only little about the data it maintains. But this also - allows to internally extend the used structures if necessary. - - You call the individual functions like " ewiki_db::GET() ", - the atomic features are: - - ::GET($id) - Fetches the latest version of the "$id" page from the database. - - ::GET($id, $version) - Retrieves a given version instead. Counting starts at 1. - - ::WRITE($data) - Saves the contents of the given data array in the database, - does _never_ overwrite an existing entry (you must keep track - of the {version} yourself) unless a second paremeter (1) was - given. - - ::GETALL($fieldnames, $mask, $filter) - Fetches an array of all existing pages in the database, but - returns it as ewiki_dbquery_result object, which will throw - the requested columns on ->get(), where the entries 'id', - 'version' and 'flags' are always present. - - ::FIND($list_of_pagenames) - Searches the database for the queried page names, returns an - array which associates the boolean value (if pages found) with - their names - - ::SEARCH($field, $content, $caseinsensitive, $regex, $mask, $filter) - Returns only those pages, where the database COLUMN has a content - that matches the requested value; the list of pages is returned - as ewiki_dbquery_result object, where you can access the - individual entries using the ->get() call, which will return the - columns 'id', 'version', 'flags' and the scanned COLUMN of course - unless you ->get("_ALL=1"). - - The following three actions are not required for correct operation, - but provide additional functionality for some plugins or tools. - - ::HIT($id) - Increases the hit counter of the given wiki page by 1, - what is not implemented in db_flat_file. - - ::DELETE($id, $version) - Removes the specified page (only the given version) from the - database; implemented in all database plugins but should be used - from within the tools/ only. - - ::INIT() - For SQL database backends this creates the required tables. - - There are also a few virtual functions, that only provide utility - code or make use of the atomic funtions itself: - - ::APPEND($id, $text) - Adds the given $text at the bottom of the named page. - - ::UPDATE(&$data) - Refreshes all the meta data fields in the given page hash, but of - the {version} field. This is usefully be called before any ::WRITE - call. - - ::CREATE($id, $flags, $author) - Returns a fresh page $data hash. - - Other functions are usually used internally only, as for example the - ->ALLFILES() command in dbff or dba/dbm plugins. - - - $ewiki_dbquery_result - --------------------- - Has the member variables $keys and $entries, where the latter - contains an array of page names that where triggered by your GETALL - or SEARCH request, and the $keys array contains the column names that - each subsequent "$result->get()" will return. - - ->get() - Returns the database entry array (see GET above), but only the - fields the database query should return (at minimum these are - 'id', 'version' and 'flags' and the searched column for SEARCH). - - ->get("_ALL=1") - Instead returns the complete entry. - - ->get(0, $mask) - The second parameter is for filtering out content: - 0x0001 strips out _HIDDEN pages from the result set - 0x0002 removes any _DISABLED pages - 0x0020 performs the _PROTECTED_MODE_HIDING checks - - ->get(0, $mask, $type) - if the $type parameter is supplied, then the results are filtered - by the given page type (_DB_F_TYPE mask) - - ->count() - Returns the number of found database entries. - - ->add($row) - [internal] This is used by the ewiki_database() core functions - to initialize the $result object with the found entries. - - - -------------------------------------------------------------------- 2 -- - - - -$GLOBALS pollution ($ewiki_ variables) -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -At least the ewiki_page() function produces variables in the -global namespace. Of course they also were named to not interfere -with anything from yoursite.php: - - $ewiki_id - Contains the current page name, after ewiki_page() - was called. - - $ewiki_action - Contains the $action/ForTheCurrentPage. - - $ewiki_title - Will be set after the first call to ewiki_page(), - it is most useful to be printed inside the - tags inside <HEAD>. So if you want to use it you - should call ewiki_page() very early, but save its - output into a variable for later use. This way - you can make the current wiki pages` title available - (the _title may be different from the pages _id). - - $ewiki_data - Contains the page data hash as retrieved from the - database, but that {content} has been removed. - - $ewiki_errmsg - Sometimes used to pass error notices back (ewiki_auth - does so for example). - - $ewiki_links - Is an array produced by ewiki_format() that associates - all found WikiPageNames with a value of 0 or 1, - depending on if the referred page exists in the - database. - - $ewiki_author - The content of this variable is saved in the author - field of newly created wiki pages (it will be filled - with IP:PORT if not set from outside). This is only an - informational setting, and does not directly correspond - to the _PROTECTED_MODE. - You should set it, whenever yoursite.php notes a logged in - user (so his login gets saved in the wiki pages 'author' - column). But you should REALLY NOT SPAM IT with your own - name or ad words. - - $ewiki_auth_user - Is set by ewiki_auth_user() whenever it successfully - authenticates a user in _PROTECTED_MODE. This variable - is then used as reliable state setting, which affects - permission granting. - - $ewiki_ring - Holds the permission level ('ring') of the currently - authenticated user (or else will be unset). This value - tells only about the user, many plugin functions have - built-in requirements which will be compared against - this value (no value or zero means full permissions). - While this is the built-in way to grant permissions - and often also suits the needs to do it, the _auth() - plugin interface allows to work at a much finer degree - of access granting. - values: 0=administrator, 1=moderator, 2=editor, 3=guest - See also plugins/auth/README.auth for more informations. - - $ewiki_plugins - Is an array which connects task names (say "database" - or "image_resize" for example) to function names. - You can utilize this if you decide to extend ewiki. - There is an own chapter on this. - - $ewiki_config - Imports some configuration settings from older constants, - and introduces newer ones, which can then be overridden at - runtime. Also holds some work and markup transform data. - - $ewiki_t - Text definitions and translations for all possible - messages. - - - - - -------------------------------------------------------------------- 3 -- - - - - -internal coding explained -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -This section is to explain some of the coding style of ewiki, and how some -things work. While many parts of ewiki carry good source code comments, it -is always difficult to quickly understand larger scripts like ewiki.php by -just reading through it. - - - - how ewiki operates - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - ewiki_page() - - decodes the $id and $action from the GET or POST parameters - - tries to load the page from ewiki_database() - - if this failed then it calls the database init function - - calls some init plugins, calls the _auth() interface - - chains to ["page"] plugins which activate for registered $id's - - alternatively calls a plugin that was registered for $action - - the default however is to render the current page via _page_view() - - adds a page title - - sends the generated output (view page or plugin output) back to - caller (for output into yoursite.php) - - ewiki_page_view() - - feeds the current page $data's ["content"] into ewiki_format() - - also decodes a few formatting parameters (e.g. if html allowed) - - returns the gererated html back - - ewiki_format() - - beatifies the source code (unifies to plain UNIX newlines) - - calls init plugins (wiki source mangling) - - splits source into blocks, calls block plugins - - then goes through each line of the wiki source to generate html - - there is line-start, in-line and complete-markup - - afterwards everything went from source into the $ooo-output var - - first calls the link_pre_scan_regex (which searches for - wikiwords and stores that information into $ewiki_links) - - then calls the wiki-link transformation regex function - - then calls post plugins and returns generated <html> - - ewiki_render_wiki_links() - - searches for all (pre-fetched) $ewiki_links via ewiki_db::FIND() - - transforms the wikiwords into html-links - - with the regex and callback func: returns output back to - - ewiki_format() - - ewiki_link_regex_callback() - - transform the wiki source snippet returned from the - preg_replace() call into a html link string - - (complicated) - - ewiki_$page_plugin_*() - - page plugins return html output, which usually is hardcoded as - strings into them - - provide some interactivity - - ewiki_$action_plugins_*() - - activate on pages with special registered $action's - - provide some interactivity (for page editing for example) - - - - used variables - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Variables in ewiki often have similar names, and are also - regularily passed by reference from one function to another (so it - is in fact the same variable). - - $id - Is often the name of the current page (which is to be - returned as output. The content of this variable is - also available via the global $ewiki_id [[for plugins - that do not have the common ($id,$data,$action) - interface parameters]]. - - $data - Contains the entry fetched with the initial - ewiki_database() call. This is an array of the form: - array( - "id" => "CurrentPageName", - "version" => 1, # 1 is the lowest possible - "flags" => 1, - "created" => 1002056301, - "lastmodified" => 1002171711, - "hits" => 235, - "author" => "localhost (127.0.0.1:4981), - "meta" => array("Http-Header"=>"X", "setting"=>"val"), - "content" => "wiki source...", - ) - - $action - The $action with wich the current page was requested - (most often "view", but everybody also knows "edit"). - - $uu - Short for "unused". Is used as temporary variable, especially - with preg_match() and string functions. - - $result - Used for database queries SEARCH and GETALL. - - $row - Holds temporarily fetched entries from the databases - (like $data), if page lists are to be generated. - - - - -------------------------------------------------------------------- 4 -- - - - - -Extension HowTo -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Best way to extend ewiki is to read the man page on vi or emacs ;-> -However the tool that made this all possible was: joe. - - - -the PlugInterface -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The $ewiki_plugins array holds an array of "task names" connected to -function names (that of course should do something senseful). As an -example: - - $ewiki_plugins["image_resize"][0] = "ewiki_binary_image_resize_gd"; - -connects the task name "image_resize" to function already inside ewiki.php, -and the task "image_resize" will be called for every uploaded or to be -cached image. The function name here does not say anything about the -parameters the function will be called with later. You have to look up -the original function implementation in ewiki.php to see which parameters -will be passed; so you could write your own task plugin. - -The [0] in the example above shows that this is the very first registered -function for the task "image_resize", there could be others as well. So -if you write a plugin you should take care to add your function name using -$ewiki_plugins["task"][] = "my_func" so you won't overwrite a previous -function name ''registration''. -There are of course tasks like ["database"] where only one of the plugin -functions will be called, in this case you should of course overwrite [0]. - -Two special case "tasks" are ["page"] and ["action"], because they aren't -counted with numerical indices, but instead carry WikiPageNames or -other idf strings as array/hash index. - - - -plugin tasks -¯¯¯¯¯¯¯¯¯¯¯¯ -Here's a short summary of current PlugInterface "tasks" and (recommended) -function interface definitions (the "= function (..." lines). A plugin hook -with [] means there can be multiple, and each one would be tried. - -basic ------ - - ["page"][$PageName] - called for requests to page "$PageName" - (like "SearchPage", "NewestPages") - = function ( $id, $data, $action ) - - ["action"][$ACTION] - called for requests with url "?id=$ACTION/pagename" - (core actions are "edit", "links", "info", "view") - = function ( $id, &$data, $action ) - - ["handler"][] - called from ewiki_page() on start-up, if it returns - a string the page was handled and no further - processing takes place, the plugins output is used - = function ( $id, &$data, $action ) - -rendering ---------- - - ["render"][0] - alias for ewiki_format() - our "WikiKernel" - - ["format_source"][] - called inside the format function for the wiki - source, implement this or the following ones to - use complex wiki markup - = function ( &$wiki_source ) - - ["format_line"][] - generic call from inside wiki format engine - for every line, you may need to use static - vars inside your plugin function - = function ( &$o, &$line, &$post ) - - ["format_tbl"][0] - called to handle "wiki|table|markup" - (the first and last | are already stripped) - = function ( &$o, &$line, &$post, $tbl_open=0 ) - - ["format_final"][] - call after wiki source was transformed into html - (WikiPageLinks were already interpolated too) - = function ( &$html ) - - ["format_block"][] - called, with the page fragment extracted using - the string patterns of the according - $ewiki_config["format_block"] entry - = function (&$currbuf, &$in, &$iii, &$s, $btype); - - ["format_para"][] - called, if the $para (text enclosed in <p></p>) - is to be written into the output stream $ooo[$in][0] - = function (&$para, &$ooo, &$s); - - ["link_url"][] - called to transform wiki source references - = function ( $href, $title ) - - ["link_final"][] - called from ewiki_link_regex_callback to transform - the final <a href> - = function ( &$str,, $type, $href, $title ) - -special tasks -------------- - - ["database"][0] - only [0] will be called in favour of the ewiki.php - internal ewiki_database_mysql() - = function ( $action, $args=array() ) - - ["image_resize"][] - all [] registered functions will be invoked - = function ( &$content, &$mime, $return=0 ) - - ["mime_magic"][0] - hooks before save_binary/image to fetch the - correct mime type for non-image files; nowadays - just an always-available get_content_type() - = function ( &$content ) - - ["binary_get"][0] - the binary_repository handles large/binary content - (to separate it out of the standard sql-database), - usually just sending it to stdout - = function ( $id, $meta ) - -page lists ----------- - - ["list_pages"][0] - <li>st generating callback function - = function ( $lines ) - - ["list_dict"][0] - special variant of the above one (called just for / - from within PageIndex and WordIndex listings) - = ??? - - ["list_transform"][] - works on the given list of links (text transformations) - = function ( &$lines ) - - ["make_title"][0] - allows to chain a replacement function for - ewiki_make_title() - = function ($title, $class, $action, $go_action, $may_split) - - ["title_transform"] - changing the currently linked title (called from - within _make_title) - = function ($id, &$title, &$go_action) - -page transform / additions --------------------------- - - ["view_append"][] - output will be printed below a rendered page - = function ( $id, $data, $action ) - - ["view_final"][] - can rework the full html of the rendered page - = function ( &$html, $id, $data, $action ) - - ["view_append"][] - add <html> code at the end of the currently - viewed page - = function ($id, $data, $action) - - ["view_final"][] - filter hook for final processing of "view/"ed pages - = function ($o, $id, $data, $action) - - ["page_final"][] - filter hook for final processing of any - shown page (any action: edit/, view/, info/, ...) - = function ($o, $id, $data, $action) - -edit/ hooks ------------ - - ["edit_preview"][] - called if edit pages [preview] button pressed - = function ( $data ) - - ["edit_form_final"][] - add <html>/<form>s to the edit/ page - = function (&$o, $id, &$data, $action) - - ["edit_form_append"][] - insert other <input> fields between <textarea> - and <submit> button on the edit/ page - = function ($id, &$data, $action) - - ["edit_hook"][] - chains into before the edit box is printed - (to allow security checks, pre-edit-tweaking, ...) - any output terminates the current edit/ attemp - = function (&$id, &$data, &$hidden_postdata) - - ["edit_save"][] - immediately called before saving the currently - "edit/"ed page into the database, allows last - transformations or rejection (unsetting $data) - = function (&$data, &$old_data) - - ["edit_patch"][0] - special hook for the patchsaving plugin - = function ($id, &$data) - -bloat extensions ----------------- - - ["auth_*"][] - plugin tasks used with ewiki_auth() - = see the plugins/auth/README.auth - - ["mpi"][...] - markup plugins, see next paragraph - - ["init"][] - run once, when the main script is included() - - ["page_init"][...] - init functions, called when ewiki_page() - is called the very first time - -aliases and variants --------------------- - - ["action_always"][$ACTION] - are called with precedence over ["page"] - plugins (for example "links" which also - works for registered page plugins) - - ["action_binary"][$ACTION] - action/admin plugins which do not care, if - the current page actually is binary data - - -Some other entries have been re-extracted into $ewiki_config, because they -were falsely in $ewiki_plugins. See the paragraph at the start of the README -on the $ewiki_config array. - -This list will probably not stay up-to-date, so please grep the ewiki.php -script for all occurrences of 'ewiki_plugins["', and you can of course -invent some new and tell the author how it helped you to implement something -very different. - - - - mpi plugins - ¯¯¯¯¯¯¯¯¯¯¯ - Plugins of the class "mpi" extend the wiki markup with html like - calls to dynamic content generating functions. They were taken from - the ewiki adaption of Hans B Pufal and are very similar to the - plugins found in PhpWiki. - - In order to use them you must first load their generic PlugInterface - file using include("plugins/mpi.php"); - As an exception to all other ewiki plugins, the mpi plugins are then - loaded only as needed (the mpi interface takes care). You could - however still load all the "mpi_*.php" scripts yourself beforehand. - - You can then call those plugins from the wiki markup with: - - <?plugin Calendar ?> - - There are many different plugins available (not all included with - this ewiki distribution), and the allowed arguments differ widely - (must all be noted inside the < > and are written in arg=value style - separated by semicolon): - - <?plugin Insert WikiPageName ?> - # this includes the referenced WikiPage in a box - # into the current one, Note the ! to prevent that - # WikiWord from getting rendered (before mpi sees - # it) - - <?plugin BackLinks page="ForGivenPageName" ?> - - <?plugin SparseTable columns="c1,c2,c3" - - c1="column 1" - c2="column 2" - c3="column 3" - - c1="#1" - c2="2.0" - - c1="#2" - c3="3.0" - - c2="2.5" - c3="--" - ?> - - See the distributed page "MpiPlugins" for a complete list. - - The API is very simple, so one could easily write a custom - code block extension. (The mpi_backlinks plugin makes a nicely - short example.) - - - - authentication/permission plugins - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The paragraph and descriptions about the _auth interfaces have gone - into plugins/auth/README.auth - - - -writing your own plugin -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Using the list of current plugin tasks, you could (hopefully) write your own -extension with ease. It is probably most simple to write a dynamic ["page"] -plugin, so we start with this as example. All you need is a function -definition like: - - function my_page_plugin($id, $data, $action) { - return("This is the returned page <b>content</b>."); - } - -And then just register it as ["page"] plugin, using your defined function -name (yes, this does NOT need to start with the usual "ewiki_" prefix!). You -also need to tell ewiki about the WikiPageName under which your plugin -should be made available: - - $ewiki_plugins["page"]["MyPagePlugin"] = "my_page_plugin"; - -That's it. But of course your function should do something more useful, than -just returning a hardcoded html string - even if this all, what's necessary -here. The parameters to your ["page"] plugin function you'll often just want -to ignore, and implement your plugin functionality (hard disk formation e.g.) -independently from such things. - -It is likewise easy to write an ["action"] plugin; but this type of plugin -should then process some parts of the $data entry and work for nearly any -page (extracting contents or presenting the current page differently). So -this kind of plugin could be used to initialize a download for the current -page or to allow to email it to someone else (beware of the spammers!). - - - -format_* / rendering plugins -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -It is rather simple to add WikiMarkup using the $ewiki_config["wm_..."] -settings, but for some tasks you need stronger weapons like rendering -and markup plugins. - -The ewiki_format() function (often blatantly referred to as "rendering -kernel") recently got rather complicated to add support for the 'block' -plugins. Therefore we'll first need to discuss the variables structures -and names used inside of it: - - - - ewiki_format() internals - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - When the function receives the input string (WikiSource), it first - escapes all html tags using & < > to replace the & < > - chars (because HTML is not allowed within Wiki, initially). - - Then it runs optional ["format_source"] plugins on the whole wiki - page (still one source string). - Afterwards ewiki_format() starts to split that wikisource into - fragments meant to get handled by ["format_block"] plugins AND/OR - the Wiki -> HTML transformation code inside of it. It creates an - array called $iii[] from it - each fragment being an array on its - own: - $iii[0] = array( - 0 => "WikiSource ...", - 1 => 0x0FFF, - 2 => "core", - ); - Initially we here just have one fragment [0] - and often this - remains the only one (if no block plugin activates for the current - WikiPage). The 0=> entry contains the body (wiki source) of a - fragment, while at the 1=> index you'll find the block flags and 2=> - is just the name of the block plugin to handle that fragment. - - If there is some block code, like <htm>...</htm> or <pre>...</pre> - in the WikiPage, you'll end up with a larger $iii[] input array: - $iii[0] = array("WikiSource...",0xFFFF,"core"), - $iii[1] = array("<b>....",0x0002,"html"), - $iii[2] = array("text",0x0FFF,""), - - Besides the $iii[] input array, we'll also have an array containing - rendering status variables called $s[]. The most important entry - there is $s["in"], which is the index into the currently accessed - $iii[] wiki page source or block fragment. - And ewiki_format() then uses various alias variable names for - entries of the status var $s[] array - for example $in and $s["in"] - are the same index number. - - After ewiki_format() separated the input source into the block - fragments of $iii[], it will then run the actual ["fragment_block"] - plugins on it. These can then apply regexs on them, or strip the - fragments completely out of $iii[] or transform then into regular - wiki source. - - Then the large wiki transform loop comes into action, but only - for $iii[] fragments, whose flags (in the $iii[...][1] number) - have the bit 0x0001 set. Other blocks/fragments of $iii[] remain - untouched. - While transforming the $iii[] arrays WikiSource a new fragments - array will be created, called $ooo[] - the output array, which has - exactly the same layout. And every $iii[$in] directly maps to the - $ooo[$in] - same index number! But the later then already contains - <html> instead of wiki source. - - Inside of the transformation loop, two other plugin types are - activated (besides applying the $ewiki_config["wm_..."] ruleset): - the ["format_line"] and ["format_para"] plugin groups. - - After all $iii[] blocks have been transformed into $ooo[], a second - loop will check the flags (this time $ooo[...][1]) for the bit 0x0002 - which tells, if WikiWords should be transformed into html <a href=> - links. - - After link conversion (on the selected fragments), all blocks (the - content entries $ooo[...][0] of course) of $ooo[] are merged together - into one <html> string. After the ["format_final"] plugins run over - this, ewiki_format() returns the resulting <html> page. - - - - the format_ plugin hooks - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - As denoted above, the ["format_source"] and ["format_final"] plugin - hooks are the simplest to work with, as both only get one parameter - (passed by reference) containing either the full WikiPage source - text or the already fully rendered <html> output. - - The ["format_line"] and ["format_tbl"] hooks are also rather simple, - lookup their interface to know which variables you could modify. - - The ["format_para"] and ["format_block"] plugins both recieve - either the $iii[] or $ooo[] and status $s[] array variables (plus - a few aliases and shortcomings). This makes these hooks look a - bit more complicated, but allows great flexibility - a "_block" - plugin could for example merge its $iii[] fragment with another - one, or replace itself with nothing. - - To write a markup plugin, you should lookup the actual interface in - the 'ewiki.php' script or in this README. And don't forget that most - parameters are meant to be passed by reference to be useful! - - - - $iii[] and $ooo[] block flags - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The $iii[...][1] and $ooo[...][1] hold the flags (as defined by - $ewiki_config["format_block"][...][2]) for each fragment of the - WikiPage. The "core" blocks (plain WikiSource) always have the - default 0x137F assigned. - - currently used bit values are: - 0x0001 - render WikiMarkup (inline / text style) - 0x0002 - render WikiLinks - 0x0004 - international character &#htmlentities; allowed - 0x0008 - enable BlockMarkup (lists, tables, headlines, ...) - *NEW* 0x0400 - decode < > htmlentities again before calling block plugin - 0x1000 - fragment further (other block plugins can split it) - - pseudo-values (OR checks / behaviour): - 0x0010 - consider to be inline block between WikiSourceBlocks - (prevents paragraph breaks between plugin and wiki block) - 0x0022 - scan for WikiWords in this paragraph - - - - your own block markup plugin - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Of course a _block plugin is a bit more complicated than a action - or page plugin, but generally you only need this small stub: - - $ewiki_plugins["format_block"]["your"] = "your_block_func"; - $ewiki_config["format_block"]["your"] = array( - "<your>", - "</your>", - false, // no special filter rule/flag - 0x0014 // see above, often also just 0x0000 - ); - function your_block_func(&$str, &$in, &$iii, &$s, $btype) { - ... - } - - Where you would just rework the conents of "$str", which will be - the text part in between the <your> and </your> tags as defined - by the $ewiki_config[] block plugin settings. The other variables - in that API aren't normally important. - - You only must take care, that "<", ">" and "&" are still encoded - in htmlentities() at this stage. - - - -xpi plugin system -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -A newer extension of ewiki (namely plugins/feature/xpi) allows to store -addon functions in the database (the code is saved as _BINARY db entry -where usually page text was stored). The "PlugInstall" page allows to load -the extension code from (even remotely located) .xpi files into the -database, from where it can be used later. -In order to use once installed xpi code, only the "feature/xpi0.php" -plugin was needed. - -Through the design of the xpi feature extension nearly all plugins could -be converted and installed in the .xpi format. Though this doesn't make -sense for database backends, and converting all to-date plugins is silly. -So this feature is further merely used for fun and mini-extensions. - -You could easily write your own .xpi plugins using the description in the -"tools/mkxpi" script. First you need to create a .src file with the plugin -code as usual (write it like an ordinary plugin script, except for page -plugins), and a few meta: informations on top of that file. Then the mkxpi -tool converts this in the binary .xpi format for distribution and -installation. -Typically this would look like: - - id: UniqueExtensionName - type: actionlink_and_textdata - license: Free to use - author: PutYourNameHere - description: adds the search/ action to the control-links line - icon: data:image/png;base64,iVBORw0KGgoAAAANS... - code: <?php - // just look'n'feel settings, no real plugin code here... - $ewiki_config["action_links"]["view"]["search"] = "SEARCH_ACTION"; - $ewiki_t["en"]["SEARCH_ACTION"] = "search in other pages"; - $ewiki_t["de"]["SEARCH_ACTION"] = "woanders suchen"; - ?> - -Most of the fields are optional (author, license, description and of course -icon) but senseful. The type: is required, but only a value of "page" has -a special meaning here (otherwise is merely descriptive). The id: gives that -plugin an internal identifier which will later be used for storing the -extension with a database-wide unique name; for "page" type plugins it of -course would be the name under which it was installed. - -The code: contains the usual plugin registration and function definition -code. But for "page" xpi plugins it may not have a function body, but lots -of 'echo' calls to output the dynamic pages contents when called (no return -allowed in this incarnation of page plugins). After this no other fields -should appear. - -Future .xpi versions may allow to embed other files for instant installation -(maybe image files for storage in database). But until now onle the code: -entry carries data which will be installed as database page. All the other -meta entries (id, type, author, ...) will however be stored in the xpi -registry database entry, which is also used to control the enable/disable -flag for each of it (only page plugins cannot be disabled). - -To share your own extensions simply send them to one of the core project -developers (Andy or Mario) or just leave a link on the "XpiPlugins" page: -http://erfurtwiki.sourceforge.net/?XpiPlugins - -because that way users will immediately see it when remotely installing -.xpi plugins from that default xpi plugin repository. It may be an -security risk for users if they install code from unchecked sources, but -the complete URL is always displayed right before storing the external -code into the database. - -The most interesting part of the .xpi system (PlugInstall page) is the -possibility to later disable or remove extensions easily. You only need -to setup the administrator password to install and control click-and-run -extensions without hacking the 'config.php'. - - - - ------------------------------------------------------------------ 5 --- - - - -mysql database structure -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The MySQL database table structure is (to a certain degree) compatible -with that of the well known »PHPWiki« v1.2.x (you only need to change -EWIKI_DB_TABLE_NAME to "wiki" to use it). This is the MySQL statement -which creates our database table (you can find it at the bottom of the -"ewiki.php" script): - CREATE TABLE ewiki ( - pagename VARCHAR(160) NOT NULL, - version INTEGER UNSIGNED NOT NULL DEFAULT 0, - flags INTEGER UNSIGNED DEFAULT 0, - content MEDIUMTEXT, - author VARCHAR(100) DEFAULT 'ewiki', - created INTEGER UNSIGNED DEFAULT 0, - lastmodified INTEGER UNSIGNED DEFAULT 0, - refs MEDIUMTEXT, - meta MEDIUMTEXT, - hits INTEGER UNSIGNED DEFAULT 0, - PRIMARY KEY id (pagename, version) - ) - -I didn't like the column name {pagename} but as I've seen this was -the only difference I renamed it, therefore now the ewiki_database() -function translates it from "pagename" to "id" and vice versa most of -the time - else this would be really slim and nice code :) - -The columns {version} holds the different saved page versions. Other -Wikis require a secondary "backup" or "history" table for old versions, -but as I couldn't imagine what this is for, there is just one table -in ewiki; and it seems this is really enough. The first {version} of -a wiki page is always numbered 1. An existing page {version} will -never get overwritten => very secure MySQL usage. - -For what's in the {flags}, see the README section about constants. The -{content} of course holds the wiki pages source. The {created} and -{lastmodified} should be clear too. - -{refs} contain a "\n" separated list of referenced WikiPages. The -code to generate that list is rather unclean, so it often contains -GhostPages. However this does not hurt ewiki and the few functions -that utilize {refs}, so there is currently no need to slow it down -by fixing this. - -{meta} can hold additional informations, which allows to extend ewiki -without requiring to ALTER and convert the ewiki database table. It -currently holds some mime headers for binary content and some other -useful informations for images and uploaded files. - -{hits} should have gone into {meta} really. But having it separate -allows us to use the very fast mysql UPDATE function. - -Note, that the ewiki database table can hold other things than wiki -pages - binary content (images) for example, depending on the setting -of the {flags} field. - -And last comment about this, the one-table-concept also made it really easy -to implement the flat file based "database backend". - - - - ------------------------------------------------------------------ 6 --- - - - -Just using the wiki source transformation -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The ewiki_format function was designed to be used independently from the -ewiki database. - - ewiki_format($wiki_source, 0); - -It just needs the "wiki_source" as argument and generates a nicely -formatted page from it. All you need to take care about is the -$ewiki_links variable. -Set the $ewiki_links=true ("true" and not "1" or anything else) to -enforce ewiki_format() to treat all references as existing. - -To separate the ewiki_format() function out of recent ewiki versions, -you'll also need ewiki_script(), ewiki_link_regex_callback(), ... and -a lot of constants to take with. It is often much easier to just -include("ewiki.php") for using ewiki_format(). You then should however -take care, that the _binary part doesn't get activated by accident. To -prevent this, just put following before the include() statement: - - unset($_REQUEST["binary"]); - include("ewiki.php"); - -If you need it more quickly, or don't want to load the whole ewiki.php -file, then just try the fragments/wiki_format.inc, which is a stripped -down version of an older rendering core function (no WikiLinks, no binary -stuff). Contributed by Frank Luithle. - - - diff --git a/mods/wiki/doc/LinkSpammers b/mods/wiki/doc/LinkSpammers deleted file mode 100644 index 542778463..000000000 --- a/mods/wiki/doc/LinkSpammers +++ /dev/null @@ -1,248 +0,0 @@ - -link spammers -------------- - -Link spammers target Blogs/Boards/Forums and Wikis in particular to -publicate hyperlinks to their sites. Those links aren't intended for -humans, but placed there purely to push search engine rankings. - -This is not a new trend, but an ongoing annoyance. Luckily ewiki -provides you with a small aresenal of useful counterfight plugins -and methods. There is a new plugin category ".../spam/" set up -exactly for this; the most useful plugins are however sprinkled -around - that's why this README tries to guide you. - - -what to do first ----------------- - -If you get spammed, you should first lock that particular page -against writing for a while - if only one is target of a massive -attack. - - -denying them success --------------------- - -Chances are, you got targeted by a link spammer because your pages -are too open for indexing. Go on and prove check, that your site -layout script loads following include() fragments: - - <html> - ... - <?php - include(".../ewiki/fragments/head/core.php"); - include(".../ewiki/fragments/head/meta.php"); - ?> - ... - </head> - -The first prevents (old) ?version= pages from getting indexed by -search engines, and new revisions cannot be indexed in the first twelve -hours. If you ensure that, then spamming your site gets uninteresting -for the pundits. It is unlikely that any search engine bot would index -the spamlinks before you remove them. - -The only problem here is, that most of the link spammers are only -semi-professionals and some won't notice this measure immediately or -at all. Nevertheless this is the most important step! Don't forget -that bringing crap onto your Wiki is only a time-consuming requirement -for spammers, what they are really targetting is Google & Co. and so -denying them success there has top priority. -Getting rid and preventing further spam is always only step two. - - (This attitude makes link spammers - as angry, as their spam makes us.) - - -mass link spamming (so called "WikiSpam") ------------------- - -Spammers need to spam a lot, else it gets financially uninteresting. -We simply call this "brute force" spamming from here. - -So most attacks against Wikis involve throwing a few dozens or even -hundreds (!!) of links onto a single page. This activity is easy to -track, and so if you see this kind of attack, all you have to do is -loading the according plugin: - - include(".../ewiki/plugins/edit/limitlinks.php"); - -This will reject any page edits with more than 5 new URLs, which -makes your Wiki a useless target for most spammers (those that operate -manually would get quickly annoyed here). Easy, Easy, Easy. Solves the -problem for most of us. - -If you run a link directory with your Wiki, this plugin will soon show -its drawbacks - but you could then specifically disable it for some -pages. - - -single comment link spammers ----------------------------- - -Many attacks against Wikis are side-effects and were originally meant -for spamming blogs and boards. You can tell apart this sort of attack -because of - - HTML or "BBcode" around the posted URL - - it's just a single link - - all previous content of the page is gone - - many many page revisions are created - -If this happens, then you are definetely attacked with a script. First -lock that particular page, after finding out the attackers entry point -(the edit/ page was typically bookmarked somewhere). - -You won't be able to stop this form of attack with simple IP-blacklist -methods, because the spammer operates with trojan-governed zombie -machines from many different locations. Our advantage is, that we can -easily tell it apart because of the edit/POST frequency. - -And also as easily we can get rid of bots, which do not specifically -target our Wiki software. Even simple captches (like the ProtectedEMail -checkbox) will normally do. - - - plugins/spam/antibot_checkbox.php - - plugins/spam/antibot_captcha.php - -Typically attacks start from bookmarked pages with some sort of VBscript -(this topic is not fully researched) running from zombie machines. So -there is little interaction, which makes the simple captchas successful. - -Moreover those bots are pretty dumb and don't behave like humans. You -can detect and blqock them as well by simply looking at how much time -is between retrieving the edit page and hitting submit/save. There is -a plugin which does exactly that, and blocks if the timespan is below -five seconds: - - - plugins/spam/antibot_captcha.php - -(Time is money for link spammers, they cannot even afford slowing their -scripts by even those 5 seconds.) - -If only few pages are targeted, you can also disable most of the protection -mechanisms selectively. There are a few "trigger" and "anti-trigger" -plugins, which specifically enable or disable the rest of our anti-spam -extensions. - - -blocking URLs -------------- - -There are also two plugins for blocking URL patterns. Look out for -"edit/spam_block" and "edit/spam_deface". For both of which you can -mantain patterns (on Wiki pages). - -With "lib/spamblock_whois" you can even go so far and lock against -domain registrants or hosters, which will block most future spamming -attempts of a person, once you find out. - -The "zero_pagerank" scripts and code is used to implement an -intermediate page, which again cripples page rank bonus of linked -pages. (Though this is less senseful now with the rise of hyperlink -flags as rel="NOFOLLOW"; read on...) - -There are many shared URL black- and blocklists, but we haven't yet -prepared a cron script to syndicate or even exchange it. But this is -definitely an option and worth considering. You can find a few big -blacklist with search engines. Projects like WardsWiki, WikiPedia, -MeatBall, CommunityWiki, but also GeekLog, WordPress, PhpNuke and -other portal/CMS-ware maintain some. - - -NOFOLLOW --------- - -Google and their page rank idea caused us all that trouble. They later -however decided to do something against link spamming, because they -itself suffered from a watered search database. It is possible to add -an rel="NOFOLLOW" to every <a> hyperlink tag. (IMHO it would be -more honest to call it "NOPAGERANK", but hey, better than nothing.) - -Use ".../ewiki/plugins/linking/a_nofollow.php" as the quick-but-dumb -solution. It adds this to all links, and prevents additional page rank -bonus for any pages. - -There is a variant of this (".../new_noffollow.php") which works -considerably slower, because it checks which links have been added the -last two weeks, and only adds the rel="NOFOLLOW" for fresh (=not yet -reviewed) links. - - -chinese spam ------------- - -If you don't have any chinese users or discussions, but are targeted -with links to there; you could lock against such content getting seen -by Google (remember: this is what we need to prevent, then spammers -will go away automatically). - - - plugins/meta/block_chinese.php - -It works by setting the NOFOLLOW flag automatically, if it detects -foreign (chinese) html entities. - - -manual ------- - -Load ".../plugins/meta/meta.php" to add a smaller input box on the -edit pages. On the pages that get targetted by spammers, simply add -"robots: NOINDEX,NOFOLLOW" -so search engines will avoid them. - -You can remove this again, if attacks go down. It turned out to be -too troublesome for most spammers to take care of this field. - - -last resort ------------ - -If everything else fails, then try to get rif of link spammers by -opting out from getting indexed by search engines. Either add an -<meta name="robots" content="NOINDEX,NOFOLLOW"> to your sites layout -or create an all-blocking "/robots.txt" file. - -Alternatively <meta name="robots" content="NOFOLLOW"> may be enough, -because search engines then wouldn't follow any spam links. You then -could operate your sites as normal, if you post a page with links to -all YOUR (real) pages on a non-blocked site. (Make your frontpage -static, and place a link to a less frequently renewed page index file; -everything else flagged with NOFOLLOW. That would work.) - - -edit locking ------------- - -Of course, if your Wiki is not publically-editable, then you won't -even have any of the above mentioned problems. But as you see, there -are enough countermeasures to live without any _PROTECTED_MODE setup. - - -edit captchas -------------- - -Another useful workaround against automated link spamming are captchas -on the edit/ screen. In the simpler cases, something like the -ProtectedEMail checkbox will do. They work because most attacks origin -from script-operated zombie machines, and those bots are too dumb to -target all possible WWW forms (they usually were meant for blog comment -fields). - -... - - -cleaning up the mess --------------------- - -Many of the tools/ can help you to remove spammy pages. Especially -the "holes" and the "revert" tool are useful here. Though most people -prefer the WikiCommander or ewikictl to rip bad page revisions. - - -more notes ----------- - -See [http://erfurtwiki.sf.net/WikiSpam] for more informations and a -more up-to-date guide. - diff --git a/mods/wiki/doc/MagicFields b/mods/wiki/doc/MagicFields deleted file mode 100644 index 10ea54515..000000000 --- a/mods/wiki/doc/MagicFields +++ /dev/null @@ -1,15 +0,0 @@ -There are a few special database {meta} field names used thoughout ewiki -and its plugins. This description tries to collect and summarize them. - - -$meta["class"] groups db entry / page into technical categories, - "temp", "calendar", "cache", "plugin", ... - -$meta["kill-after"] entry which shall be removed after given date - automatically (by cron.d/ scripts), used for - temporary and cache entries, just a time() value - - - - - diff --git a/mods/wiki/doc/NicerUrls b/mods/wiki/doc/NicerUrls deleted file mode 100644 index 27d9e6a1b..000000000 --- a/mods/wiki/doc/NicerUrls +++ /dev/null @@ -1,124 +0,0 @@ - -If you want nicer URLs (without question marks) for your Wiki, then follow -the instructions below on how to set this up with the Apache web server. - - -ModRewriteUrls --------------- - -If you want more beatiful URLs (!http://wiki.example.com/PageName) to all -your Wiki pages, you can either use the PathInfoUrls method or leverage the -power of the Apache mod_rewrite extension. - -==fragments/htaccess== provides an examplary setup. Typically it goes -by putting something like this into a .htaccess file near your ewiki -script/wrapper installation: - - RewriteEngine On - #-- let ordinary files pass through - RewriteCond %{SCRIPT_FILENAME} !-f - RewriteCond %{SCRIPT_FILENAME} !-d - RewriteCond %{SCRIPT_FILENAME} !-l - #-- every other 'filename' is however treated as page name - RewriteRule ^(.+)$ index.php?id=$1 [L,QSA] - -So then you can set the [EWIKI_SCRIPT] config constant to the right value, -using ==define("EWIKI_SCRIPT", "/wiki/");== for example. Please keep in -mind, that it should be absolute (a slash in front), because pagenames may -contain slashes and action names get prefixed using a slash too. - - define("EWIKI_SCRIPT", "/wiki/"); -# define("EWIKI_USE_ACTION_PARAM", 2); // forces ?action= param -# define("EWIKI_ACTION_TAKE_ASIS", 0); // in conjunction with this - -There are more paramters, that you might want/need to tweak (_URLENCODE -and EWIKI_DECODE for example). Please refer to the [README.config] on this. - - -virtual /wiki/ directory ------------------------- - -The most reliable approach to get non-ugly URLs for ewiki is to use -a fully virtual (= simulated by mod_rewrite) path name to access -Wiki pages. - -This example assumes you install ewiki into the DOCUMENT_ROOT -of yourserver. You should then put all ewiki files in a directory -named "ewiki". Into the .htaccess file of the DOC_ROOT directory -you'd put following: - -<code> - RewriteEngine On - RewriteRule ^wiki/(.*)$ ewiki/index.php?id=$1 [QSA,L] - RewriteRule ^wiki$ wiki/ [R] - #RewriteRule ^wiki$ http://example.com/wiki/ [R=301,L] -</code> - -So all pages can be accessed under the fake ==/wiki/== directory, while -ewiki files are actually in ==ewiki/==. The last rule should use the -absolute URL preferrably. - -You then would configure ewiki URL and link generation accordingly in our -hypothetic ==ewiki/index.php== script: - -<code> - define("EWIKI_SCRIPT", "/wiki/"); - define("EWIKI_SCRIPT_URL", "http://www.example.com/wiki/"); - define("EWIKI_SCRIPT_BINARY", "/ewiki/index.php?binary="); -</code> - -Please note the difference between _SCRIPT and _SCRIPT_BINARY (if -you need it at all). - - -PathInfoUrls ------------- - -Typically ewiki URLs will look like: - -* ~[/wiki/index.php?id=FrontPage] -* ~[/wiki/index.php?id=RecentChanges] - -If you can't use ModRewriteUrls, then you may wish to set the config -constant [EWIKI_SCRIPT] to something like "==/wiki/index.php/==" so you get -almost beatiful URLs to all Wiki pages: - -* ~[/wiki/index.php/FrontPage] -* ~[/wiki/index.php/RecentChanges] - -If you also have the permissions (providers often make this unusable for -silly reasons) to override some Apache settings, then you could put -"==**Options All +MultiViews**==" into your .htaccess file. This way the -URLs would further beautify to; - -* ~[/wiki/index/FrontPage] -* ~[/wiki/index/RecentChanges] - -Alternatively try to create an Apache .var file (index.var which maps to -index.php itself). See the ApacheManual for more informations on this -issue. - - -simple wiki/ support --------------------- - -If all of the above sounds still too complicated for you, or mod_rewrite is -not available then you could use the following trick to get prettier URLs. - -Rename your yoursite.php or "index.php" to just "wiki", and create a file -called ".htaccess" in the same directory with following content: - - <Files wiki> - ForceType application/x-httpd-php - </Files> - -This will trick Apache into parsing it as PHP script, even though the file -has no extension anymore. - -Add following to your config.php or above script: - - define("EWIKI_SCRIPT", "wiki/"); - -This works like the PathInfoUrls or virtual mod_rewrite directory as -described above. - diff --git a/mods/wiki/doc/NoticeMessages b/mods/wiki/doc/NoticeMessages deleted file mode 100644 index 18da9fed7..000000000 --- a/mods/wiki/doc/NoticeMessages +++ /dev/null @@ -1,5 +0,0 @@ -PHPs E_NOTICE flag to error_reporting() in fact means _DEBUGing messages. -While you can have it enabled on production sites (indeed I have a few), -this is not recommended and because ewiki+ sometimes emits lots of it, you -should keep it disabled - error_reporting(0). - diff --git a/mods/wiki/doc/PluginMetaFiles b/mods/wiki/doc/PluginMetaFiles deleted file mode 100644 index 4e785d0db..000000000 --- a/mods/wiki/doc/PluginMetaFiles +++ /dev/null @@ -1,259 +0,0 @@ - -what plugin .meta files are for -------------------------------- - -Plugins in ewiki have traditionally been just an asorted collection -of PHP include scripts. To accomodate real plugin management (using -the PluginLoader or the ConfigurationWizard, WikiInstaller, mkxpi, -INI-configurations and other stuff) we had to provide the necessary -data in some form. - -In-plugin (within comment fields) or centralized (in a big db file) -listings have been abandoned in favour of accompanying .meta files. -The format is a RFC822/HTTP/VCARD-like list of name:value-pairs in -a file with the .meta extension after the basename. This sort of -file is easier and faster to parse than XML-style data containers. - - -fields ------- - -Currently known and interpreted fields (most of them are optional) -and possible values are: - - api: just "ewiki" or "PHP" for us - - could signalize an incompatible plugin, if other CMS - suddenly adopted this .meta file scheme - - a value of "PHP" says that the plugin is NOT ewiki- - specific - - type: general description of what the contained code does - - this field is NOT in ewiki-specific terminology - - eventually not useful in itself, informational - for example: - "functions" - collection of (random) functions - "variables" - variable definitions - "data" - constants, large variables, etc. - "intercept" - handlers and interrupting control code - "mangle" - on strings or data hashes - "transform" - html conversion - "link" - page names / data mangling - "database" - app - "auth" - app - "input" - form fields or so - "listing" - (html) lists of page names - "special" - unspecific - "virtual" - the according .php script is ignored, - and "R" only the .meta data important - "api" - itself provides an interface, remote API - sometimes this field just simply contains the name of - an ewiki hook (not recommended) - - hooks: used ewiki plugin hooks as comma separated list, - "page" - "action" - ... - see also INTERNALS and API documentation - - page: occoupied plugin hooks for the given type, if any, - action: comma separated - list: (possible field names depend on what was set as type:) - - id: identifier for this plugin - - replaces basename of the current file - - not implemented yet - - depends: some pluginmanagers can automatically load other - conflicts: plugins or include scripts, if that's a requirement - for the current function - recommends: another plugin which makes sense in conjunction to the - described - provides: virtual plugin identifier, which other plugins may depend - upon (or conflict with) - delivers: like provides:, but that ONLY one plugin may deliver it, - and all others so become conflicting - - category: plugins are grouped by structure of the plugins/ - directory, but for some pluginmanagers a more - descriptive and divergent classification is possible - using this field and its values (more possible): - - action, admin, appearance, authentication, aview, database, - edit, extension, feature, filter, fragments, hypertext, - library, markup, meta, mpi, old, optimation, page, spam, - user - We use the plugins/ subdirectory name alternatively, but - if omitted the plugin could not appear in plugin listings. - - priority: how important is this plugin - if it's included/loaded - by default: - "core" - always - "required" - always - "standard" - enabled - "default" - enabled - "important" - often is - "recommended" - should be - "optional" - user decided - "extra" - ranks higher than "bonus" - "bonus" - super-optional gimmicks - "rare" - too special for most people - "deprecated" - NOT recommended or old - "never" - unused, can be enabled only by hand - "auto" - a pure dependency - WikiInstaller uses this to make differently feature- - loaded versions. - - this would probably be served better by numeric - importance levels (0..10), but hey - - title: shown by most pluginmanagers, informational - decription: - - author: informational fields for contributed plugins - homepage: - license: - copyright: - - url: download page for new plugin versions - - version: contributed plugins or from different project/vendor - sometimes contain a version number - - update: URL of actual plugin .php file, best if accompanied - by .meta file; used for automatic updates - - sort: some plugins must be loaded in a certain order to - function properly (e.g. database interface before most - others) - - gives a relative sequence number - - default for all other plugins is 0 - - range from -100 to +100 for ewiki plugins, - outside more for general PHP additions (like - upgrade.php) - rarely needed, rarely present, most pluginmanagers - already take care of the database plugins themselves - - funcs: for dependency/conflict checking, this entry lists - all defined functions - - config: list of configuration constants, variables; - description of multi-line format in next paragraph - -You can add fields as you wish, for some plugins special values -(like "*") are sometimes used. - - -config: field -------------- - -The only non-string field is "config:", as it is made up of -multiple lines, which describes constants and variables with -possible configuration settings. This is mostly used for -presenting <form>s which config.php/.ini fiels generated from. - -Constants are detected, because they are all-uppercase, and -configuration variables by a leading dollarg sign. A equal -sign follows with either just one default value, or nothing, -or a dash | separated list of allowed values. Finally a // -comment may follow. - - CONSTANT_NAME=value // comment, help, info - $ewiki_config["name"]= // default is empty string - ANOTHER_OPTION=1|2|3|4|5 // possible values - OR_EVEN=yes=1|never=0 // entitled, first is default - -Take care not to have spaces before or after the equal sign. - - -sort: ordering --------------- - -Some plugins must be loaded at certain positions before or with -others. Especially the database plugins need to be present -before the core script initiates the registered _binary() part. -Therefore the sort: field pre-orders loading of them. Currently -following ranges and points are defined: - - - -200 non-ewiki additions - .. - -100 minimum for ewiki plugins - .. - -50 higher-up interfaces, pre-dependencies - .. - 0 almost all plugins (the zero is implicit, plugins are - loaded unordered normally) - .. - 50 database backend - .. - 80 binary module (mostly auto-initiated in core script) - .. - 100 ewiki core - .. - -Plugins of course may be loaded after +100 and before -100, but -generally this should be avoided and the ["init"] hook be used -instead. - -Ordering of plugins must be fine-tuned by users. Registration of -action plugins for example always influences the order they are -displayed in later. The sort mechanism cannot handle any user -preferences. - - -example -------- - -As example consider following .meta file: -+-------------------------------------------- -|api: ewiki -|type: intercept -|hooks: handler, page, edit_save -|category: blocks -|page: VirtualPageName -|title: module-name -|description: adds interesting features -|config: -| PLUGIN_SETTING=1|0 // enables it - - -notes ------ - -future: - .meta plugin data can later be reimported into plugin files' - topmost comment section, if they get prefixed with an "@", - like for example: - /* - * @api: ewiki - * @title: ... - */ - - -tools ------ - -There are a few support scripts in the "dtools" package (CVS), -which can be useful, if you'd like to tweak defaults or patch -descriptions, for some reason??? (doesn't make sense except -if you'd like to help out). - -- "genmeta" created most initial description files from the - earlier FEATUREDB and SetupWizard + WikiInstaller -- "editmeta.php" can tweak various important fields for all - (200+) plugins at once -- "metafiles.php" contains general utility code -- "updatemeta" can analyze plugins and updates (=does not - overwrite) according .meta descriptions - functions, hooks, - and general informations - - -changelog ---------- - -The field names and values have been ravamped multiple times in their -initial design phase. -- "priority:" was called "inclusion:" before -- "type:" changed its semantics and possible values -- "sort:" was introduced rather late -- "name:" has been removed in favor of "id:" -- "section:" has been rejected in favour of "category:" - diff --git a/mods/wiki/doc/ProtectedMode b/mods/wiki/doc/ProtectedMode deleted file mode 100644 index 046db43a8..000000000 --- a/mods/wiki/doc/ProtectedMode +++ /dev/null @@ -1,578 +0,0 @@ - -Authentication in ewiki -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -If you'd like to restrict usage of your Wiki based on a user system and some -sort of permissions, then you may want to use the EWIKI_PROTECTED_MODE, which -enables additional access granting. (This is really optional, and won't have -any impact on the speed of ewiki if left turned off.) - -The whole _auth interface stuff was implemented with flexibility in mind, to -allow ewiki to reuse any existing user authentication scheme already working -for yoursite (or used in the container CMS surrounding ewiki). That is why -this all will look complicated at a first glance. - -While it is recommended to use the _auth interface for combination with an -existing user database (which most always requires to write your own plugin -to connect it with your user management system); it is for most people also -often satisfactory to just use one of the ewiki internal user database and -permission plugins that come as examples inside of the plugin/auth/ subdir. -You may want to give the user- and administrator-friendly UserRegistry plugin -a try if you don't already have a working user management system. - - -Leaving ewiki_auth() alone -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -If you just need a project internal Wiki or have only a small group of -active contributors, then you will often find it easier to just restrict -your Wiki using your Web servers .htaccess and .htpasswd method instead -(or see "fragments/funcs/auth.php" for the simpler inline solution). - -And often your restriction desires may be matched by the two-wrappers method -described in the main README file - one public read-only Wiki view, and one -password-protected access for contributors. - - -interfaces -¯¯¯¯¯¯¯¯¯¯ -The auth/ plugins are chained with the ewiki_auth() function, and restrict -access to the Wiki pages based on {meta} data or actions. The authentication -scheme is modular and divided into the thress basic abstractions / hooks: -- ["auth_perm"] is the main plugin function to check for access permission -- ["auth_query"] combines the user authentatication and login form printing -- ["auth_userdb"] can be used to retrieve a user entry or to verify passwords - - - ewiki_auth() - ¯¯¯¯¯¯¯¯¯¯¯¯ - Is called throughout the main ewiki script to request minimum - permissions for the current $action and requested $page. This function - chains to [auth_perm] and [auth_query] plugins to do its job. This - function then just returns a boolean, stating if the permission plugin - granted access. - - - ewiki_auth_user() - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Queries all ["auth_userdb"] plugins (multiple may be there) for the - given username and password, and returns (true) or (false) after - comparing against the database entries` password fields. - - This function additionally sets $ewiki_auth_user if the password - matches, and also $ewiki_author if it wasn't yet. - - -Variables -¯¯¯¯¯¯¯¯¯ -$ewiki_author - is only informational, but stored in each pages {author} database entry - field. It is not required to have this variable set, it is just used as - beatification for the database entries. If it was not set, then still IP - addresses appeared in the {author} field of edited pages. - -$ewiki_auth_user - on the other hand is used in some of the distributed auth plugins to - state that a user already was authenticated correctly. So this variable - is not necessary, just a convinience interface to work around the - completely functions-based _auth API. - -$ewiki_ring - could be used to allow permission granting from outside of ewiki, - without writing any custom(ized) ewiki _auth plugin. - - -ring levels -¯¯¯¯¯¯¯¯¯¯¯ -The so called "rings" are an optional simplification inside of the _auth -functions. Usually pages in ewiki are accesses pages using its name and an -action parameter, but it would to too much overhead to base permission -granting on both. So plugins like "auth_perm_ring.php" map $action/$id's -down to following "ring levels" to compare it against the current users -privilige level: - - 0 - is for "ADMINISTRATORS", allows actions like admin/ or control/ - 1 - means "MODERATOR" functions, like delete/ - 2 - for ordinary users or "EDITORS", which includes edit/ and upload/ - 3 - "GUESTS" can only view/ pages or view links/ and info/ - -While the "ring levels" are the built-in way to decide if the current -request is to be allowed or not, it is NOT the only possible. One could -still write a plugin, that completely skips the "$ewiki_ring" and bases -access granting on something completely different. However the ring levels -are also the default in the userdb plugins, and it is believed to be -satisfactory to have just four privilige groups/ levels, because otherwise -the user database needed to contain a bit mask or list of $actions which -were allowed for each individual user - what surely would be overkill. So -even if you tie an ewiki_auth plugin together with your already existing -user database, you may want to reduce it down to just these four permission -steps. - -The $ewiki_ring variable makes it therefore also possible to connect your -existing userdb with ewiki without writing a customized ["auth_query"] or -["auth_userdb"] plugin, because if you just enable the _PROTECTED_MODE -and load 'auth_perm_ring.php', then $ewiki_ring decides about access -granting. So all you needed to do from within 'yoursite.php' was to set -$ewiki_ring to 2, and sporadically to 1 for a few "moderator users". - - -ewiki_auth plugin hooks -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The ewiki_auth() function lets the ["auth_perm"][0] plugin decide about -access granting, if it finds one. It also calls the first ["auth_query"] -plugin before, and after the ["auth_perm"][0] returned false (but then -forcing to print a login form). - -The ["auth_userdb"] plugins are not called directly from within ewiki_auth(), -but they get activated by ewiki_auth_user() which itself is called by some -["auth_query"] plugins (but they do not need to do this, if they know a -better way). - -But please read the following plugin hook explanations first, if you go to -write your own customized ewiki_auth plugins: - - - $ewiki_plugins["auth_perm"][0] ($id, &$data, $action, $ring, $forcelogin) - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Is called from within ewiki_auth(), and should return a value of 1 or 0 - if permission is granted. The plugin function should determine this by - evaluating the current user name. - - The ["auth_perm"] plugin is itself responsible for retrieving the - current username and fetching associated priviliges; but at least the - user name can usually be found in the global $ewiki_auth_user or - $ewiki_author (previously used therefore) variables. And for the - "associated priviliges" the plugin could just concentrate on comparing - an already defined $ewiki_ring (which eventually was set by a previously - called ["auth_query"] or ["auth_userdb"] plugin) with the currently - requested one in the "$ring" parameter. - - Often an ["auth_perm"] plugin will want to just look at the $action - parameter to the currently requested page $id to make its decision - (not all users should be allowed all $actions). However often it is - easier to first map down the $action/$id parameters to a smaller set - of privilige levels (like the 4 ring levels, how the 'auth_perm_ring' - plugin does). - - If a perm plugin however is called with a $ring level request (this is - the $ring variable is not NULL or false), then it MUST also take it into - account (besides any other calculations on permission granting it - already did). - - The $data parameter contains the internal array of the current WikiPage - (as usual), and an ["auth_perm"] plugin could of course also use the - {meta} field to store access granting informations (the owner name or - even a password). Eventually the $data parameter is empty or only - requires a few fields; then it may be desirable for the perm plugin to - refetch the full database entry via ewiki_database("GET") before - anything else. An appropriate check for this case was for example - "if (count($data)<=5)". - - If the ["auth_perm"] plugin detects that access is to be denied, then - it should put a failure message into $ewiki_errmsg. - - One could also write an complete ewiki_auth() replacement using - this plugin hook, as all parameters for the original are passed - over and only the boolean return value counts. - - Note: The default ["auth_perm"] plugin ('.../auth_perm_ring.php') only - associates those "ring levels" to the different wiki $action tasks, and - all real user authentication is done inside "auth_query" - but this is - not required, and it's up to your fantasy to do it in a different way - (separate login page and [auth_perm] just querying cookies for example). - - - $ewiki_plugins["auth_query"][0] (&$data, $login) - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Is also called from within ewiki_auth() whenever the current users name - is required and/or a login form could be printed into the current page. - - The fourth param $login (boolean) tells whether a login form should be - printed (or some other mystic authentication should be started). This is - important because $login=0 means to just check for a username and the - password which may be currently already present in the httpd/cgi - environment (in a Cookie for example). - - With $login==1 the plugin is asked to return a login <form> by writing it - into the $ewiki_errmsg variable (unless you do some exotic authentict. - like http AUTH or access granting based on IP addresses). One could also - put a failure notice into $ewiki_errmsg. - - An $login>=2 on the other hand can be used to explicetely enforce printing - of the login <form>, even if an user was already logged in. (This then - becomes the re-login hook). - - If you then retrieved a $username and $password inside your auth_query - plugin (from wherever and regardless if $login=0 or $login=1), then - your ["auth_query"] plugin should immediately compare it against a user - database. - To comply with the rest of the ewiki auth plugins, you should do this - by calling ewiki_auth_user($username,$password) - which then just returns - true or false, if the retrieved name and pw match anything inside of any - registered user database. ewiki_auth_user() will then set $ewiki_ring, - $ewiki_auth_user, $ewiki_author if the queried database contained that - informations. Leave the $ewiki_errmsg alone if you let ewiki_auth_user() - check the $password. - - You could of course let your ["auth_query"] plugin do all that work - (comparing a $username and $password against an internal list, and - setting $ewiki_ring when possible) - some people may find this far - easier than chaining to ewiki_auth_user() or so, and this would allow - you some more flexibility and reduces complexity. - - This function doesn't need a return() value - it is not evaluated. If - you want to return something or inform some other parts or plugins, then - use $ewiki_errmsg for <html> strings, or $ewiki_ring for basic access - granting or invent another variable for later reevaluation by another - function (your custom ["auth_perm"] plugin for example). - - - $ewiki_plugins["auth_userdb"][] ($username, $password) - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - This is usally called from ewiki_auth_user() which itself got called - from within an ["auth_query"] plugin (the auth_method_* plugins). - - Should return the user 'database' entry for the given user in the form - array($encodedpassword, $ringlevel, ...) - The returned $encpassword - is afterwards compared by the ewiki_auth_user() function (usually - invoked from within auth_query() plugins). - The array should contain the $ringlevel for the queried user at array - position [1], but it does not need to be there. Everything afterwards - that in the array is ignored. So if there are other useful informations - in your userdb entries, then the ["auth_userdb"] plugin should export - this itself into $GLOBALS where useful. - - Alternatively an "auth_userdb" plugin could compare the $password - itself or remotely against the contents of its database (and not let - ewiki_auth_user() do that check). In this case it should fake the above - behaviour by returning the $password as first entry of an array() in - the form described above. - - The term 'plain auth_userdb plugin' (someties used in this README or - plugin comments) refers to the more stupid variant that just returns an - array() entry and lets ewiki_auth_user() compare the unencoded/submitted - password against the checksum from the _userdb plugin. - - -Examples for your own ewiki_auth plugins -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - - Your own userdb plugin - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - If you have an existing user database and management system, you'll - probably like to just reuse that one for ewiki. In this case you just - needed to write a custom ["auth_userdb"] plugin. - - <?php - define("EWIKI_PROTECTED_MODE", 1); - define("EWIKI_AUTH_DEFAULT_RING", 3); // read-only for unregistered - $ewiki_plugins["auth_userdb"][] = "my_userdb"; - - function my_userdb($user,$pw) { - $result = mysql_query("SELECT * FROM users - WHERE user='$user'"); - if ($row = mysql_fetch_array($result)) { - if ($flags & USERFLAG_ADMIN) { - $ring = 1; // moderator user - } else { - $ring = 2; // ordinary user, may edit/ pages - } - return( array($row["password"], $ring) ); - } - } - ?> - - In this example, we fetched the user data from a MySQL database table - 'users' with the rows 'name' containing the usernames, 'password' - containing encrypted or unencrypted (?don't care) password. The 'flags' - database column also tells wether the fetched user gets moderator - priviliges (ring 1) or not (ring level 2). - - Most SQL user databases are layed out like this one, despite the - fictional 'flags' column of course. If your database had an 'email' - field as well, you could add this to reflect it: - $GLOBALS["ewiki_author"] = $row["email"]; - - - Your own perm plugin - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - If you merge ewiki as just one piece into a CMS which already provides - user authentication, then you could write a complete ["auth_perm"] - plugin as replacement for ewiki_auth() like this: - - <?php - $ewiki_plugins["auth_perm"][0] = "cms_permissions"; - - function cms_permissions($id, &$data, $action, $rring, $login) { - - $user = & $GLOBALS["logged_in_user"]; - # if (empty($user)) { $user = CMS_Context::get_user_from_cookie(); } - if (empty($user)) { cms_print_login_form(); } - $is_admin = & $GLOBALS["user_is_root"]; - - $actions_allowed = array( - "DEFAULT" => array("view", "links"), - "root" => array("edit", "delete", "control", "admin"), - "user2" => array("edit", "delete", "info"), - "witch" => array("edit", "comment"), - "..." => ... - ); - - $ok = in_array($action, $actions_allowed[$user]) - || in_array($action, $actions_allowed["DEFAULT"]); - $ok = $ok || $is_admin; - if ($is_admin) { $GLOBALS["ewiki_ring"]=0; } - - return($ok); - } - ?> - - Instead of providing global variables your CMS may allow you to fetch - user state/settings via a function or class API. However this plugin - shows, how to ignore the $ring level stuff at all (but for the superuser - you should set it, because admin/ plugins rely on it). - - - No plugin at all - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Here's another example, on how to skip the 'plugin writing' thing - completely by just setting $ewiki_ring whenever possible (you should - then load the auth_perm_ring plugin). - - <?php - $ewiki_ring = 3; // view/browse/read-only Wiki - - if ($_COOKIE["username"] || $_COOKIE["LOGINSESS"]) { // simple guess - - $ewiki_ring = 2; // allows "edit" action and others - - if ($user_is_admin) { // (already set somewhere else) - $ewiki_ring = 0; // this grants access to admin/ plugins - } - } - ?> - - This is in fact the recommended way to do restriction stuff (the - simplest solutions are always the best). - - - Everything into auth_perm - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - As seen above the ["auth_perm"], ["auth_query"] and ["auth_userdb"] - chains do not need to get implemented completely by your plugin; - everything could be put altogether into just ["auth_perm"], as it is in - fact itself responsible for retrieving the username and printing a login - <form> when required. If you don't have a separate login page you may - then need to handle even password comparison herin. - - And as stated earlier it is the best option to use ["auth_perm"] for - full customization of access granting, because it completely replaces - the code of ewiki_auth(). - Because authentication frameworks like phplib intermix <html> output, - session management, database queries, password checking and permission - granting into a single API, writing a ["auth_perm"] plugin is often also - the only possible way to combine them with ewiki. - Not separating ["auth_perm"] and ["auth_query"] only may have the - disadvantage, that the login <form> could appear more often than - necessary. And you should therefore let users login before they browse - through the Wiki, because phplib and alike are not very $_REQUEST safe. - - -Old notes -¯¯¯¯¯¯¯¯¯ -When the wiki is in _PROTECTED_MODE, the core ewiki_auth() function is used -to check if the current user has permission to access the requested function. -Permission levels are called 'rings', but auth/perm plugins may restrict -access to functions also based on $action or page $id. - -If you just want to restrict your wiki, you will often find it -easier to write two different wrappers around ewiki. See the -paragraph in the HowTo section on top of the main README. - -The $ewiki_ring scheme is the built-in way to handle all permission -granting. Use this variable to separate users into the four groups: -guests (ring 3), ordinary users (ring 2), moderators (ring 1) and -administrators (ring 0). - -While ring permissions fit most usage restriction needs, and are -the default and built-in way to handle restrictions, they are -neither important nor required. You could write a customized -"auth_perm" plugin, which operates on a completely different basis, -and ignore those "ring levels" at all. With "auth_perm" it is -possbile to grant permissions much more controlled (finer -associations), for example by comparing $action and page $id with -allowed values for any given user. - - -Available auth plugins -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -This is a short overview about the example auth/ plugins that come with -ewiki. Please note, that all plugin files carry comments on top, which -often give more detailed informations about how to use them; and you -may often need to edit some settings inside of them to suit your needs. - -The most recommended plugins are currently: - * auth_method_http - * auth_perm_ring - * userdb_userregistry -but alternatives are always a good thing. - - - auth_method_form - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Provides a login request <form> like it is found in nearly all so-called - ContentManagementSystems. It stores the retrieved data back into a - browser Cookie once(!), after it was verified to match the user account. - - - auth_method_http - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Uses the HTTP Basic AUTH method to query users for login informations - (username and password), whenever it is needed. This is the recommended - ["auth_query"] plugin; while it cannot be made fancy-looking at all, is - more professional than the commonly found plain login <forms>. - (With Mozilla and XUL/XBL coming up, there may well be possibilities for - beatification of those otherwise boringly gray login dialog boxes.) - - - auth_perm_ring - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Maps ewiki $actions (and also page $id's or combinations) down to the - four basic ring/permission levels. Edit the config array() inside this - plugin to change the mapping for existing or new plugin $action methods. - Almost everybody wants to use this plugin for the _PROTECTED_MODE ! - - - auth_perm_unix - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Uses additional per-page UNIX-like "access rights" to map indirectly - to ring/permission levels of registered users. It does not rely upon, - but should be used in conjunction to one of the distributed simple - ["auth_userdb"] plugins. It extends user management by providing user - groups (which is not a core ewiki_auth feature, and won't become). - - The complicated internals are described in this plugins head comment. - - - userdb_array - ¯¯¯¯¯¯¯¯¯¯¯¯ - Provides the most simple/stupid internal user database - an array of - usernames and passwords and permission/ring levels. This is useful if - you only have a small group of active users, because it simplifies - user management to editing this plugin file (adding users and changing - passwords or permissions inside its PHP data array). - - - userdb_systempasswd - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Accesses an user database inside of the ewiki database as _SYSTEM page - "system/passwd". This page/file has a format like the UNIX /etc/passwd - file; but contrates on usernames, passwords and ring/perm levels. The - format of this ewiki page/file is described in the plugins comment. - The _SYSTEM flag of this ewiki page/file requires an administrator user, - which is the only one allowed to edit the "system/passwd" contents. - - To create (or edit) the page 'system/passwd' you will need to enter the - appropriate URL manually: ".../wiki.php?id=edit/system/passwd", because - the slash in the pagename makes it somewhat harder to find (ewiki else - believes the "system/" to be an action parameter). - - - userdb_userregistry - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Provides a ewiki database internal user/password list much like the - above plugin, but additionally allows user registration and account - management by non-administrators. The page "system/UserRegistry" then - contains the user,password,permission data, and can only be edited by - an ring level 0 user (administrator); while other users can go to the - virtual page "UserRegistry" to register an account or to change their - user settings (but of course not their permission level). - You can easily tweak this plugin to store additional data inside the - "system/UserRegistry" file for other uses. - - - password_locks - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Is an ["auth_perm"] all-in-one plugin, that allows to attach one - password to every page, which then locks the page for the user that - knows it. - - - you.php - ¯¯¯¯¯¯¯ - Is an ["auth_perm"] all-in-one plugin, that is handy, when you only - need the superuser/administrator account (like in PhpWiki). - - - auth_phplib - ¯¯¯¯¯¯¯¯¯¯¯ - Is an all-in-one ewiki_auth() plugin, that uses the 'phplib', which - itself provides a user management framework and authentication - functionality (<form> based). It adds permission management customized - for ewiki. Please refer to this plugins comments, because it allows - various customizations of course. - - - userdb_anonymous - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows anyone to login using just an email address as password (should - work with any ["auth_query"] user interface). Automatically grants ring - level 2 permission, if it detects an address in the HTTP From: header - field. - - - users_ldap - ¯¯¯¯¯¯¯¯¯¯ - Tries to login in a LDAP server using the given username and password - for verification. Just an example for external auth. - - - LiveUser - ¯¯¯¯¯¯¯¯ - A plugin bundle utilizing the PEAR LiveUser authentication framework - is separately available in the /plugins/auth-liveuser package, with - its own README file. It is even much more sophisticated than our - _perm_unix plugin, and provides user friendly administration pages. - - - -Terminology -¯¯¯¯¯¯¯¯¯¯¯ -administrator - Is a userdb registered user, which has permissions of ring level 0. - There exist multiple plugins, that are very dangerous to use (database - admin functions), and should not be accisible to ordinary users or - guests as well to not damage the Wiki setup or database. Therefore some - plugins rely on ring level 0 (== superuser level). - -editor - Means an "ordinary user" with ring/permission level 2, which is at least - allowed to edit/ (and then of course view/) pages. - -guest - An un/registered user in ring permission level 3 (which often is the - default for EWIKI_AUTH_DEFAULT_RING). - -moderator - A user in ring level 1, which has all permissions of ring 2 and 3, but - also can execute more dangerous page actions like page delete/ or so. - -_PROTECTED_MODE - this name is in fact used as joke here, the term origins from the - "virtual protected address mode" introduced in the i386/486 family cpus - in the late 80s (which is/was the basis for NT/Linux) - -ring levels - are connected to the "protected mode" joke, the 386 cpu also used - those ring levels (also in the range 0 till 3) - -superuser - Means the same as "administrator" or "root" (these terms in ewiki of - course do not refer to your computers filesystem). - - -Problems -¯¯¯¯¯¯¯¯ -ewiki_auth sometimes fails, because it tries to perform authentication first -when it is actually needed (unlike other systems, where you get annoyed with -the login <form> before you had the chance to see any page at all). - - diff --git a/mods/wiki/doc/README b/mods/wiki/doc/README deleted file mode 100644 index 6401ff5ac..000000000 --- a/mods/wiki/doc/README +++ /dev/null @@ -1,1388 +0,0 @@ - -ErfurtWiki - a fast, user-friendly, highly configurable Wiki engine in PHP -========================================================================== - - -README -¯¯¯¯¯¯ -This is the main documentation for ewiki. It tries to describes the basics, -and how to set it up. More detailed explanations on other issues are -separated out into the [README.config], [README.plugins], [README.fragments] -and [INTERNALS] files, and into the doc/ directory. -(Once you have the Wiki running, you could also read this file in hypertext -format.) - - 1 What is this? - 1.1 Why "ErfurtWiki"? - 1.1.1 Unique Features - 1.1.2 WikiAlternatives - 1.2 Project Pages - 1.2.1 Obtaining Support - 1.2.2 License - 1.2.3 Authors - - 2 HowTo - 2.1 Integration with yoursite.php - 2.1.1 What to do if images don't work - 2.2 Creating a "config.php" - 2.3 flat file database - 2.4 tarball directoy structure - - 3 other/advanced integration issues - 3.1 Generation of a "monsterwiki.php" script - 3.2 Supplying the WikiPageName - 3.2.1 mod_rewrite or PATH_INFO - 3.2.2 use with the 404 trick - 3.3 Security considerations - 3.3.1 PHP settings (register_globals) - 3.3.2 The two modes of operation (_protected_mode and _flat_real_mode) - 3.4 simple usage restrictions via wrappers (a locked PersonalWiki) - 3.5 PhpWiki compatibility - 3.5.1 Transition from another WikiWare - 3.6 Idea Collection - 3.6.1 Multiple Wikis / InterWiki feature abuse - - 4 Tweaking (your own wiki markup and CSS) - 4.1 Customizing ewiki_format() - 4.2 Customization using CSS - 4.3 user style classes in pages - 4.4 rendered page content - 4.5 pages enclosed in style classes - 4.6 plugin output styling - - 5 Explanations - 5.1 Binary and Text content - 5.1.1 Image Uploading - 5.1.2 Images Caching - 5.1.3 Image WikiMarkup - 5.1.4 binary_store, direct access - 5.1.5 Arbitrary Binary Content - 5.2 $action and $id - 5.2.1 ewiki URLs - - 6 Appendix - 6.1 Apache config - 6.2 PHP config - 6.3 error numbers - - - - - - - -------------------------------------------------------------------- 1 -- - - - -What is this? -¯¯¯¯¯¯¯¯¯¯¯¯¯ -This is a WikiWikiWeb engine implemented in the PHP web scripting -language. A WikiWiki is a web site which can be edited by everybody -who visits it (most commonly without requiring that user to register -before). - -It should allow easy integration into an existing web site (portal -or homepage / CMS-like software), as it is more a library and does -not output a full .html page - but instead just the formatted wiki -text for inclusion in your pages` body/content area. - -Many extension plugins are available and can easily be hooked in -(construction set principle). Try the "tools/setup" script. - - - -Why "ErfurtWiki"? -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The project name comes from the home town of the author (Erfurt is next -to Weimar.de); and our internal project name is in fact just "ewiki". - - - - Unique Features - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - ewiki is not just another Wiki engine, it has some features that - clearly separate it from other implementations: - - - contained within a single file (see the notes on "monsterwiki") - - does not impose a pre-defined layout, because it integrates - nicely into yoursite - - it is rather fast - uses regexs too, but the formatting kernel - uses the simple and quick string functions - - it is extremely featureful - - ewiki is not GPLed like 98% of all other Wiki implementations - - provides case-insensitive Wiki links, multiple database backends, - and all extended features are optional (a very exhaustive plugin - interface, and over 200 ready to use plugins) - - highlights: WikiCommander, OpenSearch, WikiSync, PHP-RPC database, - PingBack, TextUpload, click-and-run .xpi plugins, image upload, - GaGaLinks, XFN, CSS markup, WikiScript (not yet), TCN, and - in-page-macros: TableEditor, WebDAV, ... - - - - WikiAlternatives - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - If you don't like ewiki, then try at least one of these: - - - PhpWiki has a more complete approach than this WikiWare, - get it from http://freshmeat.net/projects/phpwiki, - it has support for different database types, features localization - and comes with an integrated admin area and also lots of plugins - made by its gigantic user base and development group. It initially - inspired the ewiki project, but also was the reason for starting - it. - - TikiWiki is a portal system centering around a powerful Wiki - implementation. Thousands of plugins and developers, many cool - extensions. http://tikiwiki.org/ and the http://tikipro.org/ fork - - Pie is a lean and unbloated Wiki implementation using a file based - database and storing pages as HTML. <http://pie.ekkaia.org/> - - WakkaWiki by Hendrik Mans is also a very powerful PHP implementation, - see http://www.wakkawiki.com/ - - Miki is another nice (small) implementation in PHP from Jukka - Zitting. Get it from http://miki.sourceforge.net/ - - coWiki - completely OOP and the source code layout is great; looks - very featureful, but is more a CMS than a Wiki (authentication - bloat) and has also a little weird markup, but better check it out - yourself on http://cowiki.org/ - - PmWiki is one of the more mature Wiki implementations for PHP, - it has been around for some time, has a large user base and is - still in active development. http://pmwiki.org/ - - MediaWiki drives the well-known WikiPedia project. It is very - powerful, but like Pmwiki comes with features that initially - are somehwat overkill for many users. The developer base is - huge, and features get added hourly. http://www.mediawiki.org/ - - PWiki2 was once the rising star in the world of PHP based Wikis, - but seems to have frozen in development. http://www.pwiki2.org/ - - The BEST PLACE to look for evil concurrent implementations is: - http://c2.com/cgi/wiki?WikiEngines - - And there is a new WikiEngine comparison table coming up, which - tries to sort them by supported features: - http://wikifeatures.wiki.taoriver.net/moin.cgi/WikiEngine - - Why do we recommend "concurrent" projects? Simple answer: ewiki is - not a commercial project, we do not depend upon having thousands of - "customers" or users; and it makes especially no sense to persuade - people to use it. While ewiki is very flexible, it is not believed - to met everybodys needs (that would be silly, wouldn't it?). - Choices are good, and the free software community offers a lot here, - so please just check them out, and make YOUR choice. - - Also have a visit at http://www.cmsmatrix.org/ if you've got time. - - - -Project Pages -¯¯¯¯¯¯¯¯¯¯¯¯¯ -official freshmeat project page: -- http://freshmeat.net/projects/ewiki - -demo site: -- http://erfurtwiki.sourceforge.net/ - -newest versions (unstable development releases): -- http://erfurtwiki.sourceforge.net/downloads/ - -mailing list archive -- http://www.freelists.org/archives/ewiki/ - -secondary site, WebInstaller: -- http://ewiki.berlios.de/ - - - - Obtaining Support - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Getting support for problems with ewiki is possible, but please read - this README first. The authors are thankful for BugReports, and of - course would like to know where this documentation is not detailed - enough and fails to explain things clearly. However, before you - send requests to anyone, please visit following site (this is - necessary to get FREE support): - - http://www.catb.org/~esr/faqs/smart-questions.html - - Then please feel free to contact the author or leave notes on the - BugReports or UserSuggestion pages on our project site. - - http://erfurtwiki.sourceforge.net/BugReports - - http://erfurtwiki.sourceforge.net/SupportForum - - Joining our http://erfurtwiki.sourceforge.net/MailingList would - allow you to reach a larger audience for your questions. However - you need to sign up first, and it's not much faster than the forum. - Keep in mind, that answers may come in slowly, and visiting back - first after 2 or 3 days is best practice. - - But after all: DON'T BE SHY TO ASK QUESTIONS - only because we - have a README here doesn't mean we don't want to give you real - support. - - - - License - ¯¯¯¯¯¯¯ - ErfurtWiki is PublicDomain, which means that you can do with it - whatever you want (that actually means it is free of copyright and - any restrictions). So it is free as in beer, and you can fork it, - rename it, commercialize it, or publish a derived version under the - GNU GPL, BSD, MPL, CC* licenses or even Microsofts' EULA. - - ADDITIONAL NOTE: a few plugins in the plugins/lib/ directory may not - be PD (to date all are, but that could change). Also the LiveUser - auth plugins (plugins/auth-liveuser/) are distributed under the GNU - LGPL. Everything that was a GNU GPL extension module was separated - out into our "extra"-tarball. - - - - Authors - ¯¯¯¯¯¯¯ - Mario Salzer <mario*erphesfurt·de> icq95596825 (+Yahoo,Jabber) - Andy Fundinger <andy*burgiss·com> from http://burgiss.com/ - - For the complete list of authors and contributors please see the - CREDITS file. - - This project is rather mature and well tested now, but to improve it - further we need to know what doesn't work or what could be enhanced. - Every mail is a contribution (yep, that is not measured in lines of - source code). - - - - - - -------------------------------------------------------------------- 2 -- - - - - -HowTo -¯¯¯¯¯ -ewiki is very easy to set up, you only need a web server with PHP (4.1 -or later) support. It even runs without a SQL database, but that requires -additional configuration (see for "db/flat_files" in [README.plugins]). -If you unpacked the tarball you can often simply point your browser to -there [http://localhost/ewiki/], to get it running. - -The following paragraphs are assuming you want to integrate the Wiki -engine into an existing web site / template. Otherwise you would simply -go with one of the supplied examples/, which are often ready to use. - -If you don't want to set it up yourself, you could check out our cool -new remote web install service: -http://ewiki.berlios.de/installer/ - - - -Integration with yoursite.php -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -For the next few paragraphs the "yoursite.php" refers to whatever -files and/or scripts belong to your already existing website. This -hypothetical script should at least output the <html><body> tags -around the output from ewiki. The most simple script to accomplish -this could look like this (see also example-2.php): - - <?php - mysql_connect("localhost", "DB-USER-NAME", "PASSWORD"); #[1] - mysql_query("use DATABASE-NAME-HERE"); - - define("EWIKI_SCRIPT", "yoursite.php?page="); #[2] - include_once("ewiki.php"); #[3] - ?> - <HTML> - <head>...</head> - <BODY> - <?php - echo ewiki_page(); #[4] - ?> - </BODY> - </HTML> - -[1] The first two commands open a connection to your MySQL database. -Usually one saves the result of mysql_connect() in a variable named -$db or so, but that was not used in "ewiki.php" at all (because PHP -does not depend on it if there is only a single db connection). - -[2] The define line tells ewiki about the <a href= hyperlinks it -shall create for wiki pages. - -[3] The include_once("ewiki.php") finally loads the ewiki "library" and -sets any EWIKI_ constants that have not already been defined here. Instead -of "include" we use the safer "include_once" since version R1.02b - -[4] The final call to the ewiki_page() function returns the wiki page -which was requested by the browser as <html> string. The "echo" command -lets PHP print it out. - - - - What to do if images don't work - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - If you don't start the yoursite template with a <?php code part as - shown in the initial example but have some <HTML> tags before the - initial inclusion of the "ewiki.php" script, then ewiki cannot - handle binary content (like uploaded images). - - You must ensure, that yoursite.php script starts with <?php and has - the include_once("ewiki.php") or include_once("config.php") there: - - <?php - mysql_connect(":/var/run/mysqld/mysqld.sock", "USER", "PW"); - mysql_query("use DBNAME"); - - define("EWIKI_SCRIPT", "yoursite.php?page=); - error_reporting(0); - - include_once("ewiki.php"); - - $content = ewiki_page(); - ?> - <HTML> - <HEAD> - <TITLE><?php echo $ewiki_title; ?> - </HEAD> - <BODY> - <?php - echo $content; - ?> - </BODY> - </HTML> - - Please again, note the initial <?php part before the very first plain - HTML output - yoursite.php must really start with it, or else binary - content (uploaded images) won't work! - - You could, of course use a "binary.php" besides "yoursite.php", to - get around this problem; please see fragments/ for an example. - - - -Creating a "config.php" -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Instead of including the plain "ewiki.php" script as shown in the -example above, many people may find it more useful to include_once() -a "config.php", which then itself loads the ewiki script. - -Customization of ewiki takes place, by pre-defining() some of the -EWIKI_ configuration settings and loading extension plugins (see -[README.config] and [README.plugins] for a complete overview). To -not move that work and code into yoursite it is recommended to -create some sort of "config.php" script, which then contained the -various define() and include_once() commands. - -It is sometimes even senseful to establish the database connection -(if you use SQL and not the flat_files backend) inside of such a -config script, if it wasn't already established in yoursite. - -So such a config.php script could contain: - - multiple define() commands, setting ewiki behaviour constants - - include_once() commands to load extension plugins - - evtl. some include_once() and define() for the db_flat_files plugin - (if you don't have a SQL database) - - and last but not least - an include_once("ewiki.php"); - -If you then include_once() such a config.php, you get a fully functional -and preconfigured Wiki to include into yoursite. By using this -approach, you still could override some of the EWIKI_ settings with -additional define() constants right before the include_once("config.php"). - - <?php - define("EWIKI_whatever", "..."); - include_once("includes/ewiki/myconfig.php"); - ?> - <HTML> - <BODY> - <?php - echo ewiki_page(); - ?> - </BODY> - </HTML> - -Note: All path names here are just examples, they will differ for -your setup! - -But again, creating a "config.php" script is optional; it is -supplied in the ewiki tarball for convinience, not for reference. -You may however want to create one of your own, by simply using -the "SetupWizard" script. Just point your web browser to -[http://localhost/ewiki/tools/t_setup.php] and chose the options and -extensions you want. Beware that while it provides a simplified -overview, it is not really short. - -IMPORTANT: Please use "include_once()" instead of the "include()" -feature. This is to prevent accidential double loading of plugins. -We do this since R1.02b, and this is how the generated config scripts -will work. - - - -flat file database -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -If you don't have a MySQL database, then you must configure ewiki to -store pages in a dedicated directory. You need to include_once() the -'plugins/db/flat_files.php' plugin prior to 'ewiki.php'. You must -also set the constant EWIKI_DBFILES_DIRECTORY to a location which -is world-writable ("chmod 4777 dirname" in FTP/shell). Usually this -would look like (in yoursite or a config.php): - - define("EWIKI_DBFILES_DIRECTORY", "./pages/"); - include_once("plugins/db/fast_files.php"); - ... - include_once("ewiki.php"); - -See [README.plugins] for more information on "db/flat_files". You can -also use the newer "db/dzf2" which creates a deep directory structure, -and seems to be a bit faster on some systems - moreover that one also -provided case-insensitive WikiPageLinking under Unix. - - - -tarball directoy structure -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -You get following directories and files, when you unpack the tarball: - -README.* main documentation -doc/ detailed doc on certain subjects -ewiki.php the core script, contains the minimum wiki -config.php example configuration script -example-1.php example yoursite wiki wrapper -examples/ more sample layout wrapper scripts -plugins/ large directory with extension scripts -local/ empty, use for your own/modified plugins -fragments/ code snippets, separate files, often not very ewiki specific -init-pages/ holds default wiki pages, automatically transfered into DB -spages/ "StaticPages" are dynamic/page plugins -tools/ database + administration tools, including SetupWizard -wiki.css description of CSS classes used in the core and plugins -z.php interface for Wiki-RPC, WebDAV, ?binary=, OpenSearch, sync, ... - -Feel free to explore especially plugins/ and fragments/ somewhat deeper -with your favourite file browser. Every file should carry a little amount -of documentation on top. The [README.plugins] file is always somewhat -outdated and not meant to describe everything anyhow. - - - - - - -------------------------------------------------------------------- 3 --- - - - -other/advanced integration issues -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Once you mastered the basic steps to integrate the wiki into yoursite, you -may choose to fine tune the generated URLs, behaviour and appearance. - -The following paragraphs are a selection of common issues and solutions, -like using mod_rewrite, setting up simple authentication schemes or changing -from another Wiki. - - - -Generation of a "monsterwiki.php" script -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -ewiki over the time grow larger, and nowadays isn't anymore the -SINGLE SCRIPT it once was. The distribution ships with over hundred -extension plugins. But nevertheless it is still possible to build -a single script from it all. - -That being said, the "ewiki.php" script still implements a fully -functional Wiki (and just only lacks the advanced features supplied -by the plugins). - You could still just include_once() the "ewiki.php" -script into yoursite and delete everything else the ewiki tarball -contained. - -However, it is also possible to MERGE all wanted plugins and the -core script together to built a customized (feature enhanced) Wiki -script from it. All you needed to do was: - - /unix/$ cat ewiki.php plugins/*.* > monsterwiki.php -or - C:\win\ type ewiki.php plugins/*.* > monsterwiki.php - -This way you'd get the "monsterwiki.php" file, which contained the -ewiki core script plus all plugins - but of course, you should only -copy the ones in, you really need and want (and not all "*.*" as -shown in the example above)! - -The UNIX shell script "tools/mkhuge" will do exactly that for you; -it accepts a parameter from 0 to 3, which will merge a custom set -of useful plugins into the then generated "monsterwiki.php" script. -In newer versions, you may want to use the "tools/setup" console -tool instead (for Linux), which makes this far easier. - -If you have built a "monsterwiki.php" script, you can include() this -instead of the minimal "ewiki.php" into yoursite to integrate a Wiki. - -Eventually you'd also want to merge some configuration settings into -this monsterwiki script, so you wouldn't have to put the define(...) -commands into yoursite.php before you include("monsterwiki.php"); -The define() commands however need to be the very first part merged -into that monsterwiki script, so it's best to edit the monsterscript -after generation and insert the appropriate settings then at the -very beginning. - You could also merge a (reduced!) "config.php" into the script, - using the above "cat" (or "type" for DOS/Win) method. But - beware, that this "config.php" then does not contain any - include() command; because else the resulting "monsterwiki.php" - script would fail trying to load the "ewiki.php" core script and - plugins which were probably already merged in. (The newer and - recommended "include_once()" won't help here.) Even if you merge - such a minimal config script at the start of this monsterwiki - script, you still could override some settings (at least - establishing the database connection) from within yoursite, if - you think it's useful. - -Additional note: You could still include() plugins, if you included() -such a monsterwiki script into yoursite, provided that the plugin -you try to include() wasn't already merged into that monsterwiki.php -script before (else it would crash the PHP interpreter, because -loading it twice is once too much => error + crash). - -StaticPages (read about "spages" plugin) can also be included, if -you first convert them into ordinary ["page"] plugins using the -'mkpageplugin' commandline tool. - - - -Supplying the WikiPageName -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -If you just call ewiki_page() as shown in the first example, it will -try to get the name of the requested WikiPage either from the -$_SERVER["PATH_INFO"] variable or from one of the GET-variables '?id=' -or '?name=' or '?page=' or '?file=' (available as $_REQUEST["name"]). -If yoursite.php however uses another way or another varname to receive -the WikiPageName you can just give it as first parameter: - - ewiki_page( $id = "WikiPageName" ); - -example-4.php shows how this can be used to list a second WikiPage -(the list of newest pages) somewhere else on yoursite.php. - - - - mod_rewrite or PATH_INFO - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - If you dedicate a complete directory for your wiki, you should keep - in mind, that some of the generated URLs contain slashes (for - example "edit/WikiPage"), and will look like subdirectories and thus - confuse browsers. - - So you should either set EWIKI_SCRIPT to the absolute directory - containing your wiki wrapper script: define(EWIKI_SCRIPT, - "http://myserver/wiki/"); or else put a <BASE HREF="..."> into the - generated pages. Take this precaution because some of the generated - links contain additional slashes (like "edit/ThisPage") and thus may - make browsers believe in a changed subdirectory. - - This applies to mod_rewrite usage and if you call your wiki wrapper - with the page name as PATH_INFO (like "/wiki/index.php/WikiPage"). - - Do not forget to enable EWIKI_USE_PATH_INFO, as it is per default - disabled for Apache servers! Also check, if EWIKI_URLENCODE and - _URLDECODE suit your needs, else you will find it useful that all URL - generation is encapsulated in our ewiki_script() function (so you can - easily adjust it). - - - - use with the 404 trick - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Once I've implemented a way to run a web server below another one - (actually Nanoweb below Apache, for more details see - http://nanoweb.si.kz/), because the Apache on one of my providers - servers was heavily misconfigured - so I handed work over to a - secondary WebServer. - - This trick also works without mod_rewrite support, and is therefore - also well suited for cheap WebSpace. Put following into the - .htaccess of the dedicated wiki directory: - - #-- handle "not found" pages by ewiki - ErrorDocument 404 /wiki/index.php - DirectoryIndex 404 index.php - - This will allow the "yoursite.php/ewiki.php" script to catch all - missed files, which would usually trigger a 404 error. Inside your - ewiki wrapper script, you must then however decode the originally - requested URL: - - $url = $_SERVER["REQUEST_URL"]; # Apache often uses this one - $url = preg_replace("#^/wiki#", "", $url); # strip wiki subdir name - $_SERVER["PATH_INFO"] = $url; # make ewiki see it - - The second step is very important, it strips the name of the - dedicated subdirectory from the URL, which cannot be done inside - ewiki.php. - - The $url from the above example could also be used as $id - parameter to ewiki_page(). - - It should be noted, that some Apache implementations are garbaging - POST requests in case of a triggered 404 error - but you can simply - test this by saving a changed WikiPage. - - See also the "fragments/404finder.php" example on this. - - Do not forget to enable EWIKI_USE_PATH_INFO, as it is per default - disabled for Apache servers! - - - -Security considerations -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -ewiki was developed using a PHP5 interpreter, but with limitations of PHP4.3 -in mind. There are huge differences (a rather instable, bug-prone and still -unfinished language) across the 4.x versions of PHP. The 4.0 series is not -enough to run ewiki, you'll need at least a PHP 4.1 (4.07) to make it work -reliable. - -One must also know, that there are also differences between the settings of -providers. Some for example enforce users to run their scripts in so called -"safe mode" (crippled mode) in place of real server security guidelines. -Other still use pre-4.3 settings for the PHP interpreter (the Win4 php.ini -still is outdated). So take care, and adjust settings using .htaccess` -php_option for Apache servers if you can. - - - - PHP settings (register_globals) - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Because ewiki was developed on later PHP versions (at least 4.3), it - heavily uses the $_REQUEST array and assumes a deactivated - "register_globals" setting in php.ini - If this is not the case for your setup / WebServer or with your - provider the ewiki.php script may expose some security leaks - (because of uninitialized variables). - - ewiki in general does only use a few global variables, but especially - the $ewiki_ring variable (which is used for PROTECTED_MODE) can lead - to problems, if you use it without an existing authentication - concept. The $ewiki_plugins is also a very complex task, and I - cannot safely state that it won't be able to produce exploits, if - the variable is tweaked externally (pushed into by a client). - - So the best thing you could do is to disable register_globals (this - can be done from inside a directories .htaccess file by inserting - the line "php_option register_globals off"). - - A fragments/ include will be added to strike against variables which - got set from outside (this is rather easy for variables used by - ewiki, because their names all start with "$ewiki_"). - - - - The two modes of operation (_protected_mode and _flat_real_mode) - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - While this wiki was originally developed as a real wiki, many people - use it for different things now, like private HomePages, easy CMS on - commercial web sites. - - This fact lead to the support of a restricted operation mode, now - known as the _PROTECTED_MODE. It is often used to require people to - log in before they can edit pages or upload things. It is completely - optional, and doesn't have much impact on speed when left disabled. - - Btw, the standard ewiki operation mode is - now known as the _FLAT_REAL_MODE ;) - - If you'd like to use authentication, you'll probably want to chain - some plugins which enable you to use the user database from - yoursite.php, so you do not need a separate .htaccess or an - additional relational database for passwords. Please see the section - on auth plugins. - - See also the EWIKI_PROTECTED_MODE configuration constant and the - separate [plugins/auth/README.auth] file for further and more - detailed informations on this feature. - - - -simple usage restrictions via wrappers (a locked PersonalWiki) -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The easiest way to cripple a Wiki setup to be browseable-only for the larger -public, and to allow only a small subset of users to edit pages is to write -two wrapper scripts around the ewiki.php library. - -One of the wrapper scripts should include and use ewiki as described in the -"Integration with yoursite.php" paragraph. You may want to move this wrapper -script into a password protected subdirectory (say "/wikiadmin/index.php") -or just include("fragments/funcs/auth.php"). - -Another wrapper script should then be provided for the users that are only -allowed to view pages. To disallow editing you'll just have to enrich it -with commands like: - - unset($ewiki_plugins["action"]["edit"]); # disables editing - unset($ewiki_plugins["action"]["info"]); # no info/ action - unset($ewiki_plugins["page"]["SearchPages"]); # no search function - -This code must occur after you have 'included("ewiki.php");' the library, -but before you call the 'ewiki_page();' function, so the unwanted actions -and pages really do not get activated. - -So far the basic approach. If you however have real user authentication -code behind the scenes you probably don't want to maintain two different -wrapper scripts. You'll then just put the functionality stripping code -from above into an if-clause in "yoursite.php" like: - - if (! $user_is_logged_in) { - unset($ewiki_plugins["action"]); # (you should do it less destructive ;) - } - -Note: this is again an example. DO NOT copy&paste examples and assume -they'll work for you! - - - -PhpWiki compatibility -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The MySQL database table is partially compatible to PhpWiki versions 1.2.x, -but not with the current PhpWiki 1.3.x versions. There is however now a -db/phpwiki13 plugin which allows to access those too (rw). - - - - Transition from another WikiWare - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - If you choosed ewiki to replace an already existing wiki script on - your site, you should first think about, that the syntax/WikiMarkup - isn't equal across all Wikis. There are a few markup extension - plugins, that may help you around this, but beware that transition - with a larger collection of WikiPages won't be very easy. - - The best way to import the old WikiPages to ewiki, is to first - export it using the tools of the previous WikiWare. You can then - just put the produced text/plain PageSource into "init-pages/", - because all files found therein (note, that there shouldn't be any - file name extension like .txt) are feed directly into the ewiki - database, when ewiki is run for the very first time (when the - EWIKI_PAGE_INDEX is not found in the db). - - There is a "plugins/db/phpwiki13.php" which may be useful in first - trying ewiki, but it is not recommended to use it for daily work. - Speaking of PhpWiki you could also use the "tools/t_convertdb.php" - to import (and markup convert) all pages from PhpWiki to the ewiki - database format. - - - -Idea Collection -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Here we'll note some tricks, on how to do this and that. Some of the -following paragraphs also explain workarounds for currently lacking -features. - - - - Multiple Wikis / InterWiki feature abuse - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Other WikiWare provides means to have multiple namespaces in a wiki, - what if fact is contrary to the original Wiki idea suggesting a - single flat namespace. ewiki does not support SubWikis or alike, to - get multiple Wikis using one ewiki installation you'll need multiple - layout and config wrappers (each with its own absolute URL and - differen EWIKI_DB_TABLE_NAME or EWIKI_DBFILES_DIRECTORY constants). - - This way you'd get two independent Wikis (with two different SQL - database tables, or flat_files directories), and of course links - between those two need a special syntax. And the best approach here - was to use the InterWiki linking feature. - - To do so, invent to InterWikiAbbreviations for each of your separate - Wikis and add it to $ewiki_config["interwiki"] as follows: - - $ewiki_config["interwiki"]["main"] = "/wiki/main/?id="; - $ewiki_config["interwiki"]["office"] = "/wiki/office/?id="; - $ewiki_config["interwiki"]["tech"] = "http://tech.company.com/?id="; - $ewiki_config["interwiki"]["our-www"] = "http://www.company.com/"; - - The last one is an example, on how to use the InterWiki feature to - generate references to arbitrary web documents, with a simple syntax - like "[our-www:/customers/pub/rules.html]" - it's somehow standard to - use "company-url:" or "company-www:" as InterWikiAbbreviation for this - purpose. - - - - - - -------------------------------------------------------------------- 4 -- - - - - - -Tweaking (your own wiki markup and CSS) -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -(this part of the README is also just a collection of random notes) - - - - -Customizing ewiki_format() -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -There are various markup extension plugins available for ewiki, which -allow you to use BBCode or the syntax of another WikiWare. But if you -have a closer look at $ewiki_config (the defaults are in 'ewiki.php' -around line 200), you'll notice, that you can configure the WikiMarkup -that is to be used. -Various "wm_..." entries map our obscure markup to html <tags> (or at -least fragments of them). So in order to add a feature you could insert -an own rule there. (But keep in mind, that every new WikiMarkup slows -down the transformation function.) - -Often you want to append an entry to "wm_style", for example: - - $ewiki_config["wm_style"]["==="] = array("<h1>", "</h1>"); - -Would allow you to write "===SomeText===" in a WikiPage, which then would -display as an far-too-large headline. - -You can also add markup with different 'start' and 'end' characters, using -the "wm_start_end" entry in $ewiki_config. For example the following would -render "... ((((some text)))) ..." in a page using the html <kbd> tag: - - $ewiki_config["wm_start_end"][] = array( - "((((", "))))", "<kbd>", "</kbd>", - ); - -Please see the section on "ewiki_format() internals" on how to write a -["format_..."] or markup plugin, see [README.programming]. - - - -Customization using CSS -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -There are now some interesting ways to style ewiki output, just read on. - -Please note, that it in your stylesheets you just write ".wiki" and -REALLY NOT ".ewiki" this time. - -Also important is, that we discourage use of the underscore in CSS class -names, because it is simply forbidden there, even if current browsers do -not complain as loudly as the w3c does. (That's just why you'll now see -lots of class names with minus dashes instead of underscores.) - - - -pages enclosed in generic style classes -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The most powerful way to style the content ewiki includes into your site -is to use the generic style class names which enclose every page that comes -from ewiki: - - <div class="wiki view PageName"> - ... - </div> - -This <div> is always the outermost tag around the html content that returns -from ewiki_page(). It will always contain the class "wiki", after this -the current page action/ and PageName (the action is usually "view", but -can be also "edit", "info", "links" or something similar). - -If you haven't seen that before, this is in fact valid CSS. It means that -this <div> is part of three classes. You can then use either ".wiki" or -".view" or ".PageName" or any compound of the three like ".wiki.view.PageNm" -as selectors in your stylesheet. - - Note: Non-word characters in page names are converted into '-' dashes - usually (including dots and spaces, underscores, and so on), consecutive - dashes are collapsed. If a page name originally started with a number, - then "page" will be prepended to it. - So for example "99BottlesOfBeer.en" became "page99BottlesOfBeer-en" in - the stylesheet. - -Keeping this in mind you can easily style all, a few or even just a single -page from ewiki in your stylesheet. (We'll explain it here, because the word -of multiple class names and the cascading way of using CSS is not very -widespread.) - -.wiki { // this affects every page ewiki returns - background-color: #ccccff; - font-family: "WikiFont"; - ... -} - -.wiki.view { ... } // only applies to pages that are "view"ed -.wiki.links { ... } // BackLinks -.wiki.edit { ... } // when a page gets edited - -.wiki.PageIndex { // this rule affects only a __single__ page - ... // regardless what the "action/" is now; -} // useful for "PowerSearch" or "PageIndex" - -.wiki.edit.ThisVerySpecialPage { // this css section applies to just one - ... // page again, and this time only when -} // it gets edited - - - -page style class fragmentation -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Moreover inside that generic <div> the page is fragmented further into -its individual parts to make styling it only partially really simple: - - <div class="wiki view PageName"> - - <div class="text-head"> - <h2 class="text-title"> <a>PageName</a> </h2> - </div> - - <div class="text-body"> - here comes the - actual page content - ... - </div> - - <div class="wiki-plugins"> - - <div class="action-links"> - <br/> <hr/> - <a>edit</a> <a>info</a> <a>links</a> - </div> - - </div> - </div> - -So the .wiki class itself is divided into three parts, where .text-head -typically only contains the headline (.text-title) and the actual page -content comes encapsulated in .text-body - -The part following as .wiki-plugins contains the individually named output -blocks from the so called aview-plugins, one of it is the .control-links -block containing the EditThisPage, BackLinks, ... actions and control links. -But there may be more of it inside of the .wiki-plugins block. See also -the paragraph on "plugin output styling". - -Likewise the .text-head block could contain more, but currently no plugin -throws other output above the page content or title. - -This further separation allows you for example to give headlines or page -content different borders or margins than the action links, so that it -matches better into your layout. You however don't need to use that classes -at all and could simply apply all styles onto the complete .wiki selector -as usual. - - - -rendered page content -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -If you are not interested in walking around the "ewiki.php" script -when you want to tune how the output looks, you should try to -utilize the (few) CSS classes ewiki defines (it does not include -even one color setting or <font> tag): - -<style type="text/css"> - - p { font: ... } // almost every part of the generated - // wiki pages is inside a <p>...</p> - - em { ... } // you could encolour this, if the browsers - strong { ... } // usual italic is not emphasized enough - - .indent // to specify a different space-indentation - -</style> - - - -user style classes in pages -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The plugins/markup/css allows you to use CSS classes and style definitions -in WikiPages. With the double at "@@" followed by a css classname or command -you start styling a paragraph or parts of the text. - - @@classname at the start of a paragraph will - enclose it into a <div class="classname"> - completely - - But inside of some text, the @@styledef only - affects the part until the next @@ - everything - that comes later won't be enclosed in a <span> - -While the css style classes must be defined in your sites` global stylesheet -to take effect, you could also use direct CSS style commands instead. These -also must follow the @@ immediately and may not contain spaces. So something -like @@color:#ff0000; will work, while specifying font names may not always. - - - -plugin output styling -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -There often appear special 'pieces' within a rendered page that ewiki -returns, because not everything in the returned html code belongs to the -requested pages` content. - -For example the current pages` title needs its own css class, like does -the block of action links ("EditThisPage, PageInfo, ...") below every page, -so it can be distinguished from the pages` text. - -Also note again the use of the '.wiki' selector within the following -stylesheet guide and ewiki CSS class overview: - - -.wiki h2.page.title { // all titles now have it, while many - ... // of them include links as well -} - -.wiki.view .action-links { // "EditThisPage, PageInfo, ..." links - ... // are inside such a block, like are two -} // <hr>'s - -.wiki.info .chunked-result { // some generated pages (like the history - ... // info/ ones) may need to split their -} // results; this matches those links - - //-- the edit/ pages are separated into - // following blocks: -.wiki.edit .edit-box { ... } -.wiki.edit .image-upload { ... } -.wiki.edit .preview { ... } - - //-- info/ pages contain a history of page versions, each enclosed in - // a <table class="version-info">, the <tr>s inside can be selected - // separately: -.wiki.info table.version-info { ... } -.wiki.info .version-info .action-links { ... } -.wiki.info .version-info .page-author { ... } -.wiki.info .page-refs { ... } -.wiki.info .page-flags { ... } - - -The class naming across most of the extension plugins is not unified, so you -may often need to look it up here - or inside of the plugins source code. -This is at least necessary for calendar and navbar, which follow a very -different naming scheme. - -.wiki .download-entry { ... } -.wiki .download-form { ... } -.wiki .upload-form { ... } - -.wiki .image-append { ... } - - - - - - - - -------------------------------------------------------------------- 5 -- - - - - -Explanations -¯¯¯¯¯¯¯¯¯¯¯¯ -The next few paragraphs shall enlight more detailed how some things are -handled in ewiki (and why it is that way). - - - -Binary and Text content -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Because I'd like to keep it small (see also the "Everything in one -script" paragraph) ewiki also creates just one database table. -Differently from other Wikis this one has the 'flags' setting for -each saved page. And as I successfully used this bad trick in earlier -projects many times to integrate support for hundreds of different -functions (CMS, links, boards/forums, ...) into a single table; I -thought it could be funny to have something like this in ewiki too. - -While the image thingi seemed senseful to me, other binary data -cannot be feed into database without helper plugins, because this is -a Wiki script and not an almighty portal software! - -Uploading and caching of images requires the EWIKI_SCRIPT_BINARY -constant to be set correctly (no output may be made before "ewiki.php" -is included == "binary safe"). -The ewiki_binary() function handles almost all of this, and gets -activated automagically (whenever required) as soon as ewiki.php is -included(). - -I believe these functions to be rather safe, as there are many sanity checks -throughout the code to separate between _DB_F_BINARY and _DB_F_TEXT content. - - - - Image Uploading - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The currently most important use for the BINARY flag and image - functions is to upload images with the small form below every page - edit box. - - The upload/caching functions can be disabled fully if - EWIKI_SCRIPT_BINARY and EWIKI_CACHE_IMAGES are set empty (or zero). - - URLs starting with "internal://" represent the uploaded files. The - string is just a md5() sum generated from the contents of the - uploaded file. This way files won't get saved another time if they - are uploaded twice. For uploading a JavaScript-capable browser is - recommended. It will work without, but then requires the user to - copy the [internal://...] text (from one window to another). - - The color of the temporary upload info screen can only be changed - inside the ewiki_binary() function, currently. - - Beware that images usually get downscaled if they are larger than - specified with EWIKI_IMAGE_MAXSIZE (per default 64K). - - - - Images Caching - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Images are usually redirected through EWIKI_SCRIPT_BINARY, and ewiki - tries to save them inside the database as with uploaded images. So - most of the facts from the previous paragraph apply to this function - too. - - You must enable this feature with EWIKI_IMAGE_CACHING, it is shipped - disabled currently. - Adding a ?nocache to the image URL disables this feature for just one - specific image, if _IMAGE_CACHING was otherwise enabled. - - Images are downscaled to fit the maximum defined size in - EWIKI_IMAGE_MAXSIZE (bytes) if the PHP libgd extension is available - (else dropped and then always redirecting clients which request - those image). - - - - Image WikiMarkup - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Usually one writes image references using square brackets around the - url of an image: [http://www.example.com/pics/image.png] or: - [internal://md5md5md5md5md5md5md5md5md5md5md5md5.png] - - This will include (inline) the image into the page, when rendered - and viewed. Using the standard square bracket link entitling syntax - also image references can be named (non-graphics / alternative - text): - [http://www.example.com/pics/image.png | This is an example image] - [http://.../image.pic "or entitle it using double quotes"] - - Images can also be "aligned" to either side of the screen, thus the - remaining text will flow around it. To achieve this include spaces - to the left or the right of the image URL: - - * picture to the LEFT: [http://www.example.com/pics/image.png ] - * picture to the RIGHT: [ http://www.example.com/pics/image.png] - * CENTRED picture: [ http://www.example.com/pics/image.png ] - - Note that you must use __two__ spaces, currently! - - Image rescaling is possible by appending x=... and y=... as query - string parameters behind the image URL: - [http://www.example.com/pics/image.png?x=160&y=120] - The query string parameters "width" and "height" are also accepted. - - If you have an image URL, but you do not want to get that image - inlined into the current page, then just leave out the square - brackets around. - - - - binary_store, direct access - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - While storing the binary data together with text pages in the same - database is most often a good thing and suits most sites, there - exists also a workaround/hack to keep this binary data in plain - files. The advantage is a smaller database and possibly a little - speed enhancement (with a large collection of binary things in the - db). However the drawback is, that use of plugins/binary_store is - only transparent to the main ewiki script, but all admin tools/ - won't be aware of it. - - If you choose to use the binary_store.php plugin, you can also let - ewiki generate URLs directly to the then stored data files if you - just set the EWIKI_DB_STORE_URL constant. - - Please see the paragraph on this plugin for more informations on - this. - - - - Arbitrary Binary Content - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Set the EWIKI_ACCEPT_BINARY constant, if you'd like to allow any - binary file to be uploaded and saved in the database using the image - upload function. Uploaded files will show up as ordinary (except - that "internal://" href prefix) links. - - Please also note the "plugins/download.php", which does a much - better job than this constant. - - - -$action and $id -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Inside of ewiki.php you'll see many occurrences of variables named $id and -$action. The $id refers to the current page, which usually is a string like -ThisPage, ThatPage, OrAnotherPage. - -Because just having pages wasn't believed to be sufficient enough, there -is also a way to do something with them. That is what the $action tells. -The most often used $action is "view" and is automatically assumed when -no other $action was specified in the current ewiki URL. For non-existent -pages alternatively the "edit" $action may get used instead. - -So the $action now delegates control about a requested page to a subfunc -or plugin of ewiki, so the stored data of the page can be used for -something (viewing being again the most common thing to do with it). - -"action/ForTheCurrentPage" is how both often looks in conjunction (again: -if there is no "$action/" then "view/" will be assumed). Here the $action -appears in front of the page name separated by a slash. A pagename now can -contain slashes too, because ewiki can figure out, that "view/That/Page" -separates into the $action being "view" and $id is "That/Page" in this -example (the "view" gets mandatory in such cases). - - - - ewiki URLs - ¯¯¯¯¯¯¯¯¯¯ - "$action/$id" is most commonly appended as "GET parameter" to an - ewiki URL, after a string like "?id=" or "?page=" - you've already - noticed that! - - There are of course other ways to design the URLs ewiki produces - and uses, the PATH_INFO being one of the most favoured alternatives. - (we had a paragraph on this earlier, see on top of this README) - - Other Wikis use different URLs too, but you can tweak ewiki easily - to a different behaviour, because you have the chance to pass your - $action and $id to ewiki_page() from different sources. And because - URL generation is encapsulated into the function ewiki_script() - you could easily change just a few lines to make them look like you - desire. - - The $action can be passed as "?action=" parameter already (this is - core support), so URLs could for example look like - ".../my/wiki.php?id=ThisPage&action=view" ... or something alike. - - - - - - -------------------------------------------------------------------- 6 -- - - - -Appendix -¯¯¯¯¯¯¯¯ -This sections lists things, that in fact have little to do with ewiki. - - - -Apache config -¯¯¯¯¯¯¯¯¯¯¯¯¯ -You must of course configure your Apache (or any other Webserver) to -feed .php scripts through the PHP interpreter, either libphp (Apache) -or the standalone CGI PHP interpreter. - -If your Webserver supports mod_rewrite (Apache, Nanoweb), you may wish -to use it for URL beatification as described in "fragments/htaccess". - - - - -PHP config -¯¯¯¯¯¯¯¯¯¯ -ewiki relies upon various settings of the PHP interpreter, which either -can be changed with entries in the php.ini or via option settings from -within .htaccess (only if you have Apache with libphp running). - -A .htaccess option setting looks like: - - php_option register_globals off - -while in the "php.ini" you would just write: - - register_globals = off - - - -The recommended settings are: - - magic_slashes_gpc = off ; This was enabled for old PHP versions - ; to help newbies writing more secure - ; scripts in regards to database access (makes you wonder, which - ; newbie actually could deal with databases). Nowadays this setting - ; is still enabled by some providers, which try to keep their buggy - ; site running. - ; As a workaround (SlowSlowSlow, and not WikiWiki!) you can use - ; fragments/strip_wonderful_slashes.php - - magic_quotes_runtime = off ; This is even more awful than the above, - ; and if you cannot disable it, then you - ; should not run ewiki on your Webserver. It is not believed to - ; work correctly with that setting. - - register_globals = off ; This setting is a security risk, if kept - ; enabled, because ewiki was written on a - ; system where it is disabled (like with all newer PHP versions). - ; It once was a very convinient setting, but the PHP language has - ; long lost its sinmplicity and ease. - - register_argc_argv = on ; is important for 'ewikictl' & Co. - - safe_mode = off ; The so called 'Safe Mode' was introduced - ; for mass hosters, which didn't want to - ; deal with security guidelines and needed an easy way to "secure" - ; their servers. This setting cripples various PHP functions, and - ; thus will disallow to use multiple ewiki extensions. The Safe - ; Mode renders it completely useless and stupid to run a webserver - ; on the Unix/Linux plattform, because its strenght was to invoke - ; the various fast utilities and filters through pipes. And the - ; lack of this opportunity then disables many ewiki extensions. - - allow_url_fopen = on ; You will need these, if you want ewiki - file_uploads = on ; to deal with image caching and file - ; uploads (of course). - - error_reporting = ... ; You should preferrably have this disabled, - ; even if ewiki.php already carries an - ; error_reporting() call to do exactly that. - ; The ewiki code is clean, but no longer cares about PHP "Notices" - ; and sometimes also "Warnings" that much. - - cgi.force_redirect = 0 ; This is a stupid PHP option, that is only - ; there to fix a "/cgi-bin/ install" of PHP. - - cgi.fix_pathinfo = 0 ; PHP scrambles the PATH_INFO if you keep - ; this enabled. However Apache 1.3 often - ; returns a broken value, so this may not matter to you anyhow. - - cgi.rfc2616_headers = ... ; If you don't have Apache 1.3 running - ; (any earlier versions would do, and laters - ; will be fixed again), then you should enable this; though ewiki - ; does not rely on it. - - short_open_tag = ... ; ewiki does NOT care - - output_buffering = ... ; ewiki does NOT care - - - -error numbers -¯¯¯¯¯¯¯¯¯¯¯¯¯ -A few ewiki error messages are kept uninformative to prevent abuse of -security (misconfiguration) leaks through visitors. Usually you will find -an error number besides (in the tradition of OS/2 ;-), which you can then -lookup here: - - -ERROR #0257: is triggered by fragments/strike_register_globals to signalise - that your PHP interpreter is still configured with register_globals - enabled. The whole purpose of fragments/strike_... is to prevent variable - injection from outside. Suddenly this is what happened if you've seen this - message - but if you've discovered it yourself, then the reason for this - security problem is a bogus extension plugin, which simply tried to - reinsert values from one innovocation to another in a non-standard (too - direct) way. - Simply disable register_globals and unload the fragments/strike_... - script to get rid of this error. - diff --git a/mods/wiki/doc/README.de b/mods/wiki/doc/README.de deleted file mode 100644 index 68c086066..000000000 --- a/mods/wiki/doc/README.de +++ /dev/null @@ -1,858 +0,0 @@ - -README.de -¯¯¯¯¯¯¯¯¯ -Dies ist eine teilweise Übersetzung der [README] Datei, die weiterhin als -Referenz verwendet sollte, da hier nur ein paar allgemeine und Setup- -Informationen enthalten sind. - - 1 Was ist das? - 1.1 Warum "ErfurtWiki"? - 1.1.1 Besondere Features - 1.1.2 WikiAlternativen - 1.2 ProjektSeiten - 1.2.1 Support bekommen - 1.2.2 Lizenz - 1.2.3 Autoren - - 2 Wie jetzt? - 2.1 In yoursite.php integrieren - 2.2 Den WikiSeitenNamen bestimmen - 2.9.1 WikiSprache einstellen (deutsch) - - 3 Im Detail - 3.1 die ewiki_ Funktionen - 3.2 $GLOBALS Verschmutzung - 3.3 die EWIKI_ Konstanten - 3.4 $ewiki_config[] array - - 4.1 Nur die WikiQuelltextTransformation einsetzen - - 6.1.2 Ohne MySQL DB verwenden (WICHTIG) - 6.1.3 db_fast_files - 7.3.3 BöseBäckSläshes \\\\" (WICHTIG) - - 9.5.5 Paßwörter und tools/ - - - - ------------------------------------------------------------------------- - - - -Was ist das? -¯¯¯¯¯¯¯¯¯¯¯¯ -Dies ist eine "WikiWikiWeb" Bibliothek, die in der Skriptsprache PHP -implementiert ist. Ein WikiWiki ist eine Webseite, die von wirklich jedem -verändert/ergänzt werden kann, der dort vorbeischaut (ohne vorhergehenden -Registrierungskram). - -Es sollte relativ einfach in bestehende Websites integrierbar sein, -weil es eben kein komplettes Script sondern eher eine Bibliothek ist, -die kein fertiges Seitenlayout erzwingt. Stattdessen können die -erzeugten WikiSeiten als Inhalt in das Layout einer bestehenden Seite -eingebunden werden. - - - -Warum "ErfurtWiki"? -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Der Projektname ist Zufall, hat sich der Autor ausgesucht (Heimatstadt), -und der interne Projektname ist übrigens "ewiki". - - - - Besondere Eigenschaften - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - ewiki ist nicht einfach nur schon-wieder-ein-neues-Wiki, sondern - hat einige besondere Features: - - - ewiki besteht im Grunde nur aus einer einzigen Datei (monolithisch, - siehe auch "monsterwiki" in der [README]) - - es werden keine vordefinierte Layouts werden aufgezwungen, das - Wiki läßt sich einfach in existierende Seiten einbauen - - es ist vergleichsweise schnell, reguläre Ausdrücke werden zwar - verwendet, aber nicht so exzessiv wie in anderen Wikis - (hauptsächlich einfache und flinke String-Funktionen) - - der Funktionsumfang ist inzwischen beachtlich :) - - anders als 95% aller Wikis ist es mal nicht GPL - - beherrscht Groß-/Kleinschreibungs-unempfindliche WikiLinks, - verschiedenste Datenbanktypen, und alle erweiterten Funktionen - sind rein optional (mächtige Pluginschnittstelle) - - - - WikiAlternativen - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Wem ewiki nicht zusagen sollte, dem seien folgende Wiki engines ans - Herz gelegt (testen schadet ja nix): - - - PWiki2 ist der neue Stern am Himmel PHP-basierter Wikis, es wird - aktuell sehr intensiv und schnell weiterentwickelt, immer einen - Blick wert: http://www.pwiki2.org/ - - PmWiki ist eine der ausgereifteren Wiki-Umsetzungen für PHP; gibt - es schon eine ganze Weile, hat eine große Usergemeinde und wird - aktiv gepflegt und weiterentwickelt. http://pmwiki.org/ - - WakkaWiki von Hendrik Mans ist auch eine sehr mächtige PHP - Umsetzung, siehe http://www.wakkawiki.com/ - - Miki ist eine kleine WikiImplementierung in PHP von Jukka - Zitting. http://miki.sourceforge.net/ - - coWiki - ist komplett OOP and das Quellcode-Layout ist großartig - (nur die Doku scheisse). Sehr große Funktionsvielfalt, aber ist - mehr ein CMS als ein Wiki (Authentifizierungsquark) und hat auch - etwas merkwürdiges Markup. Aber bitte selber testen: - http://cowiki.org/ - - PhpWiki has a more complete approach than this WikiWare, - get it from http://freshmeat.net/projects/phpwiki, - it has support for different database types, features localization - and comes with an integrated admin area and also lots of plugins - made by its gigantic user base and development group. It initially - inspired the ewiki project, but also was the reason for starting - it. - - PhpWiki hat einen etwas ganzheitlicheren Ansatz als ewiki, - siehe http://freshmeat.net/projects/phpwiki, - unterstützt versch. Datenbanktypen, Lokalisierung, integrierter - Administrationsbereich und jede Menge Plugins (fest verdrahtet) - durch die riesige Benutzergemeinde und immer noch aktive - Entwicklungsabteilung. War anfänglich Inspiration für ewiki - - aber auch der eigentliche Auslöser ein neues Wiki in die Welt zu - setzen. - - Der BESTE PLATZ um nach teuflischen Konkurrenz-Implementierungen zu - sehen ist: - http://c2.com/cgi/wiki?WikiEngines - - Und es gibt auch eine neue WikiEngine Vergleichs-Tabelle, in der - die verschiedenen Wikis nach Features sortiert werden sollen: - http://wikifeatures.wiki.taoriver.net/moin.cgi/WikiEngine - - Warum wir die "Konkurrenz" empfehlen? Ganz einfach: ewiki ist KEIN - kommerzielles Projekt - unser Leben hängt nicht davon ab, ob wir - tausende von Benutzern haben; es macht also auch keinen Sinn jemanden - zu überreden es zu verwenden. Obwohl ewiki zwar recht flexibel ist, - kann es kaum DIE Lösung für jedermann sein (wär doch bescheurt, - oder?) - Die freie Wahl zu haben ist eine feine Sache, und die FreeSoftware- - Gemeinde bietet im Bereich Wiki eine ganze Menge - also probier' - doch einfach selber aus, welches Wiki für DICH am meisten bringt. - - -ProjektSeiten -¯¯¯¯¯¯¯¯¯¯¯¯¯ -freshmeat -- http://freshmeat.net/ewiki - -demo: -- http://erfurtwiki.sourceforge.net/ - -neueste Versionen (instabile EnwicklerVersionen): -- http://erfurtwiki.sourceforge.net/downloads/ - -mailing list archiv -- http://www.freelists.org/archives/ewiki/ - - - - Support bekommen - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Hilfe bei der Installation gibt's natürlich, und selbstverständlich - sind wir auch dankbar für jeden Hinweis über bestehende Probleme und - Fehler (bekanntermaßen ist die REAMDE noch nicht ausführlich genug - und stellenweise überhaupt keine Hilfe). Bevor du aber einen - BugReport versendest, lies dir bitte folgende Anleitung durch - (absolut notwendig um KOSTENLOSEN support zu bekommen): - - http://www.lugbz.org/documents/smart-questions_de.html - - Danach bitte nicht zögern, einen der Autoren zu kontakten oder - einfach eine Nachricht in BugReports oder UserSuggestion auf unserer - ProjektSeite zu hinterlassen. Wenn du dich auf unserer - http://erfurtwiki.sourceforge.net/?MailingList anmeldest, hast du - die Möglichkeit Hilfe für dein Problem von einer größeren Gruppe von - Leuten zu bekommen (an- und wieder abmelden geht schnell). - - - - Lizenz - ¯¯¯¯¯¯ - Dieses "Programm" wird als "Public Domain" vertrieben. Public Domain - ist wie "FreeWare", nur ein bischen mehr frei ;-> Man kann sich das - vorstellen, wie die GPL ohne an die GPL gebunden zu sein. - - Da dies ein freies (Bier) Stück Software ist, kann mich natürlich - niemand für irgendwelche Fehler oder all die WIRKLICH SCHLIMMEN - FESTPLATTEN-SCHÄDEN verantwortlich machen, die bei der Verwendung - entstehen könnten ;> - - - - Autoren - ¯¯¯¯¯¯¯ - Mario Salzer <milky*erphesfurt·de> icq95596825 (auch Yahoo, Jabber) - Andy Fundinger <andy*burgiss·com> von http://burgiss.com/ - - Und alle anderen wurden in die Datei CREDITS verbannt ;-> - - Dies ist ein relativ neues Projekt. Um es zu verbessern, bin ich - sehr auf Rückmeldungen angewiesen. Jede Mail ist ein wertvoller - Beitrag! - - - - - ------------------------------------------------------------------------- - - - - -Wie jetzt? -¯¯¯¯¯¯¯¯¯¯ -ewiki ist supi-einfach zu installieren, du brauchst nur einen Webserver -mit Unterstützung für PHP (4.1 oder später). Es läuft auch ohne SQL- -Datenbank, allerdings mußt du dann ein paar zusätzliche Einstellungen -machen (siehe "db/flat_files" in der [README.plugins]). -Wenn du den Tarball entpackt hast, reicht es aber meistens einfach den -Browser darauf zu richten [http://localhost/ewiki/], um es zum Laufen zu -bekommen. - -In den folgenden Abschnitten geht es darum, das Wiki in eine bestehende -Seite / -Vorlage zu integrieren. Andernfalls kannst du auch einfach eines -der mitgelieferten Layouts aus examples/ verwenden, ohne daß du noch groß -irgendwas einrichten müßtest. - -Falls du keinen Bock hast, dir hier irgendwas durchzulesen, einfach nur -ein Wiki willst, wird dich sicher unser neuer cooler web-install-service -interessieren: -http://ewiki.berlios.de/installer/ - - - -In yoursite.php integrieren -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -In den nächsten Abschitten, soll mit dem Begriff "yoursite.php" der -Teil deiner bestehenden Seite verstanden werden, der das Seitenlayout -erzeugt (der also zumindest die <html><body> Tags um die Ausgaben von -ewiki.php bastelt). - - <?php - mysql_connect("localhost", "DB-USER-NAME", "PASSWORD"); #[1] - mysql_query("use DATABASE-NAME-HERE"); - - define("EWIKI_SCRIPT", "yoursite.php?page="); #[2] - include("ewiki.php"); #[3] - ?> - <HTML> - <head>...</head> - <BODY> - <?php - echo ewiki_page(); #[4] - ?> - </BODY> - </HTML> - -[1] Die ersten beiden Befehle öffnen eine Verbindung zur MySQL-Datenbank. -Normalerweise würde man das Ergebnis von mysql_conect() in einer Variable -wie "$db" ablegen, aber da PHP ohnehin nicht auf deren Verwendung besteht, -wenn es nur eine DB-Verbindung gibt, wird eine solche Variable in -"ewiki.php" auch gar nicht verwendet (und der Name dieser Variable wäre -damit hier egal). - -[2] Der Wert in der define() Zeile sagt ewiki wie die Hyperlinks zu den -referenzierten WikiSeiten lauten müssen, damit ewiki.php auch für die -nächste angeklickte WikiSeite aufgerufen wird. -Wenn du nur ein einziges "yoursite.php" Skript hast, wirst du den Wert -direkt in "ewiki.php" verändern wollen. - -[3] Das include("ewiki.php") lädt endlich die ewiki "Bibliothek" und -setzt alle bis hierher noch nicht definierten EWIKI_ Konstanten. - -[4] Der Aufruf der ewiki_page() Funktion gibt diejenige WikiSeite zurück, -die vom Browser angefragt wurde. Du mußt hier "echo" davorsetzen, denn -sonst wird der Text nicht ausgegeben (verpufft im PHP-Nirvana) - ewiki -gibt die erzeugte Seite nicht selber aus. - -Beachte, daß vor dem allerersten <HTML>-Tag zunächst einmal ein <?php- -Code-Block stehen muß, in dem die "ewiki.php" (oder auch "config.php") -geladen werden spollte. Wenn das nämlich nicht rechtzeitig geschieht, -funktionieren später die hochgeladenen Bilder und Dateien nicht. - - - - Den WikiSeitenNamen bestimmen - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Wenn du ewiki_page() einfach so aufrufst wie im oberen Beispiel angegeben - (empfohlen), dann wird es versuchen, den Namen der angefragten Seite selber - zu ermmitteln ($_SERVER["PATH_INFO"] oder GET-Variablen '?id=' oder '?name=' - oder '?page=' oder '?file=' in $_REQUEST["name"]). - - Wenn yoursite.php aber einen anderen Weg benutzt (andere Parameternamen), - um den WikiSeitenNamen zu übergeben, dann kann man ihn schlicht als ersten - Parameter angeben: - - ewiki_page( $id = "WikiSeitenNanem" ); - - Example-4.php zeigt das beispielsweise, um die Liste der aktualisierten - Seiten einzubinden. - - - - - -WikiSprache einstellen (deutsch) -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Ich hab es jetzt schon einige Leute behaupten hören, aber auch beim -IntranetExplodierer kann man die "bevorzugten Sprachen" irgendwo einstellen. -Wers nicht findet, kann ja auch gleichmal auf einen aktuellen Browser -wechseln - das lohnt sich nicht nur wegen der vielen Seiten, die es dann -plötzlich doch auf Deutsch gibt! - -Wer es partou nicht hinbekommt, kann natürlich die deutsche Sprache für -ewiki erzwingen; hilfreich hierfür ist z.B. die include()-Datei -"fragments/force_lang_de.php". - -Es funktioniert aber auch mit diesem Befehl, der irgendwo in ewiki.php, -config.php oder yoursite.php eingefügt werden kann (nicht empfohlen): - -$_SERVER["HTTP_ACCEPT_LANGUAGE"] = "de; q=1.0, en; q=0.2, eo, nl"; - - - - - ------------------------------------------------------------------------- - - - - -Im Detail -¯¯¯¯¯¯¯¯¯ -Die MySQL DB Tabellenstruktur ist zu einem gewissen Grad kompatibel mit der -des allseits bekannten »PHPWiki« (normalerweise reicht es EWIKI_DB_TABLE_NAME -auf "wiki" zu ändern, um PhpWikis DB weiterzuverwenden). -Dies ist der MySQL Befehl, der die DB-Tabelle erstellt (beim ersten Start, -automatisch): - - CREATE TABLE ewiki ( - pagename VARCHAR(160) NOT NULL, - version INTEGER UNSIGNED NOT NULL DEFAULT 0, - flags INTEGER UNSIGNED DEFAULT 0, - content MEDIUMTEXT, - author VARCHAR(100) DEFAULT 'ewiki', - created INTEGER UNSIGNED DEFAULT 0, - lastmodified INTEGER UNSIGNED DEFAULT 0, - refs TEXT, - meta TEXT, - hits INTEGER UNSIGNED DEFAULT 0, - PRIMARY KEY id (pagename, version) - ) - -Den Spaltennamen {pagename} mochte ich eigentlich nicht, aber weil das der -offensichtlich einzige Unterschied zur PhpWiki-Tabelle war, kam mir die Idee -mit der Kombatibilität un so hab ich das adaptiert. -Dummerweise muß nun die ewiki_database() Funktion "pagename" ständig von -und nach "id" übersetzen. - -Die Spalte {version} wird zur Speicherung der verschiedenen abgelegten -Seitenänderungen verwendet. In anderen Wikis gibt es zu diesem Zweck eine -Bonus-tabelle wie "backup" oder "history", aber ich hab den Sinn von sowas -bisher nicht verstanden; und daher gibt es in ewiki nur diese eine Tabelle -(und das scheint absolut zu reichen)! -Die erste {version} einer Seite erhält die Nummer 1. Eine bestehende -Seiten {version} wird niemals überschrieben werden => sehr sicherer MySQL- -Einsatz. - -Mehr über die {flags} in dem entsprechenden Abschnitt in der README. Das -Feld {content} enthält natürlich den WikiSeitenQuelltext. {created} und -{lastmodified} enthalten die entsprechenden Zeitangaben im UNIX format. - -{refs} enthälte eine "\n" - getrennte Liste von referenzierten WikiSeiten. -Der Code um diese List zu erzeugen ist etwas unsauber, so daß oftmals -GeisterSeiten aufgeführt sind. Wieauchimmer, daß beeinträchtigt ewiki -nicht wirklich, und eine Korrektur wäre Zeit- und Geschwindigkeits- -verschwendung. - -{meta} kann Bonusinfos enth, so daß die Tabellenstruktur nicht bei jeder -Erweiterung geändert werden muß. Aktuell nur für Binärdaten (Bilder) -verwendet. - -{hits} zählt die Seitenaufrufe, und ist nicht in {meta} integriert, weil -separat schneller und einfacher zu verwenden. - -Die ewiki DB Tabelle kann nicht nur Texteseiten enthalten, sondern auch -binären Inhalt (vornehmlich Bilder), siehe {flags}. - -Das Ein-Tabellen-Konzept hat es übrigens auch recht einfach gemacht, das -Datei-basierte DB-Backend zu entwickeln. Eine Beispieldatei: - - id: WikiPageName - version: 1 - flags: 1 - author: 127.0.0.1:3054 - created: 1046532697 - lastmodified: 1046532697 - refs: \nErfurtWiki\nNewestPages\n - - !! WikiSourceContent - <more-text>... - - - - -ewiki_ Funktionen -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Einige der Basis-Funktionen aus ewiki.php können getrennt von den anderen -verwendet werden, andere sind ausgelegt um durch bessere Implementierungen -ersetzt zu werden. - - - ewiki_page($id) - --------------- - Hauptfunktion, die die angefragte WikiSeite (oder die mit $id - angegebene) aus der DB holt, und mit ewiki_format() die fertige - HTML-Seite erzeugt. - Wenn die angefragte Seite nicht existert, wird eine edit-Box - zurückgegeben. - - - ewiki_page_...() - ---------------- - Die meisten Fkt. mit diesem Prefix wurden aus der Hauptfkt. - herausgetrennt, um ewiki übersichtlicher und leichter erweiterbar - zu machen. - Die meisten enthalten Code um spezielle/interne Seiten zu erzeugen - (Suche, Neuest, Info, und das Edit <FORMular>, ...) - - - ewiki_script() - -------------- - Erzeugt URL aus angegebener Seiten $id und $action, verwendet dazu - die EWIKI_SCRIPT-Konstante. Dieser wrapper ermöglicht es auch die - eigentlich reservierten Schrägstriche in Seitennamen zu verwenden. - - - ewiki_control_links($id, $data) - ------------------------------- - Gibt die Zeile mit "DieseSeiteÄndern, SeitenInfo, ... links" aus. - - - ewiki_format($wiki_source, $scan_links=1, $html_allowed=0) - ---------------------------------------------------------- - Erzeugt die formatierten (HTML) Ausgabe für den übergebenen - WikiQuelltext. - - Der zweite Parameter gibt an, ob nach denen im Quelltext referenzierten - WikiLinks in der DB nachgesehen werden soll. Wenn dieser Parameter 0 - ist, dann wird eine bereits vorh. $ewiki_links Array stattdessen - verwendet, um zu prüfen ob eine Seite in der DB vorh. ist. - - - ewiki_link_regex_callback() - --------------------------- - Aufgerufen aus ewiki_format(). Um ewiki_format() {die eigentliche - WikiEngine} weiter von der Datenbank zu trennen, verwendet diese - Fkt. das globale array in $ewiki_links, in dem normalerweise vorher - schon gefundene WikiSeiten eingetragen wurden (siehe zweiter Param. - von ewiki_format) um entweder einen normalen Verweis oder einen - Fragezeichen-Link auszugeben (wenn die angegebene Seite noch nicht - exisitiert). - - - ewiki_binary() - -------------- - Wird automatisch aufgerufen, wenn das Skript mit dem ?binary= Anhang - aufgerufen wird, um referenzierte / hochgeladene Bilder auszugeben. - - - ewiki_author() - -------------- - erzeugt einen String, der mit REMOTE_ADDR und $ewiki_author - angereichert wurde. - - - ewiki_database($FUNCTION, $args=array() ) - ------------------------------------------ - Diese Funktion ist die "Datenbankabstraktion" in ewiki. Sie enthält - ''only'' sechs SQL Kommandos, die ersetzt werden müßtem, wenn du eine - andere DB verwenden mußt. - Die einzelnen "atomaren" Funktionen sind beschrieben in der - orignialen README-Datei. - - - - - -$GLOBALS Verschmutzung -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Zumindest die ewiki_page() Funktion erzeugt einige Variablen im globalen -Namensraum. Natürlich haben auch diese Namen, die sich mit irgendetwas -aus yoursite.php überschneiden sollten: - - $ewiki_id - Enthält die DB-$id der aktuellen Seite, ist nicht - immer identisch mit $ewiki_title. - - $ewiki_action - Der $action-Parameter, mit dem die Seite angefordert - wurde. - - $ewiki_title - Wird nach dem ersten Aufruf von ewiki_page() gestzt, - am nützlichsten um in dem <TITLE> Tag ausgegeben - zu werden - dafür muß aber ewiki_page() schon im - Kopfbereich aufgerufen werden, die Ausgabe gepuffert, - damit der Seitentitel noch innerhalb von <HEAD> - ausgegeben werden kann. - - $ewiki_script - Eine Kopie von EWIKI_SCRIPT. - - $ewiki_links - Ist ein Arraym daß in ewiki_format() prodiziert wird, und - alle gesuchten WikiSeitenNamen mit einem Wert von 0 oder 1 - assoziiert, je nach dem, ob die Seite existiert oder nicht. - Wird diese variable jedoch auf ==true gesetzt (also kein - Array), wird angenommen, daß alle WikiSeiten existieren. - - $ewiki_author - Der Inhalt dieser Variable wird in der {author}-Spalte - von gespeicherten WikiSeiten abgelegt (zusammen mit - IP:PORT). - Wenn yoursite.php Benutzer kennt und authentifizieren - kann, sollte der Nutzername hier abgelegt werden. - Diese Feld sollte aber NICHT ZUGEMÜLLT werden mit - irgendwelchen Bonusinfos. - - $ewiki_auth_user - Enthält Namen eines wirklich authentifizierten - Benutzers im _PROTECTED_MODE. Nicht notwendig, wird aber - u.a. gerne von ewiki_auth() und ewiki_auth_user() zur - Vereinfachung verwendet. - - $ewiki_ring - Berechtigungslevel im _PROTECTED_MODE - 3 = nur lesen - 2 = normaler Benutzer (lesen, editieren, ...) - 1 = Moderator (auch Seiten löschen?) - 0 = Administrator (darf alles) - - $ewiki_plugins - Dieses array verbindet Aufgabengruppen (z.B. "database" - oder "image_resize") mit Funktionsnamen. - Dies stellt einen wirklich einfachen und dennoch mächtigen - Weg dar, um ewiki zu erweitern. - Es gibt ein eigenes Kapitel darüber in der orig. README. - - $ewiki_config - Ersetzt teilweise die EWIKI_ Konstanten. - -Folgende gibt's nich mehr (teilweise in $ewiki_config): - - $ewiki_data, $ewiki_interwiki, $ewiki_internal_pages, - - - - - -EWIKI_ Konstanten -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -- - WARNUNG - WARNUNG - WARNUNG - WARNUNG - WARNUNG - WARNUNG - WARNUNG - - -WARNUNG: Dieser Abschnitt ist grundsätzlich besonders inaktuell! Von daher -sollte ein Studium des gleichnamigen Abschnitts in der orig. README-Datei -wirklich vorgezogen werden!! Viele der neu hinzugekommenen Konstanten werden -hier schlichtweg nicht erwähnt, oder inzwischen sogar __falsch__ beschrieben. -- - WARNUNG - WARNUNG - WARNUNG - WARNUNG - WARNUNG - WARNUNG - WARNUNG - - - -Dieser Abschnitt erklärt einige der Konstanten und wie man sie verwenden -kann, um ewiki nach der eigenen Pfeife tanzen zu lassen. - -Normalerweise solltest diese innherhalb von "ewiki.php" angepaßt werden, einige -sind jedoch mehr wie Statusvariablen ausgelegt und sollten von "yoursite.php" -in Abhängigkeit von dort vorhanden Infos gesetzt werden (wenn dort Benutzer -eingeloggt sind z.B.). -Dann ist es gut einige der Konstanten vorzudefinieren (einmal def. Konst. -können nicht wieder geändert werden). - - - EWIKI_SCRIPT - Wichtigste Einstellung. Wird von ewiki.php verwendet, um Links zu - anderen WikiSeiten zu erzeugen. - - Es benötigt den Namen von yourscript.php, daß selbst wiederrum - ewiki.php geeignet einbindet. - Der Name der angefragten WikiSeite wird immer schlicht an den hier - definierten TextString angehängt, daher sollter dieser immer in - "/" oder "?" oder "?id=" oder "?name=" oder "?page=" enden, damit - eine gültige URL dabei herauskommt und der SeitenName von ewiki_page() - gefunden wird. - - Wenn auf deinem Server mod_rewrite vorhanden ist und funktioniert, - könntest du diese Konst. auch leer lassen, so alle Anfragen zu - http://wiki.example.com/ an das richtige Skript übergeben werden. - Ansonsten ist es gut, wenn eine URL absolut zum Server-Hauptpfad - angegeben ist, also z.B. "/~user/wiki/index.php/", damit Browser - keine ungültigen URLs erzeugen, sobald eine $action vor den - Seitennamen gesetzt wird (z.B. "edit/DieseSeite"). - - Die Konstante wird von ewiki_script() eingesetzt um URLs zu den - angegebenen Seiten zu erstellen (wobei einige Fehler abgefangen - werden). - - EWIKI_SCRIPT_URL - Sollte eine absolute URL enthalten, die ebenfalls zum ewiki-wrapper - zeigt, z.B. "http://www.example.com/wiki/?id=" - - - EWIKI_DB_TABLE_NAME - Setzt den Namen der MySQL DB Tabelle fest, die erzeugt und verwendet - werden soll, um alle WikiSeiten abzulegen. - - - EWIKI_PAGE_INDEX - Definiert den Namen der WikiSeite, die als Startseite angezeigt werden - soll. - EWIKI_PAGE_NEWEST - Name (intern erzeugt) der Seite, die List der zuletzt hinzugefügten - Seiten enthält. - EWIKI_PAGE_SEARCH - Enthält den WikiSeitenNamen für dei SuchFunktion. - - - EWIKI_CONTROL_LINE - Wenn auf 0 gestzt, wird die Zeile unter einer WikiSeite mit - "DieseSeiteÄndern, SeitenInfo, ..." nicht angezeigt. - In diesem Fall sollte der Edit-Link in yoursite.php erzeugt werden. - Besser ist es normalerweise das Aussehen der Ausgabe in - ewiki_control_links() selbst zu ändern. - - EWIKI_AUTO_EDIT - Bei 1 (voreinstellung) wird automatisch eine Edit-Box für - nicht-exisiterende Seiten angezeigt, ansonsten wird eine ZwischenSeite - ("Bitte ändere mich!") angezeigt (wie in PhpWiki). - - EWIKI_LIST_LIMIT - Maximale Anzahl von Seiten, die in den generierten Listen angezeigt - werden sollen (Suche, ...) - - EWIKI_PRINT_TITLE - Wenn 0 werden keine SeitenTitel (WikiSeiten und InterneSeiten) - angeziegt. - - - EWIKI_ALLOW_HTML - Normalerweise sollte im Wiki keine HTML erlaubt sein - böses JavaScript - und <brokenHTML/>, andere Leute nerven. - - Siehe orig. README für mehr Informationen. - - - EWIKI_RESCUE_HTML - Überholt, siehe plugins/markup_rescuehtml.php - - - EWIKI_DB_F_TEXT - Dieses Flag wird für normale WikiSeiten in der DB gesetzt. - - EWIKI_DB_F_BINARY - Für binären Inhalt in der DB. - - EWIKI_DB_F_DISABLED - DB-Eintrage werden hiermit ausgeknippst. - - EWIKI_DB_F_HTML - Erlaubt die Verwendung von HTML im WikiQuelltext, unabhängig von - EWIKI_ALLOW_HTML. - - EWIKI_DB_F_READONLY - WikiSeite kann nicht verändert werden, so dieses Flag gesetzt ist. - - EWIKI_DB_F_WRITEABLE - Umkehrung von READONLY, nur nützlich wenn zuvor alle Seiten mit - EWIKI_EDIT_AUTHENTICATE schriebgeschützt wurden. - - - EWIKI_ALLOW_OVERWRITE - Für eingeloggte nutzer kann yoursite.php diese Konst. auf 1 setzen, um - auch das Ändern von schreibgeschützten Seiten zu erlauben. - - EWIKI_EDIT_AUTHENTICATE - Hiermit kann man ewiki dahingehend kaputt machen, daß alle Seiten - schreibgeschützt werden, und nur veränderbar sind, so yoursite.php - $ewiki_author setzt. - - - EWIKI_SCRIPT_BINARY - Um binäre Daten ausgeben zu können, muß hier ein wrapper-script - angegeben werden, daß ein Datenbank-Verbindung öffnet und keine - Textausgaben erzeugt, bevor nicht ewiki.php eingebunden wurde, - da sonst nur Datenmüll ausgegeben würde. - - Um alle binary-Funktionalität (Bilder hochladen / cachen) loszuwerden, - einfach diese Konstante auf "" setzen, und die folgenden zwei auf 0: - - - EWIKI_CACHE_IMAGES - Bilder zwischenspeichern. - - EWIKI_IMAGE_MAXSIZE - Maximale Größe von Bildern die in der DB abgelegt werden sollen. - - EWIKI_IMAGE_RESIZE - Bilder herunterskalieren, wenn zu groß. - - EWIKI_IDF_INTERNAL - Wird verwendet um hochgeladene Bilder zu identifizieren. Bitte - im laufenden Betrieb nicht ändern. - - - EWIKI_ADDPARAMDELIM - Automatisch definiert, enthält entweder "?" oder "&", abhängig von - EWIKI_SCRIPT. - - - EWIKI_T_* - überholt, siehe ewiki_t() und $ewiki_t[] in der englischen README - - - EWIKI_CHARS_U - EWIKI_CHARS_L - Erlaubte Zeichen in WikiSeitenNamen (große und kleine Letter). Hiermit - kann man das wiki lokalisieren; deutsche Umlaute sind schon enthalten. - - UNIX_MILLENNIUM - Sehr wichtiges Ereignis ;) - - -Im tools/ Ordner ist ein kleines Script, mit dem man die erwähnten -SeitenFlags ändern kann. - - - -$ewiki_config[] array -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Einige der EWIKI_ Konstanten wurden durch Einträge im $ewiki_config[] Array -ersetzt oder ergänzt (die Konstanten können weiterhin zur Voreinstellung -verwendet werden). Der Vorteil dieses Arrays ist, daß die Einstellungen auch -zur Laufzeit geändert werden können. - -Für eine komplette und (einigermaßen) aktuelle Übersicht bemühe bitte die -englischsprachige README. - - - - - ------------------------------------------------------------------------- - - - - -Nur WikiQuelltextTransformation einsetzen -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Die ewiki_format Funktion war entworfen, um sie auch unabhängig von dem -restlichen WikiSkript einsetzen zu können. -Benötigt normalerweise nur den "wiki_source" Parmeter und erzeugt die -HTML-Seite daraus. - ewiki_format($wiki_source, 0); - -Alles was man noch anpassen muß ist die $ewiki_links Variable. Setze -$ewiki_links=true ("true" und nicht "1") so daß ewiki_format() später -annimmt alle WikiSeiten würden existieren. - -Wers eilig hat, kann auch die extrahierte Variante fragments/wiki_format.inc -verwenden, die Frank Luithle beigesteuert hat. - - - - - ------------------------------------------------------------------------- - - - - -Ohne MySQL DB verwenden -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Sollte dein Provider keine MySQL Datenbank für dich bereithalten, kannst -du das plugin "db_flat_files.php" verwenden (einfach include("plugins/..."); -aufrufen um es zu laden). - -Alle WikiSeiten werden dann in Textdateien in einem nur dafür -bereitgestelltem Ordner gespeichert. Stelle hierzu noch die Konstante -EWIKI_DBFILES_DIRECTORY in der Datei "ewiki.php" passend ein ("/tmp" würde -jedesmal gelöscht, wenn der Server neu startet). -Das Verzeichnus muß relativ zum ewiki.php script angegeben werden, oder -absolut zum Serverhauptverzeichnis, nicht aber relativ zum DocumentRoot -deines Webspeicherplatzes! In diesem Beispiel wäre "./pages" richtig: - -Erstelle ein neues Verzeichnis (via FTP-Programm) und gib dem Webserver -Schreibzugriff dafür mit dem Befehl " chmod 777 ./pages ". -ftp> cd .../ewiki -ftp> mkdir pages -ftp> chmod 777 pages -ftp> ls --rw----r-- 1 deinname deinname 57024 01. Jan 00:00 ewiki.php --rw----r-- 1 deinname deinname 512 01. Jan 00:00 index.php -drw----r-x 2 deinname deinname 4096 01. Jan 00:00 init-pages -drwxrwxrwx 2 deinname deinname 4096 25. Feb 23:59 pages -drw----r-x 5 deinname deinname 4096 01. Jan 00:00 plugins --rw----r-- 1 deinname deinname 15826 01. Jan 00:00 README.de -ftp> quit - -Mit einem graphischem FTP-Programm gibt es auch immer die Mglk. die -"Dateizugriffsrechte" einzustellen. - - - -db_fast_files -¯¯¯¯¯¯¯¯¯¯¯¯¯ -Diese neuere Version von db_flat_files, speichert die WikiSeiten -komprimiert in einem Binär-Format (kann man nicht mehr mit Editor -ansehen und bearbeiten). Zusätzlich wurde der HitZähler aktiviert. - -db_fast_files wurde in db_flat_files integriert, so daß das neue -Format jetzt nur noch über eine Konstante aktiviert werden muß -(beide Dateiformate können gleichzeitig in der DB vorhanden sein). -Für die schnellere Variante aktiviere in "plugins/db_flat_files.php" -die entsprechende Konstante: - define("EWIKI_DB_FAST_FILES", 1); -(Diese Einstellung könntest du aber auch schon in der "config.php" -eintragen.) - -Zusätzliche Konstante: EWIKI_DBFILES_GZLEVEL sagt wieviel Zeit -beim Komprimieren verschwendet werden soll: -0 - keine Komprimierung -1 - ein ganz klein wenig Kompr. -2 - Voreinstellung, schnell -5 - normaler Wert in zlib, gute Komprimierung -9 - langsam für allerbeste Kompression - -Dieses plugin wurde von Carsten Senf beigesteuert. - - - - - -------------------------------------------------------------------------- - - - - -BöseBäckSläshes -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Wenn auf deinen Seiten pötzlich viele "\" RückwärtsSchrägStriche -auftauchen liegt das an einer Fehlkonfiguration von PHP. In älteren -Versionen war leider immer die Option "magic_slashes_gpc" aktiviert -(siehe auch php.ini). - -Bitte am besten deinen WebserverProvider das zu ändern. Wenn du aber bei -einem der BilligHoster (umsonst wie sourceforge.net oder tripod.com) bist, -gilt wie immer: einem geschenkten Gaul... -Dann verwende bitte "fragements/strip_wonderful_slashes.php", um das -Problem zumindest zu umschiffen, oder ändere deine .htaccess Datei (Apache) -wie darin beschrieben. - - - - -------------------------------------------------------------------------- - - - -Paßwörter und tools/ -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Die tools/ sind gefährlich und daher per Voreinstellung nicht ohne weiteres -Nutzbar. In der Datei "tools/t_config.php" wird das Script -"fragmenst/funcs/auth.php" geladen, daß für den Browser-Login-Dialog -verantwortlich ist. Wenn du also die tools/ verwenden willst, mußt du dort -zuerst einen Benutzer mit Paßwort eintragen, sonst geht nix. - -Um hingegen dein Wiki zu schützen, so daß nur einige wenige Personen die -Seiten editieren können, ließ dir bitte die Datei "plugins/auth/README.auth" -durch (leider nur in Englisch). Sie beschreibt den _PROTECTED_MODE und -stellt die entsprechenden Plugins vor. - - diff --git a/mods/wiki/doc/README.fragments b/mods/wiki/doc/README.fragments deleted file mode 100644 index 5bd19a834..000000000 --- a/mods/wiki/doc/README.fragments +++ /dev/null @@ -1,642 +0,0 @@ - -ewiki code fragments/ and tools/ -================================ - -Unlike the plugins/ the code snippets and asorted data files in fragments/ -can be included() directly into yoursite.php and are sometimes also -unspecific to ewiki. And the init-pages/ for example are required only once -and can be removed after initialization. -The tools/ is a separate bundle of administration tools for the ewiki -database. They are separate from the main Wiki (even comes with a different -'config.php') to enhance safety and reliability. - - - 1 fragments/ - 1.1 strip_wonderful_slashes.php - 1.2 strike_register_globals - 1.3 404finder.php - 1.4 htaccess - 1.5 binary.php - 1.6 force_lang_de.php - 1.7 fragments/funcs/* - 1.8 fragments/css/* - 1.9 fragments/blocks/* - 1.a fragments/patches/* - 1.b fragments/php-patches/* - 2 Additional tools/ - 2.1 tools/t_flags - 2.2 tools/t_backup - 2.3 tools/t_restore - 2.4 tools/t_remove - 2.5 tools/t_holes - 2.6 tools/t_textinsert - 2.7 tools/t_transfer - 2.8 tools/t_revert - 3 commandline tools/ - 3.0 tools/setup - 3.1 tools/ewikictl - 3.2 tools/wiki2html - 3.3 tools/mkhuge - 3.4 tools/mkpluginmap - 3.5 tools/mkpageplugin - 3.6 tools/mkxpi - 3.7 tools/php5fix - 4 examples/ - 4.1 examples/homepage.php - 5 Pages in init-pages/ - - - - - -------------------------------------------------------------------- 7 -- - - - - -fragments/ -¯¯¯¯¯¯¯¯¯¯ -This directory holds some files to integrate ewiki.php within some -other web projects (for example PhpNuke) or some helper and extension -code, but even data files, code patches. - -Most stuff is grouped into subdirs: - - blocks/ plugin extractions to get included() somewhere into yoursite - (onto left or right side, like in one of those portal scripts) - head/ also output html snippets, for inclusion into the html <head> - area of pages - css/ for sample .css files and per-page .css definitions (for use - with 'fragments/css.php') - funcs/ code snippets of varying usefulness - parent-cms/ samples on how to integrate ewiki into CMS or portal scripts - patches/ code/feature tweaks - php-patches/ PHP interpreter bugfixes - ./ assorted stuff, described below: - - - - strip_wonderful_slashes.php - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - If you have a PHP 4.1 or a provider using the annoying factory-default - settings of such a version, you may find this tiny script helpful. - It removes the just-for-security-reasons-added-backslashes from the - $_REQUEST variables. I wasn't very interested in adding hundreds of - stripslashes() calls inside ewiki.php, so this is the workaround for - __your__ providers broken php.ini - - It does not hurt a well configured PHP interpreter setup. - - Newer ewiki versions come with a "plugins/lib/fix.php", which does - basically the same, but also incorporates: - - - - strike_register_globals - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Tries to secure the $GLOBALS environment for PHP setups with the - register_globals still turned on (which is a bad thing!). - - - - 404finder.php - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - Simple example on how to use "ErrorDocumet 404" rediriction to - activate the ewiki page search function automatically, which is the - poor mans mod_rewrite. - - - - htaccess - ¯¯¯¯¯¯¯¯ - To make a Wiki installation look more profession you should try to - use your Webservers mod_rewrite module to get nicer looking URLs. - This file is an example to be installed as ".htaccess" (Web server - per-directory configuration file), which allows to call your ewiki - wrapper using URLs like: - - http://www.example.de/wiki/SomePage - http://www.example.de/wiki/edit/OneOfThePages - - (For this example, you needed to set EWIKI_SCRIPT to "/wiki/"). - This example '.htaccess' script shows how to instruct mod_rewrite - to catch above URLs and to transform them into ".../index.php?id=Page" - again before calling the script. - - +++ - - Shows how to use mod_rewrite with ewiki. - - * old style: http://www.example.com/wiki.php?page=WikiPage - * PATH_INFO: http://www.example.com/WikiPage - - Remember to enable EWIKI_USE_PATH_INFO inside ewiki.php - this was - disabled once, because of the many broken Apache implementations (they - seem to support that broken CGI/1.1 specification, which was for good - reasons and luckily never blessed to become an official RFC). - - - - binary.php - ¯¯¯¯¯¯¯¯¯¯ - If yoursite.php (ewiki wrapper) is not designed carefully enough - (=not binary safe, because <html> or text is written before the - ewiki.php core script got included) or EWIKI_SCRIPT_BINARY cannot be - set correctly, you may want to use this wrapper script to allow for - uploading and retrieval of binary content (images) via ewiki. - - Copy it to where the main ewiki.php script is, and set the - EWIKI_SCRIPT_BINARY constant to the correct absolute position - (possibly including http://server.name/) of "binary.php". (this - constant must be set on top of ewiki.php) - - You must set the database access params in here, too. - - It may also be useful if you'd like to divide the database into its - two parts again - text content and binary content. You could even - let it save binary content in a flat file database, while WikiPages - remain in a RDBMS. - - - - force_lang_de.php - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Sample pre-config script for "de_DE" lang to preset the language - appearance of ewiki. If you just are too lazy to set up your - browser correctly, then this line usually fixes your language - setting problem: - - $_SERVER["HTTP_ACCEPT_LANGUAGE"] = "de"; - - (must be written before ewiki.php gets included) - - - - fragments/funcs/* - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The funcs/ subdirectory contains code snippets, that provide - additional interface functions. - - - - fragments/funcs/auth.php - ------------------------ - Include this script wherever you need authentication. It - uses the HTTP Basic Authentication scheme, but the passwords - are inside the script in the $passwords array (so no need - for .htpasswd setup). - - Note that this script needs to be called before any body - output is made (else it would be too late for http header() - output). - - - - fragments/funcs/wiki_format.inc - ------------------------------- - This php include() file contains just the reduced - wiki_format() function, the code to generate internal - WikiLinks and the binary data stuff has been removed. It is - best suited to allow rendering of WikiSource with other php - projects. - - The script was contributed by Frank Luithle. - - - - fragments/css/* - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Please understand the *.css as examples that illustrate which style - classes are defined inside ewiki.php and its companion plugins. - - Remember, you could insert those files with PHPs` include(), too - - if desired (and if a <style> area is currently to be written to - stdout). - - The 'fragments/css.php' script can be included into yoursites` - page html <head> part and inserts all *.css files from this - directory which match the current page or action name. This allows - for restyling certain pages and helps in keeping a sites main - stylesheet small. - - - - fragments/blocks/* - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Contains small include() scripts to be loaded into "yoursite.php" - as "sidebars" and the like for beatification purposes. - Oftens these are reduced but useful ["page"] or ["action"] plugins, - performing common tasks, like printing the list of newest pages or - some sort of menu, or even random page links. - - - - fragments/patches/* - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - In the patches/ directory some code tweaking tips are collected - that are either not worth a new plugin or to uncommon and unsafe - and unsupported to get into fragments/ or plugins/. Please see the - README and the files therein for more informations. - - - - fragments/php-patches/* - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - If bugs in the PHP language interpreter prevent running of ewiki - under certain versions, a patchfix will appear in the php-patches/ - directory. - - - -Additional tools/ -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -This directory holds some (external) add-ons, which are intended to -supply "admin functions" for the ewiki database. -It is strongly discouraged to integrate this with ewiki, as it could -be dangerous to have them always around and usually such stuff just -complicates things (wiki's should be easy to use). - -Per default you will be presented a HTTP Basic AUTH login dialog box -by your browser if you try to use one of the www tools. This is made -to prevent other people from doing any harm to the setup. -In the "tools/t_config.php" script you'll see a link (include) to -"fragments/funcs/auth.php", which is responsible for this integrated -security feature. Just insert a username and a password here to start -using one of the tools/. -Please keep in mind, that the $passwords array of that ".../auth.php" -script has nothing to do with the _auth API or EWIKI_PROTECTED_MODE. - -Because the www tools (all stuff named "t_*.php") use the "ewiki.php" -script and the sample "config.php", you eventually need to configure -these tools separately (they don't need any ewiki plugins, but the -database ones, if necessary). So if there are problems (for example -if your ewiki setup is configured with ewiki_auth, which then could -overlap with the ".../auth.php" script), you may need to edit the www -tools own "t_config.php" accordingly. (Note: This is not required for -the default setup.) - -If you'd like to integrate the tools/ as virtual pages into ewiki, then -the StaticPages plugin will help. You then needed to remove the line -that tries to re-include() your config.php and ewiki.php from the tools/ -"t_config.php" script (else you'll break ewiki). -To load your tools/ as static pages into the wiki, you then just needed -a call to ewiki_init_spages() with the "./tools/" directory as parameter. - - - - tools/t_flags - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - WikiPages usually have the page flag TEXT assigned. Other possible - flags are DISABLED, SYSTEM, BINARY or HTML, READONLY, WRITEABLE. - Usually page flags are copied from one page version to the next. - - - - tools/t_backup - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Use this to make backup files from the WikiPages. This www script - is a wrapper around the ewikictl commandline utility and library, - and therefore supports almost the same options. - - - - tools/t_restore - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows to reinsert the files generated with the backup utility into - the database. It is also a www wrapper around ewikictl and thus - also supports the "plain", "flat" and "fast" file formats. - - - - tools/t_remove - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Use this to delete a page from the database (including all saved - versions). - You should always prefer to set a page DISABLED with the ewiki_flags - tool to hide unwanted content. -- make love() not unlink() - - - - tools/t_holes - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - If pages are edited often / regularly you will soon get hundreds of - saved page versions. As this slows down (particularly the - db_flat_file ones) and enlarges the database content size, you may - want to strip old versions. - - This tool suggests you to remove a few page versions. You should - however NOT DELETE the page VERSION ONE and the very last (newest) - page version (of course). - The page version 1 often contains control data, not found in newer - versions, when db_flat_files or db_dba is used, so please keep - aware of this. - - There were some changes necessary in db_flat_files to support - those "version holes", but it currently seems to work stable. - - - tools/t_textinsert - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Can insert plain text files into the database. This is much the - same, what usually happens to the files inside init-pages/ - - - - tools/t_transfer - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows to download all pages in one big "binary" file, and to - reinsert it on the same way. This allows for quick moving of - the whole database content. - - - - tools/t_revert - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Can undo mass changes caused by a script attack (specifically - designed to spam or corrupt a Wiki) or someone who put enourmous - energy into garbaging multiple pages. The {auther} field always - contains at least an IP address to allow easy tracking of such - activity, and this plugin just enables you to remove page versions - whose {author} field matches a certain string (the attackers IP - address). - - - - tools/index.html - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - If this page looks ugly, it is because you are using IE prior - version 7 - it works fine with Mozilla, Opera and even text-only - browsers like w3m. - - - -commandline tools/ -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -As opposed to the web based tools/ mentioned above, a few scripts in tools/ -must be run from the commandline. That is, you need a standalone PHP -interpreter (/usr/local/bin/php) and shell access to your web server. - -If you don't have shell access, you could write temporary wrapper scripts -(see the note for ewikictl), or use one of the emulation packages (or start -up a xterm on the server in absence of ssh access). A detailed description -is out of scope of this document. - -UNIX users will find those tools very useful and handy, while they effort -additional work from Windows users. But then all those tools/ should run -on Win32 systems too, but you often want to create additional .bat files -to make this more user-friendly. There is for example a 'ewikictl.bat' -demonstrating this. - - - - tools/setup - ¯¯¯¯¯¯¯¯¯¯¯ - Using this console or X11 tool, you can create a custom "ewiki.ini" - or "config.php" script by choosing plugins and settings through a - nice interface. It even allows generation of a MonsterWiki script. - - Works only under Linux. Read [doc/SetupTool] for more informations. - - - - tools/ewikictl - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - ewikictl integrates a lot functionality of the web based tools/, - some of them less flexible and others more powerful than in the - other tools. It, for example, allows to generate database backups - automatically and is often easier to use. On the other hand it - will be of little use if you don't have a shell account on the - WebServer running your wiki (because most times one cannot make - remote mysql server connections). - - The most important feature is to make backups using the - --backup switch: - - All pages from the database will be saved into backup files - in the directory given by --dest (or if not given into - './backup-<currentdate>'). - - The --format of the backup files can be: plain, fast, flat - or xml, meta, xmlmeta, sql, mysql. But remember that only - the first three mentioned formats can be reinserted using the - ewikictl utility. - - You really should give the --all parameter too, whenever you - make a backup, because else only the very last version of each - page will get saved (and think of a garbaged last version, this - would be a bad idea). So USE --all ALLWAYS! - - Backups can be reread into the database using the - --insert switch: - - The --dest or --source parameter says where to search for the - save page files, and the --format option again tells the - correct backup format (you will get a garbaged database if you - get it wrong). - - The --all option is of course necessary again if you gave it - when doing the --backup, and ewikictl will complain if it - believes the --all option was required. - - You can also use --insert to initially fill a database, or to - add just a few new pages, as pages inside the database will - never be overwritten by the ones added with --insert. - - The --insert switch also allows to be used to load just one - file into the database. --insert <WikiPageFileName> - - Another function is to speed up the database, by creating version - --holes: - - If you utilize the db_flat_files and you have hundreds of - versions for one page, things may get slow at some point of - time, so you may wish to remove some of the unneeded versions. - That is what the --holes is for, it strips some of the page - versions from the database. Please keep in mind, that the - very first version of each page may contain special control - data, which is not available in the following ones (this is - especially true for db_flat_files). - - Per default the 2nd version of a page until the 10th before - the last page version will be removed. You can however specify - this range yourself: - --holes 2..-10 (default) - --holes 5..-5 (5th until 5th before last version) - - Please also keep some versions at the end, as the very last - one may contain mangled text (if someone backspaced around). - - The --all option is implied for --holes, but you can and you - should combine --holes also with --backup. This special - feature will save a backup into the --dest directory ('./holes' - per default) before the page version is removed from the - database. - - --format - The default backup/insert format is the 'plain' one - which - means just a pages content will be saved into the files. - - It is however recommended to use the "--format flat" or - "--format fast" instead, as both can contain the complete meta - data of a page. - - --ls - Will print a directory-listing like list of all pages from - the database. - You can add a pagename as parameter, so only that one will - get shown. - - --reset <pagename> - --disable <pagename> - --enable <pagename> - --html <pagename> - --readonly <pagename> - --writable <pagename> - Will set the according page flags for the given page. You can - give the page name also by using the --page or --file or --id - switch. - - --chmod <flags> - Will set the page flags to the given decimal value. The - pagename must be given using --page, --file or --id. This - option of course requires knowledge of the flag/option values - and their numeric/decimal representations. - - --unlink <filepattern> - Can be used to delete a page. You can use the asterisk to - remove more than one page, just an '*' would for example delete - all pages. - - - NOTE that you can also use this utility without a shell account on - your WebServer, if you create temporary .php wrapper scripts, that - contain nothing more than: - <pre><?php echo `./tools/ewikictl -ll`; ?></pre> - - Please search google or freshmeat.net for one of those shell faking - CGI scripts, to ease this, so can get the most out of ewikictl. - - - - tools/wiki2html - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Renders the WikiPages and saves the resulting <HTML> bodies into - files. It currently cannot deal with images and binary content - correctly. - - - - tools/mkhuge - ¯¯¯¯¯¯¯¯¯¯¯¯ - For lazy people - if for some reason your text editor does not - allow to enter the correct include() commands for the files from - the plugins/ directory you may find this shell script useful to - create a monster version of ewiki (plugins and core script merged - together into one file). - See the paragraph about "monsterwiki.php" for more detailed infos. - - - - tools/mkpluginmap - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Is the companion tool for the new ewiki pluginloader extension. It - traverses the plugins/ directories and generates a list which - allows automatical loading of ["page"] and ["action"] plugins. - - Use the output of this script to replace the list of available - plugins inside of the "pluginloader.php" script. But don't forget - to disable that extensions, that you wouldn't like to be available. - - - - tools/mkpageplugin - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Can convert any StaticPage file (from the spages/ directory) into - a standard ewiki page plugin (to get included() like all the others - then). It detects automatically the type of the given StaticPage - input files - Wiki source (.txt), ready HTML content, or even PHP - code. - It's intended as help for the unexperienced PHP user, or if you - needed to mass convert StaticPage files into plugins. But please - note, that including() hundreds of page plugins slows down the PHP - interpreter and eats a large amount of memory (and this was the - reason for extracting some page plugins into StaticPages). - - - - tools/mkxpi - ¯¯¯¯¯¯¯¯¯¯¯ - The new .xpi plugins can be installed at runtime (password required), - if the plugins/feature/xpi extension is loaded. This type of plugins - however must be prepared first using the 'mkxpi' tool from their - source scripts. - - A detailed description is available in the comment part of this - commandline tool. - - - - tools/php5fix - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - If you want to test ewiki with recent PHP5 beta versions, you - either need to apply the fragments/php-patches/ or mangle the ewiki - core script using the 'php5fix' commandline utility. - - It adds a few explicit typecasts, where this is known to be - necessary to keep PHP5 versions happy. - - - - tools/collectplugins - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows you to make a 'monsterplugin' script by analyzing your - config.php script. It will output a combination of all activated - plugins merged into one file, which you could afterwards glue - together with the core script to get a real monsterwiki script. - - - -examples/ -¯¯¯¯¯¯¯¯¯ -The file "examples-1.php" is the default layout, which you will see, when -you first run ewiki. The examples/ subdirectories now holds further example -'ewiki wrappers' or 'layout scripts' (commonly referred to as "yoursite.php" -scripts in the README). - -There is not much further interesting stuff in here. If you can make a -contribution, just do (however, in the ewiki core tarball, we don't want -an image or graphics directory). - - - - examples/homepage.php - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - This is an example on how to use ewiki.php with an authentication - frontend. Note that this is not the recommended way to use a wiki - (adding authentication can be considered "crippling" a wiki). - - "Authentication" means just a JavaScript based password query - dialogue (the password is however checked server-side inside the - homepage.src script). - - You should install it preferably as index.php as described on top - of the file, the ewiki.php script must be there too. Edit the source - and colours to suit your needs. Guess, it needs some images as well. - - - -Pages in init-pages/ -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -This directory just contains text files with the wiki_source of the -initial pages, which are inserted if you start ewiki.php for the -very first time. -You can create these files with the tools/ewiki_backup.php script -or the 'ewikictl' commandline utility, what is very handy for backup -purposes or partial mirroring of all your content. - -Using the "TextUpload" plugin/spage you can upgrade all of those -files that are already existing on your setup. You could also get -the latest tarball containing all default pages from -[http://ewiki.berlios.de/initpages/?MiniDump] to do so (TextUpload -can directly use that page tarball). - - diff --git a/mods/wiki/doc/README.plugins b/mods/wiki/doc/README.plugins deleted file mode 100644 index 099b24810..000000000 --- a/mods/wiki/doc/README.plugins +++ /dev/null @@ -1,2240 +0,0 @@ -NOTE: This file is again pretty outdated. But this time, there is no -way back. It is nearly impossible to correctly document ALL ewiki -plugins. But because most come with documentation inside (comments in -head area) this is not that big an issue. - -You can still use this README part for reference. Just remember that -it is incomplete and does not list all plugins. Most notes are still -accurate however. - - -ewiki plugins -============= - -The plugins/ directory contains loads of ewiki extensions, which are -simply enabled by include()ing or melting them with the main ewiki -script. This file tries to provide an overview and explanations for -all the individual extensions. - - 1 plugin culture - 1.1 plugin loading - 1.2 melting / advanced plugin usage - 2 database plugins - 2.1 built-in MySQL support - 2.2 plugins/db/flat_files - 2.3 plugins/db/fast_files - 2.4 plugins/db/any - 2.5 plugins/db/dba - 2.6 plugins/db/phpwiki13 - 2.7 plugins/db/binary_store - 2.8 plugins/db/dzf2 - 2.9 plugins/db/zip - 2.a plugins/db/rpc - 2.b plugins/db/ext_multi - 2.c plugins/db/ext_subwiki - 2.d db/oldapi - 3 core enhancements - 3.1 plugins/patchsaving - 3.2 plugins/notify - 3.3 plugins/jump - 3.4 plugins/email_protect - 3.5 plugins/spages (StaticPages) - 3.6 plugins/pluginloader - 3.7 plugins/init - 3.8 plugins/feature/appendonly - 3.9 plugins/feature/imgresize_gd - 3.a plugins/feature/imgresize_magick - 3.b plugins/feature/imgfile_naming - 3.c input_trimming - 3.d feature/pingback - 3.e feature/refererlog - 3.f feature/xpi - 3.10 feature/xpi0 - 4 action/ plugins - 4.1 plugins/action/diff - 4.2 plugins/action/translation - 4.3 plugins/action/like_pages - 4.4 plugins/action/raw - 4.5 rss - 4.6 action/info_qdiff - 4.7 action/translation - 4.8 action/relatedchanges - 5 plugins related to hypertext links - 5.1 plugins/linking/tcn - 5.2 plugins/linking/plural - 5.3 plugins/linking/autolinking - 5.4 plugins/linking/link_css - 5.5 plugins/linking/link_icons - 5.6 plugins/linking/link_target_blank - 5.7 plugins/linking/linkexcerpts - 5.8 plugins/linking/linkdatabase - 5.9 plugins/linking/instanturls - 5.a plugins/linking/titlefix - 5.b plugins/interwiki/intermap - 5.c plugins/interwiki/editable - 5.d linking/xfn - 6 appearance/ tweaks - 6.1 plugins/appearance/listpages_br - 6.2 plugins/appearance/listpages_ul - 6.3 plugins/appearance/listpages_tbl - 6.4 plugins/appearance/fancy_list_dict - 6.5 plugins/appearance/title_calendar - 7 page plugins - 7.1 plugins/page/powersearch - 7.2 plugins/page/pageindex - 7.3 plugins/page/wordindex - 7.4 plugins/page/imagegallery - 7.5 plugins/page/aboutplugins - 7.6 plugins/page/orphanedpages - 7.7 plugins/page/wantedpages - 7.8 plugins/page/since_updates - 7.9 plugins/page/textupload - 7.a plugins/page/wikidump - 7.b plugins/page/interwikimap - 7.c plugins/page/hitcounter - 7.d plugins/page/scandisk - 7.e plugins/page/wikinews - 7.f plugins/page/wikiuserlogin - 7.10 plugins/page/randompage - 7.11 plugins/page/fortune - 7.12 plugins/page/ewikilog - 7.13 plugins/page/phpinfo - 7.14 plugins/page/README - 7.15 plugins/page/recentchanges - 8 markup plugins - 8.1 Other WikiWares markup - 8.2 plugins/markup/css - 8.3 plugins/markup/css_singleat - 8.4 plugins/markup/footnotes - 8.5 plugins/markup/asciitbl - 8.6 plugins/markup/complextbl - 8.7 plugins/markup/htmltbl - 8.8 plugins/markup/rescuehtml - 8.9 plugins/markup/rendering_null - 8.a markup/1emphasis - 8.b markup/naturallists - 8.c markup/fix_source_mangling - 8.d markup/abbr - 8.e markup/table_rowspan - 8.f markup/timestamp - 8.10 markup/braceabbr - 8.11 markup/definitionlinks - 9 mpi - 9.1 mpi/backlinks - 9.2 mpi/multimedia - 9.3 mpi/syndicate - 9.4 mpi/insert - 9.5 mpi/localsitemap - 9.6 mpi/removedlinks - a visual extensions - a.1 plugins/aview/backlinks - a.2 plugins/aview/linktree - a.3 plugins/aview/toc - a.4 plugins/aview/posts - a.5 plugins/aview/threads - a.6 plugins/aview/subpages - a.7 plugins/aview/downloads - a.8 plugins/aview/imgappend - a.9 plugins/aview/piclogocntrl - a.a plugins/aview/control2 - a.b plugins/edit/pageimage - a.c plugins/edit/authorname - a.d plugins/edit/deletebutton.js - a.e plugins/edit/templates - a.f plugins/edit/log - a.10 plugins/edit/flags - a.11 plugins/edit/minor - a.12 plugins/edit/warn - a.13 plugins/edit/lock - a.14 plugins/edit/spellcheck/ - a.15 edit/spam_deface - a.16 edit/spam_block - b page filters - b.1 plugins/filter/f_fixhtml - b.2 plugins/filter/search_highlight - b.3 plugins/filter/fun_chef - b.4 plugins/filter/fun_upsidedown - b.5 plugins/filter/fun_wella - b.6 plugins/filter/fun_screamomatic - c BloatWiki extensions - c.1 plugins/module/calendar - c.2 plugins/module/downloads - c.3 plugins/module/tour - c.4 plugins/meta/meta - c.5 plugins/meta/builtincategories - c.6 plugins/meta/f_title - d utility code - d.1 plugins/lib/cache - d.2 plugins/lib/speed - d.3 plugins/lib/mime_magic - d.4 plugins/lib/navbar - d.5 plugins/lib/protmode - d.6 plugins/lib/save_storevars - d.7 plugins/lib/feed - e admin/ plugins - e.1 control - e.2 SearchAndReplace - e.3 SearchCache - f other plugins - f.1 plugins/debug/ - f.2 plugins/auth/ - f.3 plugins/auth-liveuser/ - 10 separate "extra" tarball - 11 Updates + How to deal with tweaked code - - - - - - - -------------------------------------------------------------------- 6 -- - - - -plugin culture -¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -While ewiki is a rather monolithic script, it allows for extension by -various plugin hooks (= the internal $ewiki_plugins array). This keeps -the core small (just one script) and fast, but also easy to use (not too -cluttered user interface). - -However for advanced needs, there is always the option to add a required -function very easily. Of course some plugins slow down your Wiki (for -example markup extensions often do), so it was unwise to enable all at -once. Also a few plugins can be incompatible to each other (very divorce -goals), and some require further configuration and setup in order to -be useful at all. - -You may therefore also check out the standalone 'setup.php' script, which -also provides a simplified and _shortened_ overview of the easier to use -plugins. This utility also can generate the appropriate 'config.php' for -you. - -The structure of the plugins/ directory is purely presentational, ewiki -does not depend on accessibility of that directory; none of the paths is -hardcoded anywhere. This is because YOU are responsible for loading plugins, -the core script does never load anything on itself. The only exceptions to -this rule are: spages, mpi, and the pluginloader. - - - - .meta files - ¯¯¯¯¯¯¯¯¯¯¯ - The plugins/ directory is full of .php scripts (the plugins), - accompanied by a .meta file each. These are textual data files, - that explain what's in the plugin. This data is used for the - SetupWizard and tools/setup tool and by other so called "plugin - managers". - - Read "doc/PluginMetaFiles" if you want to find out more. Ignore - those files otherwise. - - - plugin loading - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - To enable an extension, you simply load the according plugin(s) - using the PHP include_once() function, like you do with the core - ewiki.php script: - - include_once("plugins/email_protect.php"); - include_once("plugins/page/textupload.php"); - ... - include_once("ewiki.php"); - - Usually it does not matter, if you load the plugins before or - after the ewiki script. If this makes a difference, the plugin - documentation would mention it. - - (include_once() is recommended and standard since R1.02b) - - - - melting / advanced plugin usage - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The design of the ewiki script and the extension hooks and all - plugins makes it also possible to "melt" the core script with the - plugin files. This is useful to again have all functionality in - a single script, and also allows PHP to run it slightly faster - (because then the PHP language 'parser' gets invoked just once). - - You would simply use the cat(1) utility (or "type" under DOS/Win) - to merge the plugins with the core script as follows: - - cat plugins/email_protect.php >> ewiki.php - cat plugins/page/textupload.php plugins/notify.php >> ewiki.php - - See also the paragraph on "monsterwiki building" in the main - [README] file. (The 'tools/mkhuge' script did previously what's - described here.) - - Nowadays you would use the "tools/setup" console script (under - Linux) or the SetupWizard to make a monsterwiki. - - - - -database plugins -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The ewiki.php core script contains a database request function which is -tailored to a MySQL database. However that function is already prepared -to chain to another "database abstraction" function if desired. - - - - built-in MySQL support - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The first implemented, and still most recommended way to use - ewiki is with a MySQL (3.21 or later) database. RDBMS work more - reliably and of course much faster than any other of the ewiki - database backends. - - As the core ewiki_database() inside ewiki.php already includes - the MySQL database calls, there is usually nothing to do, but - opening a database connection before ewiki.php is included() - from yoursite.php - Please look at the top of this README for an example. - - As PHPs mysql_() functions don't require a db resource link to - be given anymore, the ewiki_database() function does not pass - and thus does not require it too. (If you use more than one MySQL - database, you should take care that ewiki always uses the one you - accessed least.) - - - - db/flat_files - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - If you don't have access to a MySQL database, then just include() - this plugin to save your wiki pages into simple text files (editable, - often called "flat files") inside a dedicated subdirectory. You - must set EWIKI_DBFILES_DIRECTORY in the 'ewiki.php' script to the - correct dirname. Don't forget, that it must be given either relative - to where the ewiki.php script is run from (like "./pages") or - absolute to the servers filesystem root (for example - "/export/htdocs/user528742/www.example.com/ewiki/pages") but NOT - relative to your WebSpaces DocumentRoot!. - - Usually "/tmp" will work, but this one is purged on every boot; and - therefore you should create a new sub directory (" mkdir ./pages ") - where all files go into. This newly created subdir must be made - »world-writable« using the command "chmod 777 ./pages", because the - WebServers user id counts when accessing it. - - Usually you can do both from within your ftp client (the commands - are the same if you have a shell account): - ftp> cd .../ewiki - ftp> mkdir pages - ftp> chmod 777 pages - ftp> ls - -rw----r-- 1 yourname yourname 57024 01. Jan 00:00 ewiki.php - -rw----r-- 1 yourname yourname 512 01. Jan 00:00 index.php - drwx---r-x 2 yourname yourname 4096 01. Jan 00:00 init-pages - drwxrwxrwx 2 yourname yourname 4096 25. Feb 23:59 pages - drwx---r-x 2 yourname yourname 4096 01. Jan 00:00 plugins - -rw----r-- 1 yourname yourname 33010 01. Jan 00:00 README - ftp> quit - - In graphical FTP clients there is usually a menu entry to set - "access mode" or "access rights" (sometimes "file permissions") of - files and directories equally. - - Again: don't forget to set the EWIKI_DBFILES_DIRECTORY constant to - the correct value! - If you create a subdirectory for the page files in the same directory - the main 'ewiki.php' script resides, you usually want to set the - config constant to just "./thesubdirectory" - here you could leave - out the "./" (not required as it only refers to the current path). - - Btw, the slash character will work in directory names on - windoze systems too (mr. bill once had to introduce a - hierarchical filesystem in DOS 2.0, but choosed the silly - backslashes, so no one would notice where that idea was - borought from ;) - - The saved pages are in a format usually referred to as - "message/http" (like www service request) or "message/rfc822" - (internet mail). They usually look like: - +----------------------------------------------- - | id: WikiPageName - | version: 1 - | flags: 1 - | author: 127.0.0.1:3054 - | created: 1046532697 - | lastmodified: 1046532697 - | refs: \nErfurtWiki\nNewestPages\n - | - | !! WikiSourceContent - | <more-text>... - - This file format can be exported by the "backup" tool, so you could - easily change from the MySQL database to the flat-files one, if - desired. Each page file exists in different versions, where the - version number is always appended to the saved pages` file name. - - EWIKI_DBFILES_NLR converts newlines into the string "\n", but just - for the values of the metadata. So there shouldn't occur much - inconsistency, because the wiki content is saved binary safe in - those "flat files". - - Filenames will be heavily converted on Win32 (urlencoded), while on - state of the art UNIX/Linux systems only a few characters are - replaced (slashes into backslashes) to match filesystem requirements. - - Problems: dbff WikiPageNames are currently not case-insensitive on - UNIX-filesystems (while the MySQL-table is). - Hits won't get counted; I don't think it is that essential, and it - would take too much effort and time (file accesses) to support this. - - Note: You cannot do a "backup" from a Unix server to a Win box by - using a stupid FTP program, because many characters are allowed in - Unix filenames but not on Win partitions. If you really want and - need to do so regularily, you should then setup ewiki with - EWIKI_DBFILES_ENCODE enabled from the very beginning. - The better - aproach was to use 'ewikictl' or 't_backup' or 't_transfer' for the - backup task. - - - - db/fast_files - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - NOTE: The db_fast_files has been merged into db_flat_files, so both - formats can be read now - at the same time! Updated or new pages will - however always be written in the file format determined by - EWIKI_DB_FAST_FILES (defaults to 0) - edit the "db_flat_files.php" - script to change that constant setting, or even add it to your - "config.php" so it was always present. - - While "db_flat_files" allows you to edit the WikiPage files (using - any simple text editor), the "db_FAST_files" plugin saves the pages - in a binary&compressed format (utilizing PHP's serialize function). - - This generally leads to a speed enhancement. Additionally this also - allowed the PageHit counting to be activated (which is off in plain - flat files). - - So you may wish to use this plugin in favour of the older - db_flat_files. And as now both methods are available at the same - time, you can switch whenever you want. - - Most of the setup guide from above is true for this one, too. - - An additional configuration constant introduced here is - EWIKI_DBFILES_GZLEVEL, which tells the PHP internal zlib how much - time to spend on compression of the saved pages. Usually the zlib - uses a default of 5, but for speed purposes it is set to 2 here. You - can also set the constant to 0 so the files will get saved - uncompressed (but still in 'binary' format). A value of 9 will give - you the smallest possible files, but this takes a little more CPU - cycles (a bit slower). - - This plugin was contributed by Carsten Senf. - - - - db/any - ¯¯¯¯¯¯ - If you use a relational SQL database other than MySQL, then you - may want to give this plugin a try. It itself provides a wrapper - for the PHP database access wrapper libraries ADOdb, PEAR::DB and - dbx(). - These wrappers themselves provide unified access to various SQL - databases in contrast to the many highly different db access - functions of PHP. Each of these db access wrappers has advantages - and disadvantages and so none of them is really widespread and many - users of course only jump on one of these trains. Because ewiki now - tries to be 'library' it will use whatever database access wrapper - you already have running on your site or container CMS, and the - highly simplified anydb_*() now tries to make use of it. - - The plugin is based upon the current MySQL database backend, and - thus may not be compatible to all proprietary SQL variants. - - Before you can use the db_any plugin you must ensure that you - either already have the PHP dbx extension dll loaded or the PEAR::DB - or ADOdb include files loaded. db_any will like to see an opened - database connection inside of the global '$db' variable. If - yoursite.php hasn't already a connection opened when ewiki.php - gets included, then you should preferably choose to use the - anydb_connect() function to do so (it will choose from PEAR::DB, - ADOdb and PHP dbx interfaces). - The '$db' connection handle can be shared between your site and - ewiki as long as it is a handle for one of the mentioned database - access wrapper libraries. - - Btw, "plugins/db_adodb" was obsoleted by this. - - - - db/dba - ¯¯¯¯¯¯ - including() this plugin enables ewiki to store the WikiPages in the - Berkeley DB file given with the EWIKI_DBA constant. Your PHP binary - must be compiled with either the "dba" or the "dbm" extension to use - this (and the dba extension requires at least one other database - type to be enabled). - - The plugin has a built-in list of preferred dba database types, but - it respects the filename extension of EWIKI_DBA. For example - "wiki.db3" would create a DB3 database file, while "wiki.gdbm" - resulted in a GDBM file, if that php extension was available. - - The PHP dba extension can support the db types (if compiled for): - .db3 - .gdbm - .db2 - .flatfile - .ndbm - .dbm - .db4 - - If you have the PHP "dbm" extension enabled, wrapper functions will - get enabled, so this works even if the "dba" extension is not there. - - The .flatfile is often available even if you haven't compiled your - PHP binary for anything else than "dba". This may also often be - faster than one of the db_flat_files plugins. - - If EWIKI_DBFILES_GZLEVEL is set to a value from 1 (fast) till 9 - (very good compression, but slow), the saved pages will get - compressed inside the dba database. With 0 this feature gets - disabled. - - - - db/phpwiki13 - ¯¯¯¯¯¯¯¯¯¯¯¯ - The original ewiki database table structure was compatible with the - one used in PhpWiki version 1.2.x, however it turned out that the - PhpWiki project has yet not stopped completely and choosed to - implement a more relational table structure with version 1.3 - - This plugin is only meant for transition __from__ PhpWiki v1.3.x to - ewiki, it should NOT be used to connect ewiki with PhpWiki forever. - - Write access is disabled per default, but available. However it is - probably not fully compatible with the database abstraction and usage - of PhpWiki, so it is likely to corrupt your database if you use it - for a longer period of time. This warning is mainly because the - 'latestmajor', 'latestminor and 'minor_edit' rows in the PhpWiki - database, because such stuff is not used by ewiki at all. ewiki also - tries to put some of the pages meta data into places where it could - eventually confuse PhpWiki. - Write access is however done nearly as safe as within the ewiki - database access layer (INSERT statement to not overwrite existing - entries). - - Again: this plugin is in no way meant to encourage you to keep your - old PhpWiki database! ;> - Please see also "tools/ewiki_convertdb.php". - - If you temporarily enable this plugin within the default/example - "config.php" or the "tools/ewiki_tools_config.php" you can also - utilize the very powerful 'ewikictl' cmdline utility to generate a - copy of your PhpWiki database in one of the backup formats suitable - for later use with ewiki. - - - - db/binary_store - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Is a hack into the ewiki core, which will store binary/uploaded - files outside of the default ewiki database (as plain files in a - data directory). - - Please also see the documentation on top of the plugin file. - - Per default ewiki can store "binary" entries beside ordinary text - pages in the database. If you'd like to keep uploaded files/images - out of the db, then this plugin/hack will help. It intercepts ewiki - and saves uploaded data into a plain data file, and instead creates - a "binary symlink" in the database for it (just the binary meta - data will get stored, with a hint on where to later access the plain - data file). - - This may sometimes be a speed enhancement and reduces size of the - database, however it has the drawback that only the main ewiki - script can handle this transparently and all admin tools/ fail to - deal with the stored plain data files (no backup support and so on). - - By setting the EWIKI_DB_STORE_URL constant correctly (corresponding - to your wiki setup and where you store the data files, compare with - EWIKI_DB_STORE_DIRECTORY) you can make ewiki create URLs directly - to where the stored plain data files reside (they do not contain - ewiki database meta data, and thus could be accessed directly by - http clients/browsers). - - Please be sure to configure this plugin by setting _DB_STORE_DIRECTORY - to something more useful than "/tmp", so your uploaded files will - still be there after a reboot. - - - - db/dzf2 - ¯¯¯¯¯¯¯ - The "dzf2" database plugin provides a flat file database (no SQL), - which stores its files compressed (like db_fast_files), but also - plattform-independent and in a case-insensitive manner (which is - not possible with dbff on Unix filesystems). It introduces a few - other enhancements, that make it a bit quicker than the flat_files - backend. - Also, it creates a unique sub directory tree, to provide faster - access times (disk/directory reading). - - - - db/zip - ¯¯¯¯¯¯ - This fun plugin stores files into a ZIP file. It is not - recommended for productive setups, and requires the commandline - Unix 'zip' utility to operate (DOS pkzip may also work). - - - - db/rpc - ¯¯¯¯¯¯ - Can access a remotely located ewiki database via PHP-RPC. Needs - a bit more setup (creating an interface and setting up passwords). - Could be used in conjunction with ext_multi to only have a few - pages located remotely. - - - - db/ext_multi - ¯¯¯¯¯¯¯¯¯¯¯¯ - Multiple database backends can be joined virtually into one DB for - ewiki using this extension. Needs a bit more setup, because you must - assign one of the backends as main database, where changes are - written to (exclusively). - - - - db/ext_subwiki - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Can automatically fragment your database into separate namespaces, - but must however be enabled from the beginning. You need to prepare - yoursite wrapper around ewiki to detect the currently accessed - Wiki; what however is useful to easily set up a WikiFarm. - - - - db/oldapi - ¯¯¯¯¯¯¯¯¯ - Provides a compatiblity layer for database backends after the older - non-OO interface (which is still supported in the core script). - - - -core enhancements -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Some really cool features are put into extension plugins, and the most -important, recommended and most often used ones are listed in this section: - - - - patchsaving - ¯¯¯¯¯¯¯¯¯¯¯ - If two users concurrently edit a page, then only the first save - attempt will succeed; which the second user is told by the "This - page version was already saved" failure message. - - This plugin works around this by passing the contents of the - concurrent versions through the 'diff' and 'patch' utilities, which - often merges the two different modifications in a new version that - can be saved into the database so there is no need for the failure - message. - - - - notify - ¯¯¯¯¯¯ - This plugin enables users to get notified, whenever someone changes - a watched page. To enable 'watching' one must just place an email - address into the page with following syntax: - [notify:mail@example.com] - - This bracket will be invisible, when a page is viewed, so it can be - placed anywhere. The notifications will be sent to this address - as long as the tag is there. - - If one wishes to receive notification messages in another language, - this just needs to be added after a comma or semicolon, like: - [notify:pop3@example.net,de] - This is often only necessary for the generic TLDs .com .org .net, - or where language code and TLD differ. - - - - jump - ¯¯¯¯ - Introduces magic markup for page redirection (switching to another - page). Possible notations are: - - [jump:OtherPage] - [goto:SwitchToThere] - - The EWIKI_JUMP_HTTP setting tells this plugin to send a Location: - and redirect HTTP status when encountering a page [jump:]. Else - this plugin will show up the JumpDestination page without notifying - the browser about it. - - It is also possible to perform InterWiki jumps, just be using the - common InterWikiMoniker: syntax, but generic URLs are also allowed. - - [jump:WardsWiki:WelcomeVisitors] - [jump:http://www.example.org/] - - - - email_protect - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - This plugin 'ciphers' all valid email addresses inside a WikiPage - for protection against automated spambots. Additionally it - throws fake/trap email addresses to spammer databases :> - - It ist not integrated into the core script, because some people - may prefer to have email addresses visible (intranet usage). - However it is HIGHLY RECOMMENDED to enable this plugin. Despite - its file size it is rather fast. - - - - spages (StaticPages) - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The "StaticPages"-plugin allows ewiki to access files in a given - directory. If these files are in text format, ewiki will parse them - as WikiPages. But if you put files with an extension .html, .htm or - .php into one of the specified StaticPages` directories they will - be returned as is from ewiki_page() - the .php files will of course - get executed and their output is returned. - - The basename of the files in the directories to be used by spages - will make up the WikiPageName with which the files will be - accessible. - - Any given directory (see on top of plugins/spages.php) will be read - recursively. So files in a subdirectory will get available as a - page with a name like "subdir/FileName". If the name of the - subdirectory contains a dot at the end, then the slash will be left - out in favour of a dot: resulted in "subdir.FileName" for example. - - PHP scripts in a spages directory however have some restrictions, - like not being able to return headers() or to access most global - variables without use of the $GLOBALS[] syntax. If you rely on - such functionality you should rather write an ordinary page plugin - (which in fact is often much easier). - From the output of .html and .php scripts only the parts between - <body> and </body> will be returned as page content. Any <html> - head area will get stripped, as it would lead to completely invalid - html code if it was returned as is by ewiki_page() into yoursite. - - To let this plugin load pages from directories, you should either - edit the array on top of this plugin file, or define() the - EWIKI_SPAGES_DIR (before! including the spages.php script), which - then also would be read in. - Alternatively you could call the ewiki_init_spages() function - yourself to register a directory for processing (after! loading the - spages plugin): - - include("plugins/spages.php"); - ewiki_init_spages("/var/www/wiki/staticpages/"); - - You could also use this plugin to inline the ewiki database tools/ - as virtual pages. - - Btw, it is very easy to make a StaticPage from a ewiki page plugin - and vice versa. Please also note the 'tools/mkpageplugin' which can - convert anything used as StaticPage into a page plugin. - - - - pluginloader - ¯¯¯¯¯¯¯¯¯¯¯¯ - The pluginloader plugin automatically loads ["action"] and ["page"] - plugins, whenever necessary. This allows to skip dozens of - include() statements within the config.php (which most always just - slow down script startup). It is configured via a static array, - that defines which plugins are allowed to be automatically invoked - on request. - Detailed explanaition is available within this script. - - - - init - ¯¯¯¯ - Handles database initialization using the distributed standard Wiki - files from './init-pages'. Unlike the ewiki-builtin function to - perform that task, this plugin first outputs informational notes - to the user, prior database initialization. - Once you have your SQL or ./files database initialized, you should - disable this plugin (it then isn't required anymore). - - - - feature/appendonly - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - This plugin (a family of) implements the actual support for the - _DB_F_APPENDONLY page flag. When the flag is set, and this plugin - active, then ordinary users can further only append text to the - page, and won't be able to edit the earlier written parts of it. So - this implements a much softer approach than the _READONLY page - flag. - - Also this plugin comes in three flavours, but you can often only - load one of them: - - "appendonly" - Really allows just additions to be made to the page, - each new separated by a horizontal bar. - - "appendwrite" - Allows to insert a page separator, which protects - the upper part from getting edited by ordinary - users. Everything below a horizontal bar (denoted - by at least 16 minus signs) or a double horizontal - bar remains editable by all users. - This plugin activates only if the _APPENDONLY and - _WRITEABLE flag is set. - - "appendcomments" - stores page additions in an separate database - entry marked with _DB_F_PART, but allows this part - to get edited as whole (like "appendwrite" plugin). - - The last one is probably not very useful, as it generates some - overhead and in fact is a collection of various workarounds to - accomplish the desired functionality (so it may prove little - lifetime). - - - - feature/imgresize_gd - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Was extracted from the core during the R1.00f development releases. - Automatically rescales uploaded images, if they are larger than - EWIKI_IMAGE_MAXSIZE. - As it uses the gd2 library, there must be support for this in your - PHP binary. There are a lot of problems on Win32 systems, and also - some Linux binarys (-dev ones) crash constantly if you load this - plugin but don't have the libgd activated or available. - - - - feature/imgresize_magick - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Rescales uploaded images via the ImageMagick utility "mogrify", - which is usually only available on UNIX systems. It should however - be fairly simple to make this plugin work with some other image - manipulation tool (at least with Linux). - - - - feature/imgfile_naming - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - This plugin overrides the default name assignment code for uploaded - images, and keeps the original file name to a certain degree (unless - it is considered frivolously silly, like "DSC00001.jpeg" or such - things). - - You could now also disable the "internal://" prefix usuage, as ewiki - can distinguish _TEXT from _BINARY database entries now for SQL - backends. - - - - input_trimming - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Checks all known ewiki input variables to prevent some possible - injection / overflow problems. - - - - feature/pingback - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Will automatically add links to pages, when some PingBack-enabled - blog (weblog) links it. Also will send out such pings to other - sites whenever an URL is added on any WikiPage. Verifies incoming - hyperlinks. - - - - feature/refererlog - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - When coming from an external site, adds the Referer: URL to the - current page, after its validity has been verified. - - - - feature/xpi - ¯¯¯¯¯¯¯¯¯¯¯ - Allows you to later install .xpi plugins by simply uploading them - with the "PlugInstall" page. You need to first define an - administrator password (EWIKI_ADMIN_PW constant). There are also - remote .xpi plugin directories which you can browse and allow - for click-and-run addition of new extensions. - - All plugins can be disabled through the admin interface, or at - least can be uninstalled again (for page plugins). - - With a loaded phpjs interpreter you can also allow your users to - install the safe / sandbox-executed .jpi page plugins without - password. - - - - feature/xpi0 - ¯¯¯¯¯¯¯¯¯¯¯¯ - If you don't need to install new or control old xpi plugins, - you can get rid of the "PlugInstall" interface by using xpi0 - instead of the big xpi extension. - - - -action/ plugins -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -Action plugins are those, that can be activated ON individual pages. And -usually are shown as links below a page. The ewiki-builtin EditThisPage, -BackLinks and PageInfo are ["action"] plugins for example. - - - - action/diff - ¯¯¯¯¯¯¯¯¯¯¯ - Enables to view the differences between two saved page versions - (what changes somebody has done to the page), but it is rather - stupid and guessworking in how it does so. - - On a Unix system you might want to use gnu_diff instead. - - - - action/translation - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - This plugin adds a link to the GoogleLanguageTools or AltaVista - BabelFish, which then remotely translated the current page into - the users preferred language. It has support to detect the lang - of the current pages content, to redirect to the right service. - - - - action/like_pages - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - LikePages is a search feature of WardsWiki, which scans for - WikiPages whose name is somewhat similar to the one of the current - page (the pagename must be made up of the same WikiWordParts so a - page gets listed). - - - - action/raw - ¯¯¯¯¯¯¯¯¯¯ - Can be used to download the unrendered Wiki source of a page. - - - - rss - ¯¯¯ - Adds an action link to every page, which allows to retrieve - RSS/Atom feeds for it, if the plugins/lib/feed extension was - loaded. - Also provides a Wiki-wide feed as [RSS] page or on RecentChanges - and UpdatedPages. - - - - action/info_qdiff - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Adds the "quickdiff" action to the info/ page, which allows to - review changes over all historic versions at once. - - - - action/translation - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Adds a link to Babelfish/GoogleLT to translate the current page - into whatever the visitor has configured as most preferred lang. - - - - action/relatedchanges - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Shows when back- and fore-linked pages where changed last. - - - -plugins related to hypertext links -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The linking/ plugin group deals with how links inside the Wiki will look and -work. Some of them would also fall the "core enhancements" group, while -others are just handy or for link beatification. - - - - linking/tcn - ¯¯¯¯¯¯¯¯¯¯¯ - ewiki evaluates the Accept-Language HTTP header modern browsers - send with each request. This plugin now automatically brings up - a variant of the currently requested page if it finds a match in - the database. To make it work, you need to create pages with - language suffixes in their names like: - ThisPage.es - ThisPage - ThisPage.de - or - OtherPage - OtherPage*nl - - Note, that there can always be one page in each name group without - that suffix. This page then will be assumed to be in the default - language (en) set by EWIKI_DEFAULT_LANG. - - If multiple page versions are available, then a list will be - printed above the page title to allow users to override the - prefered language guess of this plugin. - - - - linking/plural - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - This plugin tries to alias plural and singular page names against - each other. That is, "WikiPage" will be shown, whenever "WikiPages" - was requested (and vice versa). - - - - linking/autolinking - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The autolinking plugin allows to have automatic links inside the - Wiki for words which exist in the database, but are no real - WikiWords. This is made possible by the companion StaticPage - admin plugin "spages/Admin/PrepareAutolinking", which must be - invoked from time to time to update the db cache entry, which the - autolinking plugin utilizes. - - - - linking/link_css - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Adds CSS classes to the links generated by the Wiki page formatting - kernel, which then allow you to colorize (or to otherwise change - appearance of links) via a style sheet. - - - - linking/link_icons - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The link_icons plugin prepends icon <img>s before registered link - types, like the link_css plugin adds class="..." attributes to the - html formatted links in every page. - - - - linking/link_target_blank - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Adds 'target="blank"' to link tags <a>, which will result in most - browsers opening pages in a new window. Note: this is never - user-friendly. - - - - linking/linkexcerpts - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Adds a short preview text (with <a title="...">) to every link of - a page. This however requires multiple additonal database accesses - (slower) and could enlarge delivered .html page sizes dramatically. - - - - linking/linkdatabase - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Is a page plugin, which provides a nearly compliant implementation - of the page and link structure export function known from the UseMod - WikiWare and MeatBall:LinkDatabase. This is useful for contributing - to the upcoming InterWikiBatabase and BorgWiki. - - - - linking/instanturls - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows to specify URL abbreviations on one or more summary pages. - This can be done using a table or a definition list to assign - each URL a title, which then can be used on other pages as square - bracket reference. - - The 'instanturl_find' plugin in addition allows to use the [find:] - moniker to perform partial searches in the list of URL - abbreviations, but also in the list of interwiki monikers. As - fallback it searches for matching page names or redirects to - Google. - - - - linking/titlefix - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows to swap [title|PageName] in square brackets [Page|title], - because that can easily be detected, if the page already exists. - - - - interwiki/intermap - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - This plugin (in fact only a general include) extends the list of - known InterWiki: prefixes with a more complete set created from - the MeatBall interwiki.map. - - - - interwiki/editable - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Provides automatic read-in of the special page "EditableIntermap", - so users can provide shortcuts for commonly referenced sites in a - table or definition list. - - - - linking/xfn - ¯¯¯¯¯¯¯¯¯¯¯ - Adds pseudo-monikers for the "XHTML Friends Network". You can - simply mix the well-known prefixes like an InterWiki moniker - before any page name. - [met:friend:neighbor:parent:UserName] - - This will translate into the typical - <a href="?id=UserName" rel="met friend ..."> then. - - - -appearance/ tweaks -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -There are various plugin hooks within ewiki, which allow to mangle text -strings and data immediately before it would be returned as output. - - - - appearance/listpages_br - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - This plugin will produce <br> separated lists (for SearchPages, - PageIndex, MostVisitedPages, and so on). - - - - appearance/listpages_ul - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Creates real <ul> lists (WordIndex, CreatedPages, ...) instead of - the · ones, ewiki core would usually return. - - - - appearance/listpages_tbl - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The listpages_tbl plugin outputs a table instead of the ordinary - page lists (PageIndex, UpdatedPages, ...). You need to edit its - source to set colours to fit your site layout. - - - - appearance/fancy_list_dict - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The WordIndex and PageIndex plugins (unlike the other page list - returning ones like SearchPages and UpdatedPages) can utlize this - plugin to output a pretty dictionary like listing of pages. - - - - appearance/title_calendar - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Changes the titles of calendar plugin entries in the database into - a more readable format for page lists (PageIndex, PowerSearch, - UpdatedPages, and so on). - - - -page plugins -¯¯¯¯¯¯¯¯¯¯¯¯ -The page plugins provide additional "generated/internal" pages, which have -a standard WikiWordPageName and can thus be referenced easily from within -ordingary WikiPages. But they are of course uneditable (because their -content is 'hardcoded' as PHP code) and most action/ plugins cannot perform -any function on them. - -With the rise of the StaticPages plugin, the page plugins are almost -outdated, because all their code could now be extracted into a StaticPage -file, so their code had to be loaded only on request (instead of including() -them regardless if they're needed or not, how it currently is done). - - - - page/powersearch - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - This plugins provides a (probably) better search function - with the default page name "PowerSearch". It tries to guess - a value, which tells something about how good a page matches - the searched words and orders the found pages list by this - (possibly not very useful) value. It prints the top 10 results - more verbose. - - - - page/pageindex - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Lists all pages found in the database alphabetically. - - - - page/wordindex - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Lists the word parts of all wiki pages, but requires the - powersearch plugin to be present, because the result is redirected - to there as usually many of the listed words belong to multiple - page names. - - - - page/imagegallery - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Outputs a page containing all cached/uploaded images. The - images are currently not rescaled to fit on the page; this - work is left to the browser. - Needs enhancement. - - - - page/aboutplugins - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Lists all registered plugins (mpi, page, action, task/core). The - name refers to the "about:plugins" page present in recent browsers. - - - - page/orphanedpages - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Shows up a list of pages, that exist, but are not linked from any - other pages. These is often also called dead pages. - - Note that this plugin does not take into account, if any page - can be reached from the frontpage - such a hypertext tree test - would require much more work than realized in here. - - - - page/wantedpages - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Returns a list of pages to which QuestionMarkLinks? currently - exist. - - - - page/since_updates - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Provides a list of pages with actualization times. - - - - page/textupload - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The virtual TextUpload plugin allows to insert new WikiPages by - uploading text files. It can convert from various formats into Wiki - content, including some proprietary Office file formats, if one of - the possibile filters is avaiable (Unix style file piping). - It also can extract multiple files from a Tarball or ZIP archive - if the according utilities are available (even on DOS/Win systems). - - - - page/wikidump - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows to download a gzipped tarball containing all readily - rendered pages as .html files and also images. - - - - page/interwikimap - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Shows up the currently in use InterWikiMap. - - - - page/hitcounter - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Sums up the individual {hits} count of all pages and returns the - overall count. - - - - page/scandisk - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - Presents an unserious statistic. - - - - page/wikinews - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - Returns the most recently added pages in an overview, that - incorporates a small fragment from the content of those newly added - pages. - - - - page/wikiuserlogin - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows to set a free-form username, which then would be stored into - the database whenever a page was edited. It gets meanwhile saved in - the http client as cookie, but can afterwards be evaluated as - $ewiki_author, so the according field in the database entries - contains a bit more than just the IP address when a changed page - gets saved. - Note: this does not do any sort of real authentication or - authentification. - - - page/randompage - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Shows up a randomly choosen page from the database. - - - - page/fortune - ¯¯¯¯¯¯¯¯¯¯¯¯ - Calls the Unix /usr/games/fortune program and prints out returned - content. - - - - page/ewikilog - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows to review the content of the 'ewiki.log' file. - - - - page/phpinfo - ¯¯¯¯¯¯¯¯¯¯¯¯ - Shows the settings of your PHP interpreter. - - - - page/README - ¯¯¯¯¯¯¯¯¯¯¯ - Can parse the distributed README file and make a hypertext - presentation from it, for easier reading of the Wiki documentation. - It is printed in <pre> text, but with WikiLinking enabled (which - however is rarely used in the README file). It additionally - presents the README.de and README.auth files. - - - - page/recentchanges - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Provides a fancy RecentChanges page (like the built-in "UpdatedPages") - in either UseMod or MoinMoin style. The appearance can be configured - by changing the plugin registration at the top of this script. - Both variants take the {meta} log entry into account, which users can - set if the aview/aedit_log plugin is loaded also. - - - -markup plugins -¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The ewiki rendering core is rather fast and consolidated, that was the goal. -However if you ever happen to need more functionality, this can be added -easily by the use of plugins. - -Several are already available to emulate the WikiMarkup of other commonly -used WikiWare. - - - - Other WikiWares markup - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The WikiWorld still lacks a unified markup (and thus also the - interchangeablity that made html THE standard it is today), and - while ewiki usues nearly MeatBall:WikiMarkupStandard, you may want - to reuse existing pages from another Wiki. - - Currently we provide emulation for: - * PhpWiki - * sfWiki - * miki - * bbcode (BulletinBoard, not a Wiki) - - But please see the individual files on which (additional) markup - they introduce. - - These plugins on occasion only register their markup within - $ewiki_config["wm_*"] settings, but often just perform - pre-conversion of foreign markup by utilizing the ["format_src"] - plugin hook (they then pre-convert page content to use ewiki - markup rules before the ewiki_format() kernel performs - transformation). - - - - markup/css - ¯¯¯¯¯¯¯¯¯¯ - CSS markup allows you to assign visual styles (or semantic CSS - class names) to a block of text (paragraph) or to pieces of text. - @@ is used to start a styled area. The @@ must be immediately - followed by either a CSS class name (without the dot) or with - CSS instructions without any whitespaces. - The following text (after the @@, the class name and a space) will - then be assigned the class until a (possible) next @@ without - attached classname or style definition. - - If the @@ occurs at the start of a paragraph it will enclose it - in a <div> with the according style assignment, otherwise (in the - text) a @@ will become a <span>. - - See also the explanation and examples in this plugins` comments. - - - - markup/css_singleat - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - This plugin allows you (like the markup_css plugin) to attach CSS - classes to a paragraph of text with just a single @ character: - - @JAVADOCLIKE paragraphs text... - ... ... ... .... ... ... ... ... - - - - markup/footnotes - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Introduces the ability to generate footnotes by placing an - explanation into double curly brackets {{footnote text}}. - - You should activate this only if you really need it. Sometimes this - may be useful, but it is rather bad wiki style; because if someone - would like to explain something in more detail he should create a - WikiLink to a new page. So this should be used for very short - explanations, say incomplete sentences or a book reference and - other things where it really seems bloat to create a new page. - - USE THIS RARELY or better not at all! - (this is a feature copied from MS` EvilWiki) - - - - markup/asciitbl - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows to use ASCII-Art tables as outputed by lynx and other - console programs inside of WikiPages, which eases life, when - dealing with multiline table cell content. - - - - markup/complextbl - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - ewiki allows you to use tables with the || | characters in the wiki - page source. However the html code for the table layout is - hardcoded and cannot be changed on a per-page basis. - This plugin intercepts the wiki source formation process to allow - you to specify html tag attributes inside a table definition like: - - |{ border=0 cellspacing=10} here is | the table | content | - | 2nd line | 2nd line |{ rowspan=2} fills two table rows | - |{ colspan=2} 3rd line | - - Note, the opening "{" must follow the "|" character immediately. - - This code was provided by Hans B Pufal. - - It may be a security risk to include it per default, as this allows - to add SomethingScript references as well. - - - - markup/htmltbl - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Provides a block escape to use the standard html <table> code - instead of the limited pipe syntax provided by ewiki. It will parse - for <tr> and <td> tags and strip any not registered attributes to - defend against harm that could be caused by EvilScript additions. - - The common html <table> syntax then allows easily to include - multiline table cell content, which is nearly impossible (to edit) - for the "|...|..|" table syntax. - - - - markup/rescuehtml - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows to use some 'safe' HTML tags within the WikiPage. This - plugin replaces the previous EWIKI_RESCUE_HTML constant. - - Note that those 'safe' HTML tags may also lead to some confusion, - especially if you have a wiki about HTML, because then you cannot - write text about the <STRONG> tag because it will actually always - be interpolated as itself and not as the text string "<STRONG>". - - - - markup/rendering_null - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - If someone would like to use ewiki for a personal homepage, but - prefers HTML over WikiSyntax, then this rendering core replacement - may suit his needs. It allows HTML to be used, but still renders - WikiWords into valid hyperlinks (a few other features from the - original ewiki_format function are also supported, but you can - strip even those). - - - - markup/1emphasis - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Adds the /italic/, *bold* and _underlined_ markup codes, which - sometimes can heavily garbage pages (because ewiki provides no - general markup escape sequence, but the per-default disabled - <verbatim>, or respectively <nowiki>). - - - - markup/naturallists - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows to start enumerated pages in the source with simple - numbers followed by a dot, as it would naturally be written. - Those lists are of course re-converted into real enumerated html - lists again. - - - - markup/fix_source_mangling - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Speeds up ewiki page rendering, in that all older page source - oriented markup plugins are run together onto ["core"] page content - blocks only. This also fixes a few problems, which some plugins may - issue with the renewed formatting kernel. - - - - markup/abbr - ¯¯¯¯¯¯¯¯¯¯¯ - Evaluates the pages [Acronyms] and [Abbreviations] to read a - definition list or table from them, whose entries will later be - replaced in the whole wiki. Then all occourences of those - abbreviations or acronyms will be replaced by the accoring entitled - html tags (<abbr> and <acronym>), providing a lot user-visible meta - information easily. - - You could style thouse occourences via CSS as usual. - - - - markup/table_rowspan - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Merges multiple table cells automatically (to the left one) for all - occourences of || two or more dashes. - - - - markup/timestamp - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Introduces the &now markup which gets replaced with the current - time/date string AT EDIT TIME. - - - - markup/braceabbr - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows you to create in-page abbreviation tags by simply - writing something in all-uppercase and placing the definition - into round braces behind it, like: WIKI (a WikiWikiWeb). - - - - markup/definitionlinks - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Automatically creates anchors for all entries in a definition list - and links occourences of these words in the rest of the current - page to there. - - - -mpi -¯¯¯ -The so called "mpi" plugins can be embedded into pages, and produce their -output there. They are loaded on demand (only if it appears that they should -be invoked), but it is possible to include() the individual files regardless -if they would be used or not. - -In order to have the mpi plugins available, you must however first load the -mpi dispatcher: - include("plugins/mpi/mpi.php"); -Which then takes care of the markup and loading of the requested plugins. - -The syntax for calling a mpi plugin is (write this inside of a WikiPage, -when editing it): - - <?plugin PluginName arg="..." arg2=DDD ?> - -Where args are often optional or could even be written without the 'argname=' -if only one was required. The name of the mpi plugin is case-insensitive -here. - -Some plugins take longer text-only arguments, where you just put some more -paragraphs of text or some pseudo-programming code before the closing ?> -like for the TableEditor: - - <?plugin TableEditor -| use | this | -| table | for | -| editing | . | - ?> - -Just see the distributed [MpiPlugins] page for an overview of available -plugins of this type. - -It is often possible to invoke mpi plugins like ["page"] plugins, if you -create a link inside of the page using the syntax <?plugin-link PluginName ?> - - - - mpi/backlinks - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - Prints a list of BackLinks to the current page (the same as when - clicking on the title of a page or on the BackLinks action link). - <?plugin BackLinks ?> - <?plugin BackLinks page=ForThatPage ?> - - - - mpi/multimedia - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows to <embed> multimedia files into a page. - - - - mpi/syndicate - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - Embeds remote RSS feeds (abbrv. for "ReallySimpleSyndication" or - "RichSiteSummary") into the current page. It caches the fetched - data for quite some time in a pre-parsed _BINARY database entry. - - - - mpi/insert - ¯¯¯¯¯¯¯¯¯¯ - Allows to insert another readily rendered WikiPage into the current - one, usually inside of a <table border="1">. - - - - mpi/localsitemap - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Is a mix of BackLinks and LinkTree features, and prints the tree of - pages backreferencing to the current one. - - - - mpi/removedlinks - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Brings up a list of all links that were removed throughout the page - history. - - -visual extensions -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -The hook following plugins utilize is called "append-view". It allows to put -content below a pages contents (after the action links). - - - - aview/backlinks - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Adds the list of BackLinks (references from others to the current - page) to the current page below it (this list is also available, - when a user clicks on the title of a page). - - - - aview/linktree - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Prints the possible (shortest) paths to the FrontPage (determined - by the EWIKI_PAGE_INDEX constant) starting from the current one - below. Calculations and database access required by this plugin - often means a slowdown up to 2 seconds before the page is readily - rendered. - - - - aview/toc - ¯¯¯¯¯¯¯¯¯ - Analyzes a pages headlines and generates a "table of contents" box - from it, which is inserted as float box on top of it then. Use the - following CSS selector to style it: - - .wiki .page-toc { - ... - } - - - - aview/posts - ¯¯¯¯¯¯¯¯¯¯¯ - Allows to add separate comment pages, which will then always be - displayed below the current one, but remain editable as standalone - pages. (So the page they are appended to could be marked as - _READONLY). - - - - aview/threads - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - Allows to group the pages created using the "posts" plugin into - threads. - - - - aview/subpages - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Adds the list of pages, which appear to be SubPages of the current - one, below it. - - - - aview/downloads - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Shows the uploaded files, which appear to belong to the current - page (individual pages can be treated as upload sections). - - - - aview/imgappend - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Prints an image uploading box below every page, which allows to - append an image without prior clicking EditThisPage (the image - will be automatically appended to the bottom of the page). - - - - aview/piclogocntrl - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - This plugin allows users to select a logo graphic which will be - made available for use in the site template as - $ewiki_config["page_logo"]. Configureable through the internal - image list array. - - - - aview/control2 - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Shows examplarily how to replace the standard "action-links" box, - and adds it on top of the page (including the page title). - - - - edit/pageimage - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - This plugin allows users to select a page image graphic, and is a - mix of the aview/piclogocntrl and page/imagegallery plugins. - - - - edit/authorname - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Adds a text <input> field below the edit/ box, which allows to - set the AuthorName which then will get stored, when the page is - saved. This name is then also stored client-side as cookie for - at least 45 minutes. - - Before using this plugin, you must consider, that it eventually - allows to override the correct username that ProtectedMode plugins - already provided. And there is no way to prevent users from using - faked names (because this plugin cannot check if a username was - already 'registered' and thus can't initiate a password query). - - - - edit/deletebutton.js - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Adds a JavsScript snippet to allow users to quickly mark a page - for deleterequest, by inserting the link to "DeleteMe" into the - contents, when editing it. - - - - edit/templates - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Brings up a <select> element on top of the edit/ page for empty - (to be created) pages, that lists all pages which names end in - "Template". One of the templates can then be loaded into the edit - box as base for the new page. - - - - edit/log - ¯¯¯¯¯¯¯¯ - Adds an input box to the edit/ page, where users can put a summary - of the cahnges they made. This ChangeLog can later be displayed on - the RecentChanges page. ("UpdatedPages" currently does not use - this however.) - While this additional field is a bit more time consuming, users - often fill it out, to advocate the changes they've contributed to - particular pages. - - - - edit/flags - ¯¯¯¯¯¯¯¯¯¯ - Allows your users to set certain flags, when editing a page. You - must first enable the one you deem non-harmful enough to get changed - by visitors. - - - - edit/minor - ¯¯¯¯¯¯¯¯¯¯ - Is a variant of the flags setting extension, which only provides - the _MINOR edit checkbox to hide a page edit from RecentChanges. - - - - edit/warn - ¯¯¯¯¯¯¯¯¯ - Shows an informational warning notice, when two people appear to - be editing the same page. - - - - edit/lock - ¯¯¯¯¯¯¯¯¯ - Prints a stronger warning message (can be unlocked however), when it - detects that someone wants to edit a page someone else is already - working at. - - - edit/spellcheck/ - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - There are now three plugins which can turn the [preview] button - below every page edit box into a spellcheck function. - - Wether you have a working 'aspell' or 'ispell' on your system, or - the PHP internal aspell functions, you must load the according - plugin. - - - - edit/spam_deface - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Scrambles added URLs to a page (through zero_pagerank wrapper or - Google jump url) when it partially matches any fragment listed - on the special "BannedLinks" page. - - - - edit/spam_block - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Rejects edit, if a newly added URL matches with a text snippet - from the "BlockedLinks" page. - - - -page filters -¯¯¯¯¯¯¯¯¯¯¯¯ -A few plugin hooks exist to completely rework generate page output. These -are often used to insert content into the otherwise readily rendered .html -pages (some of the above aview plugins do so, too). - - - - filter/f_fixhtml - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Is a minimal tag balancer (a highly simplified HTML tidy) and can - work around various html code problems that the ewiki_format() - html rendering function has. It is for example specialized to - correct broken html that resulted from WikiMarkupAbuse as for - example nesting text style attributes like this: __''text__'' - - - - filter/search_highlight - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Evaluates the Referer header sent by many browsers to detect if - a visitor came from a search engine (even the internal PowerSearch - or SearchPages ones) and highlights the searched words in the - current pages body (using CSS). - - - - filter/fun_chef - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Borg, Borg, Borg! - - - - filter/fun_upsidedown - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Transforms a pages content using letter transformation to make - them readibly from upside down with certain fonts. This however - is a bit tricky for html pages and thus will always wrongly - intermix sentence order. - - - - filter/fun_wella - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Adds a little CSS to make text swirrling on both sides. - - - - filter/fun_screamomatic - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Detects if someone entered a FULL LINE OF YELLING into a page - when editing it, and then sets a persistent cookie. That cookie - will result in all pages contents to be converted into uppercase - characters. - - - -BloatWiki extensions -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -ewiki slowly evolves into a well-bloated portal software, and some plugins -already extend it far beyond the scope of an ordinary Wiki. - - - - module/calendar - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - The calendar plugin enables you to add an editable calendar to - every WikiPage. It is not a fully integral part of ewiki, and needs - additional calls from yoursite.php to integrate nicely into your - sites layout. - - You even don't need to allow a calendar to be added to every page, - you can just include the plugin file and use the _one_ page called - "Calendar" or "YearCalendar", where everybody can make additions. - - The coolest about this plugin is, that it nicely integrates into - the common WikiNameSpace. - - Just include("plugins/calendar.php"); so it gets available. - In yoursite.php integrate it as follows: - - <?php - ... - - echo ewiki_page(); // print current pages content, as usual - - ... - - if ( calendar_exists() ) - { - ... - echo calendar(); // print calendar for current page - } - else { - ... // else only a link to the cal. page - echo "<a href=\"?id=calendar/$ewiki_id\">ShowCalendar</a>"; - } - - ?> - - The calendar() function call emits the html for the calendar of the - currently viewed page (see ewiki_page() call). - - The function calendar_exists() only checks for already existing - event entries in the calendar, so the calendar won't show up, if - there isn't yet anything inside (so only the "ShowCalendar" link at - the bottom of the page will link to the still empty calendar). You - can of course leave out this function call or alternatively call - it with calendar_exists($always=true) if you want the calendar to - appear most of the time / or for all pages. - - Please note the "fragments/calendar.css" file, which illustrates - how to tweak layout and look of the generated calendars. - - This plugin was contributed by Carsten Senf (originally - implemented for good old PhpWiki). - - - - module/downloads - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - From the very beginning the ewiki core supported uploading image - files into the database. As time and discussions went on, there - came the idea to allow arbitrary binary files to be inserted too. - - The old EWIKI_ALLOW_BINARY way should now be avoided, because the - download plugin adds more functionality and more features, and is - easier and more intuitive to use. - - It adds the virtual page FileUpload to insert a file into the - database, and the page FileDownload, which lists all available and - uploaded binary files from the db. - - Please note, that due to the use of the database interface, the - file sizes are usually limited to 1-2M (depending on PHP and MySQL - settings), so there may still be some need to reimplement this, - using the antique world-writable incoming/ directory method. - - The mime_magic plugin should be used together with this one, and - you should change the icon file names (use the ones from the Apache - distribution for example). - - (It may also be a good idea to run a secondary database if you - use it. Have a look at fragments/binary.php, and set up a - secondary ewiki database using it and the db_flat_files plugin. - This is useful, because you then can more easily delete uploaded - files as they don't get saved into a SQL database.) - - Different download sections can be defined. The "*" merges all - allowed sections into one list again, and the "**" section even - lists the files attached to pages. - - The page attachment link (to append download functionality to each - page) can be revoked by unsetting the $ewiki_plugins["action"] - line in the downloads.php file; so only the default sections are - accepted (and page names rejected). - - The plugins/downloads_view.php brings up the list of uploaded - attachments below each page (if existing). It works rather fast - due to an improved database search call, and should therefore be - activated whenever you use the per-page attachments feature. - - See also plugins/binary_store.php to keep your SQL database small, - but note its limitations. - - - - module/tour - ¯¯¯¯¯¯¯¯¯¯¯ - Provides a shortened view of the current page and all linked ones - (even the backlinked ones). This eases navigation and page content - "scanning" (getting a quick overview). - - - - meta/meta - ¯¯¯¯¯¯¯¯¯ - Adds the general page meta data support, and a small input box - below every page, which allows users to add arbitrary invisible - infos about the current page. The data will be stored into the - page hash as $data["meta"]["meta"] entry (four levels deep - array). - All that meta data information must however be evaluated by other - specialized plugins later to make sense: - - - - meta/builtincategories - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Contains a list of category names (you first must edit it!), which - will later be displayed in/below pages to make users choose from - one. The category name is written back into a pages {meta}{meta} - field then. - - - - meta/f_title - ¯¯¯¯¯¯¯¯¯¯¯¯ - Uses a "title:" entry in the {meta} block to override the shown - page title (which otherwise and usually would be the same as the - database internal real page name). - - (Note: The mpi plugin SetTitle does basically the same.) - - - -utility code -¯¯¯¯¯¯¯¯¯¯¯¯ -The plugins/lib/ directory contains code and functionality, which often is -required by some of the other plugins (they depend on it then), but which -was too specialized to get part of the ewiki.php core script. - -Other extensions in the lib/ subdir didn't match in any of the other plugin -categories. - - - - lib/cache - ¯¯¯¯¯¯¯¯¯ - This plugin stores readily rendered Wiki page content (already in - html format) either into a dedicated directory, or into specially - named _BINARY wiki database entries. This then allows to satisfy - further requests to a page with the saved content. - - You should set EWIKI_CACHE_DIR to a useful value (a so called - "chmod 777" directory, so your webserver process can write into it), - or alternatively unset this constant and instead define - EWIKI_CACHE_DB so cache entries get stored into the ewiki database. - The _CACHE_DB constant is just prepended to the name of the current - page to get the name for the database entry for the cache data. - - - - lib/speed - ¯¯¯¯¯¯¯¯¯ - Evaluates the "conditional HTTP request headers" to tell a client - if it could reuse its existing cache entry for a requested page. - This is believed to reduce traffic and also speed up some - applications. However it is still rather untested and could anyhow - lead to some problems (never updating pages for some broken - browsers). The evaluated headers include "If-Unmodified-Since:" - which corresponds to the "Last-Modified:" answer header ewiki - always sends. - - However this will only work, if you disable EWIKI_NOCACHE - but - then some browsers will never see updated pages, if they were - misconfigured to not refetch pages, once they got into the internal - browser cache. (But on the other hand, that is users fault ;) - - - - lib/mime_magic - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Implements the mime_magic feature absent from some (older and - misconfigured current) PHP interpreter versions. - - This is recommended in conjunction with the downloads plugin to - store correct mime type data, for proper use of icons beside - download links. Also the correct Content-Type header should always - be available, when binary content is delivered. - - - - lib/navbar - ¯¯¯¯¯¯¯¯¯¯ - Provides a configureable menu for the contents of your Wiki for - inclusion in your site template, which changes depending on which - site area you're currently inside (determined partially by - the linktree plugin). - - - - lib/protmode - ¯¯¯¯¯¯¯¯¯¯¯¯ - Is an extension package (currently in development) with various - helper functions for ProtectedMode plugins. Especailly useful in - conjunction with the auth-liveuser framework. - - - - lib/save_storevars - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - An example script on how to store additional vars into page entries - of the ewiki database (session like). - - - - lib/feed - ¯¯¯¯¯¯¯¯ - Adds support for emitting RSS and Atom-feeds. Use in conjunction - with plugins/action/rss. - - - -admin/ plugins -¯¯¯¯¯¯ -Collects plugins for ewiki / database administration. Often these depend -upon $ewiki_ring==0 (superuser authentication level in EWIKI_PROTECTED_MODE), -otherwise refuse to work for security reasons (some functions are however -available to moderators too, ring level 1). - -Some of these plugins may be reimplementation of stuff from the tools/ -directory (integrated database tools). - - - - control - ¯¯¯¯¯¯¯ - Allows changing per-page settings, and adds a easily accessible - "page control" action link below every page. - - You can use this to immediately change per-page flags (_READONLY, - _HTML, _DISABLED and so on). Or you can delete a unwanted page as - soon as you discover it. - It also enables you to edit any entries in the {meta} field of - database entries (which sometimes contain HTTP headers, or page - "class" settings). - And the fourth possible action is to easily rename the page (with - letting ewiki adjust all links to it without further intervention). - - - - SearchAndReplace - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Is a powerful text/content replacement tool. It features regular - expression matching, but can also be used as any other simple string - replace-all tool. - - - - SearchCache - ¯¯¯¯¯¯¯¯¯¯¯ - This tool is intended to create 'shadow pages' (or 'ghost pages') - for ewiki internal/generated pages (the ["page"] plugins), which - usually weren't found by the PageSearch and PowerSearch. This - admin plugin just innovocates those page plugins and puts their - html output into the database (which then can is found by the - search functions, but is never displayed, because the page plugins - still have precedence over that faked database content). - - - -other plugins -¯¯¯¯¯¯¯¯¯¯¯¯¯ -These plugins actually implement some stuff, one usually should do inside -of the yoursite.php ewiki wrapper script. - - - - plugins/debug/ - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Eventually contains debug plugins. - - - - plugins/auth/ - ¯¯¯¯¯¯¯¯¯¯¯¯¯ - Contains various (example and ready to use) plugins for the - ewiki_auth() interfaces. This directory contains its own - README.auth, which describes the _PROTECTED_MODE, the _auth API and - available sample plugins in detail. - - - - plugins/auth-liveuser/ - ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - Contains the more advanced authentication and permission plugin - bundle for chaining ewiki with the PEAR LiveUser authentication - framework. There is detailed documentation within the README in - this subdirectory. - - - -separate "extra" tarball -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -There are a few plugins and extensions, which are not packaged into the -distributed ewiki tarball for size reasons. You can obtain it from your -favourite dealer, or from our downloads/ directory as "extra-CVS-*" -tarball. - http://erfurtwiki.sourceforge.net/downloads/ - -The package currently just contains a minimal spam filter (which after all -isn't very useful for a Wiki site), but in the future will also provide -additional example/ layouts and some image/graphics/icons for layout -beatification purposes. - - - -Updates + How to deal with tweaked code -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -If you ever happen to recode parts of a plugin, WHICH WE STRONGLY ENCOURAGE -TO DO (to match it better to your needs) - then there is always the risk of -losing your changes as soon as you upgrade and overwrite everything inside -of plugins/ -Therefore it is recommended to create a subdirectory like "local/" where -you copy changed plugins into, then include() them from there instead of -the distributed default from plugins/. So you won't lose your changes and -enhancements if you upgrade to a newer version. You of course should then -check (after updates) if the newer version of a plugin contained -enhancements you'd like to merge with your cutomized version of the earlier -plugin incarnation. - -For the main "ewiki.php" script, things are of course more difficult, as -you will probably always overwrite it when you update your installation. -Best approach is to keep a NOTES file, where you store your patches for -later reinclusion with newer releases, or even to keep always a second -copy of your tweaked "ewiki.php". Much better was of course to send your -changes to the ewiki -dev people so they could merge them into the CVS, -so everybody could enjoy your ideas. - - - - - diff --git a/mods/wiki/doc/ReadOnlyWiki b/mods/wiki/doc/ReadOnlyWiki deleted file mode 100644 index 34dc5d5d9..000000000 --- a/mods/wiki/doc/ReadOnlyWiki +++ /dev/null @@ -1,87 +0,0 @@ - -If you want a read-only Wiki for the public, then there is an easy method -with which you can do that without having to use any ewiki ProtectedMode -plugins. - -You just create two "wrappers". One which allows doesn't allow write -access, and a second which does (with prior HTTP login then of course). -There is also a section in the README which explains this. - - -a locked personal Wiki, without ProtectedMode ---------------------------------------------- - -Using a Wiki to create a personal homepage is of course also possible. It is -just a convinience to use the easy Wiki technics as backend, instead of a -bloated and complicated CMS like PhpNuke or so. - -It was also possible to add an overall Wiki lock, and then to afterwards -some pages as _WRITEABLE by the public. Though currently that code -(see ==plugings/auth/perm_old.php==) is still to be overhauled. - ------ - -The ==ewiki.php== script basically is some sort of library, and it is -possible to build multiple frontends to your Wiki (like the scripts in our -examples/ directory). This not only allows to have multiple layouts -available, but also to have each with a different feature set. - -A ''different feature set'' then could also mean, that you have one wrapper -for the public (which for example wouldn't allow editing), and a second for -yourself, which did (but then required a password; see also -[fragments/funcs/auth.php]). This is useful, if you want a PersonalWiki. - - -a sample public wrapper, that forbids editing ---------------------------------------------- - -<code> -<?php - define("EWIKI_SCRIPT", "public.php?id="); - include("config.php"); - // or include("ewiki.php"); - - #-- disallow some stuff, you wouldn't want visitors to do - unset($ewiki_plugins["action"]["edit"]); - unset($ewiki_plugins["action"]["info"]); -?> -... -<body> - <?php - #-- output page content - echo ewiki_page(); - ?> -</body> -... -</code> - -Often you would want to call this (see EWIKI_SCRIPT) file then "index.php" -instead. - - - -your unrestricted personal wrapper ----------------------------------- - -The wrapper which allows editing of course should be protected with a login. - -<code> -<?php - define("EWIKI_SCRIPT", "admin.php?id="); - include("config.php"); // or include("ewiki.php"); - #-- add some admin stuff - include("plugins/admin/page_searchandreplace.php"); - #-- require a password - include("fragments/funcs/auth.php"); -?> -... -<?php - echo ewiki_page(); -?> -... -</code> - -Please note, the different setting for EWIKI_SCRIPT here. It is not -necessary to keep the name "admin.php" script secret, because it is -already protected by HTTP auth (see the ==.../auth.php== script). - diff --git a/mods/wiki/doc/SetupTool b/mods/wiki/doc/SetupTool deleted file mode 100644 index 4b05db5a9..000000000 --- a/mods/wiki/doc/SetupTool +++ /dev/null @@ -1,116 +0,0 @@ -The small console/terminal tool 'setup' allows to configure used -plugins and settings like the web-based SetupWizard (t_setupwiz) -does. Most Linux users will find it more user-friendly, while it -is rather complicated to get running under Windows (you need a -dialog.exe or whiptail.exe with Cygwin probably). - -Basically you can enable and disable plugins and change their -configuration settings and constants, and then let this tool -generate a .ini file from it or write out a "config.php" script. -It is also possible to generate a MonsterWiki script (where all -plugins and settings are in one .php include) using this tool. - -Navigation through the menu is constrained by your "dialog" tool -version. There are different available, and some versions are -more deviated from the standard. The console "dialog" works best -(displays help) and so you may want to get run it in a terminal -and disable the Xdialog version by using following command: - - NO_X=1 php ./tools/setup - -It does not work together with "kdialog" and the new "zenity" -plague. Both were designed incompatible to the existing dialog -interface standard, and it's simply not possible to take them -into account. The "lxdialog" tool is used as last resort, but of -course won't feel all too user-friendly. - - -Navigation ----------- - -You often come back to the main menu using the [Cancel] button -or ESC (press twice or wait on the console/terminal). - -The tool can be exited using the DONE entry in the main menu or -by pressing Ctrl-C from the invoking terminal. The latter is -useful, if you don't want the changes you made to be stored into -the backup data file (./tools/setup.dat). - - -.ini or .php ------------- - -It is recommended to always save an .ini file first, because -that is slightly more reliable. The setup tool automatically -keeps a backup of the last session and all made changes, but -this is sometimes not what you want, because any made test -changes will live on. - -Use the .ini file with the fragments/ini.php plugin loader, which -takes care to load all plugins (and the core) after setting all -configuration constants an variables. - -A config.php script is of course senseful to generate, after -you feel finished. You may want to make a backup of your old -config.php script, before you let the setup tool OVERWRITE your -existing file. - - -Bugs ----- - -In the plugin selection lists, pressing the [Help] button will -make all made crosses vanish again. That's a problem with the -way how dialog communicates with the calling script (any made -changes cannot be detected). - -Some categories in the plugin overview cannot be selected, -because they do not contain available plugins (all that are -contained are then typically hidden - deprecated or excluded). -This visual glitch is not worked around, because it's a too -minor issue. - - -Notes ------ - -More informations about the sorting of ewiki plugins can be -found in doc/PluginMetaFiles. - -The recent settings are kept in a file called "tools/setup.dat" -nearby the script. - - -Running non-locally -------------------- - -If you have a working X11 environment on your web server, and -the Xdialog utility installed, then you could run this tool -over the network. You must make "setup.dat" and "ewiki.ini" -world-writable or use a setuid wrapper around the calling -script. -Simply create following CGI script "Xsetup.php" in the ewiki -root or tools directory: - - <body bgcolor="#000000" text="#ffffff"> - <?php - /* - start setup script over X11, - - needs Xdialog on the web server - - you must enable connections with "xhost +1.2.3.4" (server IP) - */ - - echo "Enable X11 connections, using 'xhost +$_SERVER[SERVER_ADDR]'.\n<hr>\n<br>\n"; - flush(); - ob_implicit_flush(1); - - putenv("DISPLAY=$_SERVER[REMOTE_ADDR]:0"); - putenv("DIALOG=Xdialog"); - system("./tools/setup"); - - ?> - </body> - -Call this after allowing (xhost + ) remote, unauthenticated -connections. - diff --git a/mods/wiki/doc/UPGRADE b/mods/wiki/doc/UPGRADE deleted file mode 100644 index 234172d16..000000000 --- a/mods/wiki/doc/UPGRADE +++ /dev/null @@ -1,7 +0,0 @@ -There are only minor incompatibilities in the R1.02 series of ewiki. (Two -renamed plugins.) - -If you updated from R1.01c or earlier, then use the "tools/upgrade-101d" -to convert the plugin file names in your 'config.php' file. It also works -for later versions and is supposed to collect all future changes (= never -hurts to run it). diff --git a/mods/wiki/doc/WikiXmlRpc b/mods/wiki/doc/WikiXmlRpc deleted file mode 100644 index e80d1b72a..000000000 --- a/mods/wiki/doc/WikiXmlRpc +++ /dev/null @@ -1,172 +0,0 @@ -+ interwikimapquery - -The XmlPlusRpc (XML-RPC compatible) interface of ewiki allows to query -information for the Wiki using a standardized interface (remote procedure -calls) to access the database indirectly. Speaking of standards, there are -two, and ewiki adheres to the JspWiki:WikiRPCInterface, because that is -believed to be more well-thought than the implementations in UseMod, -MoinMoin and of course TWiki (as usual). - -All <string> and <base64> values passed back and forth are supposed to be -UTF-8 encoded for compliant access (even if ewiki itself does not support -it). - -Interface methods so far: - -: wiki.getRPCVersionSupported() : - returns (int) 1 -: wiki.getPage(pagename) : - returns raw WikiSource for the given page (current version) in <base64> -: wiki.getPageVersion(pagename, version) : - returns raw WikiSource for the given page (given version) in <base64> -: wiki.getPageHtml(pagename) : - returns rendered WikiPage for the given name (current version) in <base64> -: wiki.getPageHtmlVersion(pagename, version) : - returns rendered WikiPage for the given name (specified version) in <base64> -: wiki.getPageInfo(pagename) : - returns [.#MetaDataStruct] for the WikiPage (current version), -: wiki.getPageInfoVersion(pagename, version) : - returns [.#MetaDataStruct] for the WikiPage (specified version) -: wiki.getAllPages() : - returns an array of page names -: wiki.getRecentChanges(since_timestamp) - returns an array of [.#MetaDataStruct]s -: wiki.listLinks(pagename) : - returns one [.#ListLinksStruct] for the given page (current version) -: wiki.listLinksVersion(pagename, version) : - returns one [.#ListLinksStruct] for the given page (requested version) -: wiki.putPage(pagename, content) : - not enabled (not implemented) - - -! ~MetaDataStruct [#MetaDataStruct] - -The wiki.getPageInfo() and wiki.getRecentChanges() calls return a <struct> -(or an array of) as follows: - -<code> - array( - "name" => ... as <string>, - "lastModified" => ... in <dateTime.iso8601>, - "author" => ... as <string>, - "version" => ... as <int>, - ) -</code> - -Or the same in XmlPlusRpc notation: - -<pre> -<value> - <struct> - <member> - <name>name</name> - <value><string>PageName</string></value> - </member> - <member> - <name>lastModified</name> - <value><dateTime.iso8601>20010909T01:46:40</dateTime.iso8601></value> - </member> - <member> - <name>author</name> - <value><string>AuthorNamePage</string></value> - </member> - <member> - <name>version</name> - <value><int>1</int></value> - </member> - </struct> -</value> -</pre> - ----- - -! ~ListLinksStruct [#ListLinksStruct] - -Only the wiki.listLinks() method returns this result <struct>: - -<code> - array( - "page" => URL or pagename <string>, - "type" => "external" or "local" <string>, - "href" => local (WikiLinks) or absolute URL <string>, - ) -</code> - -Or in XmlPlusRpc notation: - -<pre> -<value><array> - <data> - <value><struct> - <member> - <name>page</name> - <value><string>PageName</string></value> - </member> - <member> - <name>type</name> - <value><string>local</string></value> - </member> - <member> - <name>href</name> - <value><string>/cgi-bin/wiki.cgi?PageName</string></value> - </member> - </struct></value> - <value><struct> - <member> - <name>page</name> - <value><string>http://www.example.com/</string></value> - </member> - <member> - <name>type</name> - <value><string>external</string></value> - </member> - <member> - <name>href</name> - <value><string>http://www.example.com/</string></value> - </member> - </struct></value> - ... - </data> -</array></value> -</pre> - ------- - - -!! known WikiRpcImplementations - -There are two differing ''standards'' for the Wiki XmlPlusRpc interface. - -| version | WikiServers implementing it | WikiClients using it | implementation details | -| old | [MoinMoin:], [UseMod:], [TWiki:] | [MetaWiki:WikiGateway] | sporadically uses additional URL encoding for parameter and result <string>s that are already UTF-8 encoded | -| new | [JspWiki:], [ErfurtWiki:] | ??? | all <string>s and <base64> ''binary'' data is encoded as UTF-8, in __all__ parameters and in result values | - -So all further occourences of <string> and <base64> actually mean an UTF-8 -encoded string representation, that additionally is sometimes urlencoded(). - - -! the interface - -The current version of the interface is 1, everything else should be -considered as extension of the mentioned WikiWare. - -All WikiXmlRpc methods have a class prefix of "__wiki.__" to their -methodName(). - -|ver | XmlPlusRpc methodName() | input parameter types | result values | WikiWare notes | -|1 | getRPCVersionSupported() | - | <int> 1 | - | -|1 | getPage(pagename) | <string> | <base64>WikiPageSource</base64> | - | -|1 | getPageVersion(pagename, version) | <string>, <int> | <base64>WikiPageSource</base64> | - | -|1 | getPageHtml(pagename) | <string> | <base64>HtmlRenderedWikiPage</base64> | - | -|1 | getPageHtmlVersion(pagename, version) | <string>, <int> | <base64>HtmlRenderedWikiPage</base64> | - | -|1 | getPageInfo(pagename) | <string> | a [.#MetaDataStruct "MetaDataStruc"] | - | -|1 | getPageInfoVersion(pagename, version) | <string>, <int> | a [.#MetaDataStruct "MetaDataStruc"] | - | -|1 | getAllPages() | - | an <array> of PageName <string>s | - | -|1 | getRecentChanges(since_timestamp) | <dateTime.iso8601>, since_timestamp represents the time point from which one would like to get the list of changed pages | returns an <arrra> of [.#MetaDataStruct "meta data <struct>s"] like the one emitted by wiki.getPageInfo() | - | -|1 | listLinks(pagename) | <string> | returns an [.#ListLinksStruct "<array> of listLinks <struct>s"] | wiki.listLinks() returns the links from a page, internal and external (WWW) ones; it is unknown which of the implementations also return image links, and links to not yet existing internal pages (QuestionMarkLinks) | -|1 | putPage(pagename, content) | <string>, <base64> content to be saved as new page source | returns <boolean>1</boolean> on success, else the false value | not implemented/enabled in all Wikis | -|2 | putPage(pagename, content, attributes) | <string>, <base64> content, struct> attributes | - | where the attributes struct shall have parameters like {comment} and {minoredit} | -|2 | getBackLinks(pagename) | <string> | <array> of <string>s like for getAllPages() | proposed extension for [JspWiki:] | -|x | filterData(data, contentType, params) | <base64>, <string>, <struct> | returns <struct> with { "data" => <base64/>, "contentType" => <string/> } | a [TWiki:] extension, see [TWiki:XmlRpcFilteringPipe] | -|x | listLinksVersion(pagename, version) | - | - | only implemented in [ErfurtWiki:], works like wiki.listLinks() | - diff --git a/mods/wiki/ewiki.php b/mods/wiki/ewiki.php deleted file mode 100644 index f88d89855..000000000 --- a/mods/wiki/ewiki.php +++ /dev/null @@ -1,3981 +0,0 @@ -<?php @define("EWIKI_VERSION", "R1.02b"); - -/* - ErfurtWiki - a pretty flexible, fast and user-friendly wiki framework - ¯¯¯¯¯¯¯¯¯¯ - Is PUBLIC DOMAIN (no license, no warranty); feel free to redistribute - under any other license, if you want. (c) 2003-2005 WhoEver wants to. - - project+help: - http://erfurtwiki.sourceforge.net/ - http://ewiki.berlios.de/ - lead by: - Mario Salzer <mario*erphesfurt·de> - Andy Fundinger <andy*burgiss·com> - - call it from within yoursite.php / layout script like this: - <?php - include("ewiki.php"); - $CONTENT = ewiki_page(); - ? > - <HTML>...<BODY>... - <?php - echo $CONTENT; - ? > - ...</HTML> -*/ - -#-- for future backwards compatibility to R1.02b (temporary file dependencies) -if (!function_exists("ewiki_page_edit")) { include_once("plugins/edit.php"); } -if (!function_exists("ewiki_format")) { include_once("plugins/format.php"); } -if (!function_exists("ewiki_binary")) { include_once("plugins/feature/binary.php"); } -if (!function_exists("ewiki_author")) { include_once("plugins/misc.php"); } -if (!class_exists("ewiki_database_mysql")) { include_once("plugins/db/mysql.php"); } - - #-------------------------------------------------------- config --- - - #-- this disables most PHPs debugging (_NOTICE) messages - error_reporting(0x0000377 & error_reporting()); -# error_reporting(E_ALL^E_NOTICE); // development - - #-- the location of your ewiki-wrapper script - define("EWIKI_SCRIPT", "?id="); # relative to docroot -# define("EWIKI_SCRIPT_URL", "http://../?id="); # absolute URL - - #-- change to your needs (site lang) - define("EWIKI_NAME", "UnnamedWiki"); # Wiki title - define("EWIKI_PAGE_INDEX", "ATutorWiki"); # default page - define("EWIKI_PAGE_PRETTY_URL", 'mods\/wiki\/index.php'); #pretty URL format of this page - define("EWIKI_PAGE_LIST", "PageIndex"); - define("EWIKI_PAGE_SEARCH", "SearchPages"); - define("EWIKI_PAGE_NEWEST", "NewestPages"); - define("EWIKI_PAGE_HITS", "MostVisitedPages"); - define("EWIKI_PAGE_VERSIONS", "MostOftenChangedPages"); - define("EWIKI_PAGE_UPDATES", "UpdatedPages"); # like RecentChanges - - #-- default settings are good settings - most often ;) - #- look & feel - define("EWIKI_PRINT_TITLE", 2); # <h2>WikiPageName</h2> on top - define("EWIKI_SPLIT_TITLE", 0); # <h2>Wiki Page Name</h2> - define("EWIKI_CONTROL_LINE", 1); # EditThisPage-link at bottom - define("EWIKI_LIST_LIMIT", 20); # listing limit - #- behaviour - define("EWIKI_AUTO_EDIT", 1); # edit box for non-existent pages - define("EWIKI_EDIT_REDIRECT", 1); # redirect after edit save - define("EWIKI_DEFAULT_ACTION", "view"); # (keep!) - define("EWIKI_CASE_INSENSITIVE", 1); # wikilink case sensitivity - define("EWIKI_HIT_COUNTING", 1); - define("EWIKI_RESOLVE_DNS", 1); # gethostbyaddr() when editing - define("UNIX_MILLENNIUM", 1000000000); - #- rendering - define("EWIKI_ALLOW_HTML", 0); # often a very bad idea - define("EWIKI_HTML_CHARS", 1); # allows for È - define("EWIKI_ESCAPE_AT", 1); # "@" -> "@" - #- http/urls - define("EWIKI_SUBPAGE_LONGTITLE", 0); - define("EWIKI_SUBPAGE_START", ".:/"); # set to "" to disable [.Sub] getting a link to [CurrentPage.Sub] -# define("EWIKI_SUBPAGE_CHARS", ".:/-!"); - define("EWIKI_HTTP_HEADERS", 1); # most often a good thing - define("EWIKI_NO_CACHE", 1); # browser+proxy shall not cache - define("EWIKI_URLENCODE", 1); # disable when _USE_PATH_INFO - define("EWIKI_URLDECODE", 1); -#new! define("EWIKI_URL_UTF8", 1); # fix UTF-8 parameters - define("EWIKI_USE_PATH_INFO", 1); - define("EWIKI_USE_ACTION_PARAM", 1); # 2 for alternative link style - define("EWIKI_ACTION_SEP_CHAR", "/"); - define("EWIKI_ACTION_TAKE_ASIS", 1); - define("EWIKI_UP_PAGENUM", "n"); # _UP_ means "url parameter" - define("EWIKI_UP_PAGEEND", "e"); - define("EWIKI_UP_BINARY", "binary"); - define("EWIKI_UP_UPLOAD", "upload"); - define("EWIKI_UP_PARENTID", "parent_page"); - define("EWIKI_UP_LISTLIM", "limit"); - #- other stuff - define("EWIKI_DEFAULT_LANG", "en"); - define("EWIKI_CHARSET", "ISO-8859-1"); # nothing else supported - #- user permissions - define("EWIKI_PROTECTED_MODE", 0); # disable funcs + require auth - define("EWIKI_PROTECTED_MODE_HIDING", 0); # hides disallowed actions - define("EWIKI_AUTH_DEFAULT_RING", 3); # 0=root 1=priv 2=user 3=view - define("EWIKI_AUTO_LOGIN", 1); # [auth_query] on startup - - #-- allowed WikiPageNameCharacters - define("EWIKI_CHARS_L", "a-z_µ¤ß-ÿ$"); # \337-\377 - define("EWIKI_CHARS_U", "A-Z0-9À-Þ"); # \300-\336 - define("EWIKI_CHARS", EWIKI_CHARS_L.EWIKI_CHARS_U); - - #-- database - @define("EWIKI_DB_TABLE_NAME", "ewiki"); # MySQL / ADOdb - @define("EWIKI_DBFILES_DIRECTORY", "/tmp"); # see "db_flat_files.php" - define("EWIKI_DBA", "/tmp/ewiki.db3"); # see "db_dba.php" - define("EWIKI_DBQUERY_BUFFER", 512*1024); # 512K - define("EWIKI_INIT_PAGES", "./init-pages"); # for initialization - - define("EWIKI_DB_F_TEXT", 1<<0); - define("EWIKI_DB_F_BINARY", 1<<1); - define("EWIKI_DB_F_DISABLED", 1<<2); - define("EWIKI_DB_F_HTML", 1<<3); - define("EWIKI_DB_F_READONLY", 1<<4); - define("EWIKI_DB_F_WRITEABLE", 1<<5); - define("EWIKI_DB_F_APPENDONLY", 1<<6); - define("EWIKI_DB_F_SYSTEM", 1<<7); - define("EWIKI_DB_F_PART", 1<<8); - define("EWIKI_DB_F_MINOR", 1<<9); - define("EWIKI_DB_F_HIDDEN", 1<<10); - define("EWIKI_DB_F_ARCHIVE", 1<<11); - define("EWIKI_DB_F_EXEC", 1<<17); - define("EWIKI_DB_F_TYPE", EWIKI_DB_F_TEXT | EWIKI_DB_F_BINARY | EWIKI_DB_F_DISABLED | EWIKI_DB_F_SYSTEM | EWIKI_DB_F_PART); - define("EWIKI_DB_F_ACCESS", EWIKI_DB_F_READONLY | EWIKI_DB_F_WRITEABLE | EWIKI_DB_F_APPENDONLY); - define("EWIKI_DB_F_COPYMASK", EWIKI_DB_F_TYPE | EWIKI_DB_F_ACCESS | EWIKI_DB_F_HIDDEN | EWIKI_DB_F_HTML | EWIKI_DB_F_ARCHIVE); - - define("EWIKI_DBFILES_NLR", '\\n'); - define("EWIKI_DBFILES_ENCODE", 0 || (DIRECTORY_SEPARATOR != "/")); - define("EWIKI_DBFILES_GZLEVEL", "2"); - - #-- internal, auto-discovered - define("EWIKI_ADDPARAMDELIM", (strstr(EWIKI_SCRIPT,"?") ? "&" : "?")); - define("EWIKI_SERVER", ($_SERVER["HTTP_HOST"] ? $_SERVER["HTTP_HOST"] : $_SERVER["SERVER_NAME"]) . ( ($_SERVER["SERVER_PORT"] != "80") ? (":" . $_SERVER["SERVER_PORT"]) : "")); - define("EWIKI_BASE_URL", (@$_SERVER["HTTPS"] ? "https" : "http") . "://" . EWIKI_SERVER . substr(realpath(dirname(__FILE__)), strlen(realpath($_SERVER["DOCUMENT_ROOT"]))) . "/"); # URL to ewiki dir - define("EWIKI_BASE_DIR", dirname(__FILE__)); - - #-- binary content (images) - define("EWIKI_ENGAGE_BINARY", 1); - @define("EWIKI_SCRIPT_BINARY", /*"/binary.php?binary="*/ ltrim(strtok(" ".EWIKI_SCRIPT,"?"))."?".EWIKI_UP_BINARY."=" ); - define("EWIKI_CACHE_IMAGES", 1 &&!headers_sent()); - define("EWIKI_IMAGE_MAXSIZE", 64 *1024); - define("EWIKI_IMAGE_MAXWIDTH", 3072); - define("EWIKI_IMAGE_MAXHEIGHT", 2048); - define("EWIKI_IMAGE_MAXALLOC", 1<<19); - define("EWIKI_IMAGE_RESIZE", 1); - define("EWIKI_IMAGE_ACCEPT", "image/jpeg,image/png,image/gif,application/x-shockwave-flash"); - define("EWIKI_IDF_INTERNAL", "internal://"); - define("EWIKI_ACCEPT_BINARY", 0); # for arbitrary binary data files - - #-- misc - define("EWIKI_TMP", isset($_SERVER["TEMP"]) ? $_SERVER["TEMP"] : "/tmp"); - define("EWIKI_VAR", "./var"); # should be world-writable - define("EWIKI_LOGLEVEL", -1); # 0=error 1=warn 2=info 3=debug - define("EWIKI_LOGFILE", "/tmp/ewiki.log"); - - #-- plugins (tasks mapped to function names) - $ewiki_plugins["database"][] = "ewiki_database_mysql"; - $ewiki_plugins["edit_preview"][] = "ewiki_page_edit_preview"; - $ewiki_plugins["render"][] = "ewiki_format"; - $ewiki_plugins["init"][-5] = "ewiki_localization"; - if (EWIKI_ENGAGE_BINARY) - $ewiki_plugins["init"][-1] = "ewiki_binary"; - $ewiki_plugins["handler"][-105] = "ewiki_eventually_initialize"; - $ewiki_plugins["handler"][] = "ewiki_intermap_walking"; - $ewiki_plugins["view_append"][-1] = "ewiki_control_links"; - $ewiki_plugins["view_final"][-1] = "ewiki_add_title"; - $ewiki_plugins["page_final"][] = "ewiki_http_headers"; - $ewiki_plugins["page_final"][99115115] = "ewiki_page_css_container"; - $ewiki_plugins["edit_form_final"][] = "ewiki_page_edit_form_final_imgupload"; - $ewiki_plugins["format_block"]["pre"][] = "ewiki_format_pre"; - $ewiki_plugins["format_block"]["code"][] = "ewiki_format_pre"; - $ewiki_plugins["format_block"]["htm"][] = "ewiki_format_html"; - $ewiki_plugins["format_block"]["html"][] = "ewiki_format_html"; - $ewiki_plugins["format_block"]["comment"][] = "ewiki_format_comment"; - - #-- internal pages - $ewiki_plugins["page"][EWIKI_PAGE_LIST] = "ewiki_page_index"; - $ewiki_plugins["page"][EWIKI_PAGE_NEWEST] = "ewiki_page_newest"; - $ewiki_plugins["page"][EWIKI_PAGE_SEARCH] = "ewiki_page_search"; - if (EWIKI_HIT_COUNTING) $ewiki_plugins["page"][EWIKI_PAGE_HITS] = "ewiki_page_hits"; - $ewiki_plugins["page"][EWIKI_PAGE_VERSIONS] = "ewiki_page_versions"; - $ewiki_plugins["page"][EWIKI_PAGE_UPDATES] = "ewiki_page_updates"; - - #-- page actions - $ewiki_plugins["action"]["edit"] = "ewiki_page_edit"; - $ewiki_plugins["action_always"]["links"] = "ewiki_page_links"; - $ewiki_plugins["action"]["info"] = "ewiki_page_info"; - $ewiki_plugins["action"]["view"] = "ewiki_page_view"; - - #-- helper vars --------------------------------------------------- - $ewiki_config["idf"]["url"] = array("http://", "mailto:", EWIKI_IDF_INTERNAL, "ftp://", "https://", "data:", "irc://", "telnet://", "news://", "chrome://", "file://", "gopher://", "httpz://"); - $ewiki_config["idf"]["img"] = array(".jpeg", ".png", ".jpg", ".gif", ".j2k"); - $ewiki_config["idf"]["obj"] = array(".swf", ".svg"); - - #-- entitle actions - $ewiki_config["action_links"]["view"] = array( - "edit" => "EDITTHISPAGE", # ewiki_t() is called on these - "links" => "BACKLINKS", - "info" => "PAGEHISTORY", - "like" => "LIKEPAGES", - ) + (array)@$ewiki_config["action_links"]["view"]; - $ewiki_config["action_links"]["info"] = array( - "view" => "browse", - "edit" => "fetchback", - ) + (array)@$ewiki_config["action_links"]["info"]; - - #-- variable configuration settings (go into '$ewiki_config') - $ewiki_config_DEFAULTS_tmp = array( - "edit_thank_you" => 1, - "edit_box_size" => "77x17", - "print_title" => EWIKI_PRINT_TITLE, - "split_title" => EWIKI_SPLIT_TITLE, - "control_line" => EWIKI_CONTROL_LINE, - "list_limit" => EWIKI_LIST_LIMIT, - "script" => EWIKI_SCRIPT, - "script_url" => (defined("EWIKI_SCRIPT_URL")?EWIKI_SCRIPT_URL:NULL), - "script_binary" => EWIKI_SCRIPT_BINARY, - "qmark_links" => "0b?", - #-- heart of the wiki -- don't try to read this! ;) - "wiki_pre_scan_regex" => '/ - (?<![!~\\\\]) - ((?:(?:\w+:)*['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+){2,}[\w\d]*(?<!_)) - |\^([-'.EWIKI_CHARS_L.EWIKI_CHARS_U.']{3,}) - |\[ (?:"[^\]\"]+" | \s+ | [^:\]#]+\|)* ([^\|\"\[\]\#]+) (?:\s+ | "[^\]\"]+")* [\]\#] - |(\w{3,9}:\/\/[^\s\[\]\'\"()<>]+[^\s\[\]\'\"()<>!,.\-:;?]) - /x', - "wiki_link_regex" => "\007 [!~\\\\]?( - \#?\[[^<>\[\]\n]+\] | - \w[-_.+\w]+@(\w[-_\w]+[.])+\w{2,} | - \^[-".EWIKI_CHARS_U.EWIKI_CHARS_L."]{3,} | - \b([\w]{3,}:)*([".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L."]+){2,}\#?[\w\d]* | - ([a-z]{2,9}://|mailto:|data:)[^\s\[\]\'\"()<>]+[^\s\[\]\'\"()<>,.!\-:;?] - ) \007x", - #-- rendering ruleset - "wm_indent" => '<div style="margin-left:15px;" class="indent">', - "wm_table_defaults" => 'cellpadding="2" border="1" cellspacing="0"', - "wm_whole_line" => array(">>" => 'div align="right"'), - "wm_max_header"=>3, - "wm_publishing_headers"=>0, - "htmlentities" => array( - "&" => "&", - ">" => ">", - "<" => "<", - ), - "wm_source" => array( - "%%%" => "<br />", - "<br>" => "<br />", - "\t" => " ", - "\n;:" => "\n ", # workaround, replaces the old ;: - ), - "wm_list" => array( - "-" => array('ul type="square"', "", "li"), - "*" => array('ul type="circle"', "", "li"), - "#" => array("ol", "", "li"), - ":" => array("dl", "dt", "dd"), - #<out># ";" => array("dl", "dt", "dd"), - ), - "wm_style" => array( - "'''''" => array("<b><i>", "</i></b>"), - "'''" => array("<b>", "</b>"), - "''" => array("<em>", "</em>"), - "__" => array("<strong>", "</strong>"), - "^^" => array("<sup>", "</sup>"), - "==" => array("<tt>", "</tt>"), - #<off># "___" => array("<i><b>", "</b></i>"), - #<off># "***" => array("<b><i>", "</i></b>"), - #<off># "###" => array("<big><b>", "</b></big>"), - #<broken+bug># "//" => array("<i>", "</i>"), # conflicts with URLs, could only be done with regex - "**" => array("<b>", "</b>"), - "##" => array("<big>", "</big>"), - "µµ" => array("<small>", "</small>"), - ), - "wm_start_end" => array( - #<off># array("[-", "-]", "<s>", "</s>"), - #<off># array("(*", "*)", "<!--", "-->"), - ), - #-- rendering plugins - "format_block" => array( - "html" => array("<html>", "</html>", "html", 0x0000), - "htm" => array("<htm>", "</htm>", "html", 0x0003), - "code" => array("<code>", "</code>", false, 0x0004), - "pre" => array("<pre>", "</pre>", false, 0x0027|4), - "comment" => array("\n<!--", "-->", false, 0x0030), - #<off># "verbatim" => array("<verbatim>", "</verbatim>", false, 0x0030), - ), - "format_params" => array( - "scan_links" => 1, - "html" => EWIKI_ALLOW_HTML, - "mpi" => 1, - ), - ); - #-- copy above settings into real _config[] array - foreach ($ewiki_config_DEFAULTS_tmp as $set => $val) { - if (!isset($ewiki_config[$set])) { - $ewiki_config[$set] = $val; - } - elseif (is_array($val)) foreach ($val as $vali=>$valv) { - if (is_int($vali)) { - $ewiki_config[$set][] = $valv; - } - elseif (!isset($ewiki_config[$set][$vali])) { - $ewiki_config[$set][$vali] = $valv; - } - } - } - $ewiki_config_DEFAULTS_tmp = $valv = $vali = $val = NULL; - - #-- special pre-sets - $ewiki_config["ua"] = "ewiki/".EWIKI_VERSION - . " (".PHP_OS."; PHP/".PHP_VERSION.")" . @$ewiki_config["ua"]; - - - #-- text (never remove the "C" or "en" sections!) - # - $ewiki_t["C"] = (array)@$ewiki_t["C"] + array( - "DATE" => "%a, %d %b %G %T %Z", - "EDIT_TEXTAREA_RESIZE_JS" => '<a href="javascript:ewiki_enlarge()" style="text-decoration:none">+</a><script type="text/javascript"><!--'."\n".'function ewiki_enlarge() {var ta=document.getElementById("ewiki_content");ta.style.width=((ta.cols*=1.1)*10).toString()+"px";ta.style.height=((ta.rows*=1.1)*30).toString()+"px";}'."\n".'//--></script>', - ); - # - $ewiki_t["en"] = (array)@$ewiki_t["en"] + array( - "EDITTHISPAGE" => "EditThisPage", - "APPENDTOPAGE" => "Add to", - "BACKLINKS" => "BackLinks", - "EDITCOMPLETE" => 'Your edit has been saved click <a href="$url">here</a> to see the edited page.', - "PAGESLINKINGTO" => "Pages linking to \$title", - "PAGEHISTORY" => "PageInfo", - "INFOABOUTPAGE" => "Information about page", - "LIKEPAGES" => "Pages like this", - "NEWESTPAGES" => "Newest Pages", - "LASTCHANGED" => "last changed on %c", - "DOESNOTEXIST" => "This page does not yet exist, please click on EditThisPage if you'd like to create it.", - "DISABLEDPAGE" => "This page is currently not available.", - "ERRVERSIONSAVE" => "Sorry, while you edited this page someone else - did already save a changed version. Please go back to the - previous screen and copy your changes to your computers - clipboard to insert it again after you reload the edit - screen.", - "ERRORSAVING" => "An error occoured while saving your changes. Please try again.", - "THANKSFORCONTRIBUTION" => "Thank you for your contribution!", - "CANNOTCHANGEPAGE" => "This page cannot be changed.", - "OLDVERCOMEBACK" => "Make this old version come back to replace the current one", - "PREVIEW" => "Preview", - "SAVE" => "Save", - "CANCEL_EDIT" => "CancelEditing", - "UPLOAD_PICTURE_BUTTON" => "upload picture >>>", - "EDIT_FORM_1" => "It is <a href=\"".EWIKI_SCRIPT."GoodStyle\">GoodStyle</a> - to just start writing. With <a href=\"".EWIKI_SCRIPT."WikiMarkup\">WikiMarkup</a> - you can style your text later.<br />", - "EDIT_FORM_2" => "<br />Please do not write things, which may make other - people angry. And please keep in mind that you are not all that - anonymous in the internet (find out more about your computers - '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' at Google).", - "BIN_IMGTOOLARGE" => "Image file is too large!", - "BIN_NOIMG" => "This is no image file (inacceptable file format)!", - "FORBIDDEN" => "You are not authorized to access this page.", - ); - # - $ewiki_t["es"] = (array)@$ewiki_t["es"] + array( - "EDITTHISPAGE" => "EditarEstaPágina", - "BACKLINKS" => "EnlacesInversos", - "PAGESLINKINGTO" => "Páginas enlazando \$title", - "PAGEHISTORY" => "InfoPágina", - "INFOABOUTPAGE" => "Información sobre la página", - "LIKEPAGES" => "Páginas como esta", - "NEWESTPAGES" => "Páginas más nuevas", - "LASTCHANGED" => "última modificación %d/%m/%Y a las %H:%M", - "DOESNOTEXIST" => "Esta página aún no existe, por favor eliga EditarEstaPágina si desea crearla.", - "DISABLEDPAGE" => "Esta página no está disponible en este momento.", - "ERRVERSIONSAVE" => "Disculpe, mientras editaba esta página alguién más - salvó una versión modificada. Por favor regrese a - a la pantalla anterior y copie sus cambios a su computador - para insertalos nuevamente después de que cargue - la pantalla de edición.", - "ERRORSAVING" => "Ocurrió un error mientras se salvavan sus cambios. Por favor intente de nuevo.", - "THANKSFORCONTRIBUTION" => "Gracias por su contribución!", - "CANNOTCHANGEPAGE" => "Esta página no puede ser modificada.", - "OLDVERCOMEBACK" => "Hacer que esta versión antigua regrese a remplazar la actual", - "PREVIEW" => "Previsualizar", - "SAVE" => "Salvar", - "CANCEL_EDIT" => "CancelarEdición", - "UPLOAD_PICTURE_BUTTON" => "subir gráfica >>>", - "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."BuenEstilo\">BuenEstilo</a> es - escribir lo que viene a su mente. No se preocupe mucho - por la apariencia. También puede agregar <a href=\"".EWIKI_SCRIPT."ReglasDeMarcadoWiki\">ReglasDeMarcadoWiki</a> - más adelante si piensa que es necesario.<br />", - "EDIT_FORM_2" => "<br />Por favor no escriba cosas, que puedan - enfadar a otras personas. Y por favor tenga en mente que - usted no es del todo anónimo en Internet - (encuentre más sobre - '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' de su computador con Google).", - "BIN_IMGTOOLARGE" => "¡La gráfica es demasiado grande!", - "BIN_NOIMG" => "¡No es un archivo con una gráfica (formato de archivo inaceptable)!", - "FORBIDDEN" => "No está autorizado para acceder a esta página.", - ); - # - $ewiki_t["de"] = (array)@$ewiki_t["de"] + array( - "EDITTHISPAGE" => "DieseSeiteÄndern", - "APPENDTOPAGE" => "Ergänze", - "BACKLINKS" => "ZurückLinks", - "PAGESLINKINGTO" => "Verweise zur Seite \$title", - "PAGEHISTORY" => "SeitenInfo", - "INFOABOUTPAGE" => "Informationen über Seite", - "LIKEPAGES" => "Ähnliche Seiten", - "NEWESTPAGES" => "Neueste Seiten", - "LASTCHANGED" => "zuletzt geändert am %d.%m.%Y um %H:%M", - "DISABLEDPAGE" => "Diese Seite kann momentan nicht angezeigt werden.", - "ERRVERSIONSAVE" => "Entschuldige, aber während Du an der Seite - gearbeitet hast, hat bereits jemand anders eine geänderte - Fassung gespeichert. Damit nichts verloren geht, browse bitte - zurück und speichere Deine Änderungen in der Zwischenablage - (Bearbeiten->Kopieren) um sie dann wieder an der richtigen - Stelle einzufügen, nachdem du die EditBoxSeite nocheinmal - geladen hast.<br /> - Vielen Dank für Deine Mühe.", - "ERRORSAVING" => "Beim Abspeichern ist ein Fehler aufgetreten. Bitte versuche es erneut.", - "THANKSFORCONTRIBUTION" => "Vielen Dank für Deinen Beitrag!", - "CANNOTCHANGEPAGE" => "Diese Seite kann nicht geändert werden.", - "OLDVERCOMEBACK" => "Diese alte Version der Seite wieder zur Aktuellen machen", - "PREVIEW" => "Vorschau", - "SAVE" => "Speichern", - "CANCEL_EDIT" => "ÄnderungenVerwerfen", - "UPLOAD_PICTURE_BUTTON" => "Bild hochladen >>>", - "EDIT_FORM_1" => "Es ist <a href=\"".EWIKI_SCRIPT."GuterStil\">GuterStil</a>, - einfach drauf los zu tippen. Mit den <a href=\"".EWIKI_SCRIPT."FormatierungsRegeln\">FormatierungsRegeln</a> - kannst du den Text später noch umgestalten.<br />", - "EDIT_FORM_2" => "<br />Bitte schreib keine Dinge, die andere Leute - verärgern könnten. Und bedenke auch, daß es schnell auf - dich zurückfallen kann wenn du verschiedene andere Dinge sagst (mehr Informationen zur - '<a href=\"http://google.de/search?q=computer+IP+adresse\">IP Adresse</a>' - deines Computers findest du bei Google).", - ); - $ewiki_t["nl"] = (array)@$ewiki_t["nl"] + array( - "EDITTHISPAGE" => "BewerkPagina", - ); - - #-- InterWiki:Links - $ewiki_config["interwiki"] = (array)@$ewiki_config["interwiki"] + - array( - "javascript" => "", # this actually protects from javascript: links - "url" => "", - "jump" => "", # fallback; if jump plugin isn't loaded -# "self" => "this", - "this" => defined("EWIKI_SCRIPT_URL")?EWIKI_SCRIPT_URL:EWIKI_SCRIPT, - // real entries: - "ErfurtWiki" => "http://erfurtwiki.sourceforge.net/", - "InterWiki" => "MetaWiki", - "MetaWiki" => "http://sunir.org/apps/meta.pl?", - "Wiki" => "WardsWiki", - "WardsWiki" => "http://www.c2.com/cgi/wiki?", - "WikiFind" => "http://c2.com/cgi/wiki?FindPage&value=", - "WikiPedia" => "http://www.wikipedia.com/wiki.cgi?", - "MeatBall" => "MeatballWiki", - "MeatballWiki" => "http://www.usemod.com/cgi-bin/mb.pl?", - "UseMod" => "http://www.usemod.com/cgi-bin/wiki.pl?", - "CommunityWiki" => "http://www.emacswiki.org/cgi-bin/community/", - "WikiFeatures" => "http://wikifeatures.wiki.taoriver.net/moin.cgi/", - "PhpWiki" => "http://phpwiki.sourceforge.net/phpwiki/index.php3?", - "LinuxWiki" => "http://linuxwiki.de/", - "OpenWiki" => "http://openwiki.com/?", - "Tavi" => "http://andstuff.org/tavi/", - "TWiki" => "http://twiki.sourceforge.net/cgi-bin/view/", - "MoinMoin" => "http://www.purl.net/wiki/moin/", - "Google" => "http://google.com/search?q=", - "ISBN" => "http://www.amazon.com/exec/obidos/ISBN=", - "icq" => "http://www.icq.com/", - ); - -// end of config - - - - -#-------------------------------------------------------------------- init --- - - -#-- bring up database backend -if (!isset($ewiki_db) && ($pf = $ewiki_plugins["database"][0])) { - if (class_exists($pf)) { - $ewiki_db = new $pf; - } - elseif (function_exists($pf)) { - include("plugins/db/oldapi.php"); // eeeyk! temporary workaround! - } -} - -#-- init stuff, autostarted parts (done a 2nd time inside ewiki_page) -if ($pf_a = $ewiki_plugins["init"]) { - ksort($pf_a); - foreach ($pf_a as $pf) { - $pf($GLOBALS); - } - unset($ewiki_plugins["init"]); -} - - - -#-------------------------------------------------------------------- main --- - -/* This is the main function, which you should preferrably call to - integrate the ewiki into your web site; it chains to most other - parts and plugins (including the edit box). - If you do not supply the requested pages "$id" we will fetch it - from the pre-defined possible URL parameters. -*/ -function ewiki_page($id=false) { - - global $ewiki_links, $ewiki_plugins, $ewiki_ring, $ewiki_t, - $ewiki_errmsg, $ewiki_data, $ewiki_title, $ewiki_id, - $ewiki_action, $ewiki_config; - - #-- output str - $o = ""; - - #-- selected page - if (!strlen($id)) { - $id = ewiki_id(); - } - - #-- page action - $action = EWIKI_DEFAULT_ACTION; - if ($delim = strpos($id, EWIKI_ACTION_SEP_CHAR)) { - $a = substr($id, 0, $delim); - if (EWIKI_ACTION_TAKE_ASIS || in_array($a, $ewiki_plugins["action"]) || in_array($a, $ewiki_plugins["action_always"])) { - $action = rawurlencode($a); - $id = substr($id, $delim + 1); - } - } - - if (EWIKI_USE_ACTION_PARAM && isset($_REQUEST["action"])) { - $action = rawurlencode($_REQUEST["action"]); - } - $ewiki_data = array(); - $ewiki_id = $id; - $ewiki_title = ewiki_split_title($id); - $ewiki_action = $action; - - #-- more initialization - if ($pf_a = @$ewiki_plugins["init"]) { - ksort($pf_a); - foreach ($pf_a as $pf) { - $o .= $pf(); - } - unset($ewiki_plugins["init"]); - } - #-- micro-gettext stub (for upcoming/current transition off of ewiki_t) - if (!function_exists("_")) { - function _($text) { return($text); } - function gettext($text) { return($text); } - } - - #-- fetch from db - $version = false; - if (!isset($_REQUEST["content"]) && ($version = 0 + @$_REQUEST["version"])) { - $ewiki_config["forced_version"] = $version; - } - $ewiki_data = ewiki_db::GET($id, $version); - $data = &$ewiki_data; - - #-- pre-check if actions exist - $pf_page = ewiki_array($ewiki_plugins["page"], $id); - - #-- edit <form> or info/ page for non-existent and empty pages - if (($action==EWIKI_DEFAULT_ACTION) && empty($data["content"]) && empty($pf_page)) { - if ($data["version"] >= 2) { - $action = "info"; - } - elseif (EWIKI_AUTO_EDIT) { - $action = "edit"; - } - else { - $data["content"] = ewiki_t("DOESNOTEXIST"); - } - } - - #-- internal "create" action / used for authentication requests - if (($action == "edit")&&(($data["version"]==0) && !isset($pf_page))) { - $ewiki_config["create"] = $id; - } - - #-- require auth - if (EWIKI_PROTECTED_MODE) { - if (!ewiki_auth($id, $data, $action, $ring=false, $force=EWIKI_AUTO_LOGIN)) { - return($o.=$ewiki_errmsg); - } - } - - #-- handlers - $handler_o = ""; - if ($pf_a = @$ewiki_plugins["handler"]) { - ksort($pf_a); - foreach ($pf_a as $pf_i=>$pf) { - if ($handler_o = $pf($id, $data, $action, $pf_i)) { break; } - } } - - #-- stop here if page is not marked as _TEXT, - # perform authentication then, and let only administrators proceed - if (!$handler_o) { - if (!empty($data["flags"]) && (($data["flags"] & EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT)) { - if (($data["flags"] & EWIKI_DB_F_BINARY) && ($pf = $ewiki_plugins["handler_binary"][0])) { - return($pf($id, $data, $action)); //_BINARY entries handled separately - } - elseif ((!EWIKI_PROTECTED_MODE || !ewiki_auth($id, $data, $action, 0, 1)) && ($ewiki_ring!=0)) { - return(ewiki_t("DISABLEDPAGE")); - } - } - } - - #-- finished by handler - if ($handler_o) { - $o .= $handler_o; - } - #-- actions that also work for static and internal pages - elseif (($pf = @$ewiki_plugins["action_always"][$action]) && function_exists($pf)) { - $o .= $pf($id, $data, $action); - } - #-- internal pages - elseif ($pf_page && function_exists($pf_page)) { - $o .= $pf_page($id, $data, $action); - } - #-- page actions - else { - $pf = @$ewiki_plugins["action"][$action]; - - #-- fallback to "view" action - if (empty($pf) || !function_exists($pf)) { - - $pf = "ewiki_page_view"; - $action = "view"; // we could also allow different (this is a - // catch-all) view variants, but this would lead to some problems - } - - $o .= $pf($id, $data, $action); - } - - #-- error instead of page? - if (empty($o) && $ewiki_errmsg) { - $o = $ewiki_errmsg; - } - - #-- html post processing - if ($pf_a = $ewiki_plugins["page_final"]) { - ksort($pf_a); - foreach ($pf_a as $pf) { - $pf($o, $id, $data, $action); - } - } - - if (EWIKI_ESCAPE_AT && !isset($ewiki_config["@"])) { - $o = str_replace("@", "@", $o); - } - - $ewiki_data = &$data; - unset($ewiki_data["content"]); - return($o); -} - - - -#-- HTTP meta headers -function ewiki_http_headers(&$o, $id, &$data, $action, $saveasfilename=1) { - global $ewiki_t, $ewiki_config; - if (EWIKI_HTTP_HEADERS && !headers_sent()) { - if (!empty($data)) { - if (($uu = @$data["id"]) && $saveasfilename) @header('Content-Disposition: inline; filename="' . urlencode($uu) . '.html"'); - if ($uu = @$data["version"]) @header('Content-Version: ' . $uu); - if ($uu = @$data["lastmodified"]) @header('Last-Modified: ' . gmstrftime($ewiki_t["C"]["DATE"], $uu)); - } - if (EWIKI_NO_CACHE) { - header('Expires: ' . gmstrftime($ewiki_t["C"]["DATE"], UNIX_MILLENNIUM)); - header('Pragma: no-cache'); - header('Cache-Control: no-cache, must-revalidate' . (($ewiki_author||EWIKI_PROTECTED_MODE)?", private":"") ); - # ", private" flag only for authentified users / _PROT_MODE - } - #-- ETag - if ($data["version"] && ($etag=ewiki_etag($data)) || ($etag=md5($o))) { - $weak = "W/" . urlencode($id) . "." . $data["version"]; - header("ETag: \"$etag\""); ###, \"$weak\""); - header("X-Server: $ewiki_config[ua]"); - } - } -} -function ewiki_etag(&$data) { - return( urlencode($data["id"]) . ":" . dechex($data["version"]) . ":ewiki:" . - dechex(crc32($data["content"]) & 0x7FFFBFFF) ); -} - - - -#-- encloses whole page output with a descriptive <div> -function ewiki_page_css_container(&$o, &$id, &$data, &$action) { - $sterilized_id = trim(preg_replace('/[^\w\d]+/', "-", $id), "-"); - $sterilized_id = preg_replace('/^(\d)/', 'page$1', $sterilized_id); - $o = "<div class=\"wiki $action $sterilized_id\">\n" . $o . "\n</div>\n"; -} - - - -function ewiki_split_title ($id='', $split=-1, $entities=1) { - if ($split==-1) { - $split = $GLOBALS["ewiki_config"]["split_title"]; - } - strlen($id) or ($id = $GLOBALS["ewiki_id"]); - if ($split) { - $id = preg_replace("/([".EWIKI_CHARS_L."])([".EWIKI_CHARS_U."]+)/", "$1 $2", $id); - } - return($entities ? htmlentities($id) : $id); -} - - - -function ewiki_add_title(&$html, $id, &$data, $action, $go_action="links") { - if (EWIKI_PRINT_TITLE) - $html = "<div class=\"text-head\">\n" - . ewiki_make_title($id, '', 1, $action, $go_action) - . "\n</div>\n" . $html; -} - - -function ewiki_make_title($id='', $title='', $class=3, $action="view", $go_action="links", $may_split=1) { - - global $ewiki_config, $ewiki_plugins, $ewiki_title, $ewiki_id; - - #-- advanced handler - if ($pf = @$ewiki_plugins["make_title"][0]) { - return($pf($title, $class, $action, $go_action, $may_split)); - } - #-- disabled - elseif (!$ewiki_config["print_title"]) { - return(""); - } - - #-- get id - if (empty($id)) { - $id = $ewiki_id; - } - - #-- get title - if (!strlen($title)) { - $title = $ewiki_title; // already in &html; format - } - elseif ($ewiki_config["split_title"] && $may_split) { - $title = ewiki_split_title($title, $ewiki_config["split_title"], 0&($title!=$ewiki_title)); - } - else { - $title = htmlentities($title); - } - - #-- title mangling - if ($pf_a = @$ewiki_plugins["title_transform"]) { - foreach ($pf_a as $pf) { $pf($id, $title, $go_action); } - } - - #-- clickable link or simple headline - if ($class <= $ewiki_config["print_title"]) { - if ($uu = @$ewiki_config["link_title_action"][$action]) { - $go_action = $uu; - } - if ($uu = @$ewiki_config["link_title_url"]) { - $href = $uu; - unset($ewiki_config["link_title_url"]); - } - else { - $href = ewiki_script($go_action, $id); - } - $o = '<a href="' . $href . '">' . ($title) . '</a>'; - } - else { - $o = $title; - } - - // h2.page.title is obsolete; h2.text-title recommended - return('<h2 class="text-title page title">' . $o . '</h2>'); -} - - - - -function ewiki_page_view($id, &$data, $action, $all=1) { - - global $ewiki_plugins, $ewiki_config; - $o = ""; - - #-- render requested wiki page <-- goal !!! - $render_args = array( - "scan_links" => 1, - "html" => (EWIKI_ALLOW_HTML||(@$data["flags"]&EWIKI_DB_F_HTML)), - ); - $o .= '<div class="text-body">' . "\n" - . $ewiki_plugins["render"][0] ($data["content"], $render_args) - . "</div>\n"; - if (!$all) { - return($o); - } - - #-- control line + other per-page info stuff - if ($pf_a = $ewiki_plugins["view_append"]) { - ksort($pf_a); - $o .= "<div class=\"wiki-plugins\">\n"; - foreach ($pf_a as $n => $pf) { $o .= $pf($id, $data, $action); } - $o .= "</div>\n"; - } - if ($pf_a = $ewiki_plugins["view_final"]) { - ksort($pf_a); - foreach ($pf_a as $n => $pf) { $pf($o, $id, $data, $action); } - } - - if (!empty($_REQUEST["thankyou"]) && $ewiki_config["edit_thank_you"]) { - $o = '<div class="text-prefix system-message">' - . ewiki_t("THANKSFORCONTRIBUTION") . "</div>\n" . $o; - } - - if (EWIKI_HIT_COUNTING) { - ewiki_db::HIT($id); - } - - return($o); -} - - - - -#-------------------------------------------------------------------- util --- - - -/* retrieves "$id/$action" string from URL / QueryString / PathInfo, - change this in conjunction with ewiki_script() to customize your URLs - further whenever desired -*/ -function ewiki_id() { - ($id = @$_REQUEST["id"]) or - ($id = @$_REQUEST["name"]) or - ($id = @$_REQUEST["page"]) or - ($id = @$_REQUEST["file"]) or - (EWIKI_USE_PATH_INFO) - and isset($_SERVER["PATH_INFO"]) - and ($_SERVER["PATH_INFO"] != $_SERVER["SCRIPT_NAME"]) // Apache+PHP workaround - and (preg_replace('/\/\d+\/'.EWIKI_PAGE_PRETTY_URL.'/', '', $_SERVER['PATH_INFO']) != '') - and ($id = ltrim($_SERVER["PATH_INFO"], "/")) or - (!isset($_REQUEST["id"])) and ($id = trim(strtok($_SERVER["QUERY_STRING"], "&?;"))); - if (!strlen($id) || ($id=="id=")) { - $id = EWIKI_PAGE_INDEX; - } - (EWIKI_URLDECODE) && ($id = urldecode($id)); - return($id); -} - - - - -/* replaces EWIKI_SCRIPT, works more sophisticated, and - bypasses various design flaws - - if only the first parameter is used (old style), it can contain - a complete "action/WikiPage" - but this is ambigutious - - else $asid is the action, and $id contains the WikiPageName - - $ewiki_config["script"] will now be used in favour of the constant - - needs more work on _BINARY, should be a separate function -*/ -function ewiki_script($asid, $id=false, $params="", $bin=0, $html=1, $script=NULL) { - - global $ewiki_config, $ewiki_plugins; - - #-- get base script url from config vars - if (empty($script)) { - $script = &$ewiki_config[!$bin?"script":"script_binary"]; - } - $alt_style = (EWIKI_USE_ACTION_PARAM >= 2); - $ins_prefix = (EWIKI_ACTION_TAKE_ASIS); - - #-- separate $action and $id for old style requests - if ($id === false) { - if (strpos($asid, EWIKI_ACTION_SEP_CHAR) !== false) { - $asid = strtok($asid, EWIKI_ACTION_SEP_CHAR); - $id = strtok("\000"); - } - else { - $id = $asid; - $asid = ""; - } - } - - #-- prepare params - if (is_array($params)) { - $uu = $params; - $params = ""; - if ($uu) foreach ($uu as $k=>$v) { - $params .= (strlen($params)? "&" : "") . rawurlencode($k) . "=" . rawurlencode($v); - } - } - #-- use action= parameter instead of prefix/ - if ($alt_style) { - $params = "action=$asid" . (strlen($params)? "&": "") . $params; - if (!$ins_prefix) { - $asid = ""; - } - } - - #-- workaround slashes in $id - if (empty($asid) && (strpos($id, EWIKI_ACTION_SEP_CHAR) !== false) && !$bin && $ins_prefix) { - $asid = EWIKI_DEFAULT_ACTION; - } - /*paranoia*/ $asid = trim($asid, EWIKI_ACTION_SEP_CHAR); - - #-- make url - if (EWIKI_URLENCODE) { - $id = urlencode($id); - $asid = urlencode($asid); - } - else { - // only urlencode &, %, ? for example - } - $url = $script; - if ($asid) { - $id = $asid . EWIKI_ACTION_SEP_CHAR . $id; #= "action/PageName" - } - if (strpos($url, "%s") !== false) { - $url = str_replace("%s", $id, $url); - } - else { - $url .= $id; - } - - #-- add url params - if (strlen($params)) { - $url .= (strpos($url,"?")!==false ? "&":"?") . $params; - } - - #-- fin - if ($html) { - $url = str_replace("&", "&", $url); - } - return($url); -} - - -/* this ewiki_script() wrapper is used to generate URLs to binary - content in the ewiki database -*/ -function ewiki_script_binary($asid, $id=false, $params=array(), $upload=0) { - - $upload |= is_string($params) && strlen($params) || count($params); - - #-- generate URL directly to the plainly saved data file, - # see also plugins/db/binary_store - if (defined("EWIKI_DB_STORE_URL") && !$upload) { - $url = EWIKI_DB_STORE_URL . urlencode(rawurlencode(strtok($id, "?"))); - } - - #-- else get standard URL (thru ewiki.php) from ewiki_script() - else { - $url = ewiki_script($asid, $id, $params, "_BINARY=1"); - } - - return($url); -} - - -/* this function returns the absolute ewiki_script url, if EWIKI_SCRIPT_URL - is set, else it guesses the value -*/ -function ewiki_script_url($asid="", $id="", $params="") { - - global $ewiki_action, $ewiki_id, $ewiki_config; - - if ($asid||$id) { - return ewiki_script($asid, $id, $params, false, true, ewiki_script_url()); - } - if ($url = $ewiki_config["script_url"]) { - return($url); - } - - $scr_template = $ewiki_config["script"]; - $scr_current = ewiki_script($ewiki_action, $ewiki_id); - $req_uri = $_SERVER["REQUEST_URI"]; - $qs = $_SERVER["QUERY_STRING"]?1:0; - $sn = $_SERVER["SCRIPT_NAME"]; - - if (($p = strpos($req_uri, $scr_current)) !== false) { - $url = substr($req_uri, 0, $p) . $scr_template; - } - elseif (($qs) && (strpos($scr_template, "?") !== false)) { - $url = substr($req_uri, 0, strpos($req_uri, "?")) - . substr($scr_template, strpos($scr_template, "?")); - } - elseif (($p = strrpos($sn, "/")) && (strncmp($req_uri, $sn, $p) == 0)) { - $url = $sn . "?id="; - } - else { - return(NULL); #-- could not guess it - } - - $url = (@$_SERVER["HTTPS"] ? "https" : "http") . "://" - . EWIKI_SERVER . $url; - - return($ewiki_config["script_url"] = $url); -} - - - - -#------------------------------------------------------------ page plugins --- - - -#-- links/ action -function ewiki_page_links($id, &$data, $action) { - $o = ewiki_make_title($id, ewiki_t("PAGESLINKINGTO", array("title"=>$id)), 1, $action, "", "_MAY_SPLIT=1"); - if ($pages = ewiki_get_backlinks($id)) { - $o .= ewiki_list_pages($pages); - } else { - $o .= ewiki_t("This page isn't linked from anywhere else."); - } - return($o); -} - -#-- get all pages, that are linking to $id -function ewiki_get_backlinks($id) { - $result = ewiki_db::SEARCH("refs", $id); - $pages = array(); - $id_i = EWIKI_CASE_INSENSITIVE ? strtolower($id) : $id; - while ($row = $result->get(0, 0x0077)) { - if (strpos(EWIKI_CASE_INSENSITIVE ?strtolower($row["refs"]) :$row["refs"], "\n$id_i\n") !== false) { - $pages[] = $row["id"]; - } - } - return($pages); -} - -#-- get all existing pages (as array of pagenames), that are linked from $id -function ewiki_get_links($id) { - if ($data = ewiki_db::GET($id)) { - $refs = explode("\n", trim($data["refs"])); - $r = array(); - foreach (ewiki_db::FIND($refs) as $id=>$exists) { - if ($exists) { - $r[] = $id; - } - } - return($r); - } -} - - - -#-- outputs listing from page name array -function ewiki_list_pages($pages=array(), $limit=NULL, - $value_as_title=0, $pf_list=false) -{ - global $ewiki_plugins; - $o = ""; - - if (!isset($limit)) { - ($limit = 0 + $_REQUEST[EWIKI_UP_LISTLIM]) - or ($limit = EWIKI_LIST_LIMIT); - } - $is_num = !empty($pages[0]); - $lines = array(); - $n = 0; - - if ($pages) foreach ($pages as $id=>$add_text) { - - $title = $id; - $params = ""; - - if (is_array($add_text)) { - list($id, $params, $title, $add_text) = $add_text; - if (!$title) { $title = $id; } - } - elseif ($is_num) { - $id = $title = $add_text; - $add_text = ""; - } - elseif ($value_as_title) { - $title = $add_text; - $add_text = ""; - } - - $lines[] = '<a href="' . ewiki_script("", $id, $params) . '">' . ewiki_split_title($title) . '</a> ' . $add_text; - - if (($limit > 0) && ($n++ >= $limit)) { - break; - } - } - - if ($pf_a = @$ewiki_plugins["list_transform"]) { - foreach ($pf_a as $pf_transform) { - $pf_transform($lines); - } - } - - if (($pf_list) || ($pf_list = @$ewiki_plugins["list_pages"][0])) { - $o = $pf_list($lines); - } - elseif($lines) { - $o = "· " . implode("<br />\n· ", $lines) . "<br />\n"; - } - - return($o); -} - - -#---------------------------------------------------------- page plugins --- - - -#-- list of all existing pages (without hidden + protected) -function ewiki_page_index($id=0, $data=0, $action=0, $args=array()) { - - global $ewiki_plugins; - - $o = ewiki_make_title($id, $id, 2); - - $exclude = $args ? ("\n" . implode("\n", preg_split("/\s*[,;:\|]\s*/", $args["exclude"])) . "\n") : ""; - $sorted = array(); - $sorted = array_keys($ewiki_plugins["page"]); - - $result = ewiki_db::GETALL(array("flags"), EWIKI_DB_F_TYPE, EWIKI_DB_F_TEXT); - while ($row = $result->get(0, 0x0037, EWIKI_DB_F_TEXT)) { - if (!stristr($exclude, "\n".$row["id"]."\n")) { - $sorted[] = $row["id"]; - } - } - natcasesort($sorted); - - $o .= ewiki_list_pages($sorted, 0, 0, $ewiki_plugins["list_dict"][0]); - return($o); -} - - - -#-- scans database for extremes (by given page meta data information), -# generates page listing then from list -//@TODO: split $asc parameter into $asc and $firstver -function ewiki_page_ordered_list($orderby="created", $asc=0, $print="%n", $title="", $bad_flags=0) { - - $o = ewiki_make_title("", $title, 2, ".list", "links", 0); - - $sorted = array(); - $result = ewiki_db::GETALL(array($orderby)); - - while ($row = $result->get(0, 0x0037, EWIKI_DB_F_TEXT)) { - if ($asc >= 0) { - // version 1 is most accurate for {hits} - $row = ewiki_db::GET($row["id"], 1); - } - if (! ($bad_flags & $row["flags"])) { - $sorted[$row["id"]] = $row[$orderby]; - } - } - - if ($asc != 0) { arsort($sorted); } - else { asort($sorted); } - - if ($sorted) foreach ($sorted as $name => $value) { - if (empty($value)) { $value = "0"; } - $sorted[$name] = strftime(str_replace('%n', $value, $print), $value); - } - $o .= ewiki_list_pages($sorted); - - return($o); -} - - - -function ewiki_page_newest($id, $data, $action) { - return( ewiki_page_ordered_list("created", -1, ewiki_t("LASTCHANGED"), ewiki_t("NEWESTPAGES")) ); -} - -function ewiki_page_updates($id, $data, $action) { - return ewiki_page_ordered_list("lastmodified", -1, ewiki_t("LASTCHANGED"), EWIKI_PAGE_UPDATES, EWIKI_DB_F_MINOR); -} - -function ewiki_page_hits($id, $data, $action) { - return( ewiki_page_ordered_list("hits", 1, "%n hits", EWIKI_PAGE_HITS) ); -} - -function ewiki_page_versions($id, $data, $action) { - return( ewiki_page_ordered_list("version", -1, "%n changes", EWIKI_PAGE_VERSIONS) ); -} - - - - - - - -function ewiki_page_search($id, &$data, $action) { - - $o = ewiki_make_title($id, $id, 2, $action); - - if (! ($q = @$_REQUEST["q"])) { - $o .= "None Found<br />"; - $o .= '<form action="' . ewiki_script("", $id) . '" method="POST">'; - $o .= ewiki_form("q::30", "") . '<br /><br />'; - $o .= ewiki_form(":submit", $id); - $o .= '</form>'; - } - else { - $found = array(); - - $q = preg_replace('/\s*[^\041-\175\200-\377]\s*/', ' ', $q); - if ($q) foreach (explode(" ", $q) as $search) { - - if (empty($search)) { continue; } - - $result = ewiki_db::SEARCH("content", $search); - - while ($row = $result->get()) { - - #-- show this entry in page listings? - if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $row, "view")) { - continue; - } - - $found[] = $row["id"]; - } - } - $o .= ewiki_list_pages($found); - } - - - - return($o); -} - - -function ewiki_page_info($id, &$data, $action) { - - global $ewiki_plugins, $ewiki_config, $ewiki_links; - - $o = ewiki_make_title($id, ewiki_t("INFOABOUTPAGE")." '{$id}'", 2, $action,"", "_MAY_SPLIT=1"); - - $flagnames = array( - "TEXT", "BIN", "DISABLED", "HTML", "READONLY", "WRITEABLE", - "APPENDONLY", "SYSTEM", "PART", 10=>"HIDDEN", 17=>"EXEC", - ); - $show = array( - "version", "author", - "lastmodified", "created", "hits", "refs", - "flags", "meta", "content" - ); - $no_refs = (boolean)$ewiki_config["info_refs_once"]; - - #-- versions to show - $v_start = $data["version"]; - if ( ($uu=0+@$_REQUEST[EWIKI_UP_PAGENUM]) && ($uu<=$v_start) ) { - $v_start = $uu; - } - $v_end = $v_start - $ewiki_config["list_limit"]; - if ( ($uu=0+@$_REQUEST[EWIKI_UP_PAGEEND]) && ($uu<=$v_start) ) { - $v_end = $uu; - } - $v_end = max($v_end, 1); - - #-- go - # the very ($first) entry is rendered more verbosely than the others - for ($v=$v_start,$first=1; ($v>=$v_end); $v--,$first=0) { - - $current = ewiki_db::GET($id, $v); - - if (!strlen(trim($current["id"])) || !$current["version"]) { - continue; - } - - $o .= '<table class="version-info" border="0" cellpadding="2" cellspacing="1">' . "\n"; - - #-- additional info-actions - $o .= '<tr><td></td><td class="action-links">'; - $o .= ewiki_control_links_list($id, $data, $ewiki_config["action_links"]["info"], $current["version"]); - $o .= "</td></tr>\n"; - - #-- print page database entry - foreach($show as $i) { - - $value = @$current[$i]; - - #-- show database {fields} differently - if ($i == "meta") { - $str = ""; - if ($value) foreach ($value as $n2=>$d2) { - foreach ((array)$d2 as $n=>$d) { - if (is_int($n)) { $n = $n2; } else { $n = "_$n"; } - $str .= htmlentities("$n: $d") . "<br />\n"; - } - } - $value = $str; - } - elseif (($i =="lastmodified")||($i =="created")) { #-- {lastmodified}, {created} - $value = strftime("%c", $value); - } - elseif ($i == "content") { - $value = strlen(trim($value)) . " bytes"; - $i = "content size"; - } - elseif ($first && ($i == "refs") && !(EWIKI_PROTECTED_MODE && (EWIKI_PROTECTED_MODE_HIDING>=2))) { - $a = explode("\n", trim($value)); - $ewiki_links = ewiki_db::FIND($a); - ewiki_merge_links($ewiki_links); - foreach ($a as $n=>$link) { - $a[$n] = ewiki_link_regex_callback(array("$link"), "force_noimg"); - } - $value = implode(", ", $a); - } - elseif (strpos($value, "\n") !== false) { #-- also for {refs} - if ($no_refs && ($i == "refs")) { continue; } - $value = str_replace("\n", ", ", trim($value)); - } - elseif ($i == "version") { - $value = '<a href="' . - ewiki_script("", $id, array("version"=>$value)) . '">' . - $value . '</a>'; - } - elseif ($i == "flags") { - $fstr = ""; - for ($n = 0; $n < 32; $n++) { - if ($value & (1 << $n)) { - if (! ($s=$flagnames[$n])) { $s = "UU$n"; } - $fstr .= $s . " "; - } - } - $value = $fstr; - } - elseif ($i == "author") { - $value = ewiki_author_html($value); - } - - $o .= '<tr class="page-' . $i . '"><td valign="top"><b>' . $i . '</b></td>' . - '<td>' . $value . "</td></tr>\n"; - - } - - $o .= "</table><br />\n"; - } - - #-- page result split - if ($v >= 1) { - $o .= "<br /><div class=\"chunk-list\">\n" . ewiki_chunked_page($action, $id, -1, $v+1, 1) . "\n</div><br />"; - } - #-- ext info actions - $o .= '<div class="summary control-links">' . ewiki_control_links_list($id, $data, $ewiki_config["action_links"]["summary"]) . "</div>\n"; - - return($o); -} - - - - -function ewiki_chunked_page($action, $id, $dir=-1, $start=10, $end=1, $limit=0, $overlap=0.25, $collapse_last=0.67) { - - global $ewiki_config; - - if (empty($limit)) { - $limit = $ewiki_config["list_limit"]; - } - if ($overlap < 1) { - $overlap = (int) ($limit * $overlap); - } - - $p = ""; - $n = $start; - - while ($n) { - - $n -= $dir * $overlap; - - $e = $n + $dir * ($limit + $overlap); - - if ($dir<0) { - $e = max(1, $e); - if ($e <= $collapse_last * $limit) { - $e = 1; - } - } - else { - $e = min($end, $e); - if ($e >= $collapse_last * $limit) { - $e = $end; - } - } - - $o .= ($o?" · ":"") - . '<a href="xxx'.ewiki_script($action, $id, array(EWIKI_UP_PAGENUM=>$n, EWIKI_UP_PAGEEND=>$e)) - . '">'. "$n-$e" . '</a>'; - - if (($n=$e) <= $end) { - $n = false; - } - } - - return('<div class="chunked-result">'. $o .'</div>'); -} - - - - - - -function ewiki_page_edit($id, $data, $action) { - - global $ewiki_links, $ewiki_author, $ewiki_plugins, $ewiki_ring, - $ewiki_errmsg, $ewiki_config; - - $hidden_postdata = array(); - - #-- previous version come back - if ($ewiki_config["forced_version"]) { - - $current = ewiki_db::GET($id); - $data["version"] = $current["version"]; - unset($current); - - unset($_REQUEST["content"]); - unset($_REQUEST["version"]); - } - - #-- edit interception - if ($pf_a = @$ewiki_plugins["edit_hook"]) foreach ($pf_a as $pf) { - if ($output = $pf($id, $data, $hidden_postdata)) { - return($output); - } - } - - #-- permission checks //@TODO: move into above hook, split out flag checks - if (isset($ewiki_ring)) { - $ring = $ewiki_ring; - } else { - $ring = 3; - } - $flags = @$data["flags"]; - if (!($flags & EWIKI_DB_F_WRITEABLE)) { - - #-- perform auth - $edit_ring = (EWIKI_PROTECTED_MODE>=2) ? (2) : (NULL); - if (EWIKI_PROTECTED_MODE && !ewiki_auth($id, $data, $action, $edit_ring, "FORCE")) { - return($ewiki_errmsg); - } - - #-- flag checking - if (($flags & EWIKI_DB_F_READONLY) and ($ring >= 2)) { - return(ewiki_t("CANNOTCHANGEPAGE")); - } - if (($flags) and (($flags & EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT) and ($ring >= 1)) { - return(ewiki_t("CANNOTCHANGEPAGE")); - } - } - - #-- "Edit Me" - $o = ewiki_make_title($id, ewiki_t("EDITTHISPAGE").(" '{$id}'"), 2, $action, "", "_MAY_SPLIT=1"); - - #-- normalize to UNIX newlines - $_REQUEST["content"] = str_replace("\015\012", "\012", $_REQUEST["content"]); - $_REQUEST["content"] = str_replace("\015", "\012", $_REQUEST["content"]); - - #-- preview - if (isset($_REQUEST["preview"])) { - $o .= $ewiki_plugins["edit_preview"][0]($data); - } - - #-- save - if (isset($_REQUEST["save"])) { - - #-- check for concurrent version saving - $error = 0; - if ((@$data["version"] >= 1) && (($data["version"] != @$_REQUEST["version"]) || (@$_REQUEST["version"] < 1))) { - - $pf = $ewiki_plugins["edit_patch"][0]; - - if (!$pf || !$pf($id, $data)) { - $error = 1; - $o .= ewiki_t("ERRVERSIONSAVE") . "<br /><br />"; - } - - } - if (!$error) { - - #-- new pages` flags - $set_flags = (@$data["flags"] & EWIKI_DB_F_COPYMASK); - if (($set_flags & EWIKI_DB_F_TYPE) == 0) { - $set_flags = EWIKI_DB_F_TEXT; - } - if (EWIKI_ALLOW_HTML) { - $set_flags |= EWIKI_DB_F_HTML; - } - - #-- mk db entry - $save = array( - "id" => $id, - "version" => @$data["version"] + 1, - "flags" => $set_flags, - "content" => $_REQUEST["content"], - "created" => ($uu=@$data["created"]) ? $uu : time(), - "meta" => ($uu=@$data["meta"]) ? $uu : "", - "hits" => ($uu=@$data["hits"]) ? $uu : "0", - ); - ewiki_data_update($save); - - #-- edit storage hooks - if ($pf_a = @$ewiki_plugins["edit_save"]) { - foreach ($pf_a as $pf) { - $pf($save, $data); - } - } - - #-- save - if (!$save || !ewiki_db::WRITE($save)) { - - $o .= $ewiki_errmsg ? $ewiki_errmsg : ewiki_t("ERRORSAVING"); - - } - else { - #-- prevent double saving, when ewiki_page() is re-called - $_REQUEST = $_GET = $_POST = array(); - - $o = ewiki_t("THANKSFORCONTRIBUTION") . "<br /><br />"; - - if (EWIKI_EDIT_REDIRECT) { - $url = ewiki_script("", $id, "thankyou=1", 0, 0, ewiki_script_url()); - $o .= ewiki_t("EDITCOMPLETE", array("url"=>htmlentities($url))); - - if (EWIKI_HTTP_HEADERS && !headers_sent()) { - header("Status: 303 Redirect for GET"); - $sid = defined("SID") ? EWIKI_ADDPARAMDELIM.SID : ""; - header("Location: $url$sid"); - exit; - #header("URI: $url"); - #header("Refresh: 0; URL=$url"); - } - else { - $o .= '<meta http-equiv="Location" content="'.htmlentities($url).'">'; - } - } - else { - $o .= ewiki_page($id); - } - - } - - } - - //@REWORK - // header("Reload-Location: " . ewiki_script("", $id, "", 0, 0, ewiki_script_url()) ); - - } - else { - #-- Edit <form> - $o .= ewiki_page_edit_form($id, $data, $hidden_postdata); - - #-- additional forms - if ($pf_a = $ewiki_plugins["edit_form_final"]) foreach ($pf_a as $pf) { - $pf($o, $id, $data, $action); - } - } - - return($o); -} - - -function ewiki_data_update(&$data, $author="") { - ewiki_db::UPDATE($data, $author); -} - - -function ewiki_new_data($id, $flags=EWIKI_DB_F_TEXT, $author="") { - return(ewiki_db::CREATE($id, $flags, $author)); -} - - - -#-- edit <textarea> -function ewiki_page_edit_form(&$id, &$data, &$hidden_postdata) { - - global $ewiki_plugins, $ewiki_config; - - #-- previously edited, or db fetched content - if (@$_REQUEST["content"] || @$_REQUEST["version"]) { - $data = array( - "version" => &$_REQUEST["version"], - "content" => &$_REQUEST["content"] - ); - } - else { - if (empty($data["version"])) { - $data["version"] = 1; - } - @$data["content"] .= ""; - } - - #-- normalize to DOS newlines - $data["content"] = str_replace("\015\012", "\012", $data["content"]); - $data["content"] = str_replace("\015", "\012", $data["content"]); - $data["content"] = str_replace("\012", "\015\012", $data["content"]); - - $hidden_postdata["version"] = &$data["version"]; - - #-- edit textarea/form - $o .= ewiki_t("EDIT_FORM_1") - . '<form method="POST" enctype="multipart/form-data" action="' - . ewiki_script("edit", $id) . '" name="ewiki"' - . ' accept-charset="'.EWIKI_CHARSET.'">' . "\n"; - - #-- additional POST vars - if ($hidden_postdata) foreach ($hidden_postdata as $name => $value) { - $o .= '<input type="hidden" name="' . $name . '" value="' . $value . '" />' ."\n"; - } - - if (EWIKI_CHARSET=="UTF-8") { - $data["content"] = utf8_encode($data["content"]); - } - ($cols = strtok($ewiki_config["edit_box_size"], "x*/,;:")) && ($rows = strtok("x, ")) || ($cols=70) && ($rows=15); - $o .= '<textarea wrap="soft" id="ewiki_content" name="content" rows="'.$rows . '" cols="' .$cols. '">' - . htmlentities($data["content"]) . "</textarea>" - . $GLOBALS["ewiki_t"]["C"]["EDIT_TEXTAREA_RESIZE_JS"]; - - #-- more <input> elements before the submit button - if ($pf_a = $ewiki_plugins["edit_form_insert"]) foreach ($pf_a as $pf) { - $o .= $pf($id, $data, $action); - } - - $o .= "\n<br />\n" - . ewiki_form("save:submit", "   ".ewiki_t("SAVE")."   ") - . "   " - . ewiki_form("preview:submit", "   ".ewiki_t("PREVIEW")."   ") - . '   <a class="cancel" href="'. ewiki_script("", $id) . '">' . ewiki_t("CANCEL_EDIT") . '</a><br />'; - - #-- additional form elements - if ($pf_a = $ewiki_plugins["edit_form_append"]) foreach ($pf_a as $pf) { - $o .= $pf($id, $data, $action); - } - - $o .= "\n</form>\n" - . ewiki_t("EDIT_FORM_2"); - - return('<div class="edit-box">'. $o .'</div>'); -} - - - -#-- pic upload form -function ewiki_page_edit_form_final_imgupload(&$o, &$id, &$data, &$action) { - if (EWIKI_SCRIPT_BINARY && EWIKI_UP_UPLOAD && EWIKI_IMAGE_MAXSIZE) { - $o .= "\n<br />\n". '<div class="image-upload">' - . '<form action=' - . '"'. ewiki_script_binary("", EWIKI_IDF_INTERNAL, "", "_UPLOAD=1") .'"' - . ' method="POST" enctype="multipart/form-data" target="_upload">' - . '<input type="file" name="'.EWIKI_UP_UPLOAD.'"' - . (defined("EWIKI_IMAGE_ACCEPT") ? ' accept="'.EWIKI_IMAGE_ACCEPT.'" />' : "") - . '<input type="hidden" name="'.EWIKI_UP_BINARY.'" value="'.EWIKI_IDF_INTERNAL.'">' - . '<input type="hidden" name="'.EWIKI_UP_PARENTID.'" value="'.htmlentities($id).'">' - . '   ' - . '<input type="submit" value="'.ewiki_t("UPLOAD_PICTURE_BUTTON").'">' - . '</form></div>'. "\n"; - } -} - - -function ewiki_page_edit_preview(&$data) { - return( '<div class="preview">' - . '<hr noshade="noshade" />' - . "<div align=\"right\">" . ewiki_t("PREVIEW") . "</div><hr noshade=\"noshade\" /><br />\n" - . $GLOBALS["ewiki_plugins"]["render"][0]($_REQUEST["content"], 1, EWIKI_ALLOW_HTML || (@$data["flags"]&EWIKI_DB_F_HTML)) - . '<hr noshade="noshade" /><br />' - . "</div>" - ); -} - - - - - - - -function ewiki_control_links($id, &$data, $action, $hide_hr=0, $hide_mtime=0) { - - global $ewiki_plugins, $ewiki_ring, $ewiki_config; - $action_links = & $ewiki_config["action_links"][$action]; - - #-- disabled - if (!$ewiki_config["control_line"]) { - return(""); - } - - $o = "\n" - . '<div align="right" class="action-links control-links"><br />'; - if (!$hide_hr && !@$ewiki_config["control_line.no_deco"]) { - $o .= '<p><small>' . strftime(ewiki_t("LASTCHANGED"), @$data["lastmodified"]) . '</small></p>'; - $o .= "\n\n" . '<hr noshade="noshade" />' . "\n"; - } - - if (@$ewiki_config["forced_version"] && ewiki_auth($id, $data, "edit")) { - - $o .= '<form action="' . ewiki_script("edit", $id) . '" method="POST">' . - '<input type="hidden" name="edit" value="old">' . - '<input type="hidden" name="version" value="'.$ewiki_config["forced_version"].'">' . - '<input type="submit" value="' . ewiki_t("OLDVERCOMEBACK") . '"></form> '; - } - else { - $o .= ewiki_control_links_list($id, $data, $action_links); - } - - if (!$hide_mtime && ($data["lastmodified"] >= UNIX_MILLENNIUM)) { - // $o .= '<small>' . strftime(ewiki_t("LASTCHANGED"), @$data["lastmodified"]) . '</small>'; - } - - $o .= "</div>\n"; - return($o); -} - - -#-- the core of ewiki_control_links, separated for use in info and plugins -function ewiki_control_links_list($id, &$data, $action_links, $version=0) { - global $ewiki_plugins, $ewiki_config, $o; - $o = ""; - ($ins = @$ewiki_config["control_links_enclose"]) or ($ins = " "); - - if ($action_links) foreach ($action_links as $action => $title) - if (!empty($ewiki_plugins["action"][$action]) || !empty($ewiki_plugins["action_always"][$action]) || strpos($action, ":/")) - { - if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($id, $data, $action)) { - continue; - } - $o .= $ins[1] . '<a href="' . - ( strpos($action, "://") - ? $action # an injected "action" URL - : ewiki_script($action, $id, $version?array("version"=>$version):NULL) - ) . '">' . ewiki_t($title) .'</a> ' . $ins[2]; - - -#++   - } - - $o = $ins[0] . $o . $ins[3]; - return($o); -} - - - - -# ============================================================= rendering === - - - - - -######## ### ### ######### ### ### ### ####### -######## #### ### ######### ### #### ### ####### -### ##### ### ### ##### ### ### -###### ######### ### #### ### ######### ###### -###### ######### ### #### ### ######### ###### -### ### ##### ### ### ### ### ##### ### -######## ### #### ######### ### ### #### ####### -######## ### ### ######### ### ### ### ####### - - -/* - The _format() function transforms $wiki_source pages into <html> strings, - also calls various markup and helper plugins during the transformation - process. The $params array can activate various features and extensions. - only accepts UNIX newlines! -*/ -function ewiki_format ( - $wiki_source, - $params = array() - ) -{ - global $ewiki_links, $ewiki_plugins, $ewiki_config; - - #-- state vars - $params = (array)$ewiki_config["format_params"] + (array)$params; - $s = array( - "in" => 0, # current input $iii[] block array index - "para" => "", - "line" => "", - "post" => "", # string to append after current line/paragraph - "line_i" => 0, - "lines" => array(), - "list" => "", # lists - "tbl" => 0, # open table? - "indent" => 0, # indentation - "close" => array(), - ); - #-- aliases - $in = &$s["in"]; - $line = &$s["line"]; - $lines = &$s["lines"]; - $para = &$s["para"]; - $post = &$s["post"]; - $list = &$s["list"]; - - #-- input and output arrays - if ($wiki_source[0] == "<") { # also prepend an empty line - $wiki_source = "\n" . $wiki_source; # for faster strpos() searchs - } - $core_flags = 0x137F; # (0x0001=WikiMarkup, 0x0002=WikiLinks, 0x1000=MoreBlockPlugins) - $iii = array( - 0 => array( - 0 => $wiki_source."\n", # body + empty line - 1 => $core_flags, # rendering / behaviour options - 2 => "core", # block plugin name - ) - ); - $ooo = array( - ); - unset($wiki_source); - - #-- plugins - $pf_tbl = @$ewiki_plugins["format_table"][0]; - $pf_line = @$ewiki_plugins["format_line"]; - - #-- wikimarkup (wm) - $htmlentities = $ewiki_config["htmlentities"]; - $wm_indent = &$ewiki_config["wm_indent"]; - $s["wm_indent_close"] = "</" . strtok($wm_indent, "< />"). ">"; - $wm_table_defaults = &$ewiki_config["wm_table_defaults"]; - $wm_source = &$ewiki_config["wm_source"]; - $wm_list = &$ewiki_config["wm_list"]; - $wm_list_chars = implode("", array_keys($wm_list)); - $wm_style = &$ewiki_config["wm_style"]; - $wm_start_end = &$ewiki_config["wm_start_end"]; - $wm_max_header = &$ewiki_config["wm_max_header"]; - $wm_publishing_headers = &$ewiki_config["wm_publishing_headers"]; - $wm_whole_line = &$ewiki_config["wm_whole_line"]; - - #-- eleminate html - $iii[0][0] = strtr($iii[0][0], $htmlentities); - unset($htmlentities["&"]); - - #-- pre-processing plugins (working on wiki source) - if ($pf_source = $ewiki_plugins["format_source"]) { - foreach ($pf_source as $pf) $pf($iii[0][0]); - } - - #-- simple markup - $iii[0][0] = strtr($iii[0][0], $wm_source); - - - #-- separate input into blocks ------------------------------------------ - if ($ewiki_config["format_block"]) - foreach ($ewiki_config["format_block"] as $btype=>$binfo) { - - #-- disabled block plugin? - if ($binfo[2] && !$params[$binfo[2]]) { - continue; - } - - #-- traverse $iii[] - $in = -1; - while ((++$in) < count($iii)) { - - #-- search fragment delimeters - if ($iii[$in][1] & 0x0100) - while ( - ($c = & $iii[$in][0]) && - (($l = strpos($c, $binfo[0])) !== false) && - ($r = strpos($c, $binfo[1], $l)) ) - { - $l_len = strlen($binfo[0]); - $r_len = strlen($binfo[1]); - - $repl = array(); - // pre-text - if (($l > 0) && trim($text = substr($c, 0, $l))) { - $repl[] = array($text, $core_flags, "core"); - } - // the extracted part - if (trim($text = substr($c, $l+$l_len, $r-$l-$l_len))) { - $repl[] = array($text, $binfo[3], "$btype"); - } - // rest - if (($r+$r_len < strlen($c)) && trim($text = substr($c, $r+$r_len))) { - $repl[] = array($text, $core_flags, "core"); - } - array_splice($iii, $in, 1, $repl); - - $in += 1; - } - } - } - - #-- run format_block plugins - $in = -1; - while ((++$in) < count($iii)) { - if (($btype = $iii[$in][2]) && ($pf_a = @$ewiki_plugins["format_block"][$btype])) { - $c = &$iii[$in][0]; - if ($iii[$in][1] & 0x0400) { - $c = strtr($c, array_flip($htmlentities)); - } - foreach ($pf_a as $pf) { - # current buffer $c and pointer $in into $iii[] and state $s - $pf($c, $in, $iii, $s, $btype); - } - } - } - - #-- wiki markup ------------------------------------------------------ - $para = ""; - $in = -1; - while ((++$in) < count($iii)) { - #-- wikimarkup - if ($iii[$in][1] & 0x0001) { - - #-- input $lines buffer, and output buffer $ooo array - $lines = explode("\n", $iii[$in][0]); - $ooo[$in] = array( - 0 => "", - 1 => $iii[$in][1] - ); - $out = &$ooo[$in][0]; - $s["bmarkup"] = ($iii[$in][1] & 0x0008); # lists/tables/paras - $s["nopara"] = !($s["bmarkup"]); # disables indentation & paragraphs -# should this disable lists and tables and ... -# shouldn't it rather be a bit flag? - - #-- walk through wiki source lines - $line_max = count($lines); - if ($lines) foreach ($lines as $s["line_i"]=>$line) { - #echo "line={$s[line_i]}:$line\n"; - - #-- empty lines separate paragraphs - if (!ltrim($line)) { - ewiki_format_close_para($ooo, $s); - ewiki_format_close_tags($ooo, $s); - if (!$s["nopara"]) { - $out .= "\n"; - } - $line = ''; - } - - - #-- list/table/headline "BlockMarkup" --------------------------- - if ($s["bmarkup"]) { - - #-- horiz bar - if (!$list && !strncmp($line, "----", 4)) { - $s["para"] .= "<hr noshade=\"noshade\" />\n"; - continue; - } - #-- html comment - if (!strncmp($line, "<!--", 7)) { - $out .= "<!-- " . htmlentities(str_replace("--", "__", substr($line, 7))) . " -->\n"; - continue; - } - - strlen($line) && ($c0 = $line[0]) - or ($c0 = "\000"); - - #-- tables ------------------------ - if (($c0 == "|") && ($s["tbl"] || ($line[strlen($line)-1] == "|"))) { - if (!$s["tbl"]) { - ewiki_format_close_para($ooo, $s); - ewiki_format_close_tags($ooo, $s); - $s["list"] = ""; - } - $line = substr($line, 1); - if ($line[strlen($line)-1] == "|") { - $line = substr($line, 0, -1); - } - if ($pf_tbl) { - $pf_tbl($line, $ooo, $s); - } - else { - if (!$s["tbl"]) { - $out .= "<table " . $wm_table_defaults . ">\n"; - $s["close"][] = "\n</table>"; - } - $line = "<tr>\n<td>" . str_replace("|", "</td>\n<td>", $line) . "</td>\n</tr>"; - } - $s["tbl"] = 1; - $para = false; - } - elseif ($s["tbl"]) { - $s["tbl"] = 0; - } - - - #-- headlines - if (($c0 == "!") && ($excl = strspn($line, "!"))) { - - if ($excl > $wm_max_header) { - $excl = $wm_max_header; - } - $line = substr($line, $excl); - //publishing headers go from h2 smaller "like word" - $excl = $wm_publishing_headers? (1+$excl) :5 - $excl; - $line = "<h$excl>" . $line . "</h$excl>"; - if ($para) { - ewiki_format_close_para($ooo, $s); - } - ewiki_format_close_tags($ooo, $s); - $para = false; - } - - - #-- whole-line wikimarkup - foreach ($wm_whole_line as $find=>$replace) { - if (substr($line, 0, strlen($find)) == $find) { - $line = "<$replace>" . ltrim(substr($line,strlen($find))) . "</".strtok($replace," ").">"; - } - } - - #-- indentation (space/tab markup) - $n_indent = 0; - if (!$list && (!$s["nopara"]) && ($n_indent = strspn($line, " "))) { - $n_indent = (int) ($n_indent / 2.65); - while ($n_indent > $s["indent"]) { - $s["para"] .= $wm_indent; - $s["indent"]++; - } - } - while ($n_indent < $s["indent"]) { - $s["para"] .= $s["wm_indent_close"] . "\n"; - $s["indent"]--; - } - - - #-- list markup ------------------- - if (isset($wm_list[$c0])) { - if (!$list) { - ewiki_format_close_para($ooo, $s); - ewiki_format_close_tags($ooo, $s); - } - $new_len = strspn($line, $wm_list_chars); - $new_list = substr($line, 0, $new_len); - $old_len = strlen($list); - $lchar = $new_list[$new_len-1]; - list($lopen, $ltag1, $ltag2) = $wm_list[$lchar]; - - #-- exception: "--" is treated as literal - if (($old_len===0) && (($new_len>=2) && ($new_list=="--"))) { - $list = ''; # change this ^^ to an OR (||) - # to filter bad list markup - } - else { - #-- cut line - $line = substr($line, $new_len); - $lspace = ""; - $linsert = ""; - if ($ltag1) { - $linsert = "<$ltag1>" . strtok($line, $lchar) . "</$ltag1> "; - $line = strtok("\000"); - } - - #-- enum list types - if (($lchar == "#") && ($line[1] == " ") && ($ltype = $line[0])) { - if (($ltype >= "0") || ($ltype <= "z")) { - $line = substr($line, 2); - } else { - $ltype = ""; - } - } - - #-- add another <li>st entry - if ($new_len == $old_len) { - $lspace = str_repeat(" ", $new_len); - $out .= "</$ltag2>\n" . $lspace . $linsert . "<$ltag2>"; - } - #-- add list - elseif ($new_len > $old_len) { - while ($new_len > ($old_len=strlen($list))) { - $lchar = $new_list[$old_len]; - $list .= $lchar; - list($lopen, $ltag1, $ltag2) = $wm_list[$lchar]; - $lclose = strtok($lopen, " "); - $lspace = str_repeat(" ", $new_len); - - if (isset($ltype) && $ltype) { - $ltype = ($ltype<"A"?"1": ($ltype=="I"?"I": ($ltype=="i"?"i": ($ltype<"a"?"A": "a")))); - $lopen .= " type=\"$rltype\""; - if ($rltype!=$ltype) { $lopen .= " start=\"$ltype\""; } - } - - $out .= "\n$lspace<$lopen>\n" . "$lspace". $linsert . "<$ltag2>"; - $s["close"][] = "$lspace</$lclose>"; - $s["close"][] = "$lspace</$ltag2>"; - } - } - #-- close lists - else { - while ($new_len < ($old_len=strlen($list))) { - $remove = $old_len-$new_len; - ewiki_format_close_tags($ooo, $s, 2*$remove); - $list = substr($list, 0, -$remove); - } - if ($new_len) { - $lspace = str_repeat(" ", $new_len); - $out .= "$lspace</$ltag2>\n" . $lspace . $linsert . "<$ltag2>"; - } - } - - $list = $new_list; - $para = false; - } - } - elseif ($list) { - if ($c0 == " ") { - $para = false; - } - else { - ewiki_format_close_tags($ooo, $s); - $list = ""; - } - } - - }#--if $s["bmarkup"] -------------------------------------------- - - - #-- text style triggers - foreach ($wm_style as $find=>$replace) { - $find_len = strlen($find); - $loop = 20; - while(($loop--) && (($l = strpos($line, $find)) !== false) && ($r = strpos($line, $find, $l + $find_len))) { - $line = substr($line, 0, $l) . $replace[0] . - substr($line, $l + strlen($find), $r - $l - $find_len) . - $replace[1] . substr($line, $r + $find_len); - } - } - - #-- start-end markup - foreach ($wm_start_end as $d) { - $len0 = strlen($d[0]); - $loop = 20; - while(($loop--) && (($l = strpos($line, $d[0])) !== false) && ($r = strpos($line, $d[1], $l + $len0))) { - $len1 = strlen($d[1]); - $line = substr($line, 0, $l) . $d[2] . - substr($line, $l + $len0, $r - $l - $len0) . - $d[1] . substr($line, $r + $len1); - } - } - - #-- call wiki source formatting plugins that work on current line - if ($pf_line) { - foreach ($pf_line as $pf) $pf($out, $line, $post); - } - - - #-- add formatted line to page-output - $line .= $post; - if ($para === false) { - $out .= $line; - $para = ""; - } - else { - $para .= $line . "\n"; - } - - } - - #-- last block, or flags dictate a WikiSource blocks/para break? - if (!isset($iii[$in+1]) || (($iii[$in+1][1] & 0x0010) ^ ($iii[$in][1] & 0x0010)) ) { - ewiki_format_close_para($ooo, $s); - ewiki_format_close_tags($ooo, $s); - } - } - #-- copy as is into output buffer - else { - $ooo[$in] = $iii[$in]; - } - $iii[$in] = array(); - } - - - #-- wiki linking ------------------------------------------------------ - $scan_src = ""; - for ($in=0; $in<count($ooo); $in++) { -// BUG: does not respect the (absence of) flags of individual blocks - #-- join together multiple WikiSource blocks - if ($ooo[$in][1] & 0x0022) { - while (isset($ooo[$in+1]) && ($ooo[$in][1] & 0x0002) && ($ooo[$in+1][1] & 0x0002)) { - $ooo[$in] = array( - 0 => $ooo[$in][0] . "\n" . $ooo[$in+1][0], - 1 => $ooo[$in][1] | $ooo[$in+1][1], - ); - array_splice($ooo, $in+1, 1); - } - } - #-- html character entities - if (EWIKI_HTML_CHARS || ($ooo[$in][1] & 0x0004)) { - $ooo[$in][0] = str_replace("&#", "&#", $ooo[$in][0]); - } - $scan_src .= $ooo[$in][0]; - } - - #-- pre-scan - if ($params["scan_links"]) { - ewiki_scan_wikiwords($scan_src, $ewiki_links); - } - if ($pf_linkprep = @$ewiki_plugins["format_prepare_linking"]) { - foreach ($pf_linkprep as $pf) $pf($scan_src); - } - $scan_src = NULL; - - #-- finally the link-creation-regex - for ($in=0; $in<count($ooo); $in++) { - if ($ooo[$in][1] & 0x0002) { - ewiki_render_wiki_links($ooo[$in][0]); - } - } - - - #-- fin: combine all blocks into html string ---------------------------- - $html = ""; - for ($in=0; $in<count($ooo); $in++) { - $html .= $ooo[$in][0] . "\n"; - $ooo[$in] = 0; - } - #-- call post processing plugins - if ($pf_final = $ewiki_plugins["format_final"]) { - foreach ($pf_final as $pf) $pf($html); - } - return($html); -} - - - -function ewiki_format_close_para(&$ooo, &$s) { - $out = &$ooo[$s["in"]][0]; - #-- output text block - if (trim($s["para"])) { - #-- indentation - while ($s["indent"]) { - $s["para"] .= $s["wm_indent_close"]; - $s["indent"]--; - } - #-- enclose in <p> tags - if (!$s["nopara"]) { - $s["para"] = "\n<p>" . ltrim($s["para"], "\n") . "</p>\n"; - } - #-- paragraph formation plugins - if ($pf_a = @$GLOBALS["ewiki_plugins"]["format_para"]) { - foreach ($pf_a as $pf) { - $pf($s["para"], $ooo, $s); - } - } - $out .= $s["para"]; - $s["para"] = ""; - } -} - - -function ewiki_format_close_tags(&$ooo, &$s, $count=100) { - $out = &$ooo[$s["in"]][0]; - if (!is_array($s) || !is_array($s["close"])) { - die("\$s is garbaged == $s!!"); - } - while (($count--) && ($add = array_pop($s["close"]))) { - $out .= $add . "\n"; - } -} - - -function ewiki_format_pre(&$str, &$in, &$iii, &$s, $btype) { - $str = "<pre class=\"markup $btype\">" . $str . "</pre>"; -} - - -function ewiki_format_html(&$str, &$in, &$iii, &$s) { - $he = array_reverse($GLOBALS["ewiki_config"]["htmlentities"]); - $str = strtr($str, array_flip($he)); - $str = "<span class=\"markup html\">" . $str . "\n</span>\n"; -} - - -function ewiki_format_comment(&$str, &$in, &$iii, &$s, $btype) { - $str = "<!-- " . str_replace("--", "¯¯", $str) . " -->"; -} - - - - -/* unclean pre-scanning for WikiWords in a page, - pre-query to the db */ -function ewiki_scan_wikiwords(&$wiki_source, &$ewiki_links, $se=0) { - - global $ewiki_config, $ewiki_id; - - #-- find matches - preg_match_all($ewiki_config["wiki_pre_scan_regex"], $wiki_source, $uu); - $uu = array_merge((array)$uu[1], (array)$uu[2], (array)@$uu[3], (array)$uu[4]); - - #-- clean up list, trim() spaces (allows more unclean regex) - page id unification - foreach ($uu as $i=>$id) { - $uu[$i] = trim($id); - } - unset($uu[""]); - $uu = array_unique($uu); - - #-- unfold SubPage names - if (EWIKI_SUBPAGE_START) { - foreach ($uu as $i=>$id) { - if ($id && (strpos(EWIKI_SUBPAGE_START, $id[0]) !== false)) { - if ($id[1] == "/") { $id = substr($id, 1); } - $uu[$i] = $ewiki_id . $id; - } - } } - - #-- query db - $ewiki_links = ewiki_db::FIND($uu); - - #-- strip email adresses - if ($se) { - foreach ($ewiki_links as $c=>$uu) { - if (strpos($c, "@") && (strpos($c, ".") || strpos($c, ":"))) { - unset($ewiki_links[$c]); - } - } } -} - - - -/* regex on page content, - handled by callback (see below) -*/ -function ewiki_render_wiki_links(&$o) { - global $ewiki_links, $ewiki_config, $ewiki_plugins; - - #-- merge with dynamic pages list - ewiki_merge_links($ewiki_links); - - #-- replace WikiWords - $link_regex = &$ewiki_config["wiki_link_regex"]; - $o = preg_replace_callback($link_regex, "ewiki_link_regex_callback", $o); - - #-- cleanup -/////////// unset($ewiki_links); -} - - -/* combines with page plugin list, - and makes all case-insensitive (=lowercased) - in accord with EWIKI_CASE_INSENSITIVE - (handled within ewiki_array) -*/ -function ewiki_merge_links(&$ewiki_links) { - global $ewiki_plugins; - if ($ewiki_links !== true) { - foreach ($ewiki_plugins["page"] as $page=>$uu) { - $ewiki_links[$page] = 1; - } - $ewiki_links = ewiki_array($ewiki_links); - } -} - - - -/* link rendering (p)regex callback - (ooutch, this is a complicated one) -*/ -function ewiki_link_regex_callback($ii, $force_noimg=0) { - - global $ewiki_links, $ewiki_plugins, $ewiki_config, $ewiki_id; - - $str = trim($ii[0]); - $type = array(); - $states = array(); - - #-- link bracket '[' escaped with '!' or '~' - if (($str[0] == "!") || ($str[0] == "~") || ($str[0] == "\\")) { - return(substr($str, 1)); - } - if ($str[0] == "#") { - $states["define"] = 1; - $str = substr($str, 1); - } - if ($str[0] == "[") { - $states["brackets"] = 1; - $str = substr($str, 1, -1); - if (!strlen($str)) { return("[]"); } //better: $ii[0] - } - - #-- explicit title given via [ title | WikiLink ] - $href = $title = strtok($str, "|"); - if ($uu = strtok("|")) { - $href = $uu; - $states["titled"] = 1; - } - #-- title and href swapped: swap back - if (strpos("://", $title) || strpos($title, ":") && !strpos($href, ":")) { - $uu = $title; $title = $href; $href = $uu; - } - #-- new entitling scheme [ url "title" ] - if ((($l=strpos($str, '"')) < ($r=strrpos($str, '"'))) && ($l!==false) ) { - $title = substr($str, $l + 1, $r - $l - 1); - $href = substr($str, 0, $l) . substr($str, $r + 1); - $states["titled"] = 1; - if (!$href) { return($ii[0]); } - } - - #-- strip spaces - $spaces_l = ($href[0]==" ") ?1:0; - $spaces_r = ($href[strlen($href)-1]==" ") ?1:0; - $title = ltrim(trim($title), "^"); - $href = ltrim(trim($href), "^"); - - #-- strip_htmlentities() - if (1&& (strpos($href, "&")!==false) && strpos($href, ";")) { - ewiki_stripentities($href); - } - - #-- anchors - $href2 = ""; - if (($p = strrpos($href, "#")) && ($p) && ($href[$p-1] != "&")) { - $href2 = trim(substr($href, $p)); - $href = trim(substr($href, 0, $p)); - } - elseif ($p === 0) { - $states["define"] = 1; - } - if ($href == ".") { - $href = $ewiki_id; - } - - - - #-- SubPages - $c0 = $href[0]; - if ($c0 && (strpos(EWIKI_SUBPAGE_START, $c0) !== false)) { - $_set = EWIKI_SUBPAGE_LONGTITLE && ($href==$title); - if (($href[1] == "/")) { ##($c0 == ".") && - $href = substr($href, 1); - } - $href = $ewiki_id . $href; - if ($_set) { - $title = $href; - } - } - - #-- for case-insensitivines - $href_i = EWIKI_CASE_INSENSITIVE ? strtolower($href) : ($href); - - #-- injected URLs - if (isset($ewiki_links[$href_i]) && strpos($inj_url = $ewiki_links[$href_i], "://")) { - if ($href==$title) { $href = $inj_url; } - } - $states["title"] = &$title; - - #-- interwiki links - if (strpos($href, ":") && ($uu = ewiki_interwiki($href, $type, $states))) { - $href = $uu; - $str = "<a href=\"$href$href2\">$title</a>"; - } - #-- action:WikiLinks - elseif (isset($ewiki_plugins["action"][$a=strtolower(strtok($href, ":"))])) { - $type = array($a, "action", "wikipage"); - $str = '<a href="' . ewiki_script($a, strtok("\000")) . '">' . $title . '</a>'; - } - #-- page anchor definitions, if ($href[0]=="#") - elseif (@$states["define"]) { - $type = array("anchor"); - if ($title==$href) { - $title = ""; // was " " before, but that's not required - } - $str = '<a name="' . htmlentities(ltrim($href, "#")) . '">' . ltrim($title, "#") . '</a>'; - } - #-- inner page anchor jumps - elseif (strlen($href2) && ($href==$ewiki_id) || ($href[0]=="#") && ($href2=&$href)) { - $type = array("jump"); - $str = '<a href="' . htmlentities($href2) . '">' . $title . '</a>'; - } - #-- ordinary internal WikiLinks - elseif (($ewiki_links === true) || @$ewiki_links[$href_i]) { - $type = array("wikipage"); - $str = '<a href="' . ewiki_script("", $href) . htmlentities($href2) - . '">' . $title . '</a>'; - } - #-- guess for mail@addresses, convert to URI if - elseif (strpos($href, "@") && !strpos($href, ":")) { - $type = array("email"); - $href = "mailto:" . $href; - } - #-- not found fallback - else { - $str = ""; - #-- a plugin may take care - if ($pf_a = @$ewiki_plugins["link_notfound"]) { - foreach ($pf_a as $pf) { - if ($str = $pf($title, $href, $href2, $type)) { - break; - } } - } - #-- (QuestionMarkLink to edit/ action) - if (!$str) { - $type = array("notfound"); - $t = $ewiki_config["qmark_links"]; - $str = ewiki_script(isset($t[4]) ? "edit" : "", $href); - if (strlen($t) >= 3) { - $str = ($t[0] ? "<a href=\"$str\">$t[0]</a>" :'') - . ($t[1] ? "<$t[1]>$title</$t[1]>" : $title) - . ($t[2] ? "<a href=\"$str\">$t[2]</a>" :''); - } else { - $str = "<a href=\"$str\">" . $title . "</a>"; - if ($t<0) { $str .= "?"; } - } - $str = '<span class="NotFound">' . $str . '</span>'; - } - } - - #-- convert standard and internal:// URLs - $is_url = preg_match('°^('.implode('|', $ewiki_config["idf"]["url"]).')°', $href); - $is_internal = 0; - // - if (!$is_url && ($ewiki_links[$href_i]["flags"] & EWIKI_DB_F_BINARY)) { - $is_url = 1; - $is_internal = 1; - } - if ($is_url) { - $type[-2] = "url"; - $type[-1] = strtok($href, ":"); - - #-- [http://url titles] - if (strpos($href, " ") && ($title == $href)) { - $href = strtok($href, " "); - $title = strtok("\377"); - } - - #-- URL plugins - if ($pf_a = $ewiki_plugins["link_url"]) foreach ($pf_a as $pf) { - if ($str = $pf($href, $title, $status)) { break 2; } - } - $meta = @$ewiki_links[$href]; - - #-- check for image files - $ext = substr($href, strrpos($href,".")); - $nocache = strpos($ext, "no"); - $ext = strtok($ext, "?&#"); - $obj = in_array($ext, $ewiki_config["idf"]["obj"]); - $img = (strncmp(strtolower($href), "data:image/", 11) == 0) && ($nocache=1) - || $obj || in_array($ext, $ewiki_config["idf"]["img"]); - - #-- internal:// references (binary files) - $id = $href; - if (EWIKI_SCRIPT_BINARY && ((strpos($href, EWIKI_IDF_INTERNAL)===0) || - EWIKI_IMAGE_MAXSIZE && EWIKI_CACHE_IMAGES && $img && !$nocache) || - $is_internal ) - { - $type = array("binary"); - $href = ewiki_script_binary("", $href); - } - - #-- output html reference - if (!$img || $force_noimg || !$states["brackets"] || (strpos($href, EWIKI_IDF_INTERNAL) === 0)) { -//@FIX: #add1 || $href2 (breaks #.jpeg hack, but had a purpose?) - $str = '<a href="' . $href /*#($href2)*/ . '">' . $title . '</a>'; - } - #-- img tag - else { - $type = array("image"); - if (is_string($meta)) { - $meta = unserialize($meta); - } - $str = ewiki_link_img($href, $id, $title, $meta, $spaces_l+2*$spaces_r, $obj, $states); - } - } - - #-- icon/transform plugins - ksort($type); - if ($pf_a = @$ewiki_plugins["link_final"]) { - foreach ($pf_a as $pf) { $pf($str, $type, $href, $title, $states); } - } - if (isset($states["xhtml"]) && $states["xhtml"]) { - foreach ($states["xhtml"] as $attr=>$val) { - $str = str_replace("<a ", "<a $attr=\"$val\" ", $str); - } - } - - return($str); -} - - -/* - assembles an <img> tag -*/ -function ewiki_link_img($href, $id, $title, $meta, $spaces, $obj, $states) { - - #-- size of cached image - $x = $meta["width"]; - $y = $meta["height"]; - - #-- width/height given in url - if ($p = strpos($id, '?')) { - $id = str_replace("&", "&", substr($id, $p+1)); - parse_str($id, $meta); - if ($uu = $meta["x"].$meta["width"]) { - $x = $uu; - } - if ($uu = $meta["y"].$meta["height"]) { - $y = $uu; - } - if ($scale = $meta["r"] . $meta["scale"]) { - if ($p = strpos($scale, "%")) { - $scale = strpos($scale, 0, $p) / 100; - } - $x *= $scale; - $y *= $scale; - } - } - - #-- alignment - $align = array('', ' align="right"', ' align="left"', ' align="center"'); - $align = $align[$spaces]; - $size = ($x && $y ? " width=\"$x\" height=\"$y\"" : ""); - - #-- remove annoyances - if ($href==$title) { - $title = ""; - } - - #-- do - return - ($obj ? '<embed' : '<img') - . ' src="' . $href . '"' - . ' alt="' . htmlentities($title) . '"' - . (@$states["titled"] ? ' title="' . htmlentities($title) . '"' : '') - . $size . $align - . ($obj ? "></embed>" : " />"); - # htmlentities($title) -} - - -function ewiki_stripentities(&$str) { - static $un = array("<"=>"<", ">"=>">", "&"=>"&"); - $str = strtr($str, $un); -} - - -/* - Returns URL if it encounters an InterWiki:Link or workalike. -*/ -function ewiki_interwiki(&$href, &$type, &$s) { - global $ewiki_config, $ewiki_plugins; - - $l = strpos($href, ":"); - if ($l and (strpos($href,"//") != $l+1) and ($p1 = strtok($href, ":"))) { - $page = strtok("\000"); - - if (($p2 = ewiki_array($ewiki_config["interwiki"], $p1)) !== NULL) { - $p1 = $p2; - $type = array("interwiki", $uu); - while ($p1_alias = $ewiki_config["interwiki"][$p1]) { - $type[] = $p1; - $p1 = $p1_alias; - } - if (!strpos($p1, "%s")) { - $p1 .= "%s"; - } - $href = str_replace("%s", $page, $p1); - return($href); - } - elseif ($pf = $ewiki_plugins["intermap"][$p1]) { - return($pf($p1, $page)); - } - elseif ($pf_a = $ewiki_plugins["interxhtml"]) { - foreach($pf_a as $pf) { - $pf($p1, $page, $s); - } - $href = $page; - } - } -} - - -/* - implements FeatureWiki:InterMapWalking -*/ -function ewiki_intermap_walking($id, &$data, $action) { - if (empty($data["version"]) && ($href = ewiki_interwiki($id, $uu, $uu))) { - header("Location: $href$sid"); - return("<a href=\"$href\">$href</a>"); - } -} - - - -function ewiki_link($pagename, $title="") { - if (!($url = ewiki_interwiki($pagename, $uu, $uu))) { - $url = ewiki_script("", $pagename); - } - if (!$title) { $title = $pagename; } - return("<a href=\"$url\">".htmlentities($title)."</a>"); -} - - - -# ========================================================================= - - - -##### ## ## ## ## ##### ## ## -###### ## ### ## #### ###### ## ## -## ## ## ### ## ###### ## ## ## ## -##### ## #### ## ## ## ###### ###### -##### ## ####### ###### #### #### -## ### ## ## #### ###### ##### ## -## ### ## ## ### ## ## ## ### ## -###### ## ## ### ## ## ## ## ## -###### ## ## ## ## ## ## ## ## - - - - -/* fetch & store -*/ -function ewiki_binary($break=0) { - - global $ewiki_plugins; - - #-- reject calls - if (!strlen($id = @$_REQUEST[EWIKI_UP_BINARY]) || !EWIKI_IDF_INTERNAL) { - return(false); - } - if (headers_sent()) die("ewiki-binary configuration error"); - - #-- upload requests - $upload_file = @$_FILES[EWIKI_UP_UPLOAD]; - $add_meta = array(); - if ($orig_name = @$upload_file["name"]) { - $add_meta["Content-Location"] = urlencode($orig_name); - $add_meta["Content-Disposition"] = 'inline; filename="'.urlencode(basename("remote://$orig_name")).'"'; - } - - #-- what are we doing here? - if (($id == EWIKI_IDF_INTERNAL) && ($upload_file)) { - $do = "upload"; - } - else { - $data = ewiki_db::GET($id); - $flags = @$data["flags"]; - if (EWIKI_DB_F_BINARY == ($flags & EWIKI_DB_F_TYPE)) { - $do = "get"; - } - elseif (empty($data["version"]) and EWIKI_CACHE_IMAGES) { - $do = "cache"; - } - else { - $do = "nop"; - } - } - - #-- auth only happens when enforced with _PROTECTED_MODE_XXL setting - # (authentication for inline images in violation of the WWW spirit) - if ((EWIKI_PROTECTED_MODE>=5) && !ewiki_auth($id, $data, "binary-{$do}")) { - return($_REQUEST["id"]="view/BinaryPermissionError"); - } - - #-- upload an image - if ($do == "upload"){ - - $id = ewiki_binary_save_image($upload_file["tmp_name"], "", $return=0, $add_meta); - @unlink($upload_file["tmp_name"]); - ($title = trim($orig_name, "/")) && ($title = preg_replace("/[^-._\w\d]+/", "_", substr(substr($orig_name, strrpos($title, "/")), 0, 20))) - && ($title = ' \\"'.$title.'\\"') || ($title=""); - - if ($id) { - echo<<<EOF -<html><head><title>File/Picture UploadYour uploaded file was saved as
      -[$id] -.

      -EOF; - } - } - - #-- request for contents from the db - elseif ($do == "get") { - - #-- send http_headers from meta - if (is_array($data["meta"])) { - foreach ($data["meta"] as $hdr=>$val) { - if (($hdr[0] >= "A") && ($hdr[0] <= "Z")) { - header("$hdr: $val"); - } - } - } - - #-- fetch from binary store - if ($pf_a = $ewiki_plugins["binary_get"]) { - foreach ($pf_a as $pf) { $pf($id, $data["meta"]); } - } - - #-- else fpassthru - echo $data["content"]; - } - - #-- fetch & cache requested URL, - elseif ($do == "cache") { - - #-- check for standard protocol names, to prevent us from serving - # evil requests for '/etc/passwd.jpeg' or '../.htaccess.gif' - if (preg_match('@^\w?(http|ftp|https|ftps|sftp)\w?://@', $id)) { - - #-- generate local copy - $filename = tempnam(EWIKI_TMP, "ewiki.local.temp."); - if(!copy($id, $filename)){ - ewiki_log("ewiki_binary: error copying $id to $filename", 0); - } else { - $add_meta = array( - "Content-Location" => urlencode($id), - "Content-Disposition" => 'inline; filename="'.urlencode(basename($id)).'"', - 'PageType' => 'CachedImage' - ); - - $result = ewiki_binary_save_image($filename, $id, "RETURN", $add_meta); - } - } - - #-- deliver - if ($result && !$break) { - ewiki_binary($break=1); - } - #-- mark URL as unavailable - else { - $data = array( - "id" => $id, - "version" => 1, - "flags" => EWIKI_DB_F_DISABLED, - "lastmodified" => time(), - "created" => time(), - "author" => ewiki_author("ewiki_binary_cache"), - "content" => "", - "meta" => array("Status"=>"404 Absent"), - ); - ewiki_db::WRITE($data); - header("Location: $id"); - ewiki_log("imgcache: did not find '$id', and marked it now in database as DISABLED", 2); - } - - } - - #-- "we don't sell this!" - else { - if (strpos($id, EWIKI_IDF_INTERNAL) === false) { - header("Status: 301 Located SomeWhere Else"); - header("Location: $id"); - } - else { - header("Status: 404 Absent"); - header("X-Broken-URI: $id"); - } - } - - // you should not remove this one, it is really a good idea to use it! - die(); -} - - - - - - -function ewiki_binary_save_image($filename, $id="", $return=0, -$add_meta=array(), $accept_all=EWIKI_ACCEPT_BINARY, $care_for_images=1) -{ - global $ewiki_plugins; - - #-- break on empty files - if (!filesize($filename)) { - return(false); - } - - #-- check for image type and size - $mime_types = array( - "application/octet-stream", - "image/gif", - "image/jpeg", - "image/png", - "application/x-shockwave-flash" - ); - $ext_types = array( - "bin", "gif", "jpeg", "png", "swf" - ); - list($width, $height, $mime_i, $uu) = getimagesize($filename); - (!$mime_i) && ($mime_i=0) || ($mime = $mime_types[$mime_i]); - - #-- images expected - if ($care_for_images) { - - #-- mime type - if (!$mime_i && !$accept_all || !filesize($filename)) { - ewiki_die(ewiki_t("BIN_NOIMG"), $return); - return; - } - - #-- resize image - if ((strpos($mime,"image/")!==false) - && (EWIKI_IMAGE_RESIZE)) { // filesize() check now in individual resize plugins - if ($pf_a = $ewiki_plugins["image_resize"]) foreach ($pf_a as $pf) { - $pf($filename, $mime, $return); - clearstatcache(); - } - } - - #-- reject image if too large - if(filesize($filename) > EWIKI_IMAGE_MAXSIZE) { - ewiki_die(ewiki_t("BIN_IMGTOOLARGE"), $return); - return; - } - - #-- again check mime type and image sizes - list($width, $height, $mime_i, $uu) = getimagesize($filename); - (!$mime_i) && ($mime_i=0) || ($mime = $mime_types[$mime_i]); - - } - ($ext = $ext_types[$mime_i]) or ($ext = $ext_types[0]); - - #-- binary files - if ((!$mime_i) && ($pf = $ewiki_plugins["mime_magic"][0])) { - if ($tmp = $pf($content)) { - $mime = $tmp; - } - } - if (!strlen($mime)) { - $mime = $mime_types[0]; - } - - #-- store size of binary file - $add_meta["size"] = filesize($filename); - $content = ""; - - #-- handler for (large/) binary content? - if ($pf_a = $ewiki_plugins["binary_store"]) { - foreach ($pf_a as $pf) { - $pf($filename, $id, $add_meta, $ext); - } - } - - #-- read file into memory (2MB), to store it into the database - if ($filename) { - $f = fopen($filename, "rb"); - $content = fread($f, 1<<21); - fclose($f); - } - - #-- generate db file name - if (empty($id)) { - $md5sum = md5($content); - $id = EWIKI_IDF_INTERNAL . $md5sum . ".$ext"; - ewiki_log("generated md5sum '$md5sum' from file content"); - } - - #-- prepare meta data - $meta = array( - "class" => $mime_i ? "image" : "file", - "Content-Type" => $mime, - "Pragma" => "cache", - ) + (array)$add_meta; - if ($mime_i) { - $meta["width"] = $width; - $meta["height"] = $height; - } - - #-- database entry - $data = array( - "id" => $id, - "version" => "1", - "author" => ewiki_author(), - "flags" => EWIKI_DB_F_BINARY | EWIKI_DB_F_READONLY, - "created" => time(), - "lastmodified" => time(), - "meta" => &$meta, - "content" => &$content, - ); - - #-- write if not exist - $exists = ewiki_db::FIND(array($id)); - if (! $exists[$id] ) { - $result = ewiki_db::WRITE($data); - ewiki_log("saving of '$id': " . ($result ? "ok" : "error")); - } - else { - ewiki_log("binary_save_image: '$id' was already in the database", 2); - } - - return($id); -} - - - - -# ========================================================================= - - -#### #### #### ######## ######## -##### ##### #### ########## ########## -###### ###### #### #### ### #### ### -############# #### #### -############# #### ######## #### -#### ### #### #### ######## #### -#### # #### #### #### #### -#### #### #### ### #### #### ### -#### #### #### ######### ########## -#### #### #### ####### ######## - - - -/* yes! it is not necessary to annoy people with country flags, if - HTTP already provides means to determine the prefered language! -*/ -function ewiki_localization() { - - global $ewiki_t; - - $deflangs = ','.@$_ENV["LANGUAGE"] . ','.@$_ENV["LANG"] - . ",".EWIKI_DEFAULT_LANG . ",en,C"; - - foreach (explode(",", @$_SERVER["HTTP_ACCEPT_LANGUAGE"].$deflangs) as $l) { - - $l = strtok($l, ";"); - $l = strtok($l, "-"); $l = strtok($l, "_"); $l = strtok($l, "."); - - if ($l = trim($l)) { - $ewiki_t["languages"][] = strtolower($l); - } - } - - $ewiki_t["languages"] = array_unique($ewiki_t["languages"]); -} - - - - -/* poor mans gettext, $repl is an array of string replacements to get - applied to the fetched text chunk, - "$const" is either an entry from $ewiki_t[] or a larger text block - containing _{text} replacement braces of the form "_{...}" -*/ -function ewiki_t($const, $repl=array(), $pref_langs=array()) { - - global $ewiki_t; - - #-- use default language wishes - if (empty($pref_langs)) { - $pref_langs = $ewiki_t["languages"]; - } - - #-- large text snippet replacing - if (strpos($const, "_{") !== false) { - while ( (($l=strpos($const,"_{")) || ($l===0)) && ($r=strpos($const,"}",$l)) ) { - $const = substr($const, 0, $l) - . ewiki_t(substr($const, $l+2, $r-$l-2)) - . substr($const,$r+1); - } - } - - #-- just one string - else foreach ($pref_langs as $l) { - - if (is_string($r = @$ewiki_t[$l][$const]) || ($r = @$ewiki_t[$l][strtoupper($const)])) { - - foreach ($repl as $key=>$value) { - if ($key[0] != '$') { - $key = '$'.$key; - } - $r = str_replace($key, $value, $r); - } - return($r); - - } - } - - return($const); -} - - - - -/* takes all ISO-8859-1 characters into account - but won't work with all databases -*/ -function ewiki_lowercase($s) { - $len = strlen($s); - for ($i=0; $i<$len; $i++) { - if (ord($s[$i]) >= 192) { - $s[$i] = chr(ord($s[$i]) | 0x20); - } - } - return(strtolower($s)); -} - - - - -function ewiki_log($msg, $error_type=3) { - - if ((EWIKI_LOGLEVEL >= 0) && ($error_type <= EWIKI_LOGLEVEL)) { - - $msg = time() . " - " . - $_SERVER["REMOTE_ADDR"] . ":" . $_SERVER["REMOTE_PORT"] . " - " . - $_SERVER["REQUEST_METHOD"] . " " . $_SERVER["REQUEST_URI"] . " - " . - strtr($msg, "\n\r\000\377\t\f", "\r\r\r\r\t\f") . "\n"; - error_log($msg, 3, EWIKI_LOGFILE); - } -} - - - - -function ewiki_die($msg, $return=0) { - ewiki_log($msg, 1); - if ($return) { - return($GLOBALS["ewiki_error"] = $msg); - } - else { - die($msg); - } -} - - - -function ewiki_array_hash(&$a) { - return(count($a) . ":" . implode(":", array_keys(array_slice($a, 0, 3)))); -} - - - -/* provides an case-insensitive in_array replacement to search a page name - in a list of others; - the supplied $array WILL be lowercased afterwards, unless $dn was set -*/ -function ewiki_in_array($value, &$array, $dn=0, $ci=EWIKI_CASE_INSENSITIVE) { - - static $as = array(); - - #-- work around pass-by-reference - if ($dn && $ci) { $dest = array(); } - else { $dest = &$array; } - - #-- make everything lowercase - if ($ci) { - $value = strtolower($value); - if (empty($as[ewiki_array_hash($array)])) { // prevent working on the - foreach ($array as $i=>$v) { // same array multiple times - $dest[$i] = strtolower($v); - } - $as[ewiki_array_hash($dest)] = 1; - } - } - - #-- search in values - return(in_array($value, $dest)); -} - - - -/* case-insensitively retrieves an entry from an $array, - or returns the given $array lowercased if $key was obmitted -*/ -function ewiki_array($array, $key=false, $am=1, $ci=EWIKI_CASE_INSENSITIVE) { - - #-- make everything lowercase - if ($ci) { - $key = strtolower($key); - - $r = array(); - foreach ($array as $i=>$v) { - $i = strtolower($i); - if (!$am || empty($r[$i])) { - $r[$i] = $v; - } - else { - $r[$i] .= $v; //RET: doubling for images`meta won't happen - } // but should be "+" here for integers - } - $array = &$r; - } - - #-- search in values - if ($key) { - return(@$array[$key]); - } - else { - return($array); - } -} - - - - - -/* - generates {author} string field for page database entry updates -*/ -function ewiki_author($defstr="") { - - $author = @$GLOBALS["ewiki_author"]; - ($ip = &$_SERVER["REMOTE_ADDR"]) or ($ip = "127.0.0.0"); - ($port = $_SERVER["REMOTE_PORT"]) or ($port = "null"); - - #-- this call may be very slow (~20 sec) - if (EWIKI_RESOLVE_DNS) { - $hostname = gethostbyaddr($ip); - } - $remote = (($ip != $hostname) ? $hostname . " " : "") - . $ip . ":" . $port; - - (empty($author)) && ( - ($author = $defstr) || - ($author = $_SERVER["HTTP_FROM"]) || // RFC2068 sect 14.22 - ($author = $_SERVER["PHP_AUTH_USER"]) - ); - - (empty($author)) - && ($author = $remote) - || ($author = addslashes($author) . " (" . $remote . ")" ); - - return($author); -} - -/* - decodes {author} field for display in pages -*/ -function ewiki_author_html($orig, $tail=1) { - $str = strtok($orig, " (|,;/[{<+"); - $tail = $tail ? " " . strtok("\000") : ""; - #-- only IP - if (strpos($str, ":")) { - return('$orig"); - } - #-- mail address - elseif (strpos($str, "@")) { - // email_protect_*() now takes care of plugin pages - return("$str$tail"); - } - #-- host name - elseif (strpos($str, ".") < strrpos($str, ".")) { - return("$str$tail"); - } - #-- eventually an AuthorName - else { - return('' . $str . '' . $tail); - } - return($orig); -} - - - - - - - - - -/* Returns a value of (true) if the currently logged in user (this must - be handled by one of the plugin backends) is authenticated to do the - current $action, or to view the current $id page. - - alternatively just checks current authentication $ring permission level - - errors are returned via the global $ewiki_errmsg -*/ -function ewiki_auth($id, &$data, $action, $ring=false, $request_auth=0) { - - global $ewiki_plugins, $ewiki_ring, $ewiki_author, - $ewiki_errmsg, $ewiki_config; - $ok = true; - $ewiki_errmsg=""; - -#echo "_a($id,dat,$action,$ring,$request_auth)
      \n"; - - if (EWIKI_PROTECTED_MODE) { - - #-- set required vars - if (!isset($ewiki_ring)) { - $ewiki_ring = (int)EWIKI_AUTH_DEFAULT_RING; - } - if ($ring===false) { - $ring = NULL; - } - if ($ewiki_config["create"] && ($action=="edit")) { - $action = "create"; // used only/primarily in authentication plugins - } - - #-- plugins to call - $pf_login = @$ewiki_plugins["auth_query"][0]; - $pf_perm = $ewiki_plugins["auth_perm"][0]; - - #-- nobody is currently logged in, so try to fetch username, - # the login is not yet enforced - if ($pf_login && empty($ewiki_auth_user)) { - $pf_login($data, 0); - } - - #-- check permission for current request (page/action/ring) - if ($pf_perm) { - - #-- via _auth handler - $ok = $pf_perm($id, $data, $action, $ring, $request_auth); - - #-- if it failed, we really depend on the login , - # and then recall the _perm plugin - if ($pf_login && (($request_auth >= 2) || !$ok && $request_auth && (empty($ewiki_auth_user) || EWIKI_AUTO_LOGIN) && empty($ewiki_errmsg))) { -//@FIXME: complicated if() - strip empty(errmsg) ?? - $pf_login($data, $request_auth); - $ok = $pf_perm($id, $data, $action, $ring, $request_auth=0); - } - } - else { - $ok = !isset($ring) || isset($ring) && ($ewiki_ring <= $ring); - } - - #-- return error string - if (!$ok && empty($ewiki_errmsg)) { - ewiki_log("ewiki_auth: Access Denied ($action/$id, $ring/$ewiki_ring, $request_auth)"); - $ewiki_errmsg = ewiki_t("FORBIDDEN"); - } - } - - return($ok); -} - - -/* - Queries all registered ["auth_userdb"] plugins for the given - username, and compares password to against "db" value, sets - $ewiki_ring and returns(true) if valid. -*/ -function ewiki_auth_user($username, $password) { - global $ewiki_ring, $ewiki_errmsg, $ewiki_auth_user, $ewiki_plugins, $ewiki_author; - - if (empty($username)) { - return(false); - } - if (($password[0] == "$") || (strlen($password) > 12)) { - ewiki_log("_auth_userdb: password was transmitted in encoded form, or is just too long (login attemp for user '$username')", 2); - return(false); - } - - if ($pf_u = $ewiki_plugins["auth_userdb"]) - foreach ($pf_u as $pf) { - - if (function_exists($pf) && ($entry = $pf($username, $password))) { - - #-- get and compare password - if ($entry = (array) $entry) { - $enc_pw = $entry[0]; - } - $success = false - || ($enc_pw == substr($password, 0, 12)) - || ($enc_pw == md5($password)) - || ($enc_pw == crypt($password, substr($enc_pw, 0, 2))) - || function_exists("sha1") && ($enc_pw == sha1($password)); - $success &= $enc_pw != "*"; - - #-- return if it matches - if ($success) { - if (isset($entry[1])) { - $ewiki_ring = (int)($entry[1]); - } else { - $ewiki_ring = 2; //(EWIKI_AUTH_DEFAULT_RING - 1); - } - if (empty($ewiki_author)) { - ($ewiki_author = $entry[2]) or - ($ewiki_author = $username); - } - return($success && ($ewiki_auth_user=$username)); - } - } - } - - if ($username || $password) { - ewiki_log("_auth_userdb: wrong password supplied for user '$username', not verified against any userdb", 3); - $ewiki_errmsg = "wrong username and/or password"; -# ewiki_auth($uu, $uu, $uu, $uu, 2); - } - return(false); -} - - - - -/* - Returns field html strings, looks up previously selected values. - Don't use it for textareas, $value magically elects the input field type. -*/ -function ewiki_form($name, $value, $label="", $_text="| |\n", $inj="") { - global $_EWIKI, $ewiki_id; - static $fid = 50; - static $_sel = ' selected="selected"', $_chk = ' checked="checked"'; - - #-- prepare - $o = ""; - $_text = explode("|", $_text); - list($name, $type, $width, $height) = explode(":", $name); - $type = $type ? (strpos($type, "a") ? "a" : (strpos($type, "b") ? "b" : $type[0])) : "t"; - if ($inj) { $inj = " $inj"; } - $old_value = @$_EWIKI["form"][$ewiki_id][$name]; - - #-- select fields - if ((($type=="s") || strpos($value, "|")) && ($v = explode("|", $value))) { - $value = array(); - foreach ($v as $opt) { - $opt = strtok($opt, "="); ($title = strtok("|")) or ($title = $opt); - $value[$opt] = $title; - } - } - - #-- label, surrounding text - $o .= "$_text[0]"; - if ($fid++ && $label) { - $o .= ""; - } - //echo "$_text[1]"; - - #-- submit (as "button") - if (!$name || ($type=="b")) { - if ($name) { $name = " name=\"$name\""; } - $o .= ""; - } - #-- select - elseif (is_array($value)) { - $o .= ""; - } - #-- checkbox - elseif (($type=="c") || strpos($value, "]")) { - if (isset($old_value)) { $value = $old_value ? "1x" : ""; } - $sel = strpos($value, "x") ? $_chk : ""; - $o .= ""; - } - #-- textarea - elseif ($type=="a") { - if ($width && $height) { $inj .= " cols=\"$width\" rows=\"$height\""; } - $o .= ""; - } - #-- input field; text or hidden - else { - if ($width) { $inj .= " size=\"$width\""; } - if (isset($old_value)) { $value = $old_value; } - $type = ($type == "t") ? "text" : "hidden"; - $o .= ""; - } - - #-- fin - $o .= "$_text[2]"; - return($o); -} - - - - -/* reads all files from "./init-pages/" into the database, - when ewiki is run for the very first time and the FrontPage - does not yet exist in the database -*/ -function ewiki_eventually_initialize(&$id, &$data, &$action) { - - #-- initialize database only if frontpage missing - if (($id==EWIKI_PAGE_INDEX) && ($action=="edit") && empty($data["version"])) { - - ewiki_db::INIT(); - if ($dh = @opendir($path=EWIKI_INIT_PAGES)) { - while ($filename = readdir($dh)) { - if (preg_match('/^(['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+\w*)+/', $filename)) { - $found = ewiki_db::FIND(array($filename)); - if (! $found[$filename]) { - $content = implode("", file("$path/$filename")); - ewiki_scan_wikiwords($content, $ewiki_links, "_STRIP_EMAIL=1"); - $refs = "\n\n" . implode("\n", array_keys($ewiki_links)) . "\n\n"; - $save = array( - "id" => "$filename", - "version" => "1", - "flags" => EWIKI_DB_F_TEXT, - "content" => $content, - "author" => ewiki_author("ewiki_initialize"), - "refs" => $refs, - "lastmodified" => filemtime("$path/$filename"), - "created" => filectime("$path/$filename") // (not exact) - ); - ewiki_db::WRITE($save); - } - } - } - closedir($dh); - } - else { - echo "ewiki error: could not read from directory ". realpath($path) ."
      \n"; - } - - #-- try to view/ that newly inserted page - if ($data = ewiki_db::GET($id)) { - $action = "view"; - } - } -} - - - - -#--------------------------------------------------------------------------- - - - -######## ### ######## ### ######## ### ###### ######## -######## ### ######## ### ######## ### ###### ######## -## ## ## ## ## ## ## ## ## ## ## ## ## ## -## ## ## ## ## ## ## ## ## ## ## ## ## ## -## ## ## ## ## ## ## ## ## ## ## ## ## -## ## ## ## ## ## ## ## ## ## ## ## ## -## ## ## ## ## ## ## ######## ## ## ###### ###### -## ## ## ## ## ## ## ######## ## ## ###### ###### -## ## ######### ## ######### ## ## ######### ## ## -## ## ######### ## ######### ## ## ######### ## ## -## ## ## ## ## ## ## ## ## ## ## ## ## ## -## ## ## ## ## ## ## ## ## ## ## ## ## ## -######## ## ## ## ## ## ######## ## ## ###### ######## -######## ## ## ## ## ## ######## ## ## ###### ######## - - - - -#-- database API (static wrapper around backends) -class ewiki_db { - - - #-- load page - # returns database entry as array for the page whose name was given in - # $id key, usually fetches the latest version of a page, unless a specific - # $version was requested - # - function GET($id, $version=false) { - global $ewiki_db; - $r = $ewiki_db->GET($id, 0+$version); - ewiki_db::expand($r); - return($r); - } - - - #-- save page - # stores the page $hash into the database, while not overwriting existing - # entries unless $overwrite was set; returns 0 on failure, 1 if completed - # - function WRITE($hash, $overwrite=0) { - global $ewiki_db; - if (is_array($hash) && count($hash) && !defined("EWIKI_DB_LOCK")) { - #-- settype (for flat-file databases) - $hash["version"] += 0; - $hash["hits"] += 0; - $hash["lastmodified"] += 0; - $hash["created"] += 0; - ewiki_db::shrink($hash); - return $ewiki_db->WRITE($hash, $overwrite); - } - } - - #-- search - # returns dbquery_result object of database entries (also arrays), where - # the one specified column matches the specified content string; - # it is not guaranteed to only search/return the latest version of a page; - # $field may be an array, in which case an OR-search is emulated - # - function SEARCH($field, $content, $ci=1, $regex=0, $mask=0x0000, $filter=0x0000) { - global $ewiki_db; - $ci = ($ci ? "i" : false); - #-- multisearch (or connected) - if (is_array($field)) { - if (isset($field[0])) { // multiple $field names, just one $content string - $uu = $field; $field = array(); - foreach ($uu as $f) { - $field[$f] = $content; - } - } - $r = new ewiki_dbquery_result(array($field)); - foreach ($field as $f=>$c) { - $add = $ewiki_db->SEARCH($f, $c, $ci, $regex, $mask, $filter); - $r->entries = array_merge($r->entries, $add->entries); - unset($add); // dispose, hopefully - } - } - #-- single query - else { - $r = $ewiki_db->SEARCH($field, $content, $ci, $regex, $mask, $filter); - ewiki_db::dbquery_result($r); - } - return($r); - } - - - #-- full page list - # returns an dbquery_result object with __all__ pages, where each entry - # is made up of at least the fields from the database requested with the - # $fields array, e.g. array("flags","meta","lastmodified"); - # - function GETALL($fields, $mask=0x0000, $filter=0x0000) { - global $ewiki_db; - $fields[] = "flags"; - $fields[] = "version"; - $fields = array_flip($fields); - unset($fields["id"]); - $fields = array_flip($fields); - $r = $ewiki_db->GETALL($fields); - ewiki_db::dbquery_result($r); - return($r); - } - - - #-- check page existence - # searches for all given page names (in $list) in the database and returns - # an associative array with page names as keys and booleans as values; - # (int)0 for missing pages, and for existing ones the associated value is - # the page {flags} value or the {meta} data array (for binary entries) - # - function FIND($list) { - global $ewiki_db; - if (!count($list)) { - return($list); - } - return $ewiki_db->FIND($list); - } - - - #-- page hits - # increases the {hit} counter for the page given by $id - # - function HIT($id) { - global $ewiki_db; - return $ewiki_db->HIT($id); - } - - - #-- admin functions - function DELETE($id, $version=false) { - global $ewiki_db; - if (!defined("EWIKI_DB_LOCK")) - return $ewiki_db->DELETE($id, $version); - } - function INIT() { - global $ewiki_db; - return $ewiki_db->INIT(); - } - - - #-- virtual features - # ::CREATE() creates a new page hash (template) - # ::UPDATE() renews meta data (except version) to allow ::WRITE() - # ::APPEND() adds content to an existing text page - # - function CREATE($id, $flags=EWIKI_DB_F_TEXT, $author="") { - $data = array( - "id"=>$id, "version"=>1, "flags"=>$flags, - "content"=>"", "meta"=>array(), - "hits"=>0, "created"=>time(), - "lastmodified"=>time(), - "author"=>ewiki_author($author), - ); - return($data); - } - function UPDATE(&$data, $author="") { - global $ewiki_links; - #-- regenerate backlinks entry - ewiki_scan_wikiwords($data["content"], $ewiki_links, "_STRIP_EMAIL=1"); - $data["refs"] = "\n\n".implode("\n", array_keys($ewiki_links))."\n\n"; - #-- update meta info - $data["lastmodified"] = time(); - $data["author"] = ewiki_author($author); - $data["meta"]["user-agent"] = trim($_SERVER["HTTP_USER_AGENT"]); - } - function APPEND($id, $text, $textonly=1) { - ($data = ewiki_db::GET($id)) - or ($data = ewiki_db::CREATE($id)); - if (!strlen(trim($text)) or $textonly && (($data["flags"]&EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT)) { - return; - } - $data["content"] .= $text; - ewiki_db::UPDATE($data); - $data["version"]++; - return ewiki_db::WRITE($data); - } - - - #-- helper code - function expand(&$r) { - if (isset($r["meta"]) && is_string($r["meta"]) && strlen($r["meta"])) { - $r["meta"] = unserialize($r["meta"]); - } - } - function shrink(&$r) { - if (isset($r["meta"]) && is_array($r["meta"])) { - $r["meta"] = serialize($r["meta"]); - } - } - function dbquery_result(&$r) { - if (is_array($r)) { - $z = new ewiki_dbquery_result(array_keys($args)); - foreach ($r as $id=>$row) { - $z->add($row); - } - $r = $z; - } - } - -} // end of class - - - -#-- returned for SEARCH and GETALL queries, as those operations are -# otherwise too memory exhaustive -class ewiki_dbquery_result { - - var $keys = array(); - var $entries = array(); - var $buffer = EWIKI_DBQUERY_BUFFER; - var $size = 0; - - function ewiki_dbquery_result($keys) { - $keys = array_merge((array)$keys, array(-50=>"id", "version", "flags")); - $this->keys = array_unique($keys); - } - - function add($row) { - if (is_array($row)) { - if ($this->buffer) { - $this->size += strlen(serialize($row)); - $this->buffer = $this->size <= EWIKI_DBQUERY_BUFFER; - ewiki_db::expand($row); - } - else { - $row = $row["id"]; - } - } - $this->entries[] = $row; - } - - function get($all=0, $flags=0x0000, $type=0) { - $row = array(); - - $prot_hide = ($flags&0x0020) && EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING; - $flag_hide = ($flags&0x0003); - do { - if (count($this->entries)) { - - #-- fetch very first entry from $entries list - $r = array_shift($this->entries); - - #-- finish if buffered entry - if (is_array($r) && !$all) { - $row = $r; - } - #-- else refetch complete entry from database - else { - if (is_array($r)) { - $r = $r["id"]; - } - $r = ewiki_db::GET($r); - if (!$all) { - foreach ($this->keys as $key) { - $row[$key] = $r[$key]; - } - } else { - $row = $r; - } - } - unset($r); - } - else { - return(NULL); // no more entries - } - - #-- expand {meta} field - if (is_array($row) && is_string(@$row["meta"])) { - $row["meta"] = unserialize($row["meta"]); - } - - #-- drop unwanted results - if ($prot_hide && !ewiki_auth($row["id"], $row, 'view') - || ($flag_hide && ($row["flags"] & (EWIKI_DB_F_HIDDEN|EWIKI_DB_F_DISABLED))) - || ($type) && (($row["flags"] & EWIKI_DB_F_TYPE) != $type)) { - $row = array(); - } - } while (empty($row) && ($prot_hide || $flag_hide)); - - return($row); - } - - function count() { - return(count($this->entries)); - } -} - - - -#-- obsolete compatibility wrapper -function ewiki_database($action, $args, $sw1=0, $sw2=0, $pf=false) { - switch ($action) { - case "GET": - return ewiki_db::GET($args["id"], @$args["version"]); - case "WRITE": - return ewiki_db::WRITE($args, 0); - case "OVERWRITE": - return ewiki_db::WRITE($args, 1); - case "FIND": - return ewiki_db::FIND($args); - case "GETALL": - return ewiki_db::GETALL($args); - case "SEARCH": - return ewiki_db::SEARCH(implode("",array_keys($args)), implode("",$args)); - case "HIT": - return ewiki_db::HIT($args["id"]); - case "DELETE": - return ewiki_db::DELETE($args["id"], $args["version"]); - case "INIT": - return ewiki_db::INIT(); - } - echo "error: unknown database call '$action'
      \n"; - return false; -} - - - -#-- MySQL database backend (default, but will be teared out soon) -# Note: this is of course an abuse of the relational database scheme, -# but necessary for real db independence and abstraction -class ewiki_database_mysql { - - function ewiki_database_mysql() { - $this->table = EWIKI_DB_TABLE_NAME; - } - - - function GET($id, $version=false) { - $id = mysql_escape_string($id); - if ($version) { - $version = "AND (version=$version)"; - } else { - $version=""; - } - $result = mysql_query("SELECT *, pagename as id FROM {$this->table} - WHERE (pagename='$id') $version ORDER BY version DESC LIMIT 1" - ); - echo mysql_error(); - if ($result && ($r = mysql_fetch_array($result, MYSQL_ASSOC))) { - unset($r["pagename"]); - return($r); - } - } - - - function HIT($id) { - $id = mysql_escape_string($id); - mysql_query("UPDATE {$this->table} SET hits=(hits+1) WHERE pagename='$id'"); - } - - - function WRITE($hash, $overwrite=0) { - - $COMMAND = $overwrite ? "REPLACE" : "INSERT"; - $sql1 = $sql2 = ""; - $hash["pagename"] = $hash["id"]; - unset($hash["id"]); - foreach ($hash as $index=>$value) { - if (is_int($index)) { - continue; - } - $a = ($sql1 ? ', ' : ''); - $sql1 .= $a . $index; - $sql2 .= $a . "'" . mysql_escape_string($value) . "'"; - } - - $result = mysql_query("$COMMAND INTO {$this->table} ($sql1) VALUES ($sql2)"); - $result = ($result && mysql_affected_rows()) ?1:0; - return($result); - } - - - function FIND($list) { - $r = array(); - $sql = ""; - foreach (array_values($list) as $id) { - if (strlen($id)) { - $r[$id] = 0; - $sql .= ($sql ? " OR " : "") . - "(pagename='" . mysql_escape_string($id) . "')"; - } - } - $result = mysql_query("SELECT pagename AS id, meta, flags FROM {$this->table} WHERE $sql"); - if ($result) { - while ($row = mysql_fetch_array($result)) { - $id = $row["id"]; - if (strlen($row["meta"])) { - $r[$id] = unserialize($row["meta"]); - $r[$id]["flags"] = $row["flags"]; - } else { - $r[$id] = $row["flags"]; - } - } - } - return($r); - } - - - function GETALL($fields, $mask=0, $filter=0) { - $fields = implode(", ", $fields); - $f_sql = $mask ? "WHERE ((flags & $mask) = $filter)" : ""; - $result = mysql_query("SELECT pagename AS id, $fields FROM - {$this->table} $f_sql GROUP BY id, version DESC" - ); - $r = new ewiki_dbquery_result($fields); - $last = ""; - if ($result) while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { - $drop = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"]; - if (($last != $drop) && ($last = $drop)) { - $r->add($row); - } - } - return($r); - } - - - function SEARCH($field, $content, $ci="i", $regex=0, $mask=0, $filter=0) { - - $sql_fields = ", $field"; - if ($field == "id") { - $field = "pagename"; - $sql_fields = ""; - } - $content = mysql_escape_string($content); - if ($mask) { - $sql_flags = "AND ((flags & $mask) = $filter)"; - } - if ($regex) { - $sql_strsearch = "($field REGEXP '$content')"; - } - elseif ($ci) { - $sql_strsearch = "LOCATE('".strtolower($content)."', LCASE($field))"; - } - else { - $sql_strsearch = "LOCATE('$content', $field)"; - } - - $result = mysql_query( - "SELECT pagename AS id, version, flags $sql_fields - FROM {$this->table} - WHERE $sql_strsearch $sql_flags - GROUP BY id, version DESC - "); - - $r = new ewiki_dbquery_result(array("id","version",$field)); - $last = ""; - if ($result) while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { - $drop = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"]; - if (($last != $drop) && ($last = $drop)) { - $r->add($row); - } - } - return($r); - } - - - function DELETE($id, $version) { - $id = mysql_escape_string($id); - mysql_query("DELETE FROM {$this->table} WHERE pagename='$id' AND version=$version"); - } - - - function INIT() { - mysql_query("CREATE TABLE {$this->table} - (pagename VARCHAR(160) NOT NULL, - version INTEGER UNSIGNED NOT NULL DEFAULT 0, - flags INTEGER UNSIGNED DEFAULT 0, - content MEDIUMTEXT, - author VARCHAR(100) DEFAULT 'ewiki', - created INTEGER UNSIGNED DEFAULT ".time().", - lastmodified INTEGER UNSIGNED DEFAULT 0, - refs MEDIUMTEXT, - meta MEDIUMTEXT, - hits INTEGER UNSIGNED DEFAULT 0, - PRIMARY KEY id (pagename, version) ) - "); - echo mysql_error(); - } - - -} // end of class ewiki_database_mysql - -?> diff --git a/mods/wiki/fragments/404finder.php b/mods/wiki/fragments/404finder.php deleted file mode 100644 index 78ae357ef..000000000 --- a/mods/wiki/fragments/404finder.php +++ /dev/null @@ -1,86 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/fragments/binary.php b/mods/wiki/fragments/binary.php deleted file mode 100644 index c028d7ada..000000000 --- a/mods/wiki/fragments/binary.php +++ /dev/null @@ -1,27 +0,0 @@ - output is made inside "yoursite.php", you - could use such a lib wrapper beside yoursites/index.php - - It is also useful, if you want to keep binary data in a separate - database, say a db_flat_files one - because you can then set this up - herein without any affect to yoursites/ewiki.php - - Try also the new "z.php" wrapper instead, which provides access - to ?binary= database entries. -*/ - - - # remember to define() inside ewiki.php or yoursite.php: - define("EWIKI_SCRIPT_BINARY", "binary.php?binary="); - - - #-- that's all: - mysql_connect("localhost", "DBUSER", "DBPASSWORD"); - mysql_query("use DATABASENAME"); - - include("ewiki.php"); - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/blocks/README b/mods/wiki/fragments/blocks/README deleted file mode 100644 index 0d5e97a91..000000000 --- a/mods/wiki/fragments/blocks/README +++ /dev/null @@ -1,2 +0,0 @@ -"blocks" are basically rewritten plugins to be included() into yoursite.php -whereever you'd like its output to be. diff --git a/mods/wiki/fragments/blocks/calendar.php b/mods/wiki/fragments/blocks/calendar.php deleted file mode 100644 index aa19ed6d9..000000000 --- a/mods/wiki/fragments/blocks/calendar.php +++ /dev/null @@ -1,13 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/fragments/blocks/editsidetext.php b/mods/wiki/fragments/blocks/editsidetext.php deleted file mode 100644 index 015ed65e3..000000000 --- a/mods/wiki/fragments/blocks/editsidetext.php +++ /dev/null @@ -1,10 +0,0 @@ -'; - } - echo '
      Add some text here...
      ' . "\n\n"; - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/blocks/intpages.php b/mods/wiki/fragments/blocks/intpages.php deleted file mode 100644 index c50ac3ccd..000000000 --- a/mods/wiki/fragments/blocks/intpages.php +++ /dev/null @@ -1,19 +0,0 @@ -$uu) { - - echo "· " . ewiki_script("", $pid) . "
      \n"; - - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/blocks/mainmenu.php b/mods/wiki/fragments/blocks/mainmenu.php deleted file mode 100644 index c096e86bd..000000000 --- a/mods/wiki/fragments/blocks/mainmenu.php +++ /dev/null @@ -1,22 +0,0 @@ -' . "\n" . $mm . "\n\n"; - } - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/blocks/news.php b/mods/wiki/fragments/blocks/news.php deleted file mode 100644 index 177524754..000000000 --- a/mods/wiki/fragments/blocks/news.php +++ /dev/null @@ -1,59 +0,0 @@ -$id) { - - if ($row = ewiki_db::GET($id)) { - - $text = substr($row["content"], 0, $n_len); - $text = trim(strip_tags(strtr($text, "\r\n\t", " "))); - $text = str_replace("[internal://", "[ internal://", $text); - $text .= "\n"; -# $text .= " [...[read more | $id]]\n"; - - $o .= "__[$id]__\n" - . "$text\n" - . "%%%\n"; - } - } - - #-- pass thru renderer - if ($o) { - $o = ewiki_format($o); - echo('
      ' . $o . '
      '); - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/blocks/printhint.php b/mods/wiki/fragments/blocks/printhint.php deleted file mode 100644 index cbad84926..000000000 --- a/mods/wiki/fragments/blocks/printhint.php +++ /dev/null @@ -1,20 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/fragments/blocks/search.php b/mods/wiki/fragments/blocks/search.php deleted file mode 100644 index 45996e750..000000000 --- a/mods/wiki/fragments/blocks/search.php +++ /dev/null @@ -1,19 +0,0 @@ -. -*/ - - -if (true) { - - $pid = defined("EWIKI_PAGE_POWERSEARCH") ? EWIKI_PAGE_POWERSEARCH : EWIKI_PAGE_SEARCH; - - echo '' - . '' - . '' - . '' . "\n"; -} - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/css.php b/mods/wiki/fragments/css.php deleted file mode 100644 index 8754d0cd5..000000000 --- a/mods/wiki/fragments/css.php +++ /dev/null @@ -1,35 +0,0 @@ - diff --git a/mods/wiki/fragments/css/PlugInstall.css b/mods/wiki/fragments/css/PlugInstall.css deleted file mode 100644 index 296381978..000000000 --- a/mods/wiki/fragments/css/PlugInstall.css +++ /dev/null @@ -1,48 +0,0 @@ -.wiki.PlugInstall .xpi-upload { - color: black; - background: #aaaacc; - border: 2px solid #666699; - padding: 3px; -} -.wiki.PlugInstall .xpi-upload h4 { - margin-top: 0px; - padding: 2px; - background: #666699; - color: #ffffff; -} -.wiki.PlugInstall .xpi-upload td { - color: black; - background: #9999bb; - border: 1px solid #8888aa; -} - - -.wiki.PlugInstall .xpi-settings { - color: black; - background-color: #ccccdd; - border: 2px solid #aaaabb; - padding: 3px; -} -.wiki.PlugInstall .xpi-settings h4 { - margin-top: 0px; - padding: 2px; - background: #888899; - color: #ffffff; -} -.wiki.PlugInstall .xpi-settings td{ - color: black; - background: #bbbbcc; - border: 1px solid #aaaabb; -} -.wiki.PlugInstall td.xs-id { - background: #aa99af; -} -.wiki.PlugInstall td.xs-check { - background: #99889f; -} - -.wiki.PlugInstall input { - background: #bb4444; - border-color: #994444; - color: #ffffff; -} diff --git a/mods/wiki/fragments/css/README b/mods/wiki/fragments/css/README deleted file mode 100644 index 1f42a319d..000000000 --- a/mods/wiki/fragments/css/README +++ /dev/null @@ -1,31 +0,0 @@ - -The files in the css/ directory are either examples or page styles, -which were automatically loaded by the 'fragments/css.php' snippet. -You could create a "PageStyleFile.css" for every page of your wiki, -if you just include() the 'css.php' script. - - -core.css -¯¯¯¯¯¯¯¯ - Is an example (text/css) stylesheet, which shows how to tweak - the look of rendered pages using CSS. - - You could copy it into yoursites.css or do something like this in - yoursite.php: - - - - - - - - -calendar.css -¯¯¯¯¯¯¯¯¯¯¯¯ - These stylesheet definitions show all possible CSS classes that - are used within the calendar.php plugin. Use like core.css - diff --git a/mods/wiki/fragments/css/UserRegistry.css b/mods/wiki/fragments/css/UserRegistry.css deleted file mode 100644 index 9a7c34d10..000000000 --- a/mods/wiki/fragments/css/UserRegistry.css +++ /dev/null @@ -1,31 +0,0 @@ -/* - beatification for the UserRegistry - (overlaping login fields) -*/ - -.wiki .userreg-form-settings { - border:1px solid #993333; - background:#cc7766; - padding:10px; - width:200px; - overflow:display; -} -.wiki .userreg-form-settings input { - border-color:#883333; - background-color:#eecccc; -} - -.wiki .userreg-form-register { - border:1px solid #339933; - background:#77cc66; - padding:5px; - position:relative; - left:-30px; - padding-left:30px; - width:350px; - -moz-opacity:0.75; -} -.wiki .userreg-form-register input { - border-color:#338833; - background-color:#cceecc; -} diff --git a/mods/wiki/fragments/css/WikiNavBarStyle.css b/mods/wiki/fragments/css/WikiNavBarStyle.css deleted file mode 100644 index 63bb7740a..000000000 --- a/mods/wiki/fragments/css/WikiNavBarStyle.css +++ /dev/null @@ -1,60 +0,0 @@ -.wikiNavBar{ - width:150px; - padding: 0 0 1em 0; - margin-bottom: 0; - font-family: 'Trebuchet MS', 'Lucida Grande', - Verdana, Lucida, Geneva, Helvetica, - Arial, sans-serif; - color: #333; - background:inherit; - } - .wikiNavBar ul { - list-style-type: none; - margin: 0; - padding: 0; - border: none; - } - .wikiNavBar ul li { - display: block; - background-color:#ee9933; - } - .wikiNavBar ul a { /* ul needed for specificity */ - display: block; - padding: .2em 20px .1em 0.1em; - border-left: 10px solid #770011; - border-right: 10px solid #dd8822; - font-size:10pt; - background-color:#ee9933; - color: #fff; - font-weight:bold; - text-decoration: none; - width: 100%; - } - .wikiNavBar ul.wikiNavBarDepth2 a { - border-left: 20px solid; - padding-right: 10px; - } - .wikiNavBar ul.wikiNavBarDepth3 a { - border-left: 30px solid; - padding-right: 0px; - } - .wikiNavBar ul.wikiNavBarDepth4 a { - border-left: 40px solid; - border-right: none; - padding-right: none; - } - /* IE gets kind of confused on classes*/ - .wikiNavBar .activebutton li.inactivebutton a { - background-color:#ee9933; - } - .wikiNavBar li.activebutton a { - background-color:#992233; - } - .wikiNavBar a:hover { - background-color:#992233; - } - .wikiNavBar a:visited { - color: #fff; - font-weight:bold; - text-decoration: none; - } diff --git a/mods/wiki/fragments/css/WikiSetupWizard.css b/mods/wiki/fragments/css/WikiSetupWizard.css deleted file mode 100644 index 5a12c8230..000000000 --- a/mods/wiki/fragments/css/WikiSetupWizard.css +++ /dev/null @@ -1,5 +0,0 @@ -.wiki.view.WikiSetupWizard td { - background-color:#997777; - color:#ffffff; -} - diff --git a/mods/wiki/fragments/css/calendar.css b/mods/wiki/fragments/css/calendar.css deleted file mode 100644 index defa8cc49..000000000 --- a/mods/wiki/fragments/css/calendar.css +++ /dev/null @@ -1,54 +0,0 @@ - -/* - Include these style definitions into your sites` css for use with - the calendar plugin. - Note that there often two class names (old and new style), and that - we now prefer the cascading selector style: - - new old - ------------------------------------------------------------ - table.calendar table.caltable - .calendar .head td.calhead - .calendar .daynames th.caldays - .calendar .day td.calday - .calendar .today td.caltoday - .calendar a.found a.calpg - .calendar a.hide a.calhide -*/ - - -table.calendar { - background-color: #CDBDAD; -} -table.calendar td { - font-family: "Verdana", "Arial", sans-serif; -} - -table.calendar .head { - font-size: 8pt; - text-align: center; -} - -table.calendar .daynames { - color:#BA997A; - font-size: 8pt; - text-align:center; -} - -table.calendar .day { - font-size: 8pt; - text-align:right; -} -table.calendar .today{ - background-color:#D7CFC7; - font-size: 8pt; - text-align:right; -} - -table.calendar a.found { - text-decoration: none; - font-weight:600; -} -table.calendar a.hide { - text-decoration: none; -} diff --git a/mods/wiki/fragments/css/core.css b/mods/wiki/fragments/css/core.css deleted file mode 100644 index 3d4ffe524..000000000 --- a/mods/wiki/fragments/css/core.css +++ /dev/null @@ -1,137 +0,0 @@ - -/* - This is an commented example on how to use ewikis` CSS class names. Note - that everything here starts with ".wiki" and NOT ".ewiki"! - -*/ - - -/* ---------------------------------------------- - every page that comes thru - ewiki is wrapped into: -*/ -.wiki { - background: url("wikibg.png") repeat-y; -} - - -/* ---------------------------------------------- - then you can select on $actions - or even page names -*/ -.wiki.edit { - background-color: #993322; -} - -.wiki.info { - background-color: #55cc50; -} - -.wiki.view.PageIndex { /* "PageIndex" when "view"ed */ - background-color: #ffee55; -} - -.wiki.SiteOverview { /* "SiteOverview" regardless of $action */ - font-family: "Lucida Bright"; -} - - - -/* ----------------------------------------------- - every page has a title now, always

      , - some of them enclose links (when "view"ed) -*/ -.wiki h2.page.title { - color: red; - border-bottom: 2px #eedddd solid; -} - -.wiki h2.page.title a { - color: #5555cc; - text-decoration: none; -} - - -/* ----------------------------------------------- - the ".action-links" or ".control-links" are the - list of links below every wiki page ('PageInfo' - and 'EditThisPage' ...) -*/ -.wiki.view .action-links { - background-color: #444444; - border: dashed 4px #444444; -} - -.wiki.view .action-links hr, .wiki .action-links br { - display: none; -} - -.wiki.view .action-links a { - color: #ffffff; -} - -.wiki.view .action-links a:hover { - background: #151155; -} - - -/* ----------------------------------------------- - the "info" pages result list is often - chunked into parts -*/ -.wiki.info .chunked-result a { - text-decoration: underline; - basckground-color: #ddbb55; -} - - -/* ----------------------------------------------- - the "edit" pages form elements are grouped -*/ -.wiki.edit .edit-box { - /* usually encloses a textarea and two submit buttons */ -} - -.wiki.edit .edit-box textarea { - border: 2px solid #000000; - background-color: #ccccff; -} - -.wiki.edit form[name=ewiki] { - /* old way, doesn't work with good old IE reliable */ -} - -.wiki.edit .image-upload { - background: url("image-upload.jpeg") no-repeat; -} - -.wiki.edit .preview { - background-image: url("dashed.png"); - font-size:50%; -} - - -/* - for the complete list of available class names - please always visit the README and the plugins - which also provide documentation of any such - features -*/ - - - -/* ----------------------------------------------- - inside of rendered pages, there is only little - CSS, if you do not utilize plugins/markup_css - and create some of your own -*/ - -.wiki .indent { /* space-indentation */ - margin-left: 5px; -} - -.wiki em { - color:#331111; -} - - diff --git a/mods/wiki/fragments/css/forum.css b/mods/wiki/fragments/css/forum.css deleted file mode 100644 index cbf652adc..000000000 --- a/mods/wiki/fragments/css/forum.css +++ /dev/null @@ -1,24 +0,0 @@ - - -.wiki .forum li { - background-color:#444444; - color:#ffffff; - list-bullet-style:none; -} - -.wiki .forum li .title { -} -.wiki .forum li .title a { - text-decoration:none; - color:#9999ff; -} - -.wiki .forum li .author { - color:#cccccc; -} -.wiki .forum li .date { - color:#cccc99; - font-size:8px; - width:30px; -} - diff --git a/mods/wiki/fragments/force_lang_de.php b/mods/wiki/fragments/force_lang_de.php deleted file mode 100644 index b5add283c..000000000 --- a/mods/wiki/fragments/force_lang_de.php +++ /dev/null @@ -1,50 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/fragments/funcs/README b/mods/wiki/fragments/funcs/README deleted file mode 100644 index 2ed683183..000000000 --- a/mods/wiki/fragments/funcs/README +++ /dev/null @@ -1,5 +0,0 @@ -This subdir collects various code snippets, which may or may not be useful -for some of your purposes. - -Everyone who believes to have a somehow interesting piece of code, is asked -to just send it to us. diff --git a/mods/wiki/fragments/funcs/auth.php b/mods/wiki/fragments/funcs/auth.php deleted file mode 100644 index 41b90cb18..000000000 --- a/mods/wiki/fragments/funcs/auth.php +++ /dev/null @@ -1,53 +0,0 @@ - "password", -// "u2" => "password", - ); - if (defined("EWIKI_ADMIN_PW")) { - $passwords["admin"] = EWIKI_ADMIN_PW; - } - if (empty($passwords)) { - die("

      Restricted Access

      \nPlease first create an admin account in '.../fragments/funcs/auth.php' or define() the 'EWIKI_ADMIN_PW' constant."); - } - - - #-- fetch user:password - if ($uu = $_SERVER["HTTP_AUTHORIZATION"]) { - foreach (explode(",", $uu) as $uu) { - $uu = trim($uu); - if (strtoupper(strtok($uu, " ")) == "BASIC") { - $uu = strtok(" "); - $uu = base64_decode($uu); - list($_a_user, $_a_password) = explode(":", $uu, 2); - } - } - } - elseif (strlen($_a_user = trim($_SERVER["PHP_AUTH_USER"]))) { - $_a_password = trim($_SERVER["PHP_AUTH_PW"]); - } - - #-- check password - $_success = false; - if ($_a_user && $_a_password && ($_a_password==@$passwords[$_a_user])) { - $_success = $_a_user; - } - - #-- request HTTP Basic authentication otherwise - if (!$_success) { - header('HTTP/1.1 401 Authentication Required'); - header('Status: 401 Authentication Required'); - header('WWW-Authenticate: Basic realm="restricted access"'); - die(); - } - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/funcs/save_newest_pages b/mods/wiki/fragments/funcs/save_newest_pages deleted file mode 100644 index 02332fd27..000000000 --- a/mods/wiki/fragments/funcs/save_newest_pages +++ /dev/null @@ -1,32 +0,0 @@ -/* - Reads the recently updated pages list from the database (like - "UpdatedPages") and tries to save it in another database table - (this example does so in my privately used webcms for speed purposes). -*/ - - -#-- save newest pages -function save_newest_pages() -{ - $sorted = array(); - $result = ewiki_db::GETALL(array("lastmodified", "flags", "version")); - while ($row = $result->get()) { - if (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) { - $sorted[$row["id"]] = $row["lastmodified"]; - } - } - arsort($sorted); - $n = 0; - $o = ""; - foreach ($sorted as $id=>$uu) { - $o .= '·' . - preg_replace('/(\w{15}[a-zäöüß]*)(\w{3,5})/', '$1­$2', $id) . "
      \n"; - if ($n++ >= 15) break; - } - $o = addslashes($o); - - mysql_query("UPDATE text_table SET html='$o' WHERE filename='wiki-updated' ") - or - return($o); -} - diff --git a/mods/wiki/fragments/funcs/wiki_format.inc b/mods/wiki/fragments/funcs/wiki_format.inc deleted file mode 100644 index dda6ad08b..000000000 --- a/mods/wiki/fragments/funcs/wiki_format.inc +++ /dev/null @@ -1,291 +0,0 @@ - - * Adapted by Frank Luithle - * - * WikiLinks and binary already stripped off -> just the rendering core - */ - -// URL prefixes -$ewiki_idf_url = array( "http://", - "mailto:", - "ftp://", - "irc://", - "telnet://", - "news://", - "internal://", - "chrome://", - "file://" ); - -// allowed wikinames -//define( "EWIKI_CHARS_L", "a-zäöüß_µ¤$" ); -//define( "EWIKI_CHARS_U", "A-ZÄÖÜ" ); - -function wiki_format( $wiki_source, - $strip_slashes = true, - $safe_html_allowed = true, - $table_html_allowed = false ) { - - if ( $strip_slashes ) { - $wiki_source = stripslashes( $wiki_source ); - } - - // formatted output - $o = "

      \n"; - - // state vars - $li_o = ""; - $tbl_o = 0; - $post = ""; - - $wm_whole_line = array( "!!!" => "h2", - "!!" => "h3", - "!" => "h4", - " " => "tt", - ";:" => 'div style="left-margin:10pt;"' ); - - $table_defaults = 'cellpadding="2" border="1" cellspacing="0"'; - - // these tags will be preserved if the $safe_html_allowed argument - // is set to 'true' - $rescue_html = array( "tt", "b", "i", "strong", "em", "s", "kbd", "var", - "xmp", "sup", "sub", "pre", "q", "h2", "h3", "h4", - "h5", "h6", "cite", "code", "u" ); - - $syn_htmlentities = array( "&" => "&", - ">" => ">", - "<" => "<", - "%%%" => "
      " ); - - $wm_list = array( "-" => array('ul type="square"', "", "li"), - "*" => array('ul type="circle"', "", "li"), - "#" => array("ol", "", "li"), - ":" => array("dl", "dt", "dd") ); - - $wm_text_style = array( "'''" => array("''__", "__''"), - "___" => array("''__", "__''"), - "''" => array("", ""), - "__" => array("", ""), - // "^^" => array("", ""), - // "***" => array("", ""), - // "###" => array("", ""), - "**" => array("", ""), - "##" => array("", ""), - "µµ" => array("", "") ); - - $link_regex = "#(!?\[[^[\]\n]+\])|((?:!?[a-z]{2,6}://|mailto:)[^\s\[\]\'\"\)\,<]+)#"; - - #$link_regex = "#(!?\[[^[\]\n]+\])|((?:!?[".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L. - # ":]+){2}[\w\d]*)|((?:!?[a-z]{2,6}://|mailto:)[^\s\[\]\'\"\)\,<]+)#"; - - // eliminate html - foreach ( $syn_htmlentities as $find => $replace ) { - $wiki_source = str_replace( $find, $replace, $wiki_source ); - } - array_pop( $syn_htmlentities ); - - // unescape allowed html - if ( $safe_html_allowed ) { - foreach ( $rescue_html as $tag ) { - foreach( array( $tag, "/$tag", ( $tag = strtoupper($tag) ), "/$tag" ) - as $tag ) { - $wiki_source = str_replace( '<' . $tag . '>', - "<" . $tag . ">", - $wiki_source ); - } - } - } - - $wiki_source = trim( $wiki_source ) . "\n"; - - foreach ( explode( "\n", $wiki_source ) as $line ) { - $line = rtrim( $line ); - $post = ""; - - // paragraphs - if ( empty($line) ) { - $post .= "

      \n\n

      "; - } elseif ( strpos( $line, "----" ) === 0 ) { - $o .= "


      \n"; - continue; - } elseif ( strpos( $line, "<!--" ) === 0 ) { - $o .= "\n"; - continue; - } - - // unescape html markup || tables wiki markup - if ( strlen( $line ) && ( $line[0] == "|" ) ) { - if ( strlen( $line ) > - strlen( trim( $line, "|" ) ) + 1 ) { - $line = substr( $line, 1, strlen( $line ) - 2 ); - if ( !$tbl_o ) { - $o .= "\n"; - } - $line = "\n\n\n"; - $tbl_o = 1; - } elseif ( $table_html_allowed ) { - $line = ltrim( substr( $line, 1 ) ); - foreach ( array_flip( $syn_htmlentities ) as $find => $replace ) { - $line = str_replace( $find, $replace, $line ); - } - } - } elseif ($tbl_o) { - $o .= "
      " . str_replace("|", "", $line) . "
      \n"; - $tbl_o = 0; - } - - // whole-line wikimarkup - foreach ( $wm_whole_line as $find => $replace ) { - if ( substr( $line, 0, strlen($find) ) == $find ) { - $line = ltrim( substr( $line, strlen($find) ) ); - $o .= "<$replace>"; - $post = "" . $post; - } - } - - // wiki list markup - if ( strlen( $li_o ) || - strlen( $line ) && isset( $wm_list[@$line[0]] ) ) { - $n = 0; - $li = ""; - // count differences to previous list wikimarkup - while ( strlen( $line ) && ( $li0 = $line[0] ) && isset( $wm_list[$li0] ) ) { - $li .= $li0; - $n++; - $line = substr($line, 1); - } - $line = ltrim($line); - - // fetch list definition - if ( strlen( $li ) && ( $last_list_i = $li[strlen($li)-1] ) ) - list( $list_tag, $list_dt0, $list_entry_tag ) = $wm_list[$last_list_i]; - - // output
        until new list wikimarkup rule matched - while ( strlen($li_o) < strlen($li) ) { - $add = $li[ strlen($li_o) ]; - $o .= "<" . $wm_list[ $add ][ 0 ] . ">\n"; - $li_o .= $add; - } - - // close
      lists until "$li_o" == "$li" (list wikimarkup state var) - while ( strlen($li_o) > strlen($li) ) { - $del = $li_o[ strlen($li_o) - 1 ]; - $o .= "\n"; - $li_o = substr( $li_o, 0, strlen($li_o) - 1 ); - } - - // more work for
      lists - if ( !empty($list_dt0) ) { - list( $line_dt, $line ) = explode( $last_list_i, $line, 2 ); - $o .= "<$list_dt0>$line_dt"; - $list_dt0 = $last_list_i = false; - } - - // finally enclose current line in
    • ...
    • - if ( !empty($line) ) { - $o .= "<$list_entry_tag>"; - $post = "" . $post; - } - - $li_o = $li; - } - - // link-regex here?? - // (was formerly, may be faster if applied to the whole formatted - // page, but this could also introduce some rendering bugs) - - // text style triggers - foreach ( $wm_text_style as $find => $replace ) { - $n = strlen( $find ); - $loop = 20; - while( ( $loop-- ) && - ( ($l = strpos($line, $find)) !== false ) && - ( $r = strpos($line, $find, $l + $n) ) ) { - $line = substr( $line, 0, $l ) . $replace[0] . - substr( $line, $l + strlen($find), $r - $l - $n ) . - $replace[1] . substr( $line, $r + $n ); - } - } - - // add formatted line to page-output - $o .= $line . $post . "\n"; - - } - - // close last line - $o .= "

      \n"; - - // finally the link-detection-regex - // (impossible to do with simple string arithmetics) - $o = preg_replace_callback( $link_regex, "wiki_link_regex_callback", $o ); - - return( $o ); -} - - -function wiki_link_regex_callback( $uu ) { - - global $ewiki_idf_url; - - $str = $uu[0]; - - // link bracket '[' escaped with '!' - if ( $str[0] == "!" ) { - return(substr($str, 1)); - } elseif ( $str[0] == "[" ) { - $str = substr( $str, 1, strlen($str) - 2 ); - } - - // explicit title given via [ foo | bar ] - $href = $title = strtok( $str, "|" ); - if ( $uu = strtok("|") ) { - $href = $uu; - } - - // title and href swapped: swap back - if ( strpos( "://", $title ) || - strpos( $title, ":" ) && !strpos( $href, ":" ) ) { - $uu = $title; - $title = $href; - $href = $uu; - } - - $title = trim($title); - $href = trim($href); - - /* create _no_ WikiLinks */ - if ( false ): - // interwiki links - if ( strpos($href, ":") && - !strpos($href, "//") && - ($p1 = @$ewiki_interwiki[strtok($href, ":")]) ) { - while ($p1_alias = @$ewiki_interwiki[$p1]) { - $p1 = $p1_alias; - } - $href = $p1 . strtok("\000"); - } elseif (($ewiki_links === true) || - @$ewiki_links[$href] || - @$ewiki_internal_pages[$href]) { - // ordinary internal WikiLinks - $str = '' . $title . ''; - } else { - $str = '' . $title . '?'; - } - endif; - - // convert normal URLs - foreach ( $ewiki_idf_url as $find ) { - if ( strpos( $href, $find ) === 0 ) { - $str = '' . $title . ''; - break; - } - } - - return($str); -} - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/head/core.php b/mods/wiki/fragments/head/core.php deleted file mode 100644 index 0447c0b0e..000000000 --- a/mods/wiki/fragments/head/core.php +++ /dev/null @@ -1,17 +0,0 @@ - - - meta tags, if appropriate: - - NOINDEX for old revisions -*/ - -if (isset($_REQUEST["version"]) -or ($ewiki_data["lastmodified"]+12*60*60 > time())) { - echo ''."\n"; -} -elseif (isset($ewiki_id) && empty($ewiki_data["version"])) { - echo ''."\n"; -} - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/head/meta.php b/mods/wiki/fragments/head/meta.php deleted file mode 100644 index 9c902fcba..000000000 --- a/mods/wiki/fragments/head/meta.php +++ /dev/null @@ -1,51 +0,0 @@ - - - <&php echo $ewiki_title; &> - <&php include("fragments/head/meta.php"); &> - <&php include("fragments/css.php"); &> - - ... -*/ - -if ($ewiki_data && function_exists("ewiki_script")) { - if ($m = &$ewiki_data["meta"]["meta"]) { - - #-- real page data - $real_meta = array("keywords", "description", "author", "robots"); - foreach ($real_meta as $i) { - if ($m[$i]) { - echo ''."\n"; - } - } - - #-- site structure meta s - $rel_links = array("prev", "next", "contents", "chapter", "section", "start"); - foreach ($rel_links as $i) { - if ($m[$i]) { - echo ''."\n"; - } - } - - #-- alternate representations - $alt_repr = array("links", "edit"); - foreach ($alt_repr as $i) { - if ($ewiki_action==$i) { $i = ""; } - echo ''."\n"; - } - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/htaccess b/mods/wiki/fragments/htaccess deleted file mode 100644 index f0dc9651d..000000000 --- a/mods/wiki/fragments/htaccess +++ /dev/null @@ -1,25 +0,0 @@ -# This file is to be used with the Apache or Nanoweb webserver. -# -# Rename it to .htaccess (or .nwaccess for Nanoweb) in a dedicated -# directory for your Wiki. -# -# It uses the mod_rewrite to look a bit more professional than -# the usual GET-vars at the end of our URLs. This is highly -# recommended as things like "script.php?edit=1&id=page" usually -# scare search engines and may prevent your Wiki from getting -# indexed fully. -# -# Please edit ewiki.php and enable EWIKI_USE_PATH_INFO for Apache -# webservers - the PATH_INFO implementation is very broken for many -# versions (at least when you use the PHP-CGI variant), because the -# Apache Group once choosed to follow that never finished and -# heavily broken (proposed) "CGI/1.1 RFC". - -#-- enable mod_rewrite (Apache + Nanoweb) -RewriteEngine On - -#-- pass WikiWord-URLs to the wiki wrapper script: -RewriteRule ^((\w+/)?[A-Z]+[a-z]+\w*[A-Z]+\w+)$ yoursite.php/$1 [L] - -#-- or this one, if there is really nothing else in the same directory: -#RewriteRule ^(.*)$ yoursite.php?id=$1 [L] diff --git a/mods/wiki/fragments/ini.php b/mods/wiki/fragments/ini.php deleted file mode 100644 index 5c5ac49df..000000000 --- a/mods/wiki/fragments/ini.php +++ /dev/null @@ -1,85 +0,0 @@ -$v) { - $v = $v[0]; - if ($i[0] == "\$") { - $i = preg_replace("/[\s\"\'\$\]]/", "", $i); - $i = explode("[", $i); - switch (count($i) + (strlen($i[count($i)-1]) ? 0 : 10)) { - case 1: $GLOBALS[$i[0]] = $v; break; - case 2: $GLOBALS[$i[0]][$i[1]] = $v; break; - case 12: $GLOBALS[$i[0]][] = $v; break; - case 3: $GLOBALS[$i[0]][$i[1]][$i[2]] = $v; break; - case 13: $GLOBALS[$i[0]][$i[1]][] = $v; break; - case 4: $GLOBALS[$i[0]][$i[1]][$i[2]][$i[3]] = $v; break; - case 14: $GLOBALS[$i[0]][$i[1]][$i[2]][] = $v; - } - } - else { - @define($i, $v); - } - } - - #-- load plugins - foreach ($ini["plugins"]["load"] as $v) { - include_once($v); - } - $i = $v = $ini = NULL; -} - -#-- add core scripts -include_once("ewiki.php"); - - - -#-- load and decipher .ini files -function ewiki_parse_ini_file($fn) { - return ewiki_parse_ini_str(@implode("",file($fn))); -} -function ewiki_parse_ini_str($s) -{ - $r = array(); - $sect = "global"; - foreach (explode("\n", $s) as $line) { - $line = trim($line); - if ($line[0] == "[") { - $sect = trim(strtok(substr($line, 1), "]")); - } - elseif (($line[0] == ";") || ($line[0] == "#")) { - } - elseif (strpos($line, "=")) { - $opt = trim(strtolower(strtok($line, "="))); - $val = trim(strtok("\r\n")); - $r[$sect][$opt][] = $val; - } - } - return($r); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/js/pngbehaviour.htc b/mods/wiki/fragments/js/pngbehaviour.htc deleted file mode 100644 index e82c7aa08..000000000 --- a/mods/wiki/fragments/js/pngbehaviour.htc +++ /dev/null @@ -1,55 +0,0 @@ - - - - - diff --git a/mods/wiki/fragments/parent-cms/nuke_mod_wiki_index b/mods/wiki/fragments/parent-cms/nuke_mod_wiki_index deleted file mode 100644 index 56ffa2439..000000000 --- a/mods/wiki/fragments/parent-cms/nuke_mod_wiki_index +++ /dev/null @@ -1,58 +0,0 @@ - diff --git a/mods/wiki/fragments/patches/README b/mods/wiki/fragments/patches/README deleted file mode 100644 index aeaaceb2b..000000000 --- a/mods/wiki/fragments/patches/README +++ /dev/null @@ -1,14 +0,0 @@ -This directory is used to collect source code patches to get some -non-standard features to work. You'll find more detailed info on -what the patch does, and how to integrate it, in the according -code snippet files. - -Some of these patches may get integrated into the core and others -may be converted into plugins in future releases, however most stuff -in here is to uncommon and disliked to do so currently. - -Please also note, that the patches/ subdirectory should be used by -experienced users only, as it often requires you to have read the -README file and it also requires more skills than using the "unzip" -utility. -There is no support at all for these patches. \ No newline at end of file diff --git a/mods/wiki/fragments/patches/auth_ldap.patch b/mods/wiki/fragments/patches/auth_ldap.patch deleted file mode 100644 index 4737e4377..000000000 --- a/mods/wiki/fragments/patches/auth_ldap.patch +++ /dev/null @@ -1,148 +0,0 @@ - -This patch from AllianceTec modifies the users_ldap authentication backend, -and fixes caching problems for the HTTP login module (in the core). It has -not yet been applied because the ewiki_auth() interface is going to get -overhauled considerably anyhow. - - cd .../ewiki-R1.0Nx/ - patch -p1 < .../auth_ldap.patch - - ---- ewiki-R1.02a+dev3/ewiki.php 2004-09-29 14:14:48.000000000 -0500 -+++ at_patches/ewiki.php 2005-03-01 10:42:45.883229728 -0600 -@@ -3232,7 +3232,7 @@ - $ok = true; - $ewiki_errmsg=""; - --#echo "_a($id,dat,$action,$ring,$request_auth)
      \n"; -+#echo "_a($id,$data,$action,$ring,$request_auth)
      \n"; - - if (EWIKI_PROTECTED_MODE) { - -@@ -3337,6 +3337,13 @@ - if ($username || $password) { - ewiki_log("_auth_userdb: wrong password supplied for user '$username', not verified against any userdb", 3); - $ewiki_errmsg = "wrong username and/or password"; -+ // Alliance Technologies addition -+ #-- If the ewiki_auth_query_http plugin is loaded, we need the following to prevent the HTTP auth from being cached by the browser -+ if ($ewiki_plugins["auth_query"][0] == "ewiki_auth_query_http") { -+ header('HTTP/1.1 401 Authentication Required'); -+ header('Status: 401 Authentication Required'); -+ header('WWW-Authenticate: Basic realm="Login incorrect"'); -+ } - # ewiki_auth($uu, $uu, $uu, $uu, 2); - } - return(false); -@@ -3962,4 +3969,4 @@ - - - -- -\ No newline at end of file -+ - ---- ewiki-R1.02a+dev3/plugins/auth/users_ldap.php 2003-12-01 11:14:05.000000000 -0600 -+++ at_patches/users_ldap.php 2005-03-01 10:42:46.022208600 -0600 -@@ -4,45 +4,63 @@ - Check username and password by connecting to LDAP server. - */ - -- --#-- config --define("EWIKI_LDAP_SERVER", "ldap.example.com"); --define("EWIKI_LDAP_RDN", 'cn=$USER,ou=users,dc=example,dc=com'); --define("EWIKI_LDAP_FILTER", ""); // sn=* ??? --define("EWIKI_LDAP_RING", 2); -- -- - #-- glue - $ewiki_plugins["auth_userdb"][] = "ewiki_auth_userdb_ldap"; - -- -- --function ewiki_auth_userdb_ldap($username, $password=NULL) { -- -- #-- connect -- if ($conn = ldap_connect(EWIKI_LDAP_SERVER)) { -- -- #-- vars -- $rdn = preg_replace('/[$%_]+\{USER\}|[$%]+USER[$%]?/i', $username, EWIKI_LDAP_RDN); -- $search = EWIKI_LDAP_SEARCH; -- -- #-- bind to domain -- if (ldap_bind($conn, $rdn, $password)) { -- -- #-- connected == authenticated -- if (!$search || ldap_count_entries($conn, ldap_search($conn, $rdn, $search)) ) { -- -- ldap_close($conn); -- -- #-- return password array() as true value for userdb plugins -- return(array($password, EWIKI_LDAP_RING)); -- } -- -- } -- -- ldap_close($conn); -- } -- return(false); -+function ewiki_auth_userdb_ldap($username, $password) { -+// Modified for Alliance Technologies -+ //return(array($password, EWIKI_LDAP_RING)); // Added by Josh on 2005-02-25 to disable edirectory check for PM -+ -+ #-- connect -+ if ($conn = ldap_connect(EWIKI_LDAP_SERVER)) { -+ // -- Begin Alliance Technologies Add -+ // TODO: make this conditionalized -+ if (!ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3)) { -+ fatal_error("Failed to set LDAP Protocol version to 3, TLS not supported."); -+ } -+ if (!ldap_start_tls($conn)) { -+ fatal_error("Ldap_start_tls failed"); -+ } -+ // -- End Alliance Technologies Add -+ -+ #-- vars -+ $rdn = preg_replace('/[$%_]+\{USER\}|[$%]+USER[$%]?/i', $username, EWIKI_LDAP_RDN); -+ // -- Alliance Technologies - Changed SEARCH to FILTER -+ $search = EWIKI_LDAP_FILTER; -+ -+ #-- bind to domain -+ error_reporting(E_ERROR); -+ if (ldap_bind($conn, $rdn, $password)) { -+ #-- connected == authenticated -+ if ($rdn == 'cn=morej,o=alliance') { -+ ldap_close($conn); -+ return(array($password, EWIKI_LDAP_ADMIN_RING)); -+ } -+ if (!$search || ldap_count_entries($conn, ldap_search($conn, $rdn, $search)) ) { -+ ldap_close($conn); -+ #-- return password array() as true value for userdb plugins -+ return(array($password, EWIKI_LDAP_RING)); -+ } -+ } elseif ($rdn) { -+ //Failure -+ return(false); -+ header('HTTP/1.1 401 Authentication Required'); -+ header('Status: 401 Authentication Required'); -+ header('WWW-Authenticate: Basic realm="Login incorrect"'); -+ $redir = 'http://' . $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"] ; -+ $redir = ereg_replace('=.+/','=',$redir); -+ #header("Location: $redir"); -+ -+ echo('
      ');
      -+			var_dump($_SERVER);
      -+			echo('
      '); -+ die(); -+ } -+ error_reporting(E_ALL & ~E_NOTICE); -+ -+ ldap_close($conn); -+ } -+return(false); - } - --?> -\ No newline at end of file -+?> - diff --git a/mods/wiki/fragments/patches/binarystoredirect b/mods/wiki/fragments/patches/binarystoredirect deleted file mode 100644 index a384e2768..000000000 --- a/mods/wiki/fragments/patches/binarystoredirect +++ /dev/null @@ -1,37 +0,0 @@ -OBSOLETED: This patch is now worthless, cause there is now the possibility -to just set the EWIKI_DB_STORE_URL constant, so ewiki_script_binary() will -automatically take care and generate URLs directly to the binary_store data -directory then. - ---------------------------------------------------------------------------- - -If you use the plugins/binary_store.php to save binary files outside of the -SQL or dbff database, and you additionally store those plain files at a -location which is accessible via your webserver, then you will find it -useful to let ewiki generate URLs directly to there. -This means binary stuff like images is kept separate from the database and -can thus be accessed by the http clients directly. If you however direct -them directly to the stored files, you will loose some advantages of the -ewiki ?binary= code, like the Content-Type headers for example (you should -work around that by telling your webserver to utilize mime_magic for all -files in that binary_store directory). - - -- edit ewiki.php -- find the "function ewiki_script_binary(" -- add after the line "$url = ewiki_script(..." following: - - if (!$upload) { - $url = "http://www.mywikiserver.net/wiki/files/binary_store/" - . rawurlencode($id); - } - -- fin - -The above example assumes, that you directed the "binary_store" plugin to -save your binary files as is in the "/wiki/files/binary_store/" subdirectory -(see also your EWIKI_DB_STORE_DIRECTORY constant). - -This is an example and will not work if you do copy&paste without changing -the example url and path string. There is no support for this patch. - diff --git a/mods/wiki/fragments/patches/clickableimages b/mods/wiki/fragments/patches/clickableimages deleted file mode 100644 index 5bee3060f..000000000 --- a/mods/wiki/fragments/patches/clickableimages +++ /dev/null @@ -1,27 +0,0 @@ -To make clickable images, we'll need to patch the ewiki_link_regex_callback() -function. It must recall itself to get images rendered as links. - -- edit ewiki.php -- search for "function ewiki_link_regex_callb" -- after the whole code block "#-- anchors"\n... insert: - - #-- image links - if (strpos($title, "://") && ($title != $href)) { - $tmp_img = ewiki_link_regex_callback(array("[$title]")); - if (strpos($tmp_img, ") { - $text .= $_; - } - close F; - - $text =~ s/\$_GET/\$HTTP_GET_VARS/; - $text =~ s/\$_POST/\$HTTP_POST_VARS/; - $text =~ s/\$_REQUEST/\$HTTP_POST_VARS/; - $text =~ s/\$_SERVER/\$HTTP_SERVER_VARS/; - $text =~ s/\$_FILES/\$HTTP_POST_FILES/; - $text =~ s/\$_COOKIE/\$HTTP_COOKIE_VARS/; - $text =~ s/\$_ENV/\$HTTP_ENV_VARS/; - - open F, ">$file"; - print F $text; - close F; -} - diff --git a/mods/wiki/fragments/patches/uploadedfilenames b/mods/wiki/fragments/patches/uploadedfilenames deleted file mode 100644 index 017c9916b..000000000 --- a/mods/wiki/fragments/patches/uploadedfilenames +++ /dev/null @@ -1,18 +0,0 @@ -This patch will add the orignial (client side) filename to the internal:// -string generated by the binary upload functions. Usually these database -names only carry the md5 sum of the uploaded files content (which is good, -because no file can be uploaded twice). -You will get more readable filenames with db_flat_files, but this also -introduces a security risk because the client (and the users) define the -database filename. - - -- edit ewiki.php -- find the "function ewiki_binary_save_image(" -- go the the code block "#-- generate db file name" -- after the line "$md5sum = md5($content);" - insert following line: - - $md5sum = $add_meta["Content-Location"] . "." . $md5sum; - -- (alternatively you could replace the first "$md5sum = ..." line) diff --git a/mods/wiki/fragments/rss.php b/mods/wiki/fragments/rss.php deleted file mode 100644 index ea88091e2..000000000 --- a/mods/wiki/fragments/rss.php +++ /dev/null @@ -1,27 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/fragments/site_prot.php b/mods/wiki/fragments/site_prot.php deleted file mode 100644 index f4bbe09b7..000000000 --- a/mods/wiki/fragments/site_prot.php +++ /dev/null @@ -1,171 +0,0 @@ -= $max_hits) { - site_prot_trap($delay); - } - - #-- ignore following checks for humans - if ($ignore_humans && $data[4]) { - return(+1); - } - - #-- too many requests per time, - # measured according to the time slice the current lockfile exists - if ($data[0] > ($data[1]-$data[2]) / $a_ratio) { - site_prot_trap($delay); - } - - return(+2); - } - else { - if ($f = fopen($lockfile, "w")) { - fwrite($f, serialize($data)); - fclose($f); - - return(+1); - } - } - - return(-1); -} - - -#-- called if we want to stop the client -function site_prot_trap($delay=3) { - - #-- we want to slow down the bot, but not ourselfes - ignore_user_abort(0); - set_time_limit(30); - - #-- disable any establish output buffering - if (function_exists("ob_end_clean")) { - while (function_exists("ob_get_level") && ob_get_level() || ob_get_length()) { - ob_end_clean(); - } - } - - #-- send out a warning message for humans (to also allow for lock removal) - echo<< -

      Lock

      -Your IP -has been locked and you cannot make further
      -requests to this site.
      -
      -
      - No, please - -
      -EOF; - flush(); - - #-- should we flood our syslog here? - /* - ... - */ - - #-- slow down the bot, and exit the script - sleep($delay); - die(34); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/strike_register_globals.php b/mods/wiki/fragments/strike_register_globals.php deleted file mode 100644 index b80298c7e..000000000 --- a/mods/wiki/fragments/strike_register_globals.php +++ /dev/null @@ -1,49 +0,0 @@ - $value) { - - if (isset($GLOBALS[$varname]) && (substr($varname, 0, 5) == "ewiki")) { - - $uu_security_leak = 1; - - unset($GLOBALS[$varname]); - - $err_msg = "ewiki security alert: ".$_SERVER["REMOTE_ADDR"].":".$_SERVER["REMOTE_PORT"]." tried to set the variable \$$varname to '".rawurlencode($value)."'. Please deactivate register_globals!"; - syslog(LOG_CRIT, $err_msg); - error_log($err_msg, 0); - error_log($err_msg, 3, "/tmp/ewiki.log"); - } - } - - - if ($uu_security_leak) { - - if (EWIKI_DIE_FOR_SECURITY) { - die("

      Forbidden

      \nERROR #0257: For security reasons your request has been cancelled (and logged)."); - } - } - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/strip_wonderful_slashes.php b/mods/wiki/fragments/strip_wonderful_slashes.php deleted file mode 100644 index ca858c44e..000000000 --- a/mods/wiki/fragments/strip_wonderful_slashes.php +++ /dev/null @@ -1,49 +0,0 @@ - $value) { - - if (!is_array($value)) { - $GLOBALS[$AREA][$name] = stripslashes($value); - } - } - } - - } - - -?> \ No newline at end of file diff --git a/mods/wiki/fragments/zero_pagerank.php b/mods/wiki/fragments/zero_pagerank.php deleted file mode 100644 index 3f1ad5199..000000000 --- a/mods/wiki/fragments/zero_pagerank.php +++ /dev/null @@ -1,34 +0,0 @@ - - - - Zero PageRank - - - - - - - - - -

      Zero PageRank

      - -

      The link to was - identified as possible WikiSpam - and therefore is filtered through this page, which prevents indexing by - search engines and thus hinders spammers to achieve their (anyhow minimal) - Google page ranking bonus.

      - - -


      this page was brought to you by the - ewiki (hypertext management system) - project

      - - - \ No newline at end of file diff --git a/mods/wiki/index.php b/mods/wiki/index.php deleted file mode 100644 index a0c705a3b..000000000 --- a/mods/wiki/index.php +++ /dev/null @@ -1,60 +0,0 @@ -'; - echo $o; - echo '
      '; - } - echo $content; - // Show the Calendar if the page displayed has one associated with it. - if (function_exists("calendar_exists") && calendar_exists()) { - echo calendar(); - } - - require(AT_INCLUDE_PATH.'footer.inc.php'); - ?> diff --git a/mods/wiki/index_admin.php b/mods/wiki/index_admin.php deleted file mode 100644 index f8f43bda9..000000000 --- a/mods/wiki/index_admin.php +++ /dev/null @@ -1,10 +0,0 @@ - - -Hello Administrator!! :) - - \ No newline at end of file diff --git a/mods/wiki/index_instructor.php b/mods/wiki/index_instructor.php deleted file mode 100644 index 23f72af4e..000000000 --- a/mods/wiki/index_instructor.php +++ /dev/null @@ -1,11 +0,0 @@ - - \ No newline at end of file diff --git a/mods/wiki/init-pages/ATutorWiki b/mods/wiki/init-pages/ATutorWiki deleted file mode 100644 index b46da6e52..000000000 --- a/mods/wiki/init-pages/ATutorWiki +++ /dev/null @@ -1,15 +0,0 @@ - -* read the WikiHowto if you'd like to know what this can be used for -* learn how to CreatePages -* just click on EditThisPage to change the contents of a page -* make friends with WikiMarkup -* SearchPages or go to the list of NewestPages -* there are also lists of the MostVisitedPages, MostOftenChangedPages -* __UpdatedPages__ is however the most interesting place to go, because that's where you can keep track of editing activity (bookmark it!) -* Here are some FommatingOption you might use - -WordIndex ImageGallery OrphanedPages TextUpload WantedPages WikiDump WikiNews - -HitCounter FileUpload FileDownload EwikiLog PowerSearch ScanDisk RecentChanges - - diff --git a/mods/wiki/init-pages/CamelCase b/mods/wiki/init-pages/CamelCase deleted file mode 100644 index a10f12519..000000000 --- a/mods/wiki/init-pages/CamelCase +++ /dev/null @@ -1,7 +0,0 @@ -CamelCase describes rather nice what [WikiWord]s look like. Uppercase and -lowercase letters show up like the humps of camels. - -This linking scheme is often also called !BumbyText. - -While language purists hate Wikis for that naming scheme, it is on the other -hand very common in the computing world and well known to most programmers. diff --git a/mods/wiki/init-pages/CreatePages b/mods/wiki/init-pages/CreatePages deleted file mode 100644 index 73859cf57..000000000 --- a/mods/wiki/init-pages/CreatePages +++ /dev/null @@ -1,13 +0,0 @@ -If you'd like to add a new page to this site you first should find a page -with a related subject, as it is the goal of a Wiki hypertext system -to have its contents sensefully connected. - -If you found a page just click on EditThisPage so you can change -its contents. Find the right place to insert a HyperLink to your new page -and give it a nice new WikiWord. You should spend some time on choosing a -name for the new page, give it a talking name so others will want to click -it. - -After saving your changes, you'll see a question mark appear behind -the newly inserted WikiWord, because the specified page DoesNotYetExist. -Just click on it, so you get to the edit box for your new page. diff --git a/mods/wiki/init-pages/EditThisPage b/mods/wiki/init-pages/EditThisPage deleted file mode 100644 index 7c0d718ee..000000000 --- a/mods/wiki/init-pages/EditThisPage +++ /dev/null @@ -1,9 +0,0 @@ -There is a [EditThisPage] Link at the bottom of every page. Just click -on it to edit the currently shown page. - -You'll see a large input box appear with the current content inside. -Just make your additions or fix some typing errors and push the ![Save] -button. - -You do not need to be enrolled in this course to use this function! - diff --git a/mods/wiki/init-pages/ErfurtWiki b/mods/wiki/init-pages/ErfurtWiki deleted file mode 100644 index 18b734743..000000000 --- a/mods/wiki/init-pages/ErfurtWiki +++ /dev/null @@ -1,16 +0,0 @@ -ErfurtWiki is a WikiWikiWeb implementation in the PHP scripting -language and mainly contained in one script file. It is PublicDomain -(''you are free''). It was implemented more like a library and thus -allows very quick integration into existing web sites, also because -it does not enforce a specific page layout or requires you to choose -from a few factory page themes/skins. - -See the FeatureList or SoftwareNotes for what it can do. Or find out -more about it at [ErfurtWiki:] or http://ewiki.berlios.de/ (where -you could also get your own, using the very simple -[http://ewiki.berlios.de/installer/ WebInstaller]). - -There are also hundreds of other implementations available. You can -find out about them on the large WardsWiki:WikiEngines list or using -the [http://wikifeatures.wiki.taoriver.net/moin.cgi/WikiEngine WikiFeatures:WikiEngine] -comparision table (though still incomplete). diff --git a/mods/wiki/init-pages/ExtendedWikiMarkup b/mods/wiki/init-pages/ExtendedWikiMarkup deleted file mode 100644 index 616d1c372..000000000 --- a/mods/wiki/init-pages/ExtendedWikiMarkup +++ /dev/null @@ -1,180 +0,0 @@ -You really should learn what the basic WikiMarkup can do for you, before you -start to read about more complex features. - - -!! Image markup - -Images can be inlined into a page using square brackets around the absolute -www-address of the image file, like ![http://www/image.png]. - -To align an image (define how the following text flows around it) one -can add space characters inside the square brackets before and/or after -its !http://-address: -* text flows around on the right ![http://example.com/image.png ] -* left aligned image ![ http://example.com/image.png] -* with spaces on the left and right, a image will display centred - -One can also specify to which size a image shall be rescaled by the browser, -if this is added as parameters with a query string like appendation; for -example ![http://www.example.com/image.png?x=200&y=100] would scale the -image to 200 pixels width and 100 pixels height. One can also use width= and -height= parameters to do so. - - -!! Anchors [#AnchOrs] - -Instead of linking from page to page, one can also create inner page links -using so called anchors. Anchors are defined and referenced using the hash -sign inside square brackets. ![#anchorname] for example creates an anchor, -to reference it one must put the page name in front of the hash sign, -like ![ThisPage#anchorname]. - -Requiring a pagename in front of the anchor name to reference to it is some -overhead but the only senseful way to create valid links. So to create -links to an anchor on the current page one must write ![CurrentPage#anchor]. -But there is also the special dot notation, which allows to write -~[.#anchor] for a jump to an anchor inside of the current page. - -Anchors and anchor references can and should also be entitled using -quotation marks or the dash sign: -* ![#anchor "Title for this anchor"]. -* ![anchors title | #anchor2] - -If you ever happen to have a page name including the hash # sign as part of -its name, then you must escape this one by appending another hash at the end -of links to that page, like ~[PageAboutThe#Sign#] for example. - -Please also note, that this behaviour is configurable, so defining anchors -and referencing them may work differently on other sites. - - -!! footnotes - -To create a footnote {{ a footnote can contain additional information snippets}} -use double curly brackets. Usually creating a new page to explain something -in more detail is a much better approach, so the footnotes extension is a -plugin in ErfurtWiki and thus not available per default. - -!! Links - -* a WikiWord will form a hyperlink -* any valid www-address like http://www.example.com/ will do too -* many nonvalid addresses will do too, see file://localhost/etc/passwd -* [square brackets around text] makes a hyperlink -** adding (more) [[square brackets around it]] is more [[[[intuitive]]]] than with other wikis -** a ![title | for square bracket links ] can be added using the | character -*** the title should be on the left to the linked WikiWord -*** but for ewiki it can be on either side, because a http://www can be easily distinguished -** a !["title" for square bracket links] can also be assigned using quotation marks -*** the title inside the quotation marks can be on either side of the !["..." wiki link] or ![http:// "URL"] -*** you can use this too for image links -*** this scheme is useful, but incompatible with other !WikiSoftware -* the ! exclamation mark or the tilde ~ can be used to escape a !!WikiWord or a !!http://www.address.net/ and of course escapes !![square brackets] as easily -** this is more understandable than escaping with "[" like in other wikis (like [PhpWiki|PhpWiki:]) -* instead of square brackets, one may utilize the ^ character to make a ^^wikilink of !NotBumpyWords - - -!! Lists - -* one can create lists by writing an asterisk at the beginning of a line -*# or enumerated lists by using a hash sign instead -*# instead of the asterisk the - minus character can be used sometimes -* definition lists can be created using :: at the line start or as sublist -*:definition: explanation -*:anotherdef: another description -* there are some more rules -*# lists should be separated with an empty line from other text -*# put a space behind the list bullet (*, #, -, ::) -*# a space in front of a list bullet escapes it (the line won't become a list entry) - - -!! Paragraphs - -Every block of text (without empty lines) will form a paragraph. - - Text can be indented using spaces or TABs at the start of a line. - Lists, Tables and headlines cannot be indented. (Indentation is - counted in steps of ''nearly'' 3 spaces.) - -You can right align text by using two minus characters at the beginning of a -line, which is often used to sign a bracket of text. --- author - - -!! Text style - -* text can be made __bold__ or **bold** -* or ''italic'' -* ##big## and µµsmallµµ -* up^^set^^ - -But there exist equivalents in old style WikiMarkup: - -* '''bold''' -* '''''bold and italic''''' - -And ##most## of µµtheseµµ things **can** be __''combined''__. - - -!! hidden comments - -* you can add hidden comments to your page -** users just viewing the page won't notice it -** it can only be seen, when the page gets edited -* click on EditThisPage to see, how the standard HTML comment escape is used for this - - - - -!! !InterWiki:Links - -* there exist abbreviations for concurrent wikis on the web -* to reference a page from another wiki, just prepend the Wikis name and a colon before the remote !WikiPageName -** ErfurtWiki:ErfurtWiki -** WardsWiki:WikiClones -** WardsWiki:InterWiki -* that's why you should avoid the colon inside of square brackets - - -!!! page blocks - - - There can be some special areas within a Wiki page. And they are often - enclosed in so called tags, which look much like the ones of - [HTML|HyperTextMarkupLanguage]. You however must write them - all-lowercase, or else they won't work. - - - -! PRE-formatted text - -If you wish text to appear as you type it - that is, all spaces remain -where they are, and lines stay as long as you inserted it - then you need -a block of "pre-formatted" text. -* use the ...
      'tags' for a paragraph of preformatted text, - that still allowed to use [WikiWord]s and simple markup -* with ... instead you would really see text as you typed it, - with square brackets and other escapes not garbaging your text - -
      -   This    fragment is        a  ''pre-formatted''
      -      paragraph.
      -
      - - -! inline HTML - -Per default most HTML won't work in a Wiki (using the rescuehtml plugin at -least the simple tags would be allowed). So to use HTML in a Wiki page, it -must be specifically configured (the _DB_F_HTML flag) or this needed to be -globally allowed for your Wiki. - -* you can however designate blocks of HTML using -** ... (all lowercase!) -** ... which still allowed [WikiWord]s and most markup - - - -!! in-page plugins (macros) - -If configured, this wiki also allows to activate plugins inside of pages, which are called MpiPlugins. diff --git a/mods/wiki/init-pages/FormattingOptions b/mods/wiki/init-pages/FormattingOptions deleted file mode 100644 index d11192700..000000000 --- a/mods/wiki/init-pages/FormattingOptions +++ /dev/null @@ -1,18 +0,0 @@ -basic html can be used - -ABBR( a Adaptive Technology Resource Centre) - -|table|cells|can| -|be|merged|| -|| - - -an enumerated list -1. item 1 -2. item 2 \ No newline at end of file diff --git a/mods/wiki/init-pages/FrontPage b/mods/wiki/init-pages/FrontPage deleted file mode 100644 index 799caada8..000000000 --- a/mods/wiki/init-pages/FrontPage +++ /dev/null @@ -1,16 +0,0 @@ - -* read the WikiHowto if you'd like to know what this can be used for -* learn how to CreatePages -* just click on EditThisPage to change the contents of a page -* make friends with WikiMarkup -* SearchPages or go to the list of NewestPages -* there are also lists of the MostVisitedPages, MostOftenChangedPages -* __UpdatedPages__ is however the most interesting place to go, because that's where you can keep track of editing activity (bookmark it!) -* Here are some FormattingOptions you might use -8 Tools can be added to pages by typing in the following wiki words. - -WordIndex ImageGallery OrphanedPages TextUpload WantedPages WikiDump WikiNews - -HitCounter FileUpload FileDownload EwikiLog PowerSearch ScanDisk RecentChanges - - diff --git a/mods/wiki/init-pages/HyperLink b/mods/wiki/init-pages/HyperLink deleted file mode 100644 index fdf19b6be..000000000 --- a/mods/wiki/init-pages/HyperLink +++ /dev/null @@ -1,6 +0,0 @@ -Hyperlinks connect pieces of text technically and visually. Many text -snippets that are tied together this way are often called ''Hypertexts''. - -A WikiWikiWeb is a Hypertext system where you can easily add links using -contracted capitalized words called [WikiWord]s. - diff --git a/mods/wiki/init-pages/HyperTextMarkupLanguage b/mods/wiki/init-pages/HyperTextMarkupLanguage deleted file mode 100644 index 9240cb1f5..000000000 --- a/mods/wiki/init-pages/HyperTextMarkupLanguage +++ /dev/null @@ -1,7 +0,0 @@ -This is a language which applies formatting rules (color and size) to text -and which can be used to insert [HyperLink]s into it. HTML is __not__ a -programming language. - -Inside a [Wiki|WikiWikiWeb] HTML is usually disallowed (Wiki:WhyDoesntWikiDoHtml), -so the tags will show up as ordinary text and thus cannot be used to -encolor text or annoy other people. diff --git a/mods/wiki/init-pages/ImageUploading b/mods/wiki/init-pages/ImageUploading deleted file mode 100644 index 60d06efa7..000000000 --- a/mods/wiki/init-pages/ImageUploading +++ /dev/null @@ -1,10 +0,0 @@ -Most wiki software allows to include references to image files located on -some remote WorldWideWeb server. ErfurtWiki permits this too, but it can -additionally caches those referenced images, because of its database -design. - -This feature also allowed to implement a very easy to use image uploading -function, which can be used to insert images into a page while you edit -it (just see EditThisPage). This is usually allowed for all users -and thus is likely to grow the sites` content very quickly, not only in -means of text pieces, but instead more multimedia like. diff --git a/mods/wiki/init-pages/WikiHowto b/mods/wiki/init-pages/WikiHowto deleted file mode 100644 index 0db21ff9a..000000000 --- a/mods/wiki/init-pages/WikiHowto +++ /dev/null @@ -1,10 +0,0 @@ -A WikiWikiWeb allows its users to quickly and easy add or -change pages. Its best use is for collecting informations -to one very specific subject to build a powerful knowledge -base. But without contributors or editorial staff it won't -be a very useful tool. - -For informations on how to contribute read the notes about -how to CreatePages and the summary of available WikiMarkup, -then try out the EditThisPage link on the bottom of the -every page. diff --git a/mods/wiki/init-pages/WikiMarkup b/mods/wiki/init-pages/WikiMarkup deleted file mode 100644 index 4cf080808..000000000 --- a/mods/wiki/init-pages/WikiMarkup +++ /dev/null @@ -1,74 +0,0 @@ -Each page inside a WikiWikiWeb can be edited easily, and as writing -a page should be very easy to accomplish, there are only a few -rules, which are not all that senseless and annoying as the ones of the -HyperTextMarkupLanguage. - -Click on the [EditThisPage]Link at the bottom of this page or else -all you read here won't make much sense to you. - - -! Paragraphs - -* separate paragraphs inside the text with empty lines -* use three percent signs %%''''% to enforce a line break -* if you prepend text with spaces or tabs it will get indented - - -! !! Headlines - -* use an exclamation mark ! at the beginning of a line to create a small headline -* !! for medium -* !!! for large headlines - - -! text style - -* if you want to ''emphasize text'' enclose it in two single-quotes '' (usually looks italic) -* __text gets bold__ with two underscores __ (or if enclosed with two asterisks **) -* to make ##text big## enclose it in hash characters ## -* you can get µµ smaller text µµ using "µµ" likewise -* a ==typewrite like font== will be used if you enclose text in two equal == signs - - -! Lists - -* start a line with an asterisk * to begin a list -* use # instead for numerated lists -*# you can create sublists -*# subsequent list points should start with the same mix of * and # - - -! !HyperLinks - -* just enter a WikiWord inside your text to create a new HyperLink -* enclose some [words in square brackets] to create a !HyperLink inside the WikiWikiWeb which is not made up of a valid WikiWord -* any valid internet address (starting with [http://]) like http://www.example.com/ inside the text will be made clickable automagically -* enclose a www address or a !WikiLink inside square brackets [[freshmeat | http://www.freshmeat.net/projects/ewiki]] and assign it a neat title using quotation marks or the | character -** ![title | http://example.com] -** ![WikiWord "title"] or !["title for" WikiLink] -* if you don't want a !WikiWord or a !http://www-address (or ![anything] inside square brackets) to become a !HyperLink then just prepend it with a exclamation mark or a tilde -** !!NoHyperLink, ~~NoHyperLink -** !![no hyperlink], !!http://nolink.org/ - - -! Tables with | - -| just enclose | things with the dash | character | -| to build a | table structure | -| browsers usually | leave out the missing | cells | - -Please always put an empty line before and after a table, so it stands out from other text in its own paragraph. - - -! Pictures - -* to include an image into a page enclose its absolute www-address in square brackets, like ![[http://www.example.com/pics/image.png]] -* alternatively you could use the ImageUploading function, see EditThisPage - - -! More markup - -Please see the page about ExtendedWikiMarkup, if you'd like to know a bit -more about available markup. - - diff --git a/mods/wiki/init-pages/WikiWikiWeb b/mods/wiki/init-pages/WikiWikiWeb deleted file mode 100644 index 8daba23f4..000000000 --- a/mods/wiki/init-pages/WikiWikiWeb +++ /dev/null @@ -1,8 +0,0 @@ -WikiWikiWeb is the name of a Hypertext system implemented as application on -top of the WorldWideWeb service. It tries to make it much easier and faster -to contribute to existing content. Ward Cunningham had the idea and build -the [very first Wiki|http://c2.com/cgi/wiki?WelcomeVisitors] nowadays known -as [WardsWiki:]. - -ErfurtWiki is a piece of software which implements such an -application in the [PHP web scripting language | http://www.php.net/]. diff --git a/mods/wiki/init-pages/WikiWord b/mods/wiki/init-pages/WikiWord deleted file mode 100644 index 376d8b3cd..000000000 --- a/mods/wiki/init-pages/WikiWord +++ /dev/null @@ -1,31 +0,0 @@ -A !WikiWord is made up of two or more concatenated words with -uppercase letters (this is often also referred to as CamelCase). -If you write a word this way into a page of the WikiWikiWeb, you create -a new HyperLink. - -These are valid !WikiWords for example: - -* RunCapitalizedWordsTogether -* EditThisPage -* ThisIsAWikiWordAsWell - -while those are not: - -* IBM -* somewordswithoutuppercaseletters -* 123456789 - -You can also create [HyperLink]s inside your WikiWikiWeb which -are not made up of [WikiWord]s by using square brackets: - -* [[This is a sentence in square brackets which becomes a Hyperlink]] -* [[I'm a link too]] - -Sometimes you must be a bit creative to invent nice and talking !WikiWords, -but this can also be very funny. - -The letter case does not matter in ErfurtWiki, so that 'ErFurtWiKi' -points to the front page too. - -Read more about this on the page about WikiMarkup and the -[page about creating other pages | CreatePages]. diff --git a/mods/wiki/init-pages/WorldWideWeb b/mods/wiki/init-pages/WorldWideWeb deleted file mode 100644 index 37659a41a..000000000 --- a/mods/wiki/init-pages/WorldWideWeb +++ /dev/null @@ -1,4 +0,0 @@ -The most well-known internet service is the WWW, which is a Hypertext system built upon the HyperTextTransferProtocol and the HyperTextMarkupLanguage. - -WikiWikiWeb is a Hypertext system, but implemented as just one application of the WWW service itself (utilizing the already existing technical basis). -Contributing to a Wiki is not as complicated as creating and maintaining a www page (with all the additionally software and services which were necessary for that). diff --git a/mods/wiki/module.css b/mods/wiki/module.css deleted file mode 100644 index 9e4e795ad..000000000 --- a/mods/wiki/module.css +++ /dev/null @@ -1,225 +0,0 @@ - -/* - This sample stylesheet lists all possible stylesheet sections, that - ewiki and its plugins may output. But don't forget to also have a look - into the README section about this. (This also obsoletes the 'core.css' - sample in the fragments/css/ directory.) -*/ - - - -/* a typical wiki page outout is separated into following classes: - - .wiki.. - .text-head - h2.text-title - .text-body - <...> - .wiki-plugins - .action-links - . -*/ -.wiki.edit.FrontPage { - background: transparent; - background-color: white; - border:thin #cccccc solid; - padding:1em; - margin-right:1em; -} - -input[type=submit]{ - color:black; - border:thin black solid; - background-color:white; -} - -.wiki-plugins{ - background-color: white; - border:thin #999 solid; - font-weight:600; - padding:.2em; - -} - - -.edit-box{ - border: 1px solid #999; - background-color: white; - padding:1em; - -} - -/*-- links to non-existent pages*/ -.NotFound * { - text-decoration: none; - border-bottom: dashed 1px blue; -} -.NotFound a { - color: red; - border-bottom-style: none; -} - - -/*.wiki { - background: url("wikibg.png") repeat-y; -}*/ - - -/* ---------------------------------------------- - then you can select on $actions - or even page names -*/ -/*.wiki.edit { - background-color: #993322; -}*/ - -.wiki.info { - background-color: white; - border:thin #cccccc solid; - padding: 1em; -} - -.wiki.view.PageIndex { /* "PageIndex" when "view"ed */ - background-color: #ffee55; -} - -.wiki.SiteOverview { /* "SiteOverview" regardless of $action */ - font-family: "Lucida Bright"; -} -.version-info{ - border:thin black solid; - padding:1em; -} - - - -/* ----------------------------------------------- - every page has a title now, always

      , - some of them enclose links (when "view"ed) -*/ -/*.wiki h2.page.title { - color: red; - border-bottom: 2px #eedddd solid; -}*/ - -/*.wiki h2.page.title a { - color: #5555cc; - text-decoration: none; -}*/ - - -/* ----------------------------------------------- - the ".action-links" or ".control-links" are the - list of links below every wiki page ('PageInfo' - and 'EditThisPage' ...) -*/ -/*.wiki.view .action-links { - background-color: #444444; - border: dashed 4px #444444; -}*/ - -.wiki.view .action-links hr, .wiki .action-links br, hr { - display: none; -} - -/*.wiki.view .action-links a { - color: #ffffff; -}*/ - -/*.wiki.view .action-links a:hover { - background: #151155; -}*/ - - -/* ----------------------------------------------- - the "info" pages result list is often - chunked into parts -*/ -.wiki.info .chunked-result a { - text-decoration: underline; - background-color: #ddbb55; -} - - -/* ----------------------------------------------- - the "edit" pages form elements are grouped -*/ -.wiki.edit .edit-box { - /* usually encloses a textarea and two submit buttons */ -} - -.wiki.edit .edit-box textarea { - border: 1px solid #000000; - background-color: #eeeeee; -} - -.wiki.edit form[name=ewiki] { - /* old way, doesn't work with good old IE reliable */ -} - -/*.wiki.edit .image-upload { - background: url("image-upload.jpeg") no-repeat; -} -*/ -.wiki.edit .preview { - margin-bottom:1em; - border:thin #cccccc dashed; - font-size:100%; -} - -.attachments{ - background-color:white; - border:thin #cccccc solid; - margin:1em; - padding: 1em; -} - -.links, .view, .tour{ - border: thin #cccccc solid; - margin-right:1em; -padding:.5em; - -} -/* - -Calendar styles -*/ - -table.calendar { - background-color: #CDBDAD; - margin-top:1em; -} -table.calendar td { - font-family: "Verdana", "Arial", sans-serif; -} - -table.calendar .head { - font-size: 10pt; - text-align: center; -} - -table.calendar .daynames { - color:#BA997A; - font-size: 10pt; - text-align:center; -} - -table.calendar .day { - font-size: 10pt; - text-align:right; -} -table.calendar .today{ - background-color:#D7CFC7; - font-size: 8pt; - text-align:right; -} - -table.calendar a.found { - text-decoration: none; - font-weight:600; -} -table.calendar a.hide { - text-decoration: none; -} - - diff --git a/mods/wiki/module.php b/mods/wiki/module.php deleted file mode 100644 index 4dad17622..000000000 --- a/mods/wiki/module.php +++ /dev/null @@ -1,32 +0,0 @@ -getPrivilege()); -define('AT_ADMIN_PRIV_EWIKI', $this->getAdminPrivilege()); - -/******* - * if this module is to be made available to students on the Home or Main Navigation. - */ -$_student_tool = 'mods/wiki/index.php'; - - -/******* - * instructor Manage section: - */ -$this->_pages['mods/wiki/index.php']['title_var'] = 'wiki'; -$this->_pages['mods/wiki/index.php']['parent'] = 'tools/index.php'; -$this->_pages['mods/wiki/index.php']['img'] = 'mods/wiki/tlogo.png'; - - -?> \ No newline at end of file diff --git a/mods/wiki/module.sql b/mods/wiki/module.sql deleted file mode 100644 index e87c19e10..000000000 --- a/mods/wiki/module.sql +++ /dev/null @@ -1,3 +0,0 @@ -# sql file for EWiki module - -INSERT INTO `language_text` VALUES ('en', '_module','wiki','Wiki',NOW(),''); diff --git a/mods/wiki/module.xml b/mods/wiki/module.xml deleted file mode 100644 index c1bf1fb9c..000000000 --- a/mods/wiki/module.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - EWiki - This is an almost verbatim copy of ErfurtWiki, with a set of ATutor module files, embedded in the ATutor environment as a fully integrated Wiki application. - - - ATutor Team - info@atutor.ca - - - http://atutor.ca - GPL - - 0.4 - 2010-10-25 - stable - - - \ No newline at end of file diff --git a/mods/wiki/module_delete.php b/mods/wiki/module_delete.php deleted file mode 100644 index 322d3a611..000000000 --- a/mods/wiki/module_delete.php +++ /dev/null @@ -1,21 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/module_install.php b/mods/wiki/module_install.php deleted file mode 100644 index b1f735b39..000000000 --- a/mods/wiki/module_install.php +++ /dev/null @@ -1,65 +0,0 @@ -addError(array('MODULE_INSTALL', '
    • '.$directory.' does not exist. Please create it.
    • ')); -//} else if (!is_writable($directory) && @chmod($directory, 0666)) { -// $msg->addError(array('MODULE_INSTALL', '
    • '.$directory.' is not writeable. On Unix issue the command chmod a+rw.
    • ')); -//} - - -/****** - * 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); -} - -?> \ No newline at end of file diff --git a/mods/wiki/module_uninstall.php b/mods/wiki/module_uninstall.php deleted file mode 100644 index 60ce25da8..000000000 --- a/mods/wiki/module_uninstall.php +++ /dev/null @@ -1,26 +0,0 @@ -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->revertQueryFromFile(dirname(__FILE__) . '/module.sql', TABLE_PREFIX); -} - -?> \ No newline at end of file diff --git a/mods/wiki/page.php b/mods/wiki/page.php deleted file mode 100644 index 5fcfcbdcd..000000000 --- a/mods/wiki/page.php +++ /dev/null @@ -1,74 +0,0 @@ -
      '; - echo $o; - echo '

      '; - } - echo $content; - // Show the Calendar if the page displayed has one associated with it. - if (function_exists("calendar_exists") && calendar_exists()) { - echo calendar(); - } - - require(AT_INCLUDE_PATH.'footer.inc.php'); - ?> diff --git a/mods/wiki/plugins/.htaccess b/mods/wiki/plugins/.htaccess deleted file mode 100644 index fc35e4612..000000000 --- a/mods/wiki/plugins/.htaccess +++ /dev/null @@ -1,2 +0,0 @@ -Order Deny,Allow -Deny from All diff --git a/mods/wiki/plugins/action/calendarlist.meta b/mods/wiki/plugins/action/calendarlist.meta deleted file mode 100644 index c3ff2aa93..000000000 --- a/mods/wiki/plugins/action/calendarlist.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: action -hooks: action -type: action -title: calendarlist -description: lists all calendar entries for a page -priority: bonus diff --git a/mods/wiki/plugins/action/calendarlist.php b/mods/wiki/plugins/action/calendarlist.php deleted file mode 100644 index f6a4228a0..000000000 --- a/mods/wiki/plugins/action/calendarlist.php +++ /dev/null @@ -1,37 +0,0 @@ -$uu){ - if(! ewiki_isCalendarId($pageId)){ - unset($pages[$pageId]); - } - } - - if(0==count($pages)){ - return(ewiki_t("NOCALENDAR")); - }else{ - //ksort($pages); - $o = '
      '.ewiki_t('CALENDERFOR')." $id:
      "; - $o .= ewiki_list_pages($pages)."
      \n"; - } - - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/action/diff.meta b/mods/wiki/plugins/action/diff.meta deleted file mode 100644 index df89c2202..000000000 --- a/mods/wiki/plugins/action/diff.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -type: action -category: action -title: diff -description: shows text differences between two page versions -priority: recommended -hooks: action diff --git a/mods/wiki/plugins/action/diff.php b/mods/wiki/plugins/action/diff.php deleted file mode 100644 index 0bc8915bd..000000000 --- a/mods/wiki/plugins/action/diff.php +++ /dev/null @@ -1,86 +0,0 @@ - 0) { - $data0 = ewiki_db::GET($id, $old_ver); - } - - $o = ewiki_make_title($id, "Differences between version $new_ver and $old_ver of »{$id}«"); - - $o .= ewiki_stupid_diff($data["content"], $data0["content"]); - - return($o); - } - - - function ewiki_stupid_diff($new, $old, $show_unchanged=1, $informational=0) { - - $old = preg_split("/\s*\n/", trim($old)); - $new = preg_split("/\s*\n/", trim($new)); - - $diff_rm = array_diff($old, $new); - $diff_add = array_diff($new, $old); - if ($informational) { - $i = array_intersect($new, $old); - if (empty($i)) { - if (count($diff_add) >= (6.5 * count(array_unique($diff_rm)))) { - $o .= '
      (overwritten with previous[?] content)
      ' . "\n"; - $diff_add = array(); - } - elseif ($diff_rm) { - $o .= '
      (previous content completely removed)
      ' . "\n"; - $diff_rm = array(); - } - } - } - - foreach ($new as $i=>$line) { - - $i2 = $i; - while ($rm = $diff_rm[$i2++]) { - $o .= '
      - ' . htmlentities($rm) . "
      \n"; - unset($diff_rm[$i2-1]); - } - - if (in_array($line, $diff_add)) { - $o .= '
      + ' . htmlentities($line) . "
      \n"; - } - elseif ($show_unchanged) { - $o .= "
        " . htmlentities($line) . "
      \n"; - } - - } - - foreach ($diff_rm as $rm) { - $o .= '
      - ' . htmlentities($rm) . "
      \n"; - } - - return('
      ' . $o . '
      '); - } - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/action/diff_gnu.meta b/mods/wiki/plugins/action/diff_gnu.meta deleted file mode 100644 index 21d73a7ef..000000000 --- a/mods/wiki/plugins/action/diff_gnu.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: action -title: GNU diff -description: shows text difference of two page versions using 'diff' system utility -hooks: action -type: action diff --git a/mods/wiki/plugins/action/diff_gnu.php b/mods/wiki/plugins/action/diff_gnu.php deleted file mode 100644 index 6a1eeb5f5..000000000 --- a/mods/wiki/plugins/action/diff_gnu.php +++ /dev/null @@ -1,76 +0,0 @@ - 0) - $data0 = ewiki_db::GET($id, $old_ver); - - $o = ewiki_make_title($id, "Differences between version $new_ver and $old_ver of »{$id}«"); - - #-- create temporary files from wikipages - $file0 = tempnam(EWIKI_TMP, "ewiki.diff.gnu."); - $f = fopen($file0, "w"); - fwrite($f, $data0["content"]); - fclose($f); - $file1 = tempnam(EWIKI_TMP, "ewiki.diff.gnu."); - $f = fopen($file1, "w"); - fwrite($f, $data["content"]); - fclose($f); - - #-- parse thru GNU diff util - $fn = addslashes($id); - $OPTIONS .= " --label='$fn (version $old_ver)' --label='$fn (version $new_ver)' "; - $diff = shell_exec("diff $OPTIONS $file0 $file1"); - - #-- remove temporary files - unlink($file0); - unlink($file1); - - #-- encolor diff output - foreach (explode("\n", $diff) as $dl) { - - $str = substr($dl, 1); - - switch (substr($dl, 0, 1)) { - case "<": - case "-": - $o .= "- $str
      \n"; - break; - case ">": - case "+": - $o .= "+ $str
      \n"; - break; - case "*": - case "-": - break; - default: - $o .= "$dl
      "; - } - - } - - return($o); - } - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/action/diff_gnu_safemode.meta b/mods/wiki/plugins/action/diff_gnu_safemode.meta deleted file mode 100644 index e107e1b60..000000000 --- a/mods/wiki/plugins/action/diff_gnu_safemode.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: action -hooks: action -type: action -title: diff GNU/safemode -description: modification of the original diff_gnu plugin -priority: deprecated diff --git a/mods/wiki/plugins/action/diff_gnu_safemode.php b/mods/wiki/plugins/action/diff_gnu_safemode.php deleted file mode 100644 index 27d26b509..000000000 --- a/mods/wiki/plugins/action/diff_gnu_safemode.php +++ /dev/null @@ -1,99 +0,0 @@ - 0) - $data0 = ewiki_db::GET($id, $old_ver); - - $o = ewiki_make_title($id, "Differences between version $new_ver and $old_ver of »{$id}«"); - - #-- create temporary files from wikipages - $file0 = tempnam(EWIKI_TMP, "ewiki.diff.gnu."); - $f = fopen($file0, "w"); - fwrite($f, $data0["content"]); - fclose($f); - $file1 = tempnam(EWIKI_TMP, "ewiki.diff.gnu."); - $f = fopen($file1, "w"); - fwrite($f, $data["content"]); - fclose($f); - - #-- parse thru GNU diff util - $fn = addslashes($id); - $OPTIONS .= " --label='$fn (version $old_ver)' --label='$fn (version $new_ver)' "; - //following lines replace the original - //$diff = shell_exec("diff $OPTIONS $file0 $file1"); - $dfd = popen("diff $OPTIONS $file0 $file1", "r"); - $diff = ""; - while (!feof($dfd)) { - $diff .= fread($dfd, 5000); - } - pclose($dfd); - //end of moderation - - #-- remove temporary files - unlink($file0); - unlink($file1); - - #-- encolor diff output - foreach (explode("\n", $diff) as $dl) { - - $str = substr($dl, 1); - - switch (substr($dl, 0, 1)) { - case "<": - case "-": - $o .= "- $str
      \n"; - break; - case ">": - case "+": - $o .= "+ $str
      \n"; - break; - case "*": - case "-": - break; - default: - $o .= "$dl
      "; - } - - } - - return($o); - } - - -?> diff --git a/mods/wiki/plugins/action/email_page.meta b/mods/wiki/plugins/action/email_page.meta deleted file mode 100644 index 483f4dfb7..000000000 --- a/mods/wiki/plugins/action/email_page.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: action -hooks: action -type: action -title: email page -description: allows to email the current page to someone else -priority: extra diff --git a/mods/wiki/plugins/action/email_page.php b/mods/wiki/plugins/action/email_page.php deleted file mode 100644 index 1b7d9e42e..000000000 --- a/mods/wiki/plugins/action/email_page.php +++ /dev/null @@ -1,258 +0,0 @@ -When you are ready, click the \"_{EMAIL_THIS_PAGE}\" button.
      "; -$ewiki_t["en"]["EMAIL_THIS_PAGE"] = "Email this page"; - -#-- glue -if(function_exists("mail")) -{ - $ewiki_plugins["action"]['emailpage'] = "ewiki_page_wiki_email_page"; - $ewiki_config["action_links"]["view"]["emailpage"] = "EMAIL_THIS_PAGE"; -} - -$ewiki_t["c"]["EWIKIEMAILCSS"] = ' - - '; - -function isRequestNotSet($email_page,$email_address) -{ - return ( empty($email_page) || empty($email_address) ); -} - -function checkEmailField($email_page_to,$not_first_time) -{ - if ( empty($email_page_to) && $not_first_time == "1" ) - return "

      Please enter a valid e-mail address"; - else - return ""; -} - -function isUserInfoDefined($from_email,$from_name) -{ - return ( !empty($from_email) && !empty($from_name) ); -} - -function getUserInfo(&$email,&$name) -{ - global $ewiki_uservars; - - $email = $ewiki_uservars["E-Mail Address"]; - $name = $ewiki_uservars["Name"]; -} - -function htmlFormGenerate($defined,$id,$warning,$from_email,$from_name) -{ - $url = ewiki_script("emailpage", "$id"); - $info_url = ewiki_script("view","UserInfo"); - - if ($defined) - { - return(ewiki_make_title($id, $id, 2) . ewiki_t( -//-------------------------------------------- -<< -

      -

      - Your e-mail address: $from_email.
      Your name: $from_name
      These will be included in the e-mail content and used in the "From" header of the e-mail. -

      - If this is incorrect, please update your information -

      - Email address:
      - -

      - Send an additional note to the sender:
      - (Use <br> for a new line if necessary)
      - -

      - - -

      -END -)); -//-------------------------------------------- - } - else - { - return(ewiki_make_title($id, $id, 2) . ewiki_t( -//-------------------------------------------- -<< - Your e-mail address and/or name are currently not defined. -

      - In order to use this feature you must update your information and fill out both fields. - -END -)); -//-------------------------------------------- - } -} - -function buildEmail($id,$data,$emailText) -{ - $top = getTop(); - $preamble = getPreamble($id,$emailText); - $page = renderPage($id,$data); - $disclaimer = getDisclaimer(); - $bottom = getBottom(); - - $body = $top.$preamble.$page.$disclaimer.$bottom; - - return($body); -} - -function renderPage($id,$data) -{ - global $ewiki_plugins, $ewiki_links; - $ewiki_links = true; - - getUserInfo($from_email,$from_name); - - //allowed html tags for the email - $allow = "



        1. "; - - //Assume all links in page exist (eliminate the ? after undefined pages) - $render_args = array("scan_links" => 0,"html" => (EWIKI_ALLOW_HTML||(@$data["flags"]&EWIKI_DB_F_HTML)),); - - $page = ewiki_make_title($id, $id, 2); - $page .= $ewiki_plugins["render"][0] ($data["content"], $render_args); - $page = strip_tags($page,$allow); - - return($page); -} - -function getNote($emailText) -{ - if (empty($emailText)) - { - return NULL; - } - else - { - //allowed html tags for the note - $allow_note = "
          "; - - $note = "

          Here is a small message from the sender:
          $emailText


          "; - $note = strip_tags($note,$allow_note); - - return($note); - } -} - -function getTop() -{ - $top = ""; - $top .= ewiki_t("EWIKIEMAILCSS"); - $top .= "[LiveWeb Snapshot]
          "; - return($top); -} - -function getPreamble($id,$emailText) -{ - getUserInfo($from_email,$from_name); - - $link_url = ewiki_script("view","$id"); - $link="https://www.burgiss.com/liveweb/$link_url"; - - $note = getNote($emailText); - - $preamble = "

          The following e-mail is a stripped down snapshot of the \"$id\" page from Burgiss LiveWeb. "; - $preamble .= "If you have an account with us, click here to view it. "; - $preamble .= "This was sent from $from_name with an e-mail address registered as $from_email

          "; - $preamble .= "$note
          "; - - return($preamble); -} - -function getDisclaimer() -{ - $disclaimer = "

          NOTICE: If you have received this in error, rest asured that you are not on any mailing lists. "; - $disclaimer .= "If you have any concerns, please e-mail the webmaster.

          "; -} - -function getBottom() -{ - $bottom = "
          "; -} - -function getSubject($id) -{ - $subject = "[LiveWeb Snapshot] \"$id\""; - return($subject); -} - -function getHeaders($from_email,$from_name) -{ - /* To send HTML mail, you can set the Content-type header. */ - $headers = "MIME-Version: 1.0\r\n"; - $headers .= "Content-type: text/html; charset=iso-8859-1\r\n"; - - /* additional headers */ - $headers .= "From: \"$from_name\" <$from_email>\r\n"; - $headers .= "X-Mailer: ErfurtWiki/".EWIKI_VERSION."\r\n"; - - return($headers); -} - -function ewiki_page_wiki_email_page($id=0, $data=0, $action=0) -{ - if ( isRequestNotSet($_REQUEST["email_page"],$_REQUEST["email_address"]) ) - { - if($action == "emailpage") - { - getUserInfo($from_email,$from_name); - $defined = isUserInfoDefined($from_email,$from_name); - - $warning = checkEmailField($_REQUEST["email_address"],$_REQUEST["not_first_time"]); - - $html = htmlFormGenerate($defined,$id,$warning,$from_email,$from_name); - - return($html); - } - else - { - return "You shouldn't be here."; - } - } - - #-- email generation and sending - else - { - $emailAddress = $_REQUEST["email_address"]; - $emailText = $_REQUEST["email_text"]; - - getUserInfo($from_email,$from_name); - $headers = getHeaders($from_email,$from_name); - $subject = getSubject($id); - - $body = buildEmail($id,$data,$emailText); - - mail($emailAddress,$subject,$body,$headers); - - $success_message = "

          Success!

          Page sent to $emailAddress

          "; - $success_message .= "

          Click here to return to the page you just sent.

          "; - - return ( ewiki_t($success_message) ); - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/action/extract.meta b/mods/wiki/plugins/action/extract.meta deleted file mode 100644 index 7569b8da2..000000000 --- a/mods/wiki/plugins/action/extract.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: action -hooks: action -type: action -title: extract todo items -description: extracts todo items (@@TODO, @@DONE, @@CANCELLED), adds CSS for it -priority: bonus diff --git a/mods/wiki/plugins/action/extract.php b/mods/wiki/plugins/action/extract.php deleted file mode 100644 index c846609f0..000000000 --- a/mods/wiki/plugins/action/extract.php +++ /dev/null @@ -1,99 +0,0 @@ -".$ewiki_plugins["render"][0] ( $extractedContent.ewiki_t(strtoupper($action)."POSTSCRIPT") , 1, - EWIKI_ALLOW_HTML || (@$data["flags"]&EWIKI_DB_F_HTML) )."
          "; - - #-- control line + other per-page info stuff - if ($pf_a = $ewiki_plugins["view_append"]) { - ksort($pf_a); - foreach ($pf_a as $n => $pf) { - - $o .= $pf($id, $data, $action); - } - } - if ($pf_a = $ewiki_plugins["view_final"]) { - ksort($pf_a); - foreach ($pf_a as $n => $pf) { - if(!preg_match('/_title/',$pf)){ - $pf($o, $id, $data, $action); - } - } - } - - return($o); - } - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/action/htm.meta b/mods/wiki/plugins/action/htm.meta deleted file mode 100644 index 524511e8e..000000000 --- a/mods/wiki/plugins/action/htm.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: action -hooks: action -type: action -title: WikiFeatures:SnippetPublishing -description: sends the html text body of a page only diff --git a/mods/wiki/plugins/action/htm.php b/mods/wiki/plugins/action/htm.php deleted file mode 100644 index 18659073e..000000000 --- a/mods/wiki/plugins/action/htm.php +++ /dev/null @@ -1,13 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/action/info_qdiff.meta b/mods/wiki/plugins/action/info_qdiff.meta deleted file mode 100644 index da0c4ca55..000000000 --- a/mods/wiki/plugins/action/info_qdiff.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: action -hooks: action -type: action -title: QuickDiff -description: 'quickdiff' shows the differences between all page versions contiguous -priority: extra diff --git a/mods/wiki/plugins/action/info_qdiff.php b/mods/wiki/plugins/action/info_qdiff.php deleted file mode 100644 index b24e7e575..000000000 --- a/mods/wiki/plugins/action/info_qdiff.php +++ /dev/null @@ -1,50 +0,0 @@ -= 2) { - - #-- get - if ($d = ewiki_db::GET($id, $ver-1)) { - $curr = $prev; - $prev = $d; - $d = NULL; - } - else { - continue; - } - - #-- info header - $o .= '' . "\n" . '\n"; - - #-- diff part - $diff = ewiki_stupid_diff($curr["content"], $prev["content"], $show_unchanged=0, $magic_notes=1); - $o .= '\n
          ' - . 'version $ver" - . '' . ewiki_author_html($curr["author"]) - . '' . strftime($CLK, $curr["lastmodified"]) - . "
          ' . $diff; - $o .= "\n
          \n
          \n"; - - } - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/action/like_pages.meta b/mods/wiki/plugins/action/like_pages.meta deleted file mode 100644 index 0eed52c12..000000000 --- a/mods/wiki/plugins/action/like_pages.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -type: action -category: action -title: LikePages -description: shows up a list of similar named pages -priority: standard -hooks: action diff --git a/mods/wiki/plugins/action/like_pages.php b/mods/wiki/plugins/action/like_pages.php deleted file mode 100644 index 9f39bc55e..000000000 --- a/mods/wiki/plugins/action/like_pages.php +++ /dev/null @@ -1,37 +0,0 @@ -get()) { - if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $row, "view")) { - continue; - } - - $pages[$row["id"]] = ""; - } - - } - - $o = ewiki_make_title($id, ewiki_t(strtoupper($action)."_TITLE"), 3); - $o .= ewiki_list_pages($pages, 0); - - return($o); - } - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/action/manpage.meta b/mods/wiki/plugins/action/manpage.meta deleted file mode 100644 index a8f85d33a..000000000 --- a/mods/wiki/plugins/action/manpage.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: action -hooks: action -type: action -title: ManPage -description: converts page into man(1) document (nroff/troff) -priority: rare diff --git a/mods/wiki/plugins/action/manpage.php b/mods/wiki/plugins/action/manpage.php deleted file mode 100644 index 77c03a313..000000000 --- a/mods/wiki/plugins/action/manpage.php +++ /dev/null @@ -1,144 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/action/raw.meta b/mods/wiki/plugins/action/raw.meta deleted file mode 100644 index d92a0d95d..000000000 --- a/mods/wiki/plugins/action/raw.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: action -title: RawSource -description: allows to download the 'source code' of a page (text/wiki) -priority: bonus -hooks: action -type: action diff --git a/mods/wiki/plugins/action/raw.php b/mods/wiki/plugins/action/raw.php deleted file mode 100644 index b6a66c936..000000000 --- a/mods/wiki/plugins/action/raw.php +++ /dev/null @@ -1,25 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/action/relatedchanges.meta b/mods/wiki/plugins/action/relatedchanges.meta deleted file mode 100644 index a0887d34e..000000000 --- a/mods/wiki/plugins/action/relatedchanges.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: action -hooks: action_always -type: action -title: RelatedChanges -description: relchanges/WikiPage will look for changed pages in backlinks -priority: extra diff --git a/mods/wiki/plugins/action/relatedchanges.php b/mods/wiki/plugins/action/relatedchanges.php deleted file mode 100644 index c1f74ffc0..000000000 --- a/mods/wiki/plugins/action/relatedchanges.php +++ /dev/null @@ -1,18 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/action/rss.meta b/mods/wiki/plugins/action/rss.meta deleted file mode 100644 index 2af994d71..000000000 --- a/mods/wiki/plugins/action/rss.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: action -hooks: action, page -type: page -title: RSS/Atom -description: provides a RSS/Atom feed for individual pages (w/ content-negotiation) -priority: optional diff --git a/mods/wiki/plugins/action/rss.php b/mods/wiki/plugins/action/rss.php deleted file mode 100644 index f6af1a867..000000000 --- a/mods/wiki/plugins/action/rss.php +++ /dev/null @@ -1,48 +0,0 @@ -get(0, 0x0137, EWIKI_DB_F_TEXT)) { - $sort[$data["id"]] = $data["lastmodified"]; - } - arsort($sort); - $limit = 100; - foreach ($sort as $id=>$uu) { - $list[] = ewiki_db::GET($id); - if ($limit-- < 0) { break; } - } - } - - #-- history of current page - else { - $list[] = $data; - for ($v=$data["version"]-1; $v>=1; $v--) { - $d = ewiki_db::GET($id, $v); - $list[] = $d; - } - } - - ewiki_feed($list); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/action/translation.meta b/mods/wiki/plugins/action/translation.meta deleted file mode 100644 index e8023e38e..000000000 --- a/mods/wiki/plugins/action/translation.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: action -title: AutomaticTranslation -description: checks text language and provides a BabelFish or GoogleTrans link -priority: extra -hooks: handler -type: intercept diff --git a/mods/wiki/plugins/action/translation.php b/mods/wiki/plugins/action/translation.php deleted file mode 100644 index e5164f242..000000000 --- a/mods/wiki/plugins/action/translation.php +++ /dev/null @@ -1,185 +0,0 @@ - array("http://translate.google.com/translate_p?hl=en&ie=ISO-8859-1&prev=/language_tools", "langpair", "u"), - "babelfish" => array("http://babelfish.altavista.com/babelfish/urlload?tt=url", "lp", "url"), - "intertran" => array("http://intertran.tranexp.com.com/Translate/index.shtml&type=url", array("from", "to"), "url"), -); -$language_detect = array( - "en" => "the to of is and this for be if you with an or it on not as that by will are see also can from use only file your at note may no which all false when about has have new one true any else more should without into first these own but must there do other", - ".en" => "ing ght y", - "de" => "die der und mit das sie den ist wird von eine im ein zu des auf dem werden oder aus wie datei es als nicht nen bei auch wenn einer einen an sind zur sich einem daß dass diese um zum nur gibt eines kann nach beim dann also dieser durch haben hat dabei alle jedoch noch aber dazu er diesem soll keine", - ".de" => "en ag", - "*de" => "isch cht wert ung ä ö ü ß", - "es" => "de en la el para que un una no los con por es se del como su las puede al página si ud texto ser sobre lo gina ginas esta entre más debe hay dos son este sus est nueva esto desde versi sin tiene pero dise cual uno sea nuevo mismo nea usar caso as pues ha eso all mucho bien dar estas estar tema tan desee aún nz os hace otros ya muy uno tulo nuevos deber poco le esa tal menos cap buena qu muchos hacer trav modo vaya tres lea nada vez vea ar met ve mi il út así está ese deja bajo sino muchas an qui está eso tema", - "fr" => "de la les le des pour est et l un en vous une sur dans du que par il qui es pas avec ne ce ou tre sont plus au qu me comme donn acc on pr cette peut tout si mais re se votre cela bien je sans autres aux vos cr ces ont fa fait puis cas avez ment ils temps autre sous mes fen donc ainsi tous alors apr te doit son chez deux tant res leur devez soit tat moins sa nom non ci faut peu avant avoir elle ses mot tes vue ceci elles bas ois ma er tait voulez ceux ex quoi", - "*fr" => "è", - "it" => "gli di nel ed per i della sono dell e con pi", - ".it" => "zion zione zioni zie zia ierie i", - "pt" => "do seu seus", - ".pt" => "ê", -); -$language_comb = array( - "google" => array( - "en|es", "en|fr", "en|de", "en|it", "en|pt", - "es|en", "fr|en", "de|en", "it|en", "pt|en", - "fr|de", "de|fr", - ), - "babelfish" => array( - "en|zh", "en|fr", "en|de", "en|it", "en|ja", "en|ko", "en|pt", "en|es", - "zh|en", "fr|en", "de|en", "it|en", "ja|en", "ko|en", "pt|en", "es|en", - "ru|en", "fr|de", "de|fr", - ), - "intertran" => array( - "*|*", - ), -); -$language_names = array( // for intertran - "ch" => "chi", "en" => "eng", "fr" => "fre", "it" => "ita", - "jp" => "jpn", "nl" => "dut", "po" => "pol", "pt" => "poe", - "ru" => "rus", "de" => "ger", "ed" => "spa", "lt" => "ltt", -); -$ewiki_t["C"]["en"] = "English"; -$ewiki_t["C"]["de"] = "German"; -$ewiki_t["C"]["fr"] = "French"; -$ewiki_t["C"]["es"] = "Spanish"; -$ewiki_t["C"]["it"] = "Italian"; -$ewiki_t["C"]["pt"] = "Portuguese"; - - - -$ewiki_plugins["handler"][] = "ewiki_add_action_link_for_translation"; - - - -function ewiki_add_action_link_for_translation($id, &$data, $action) { - - global $language_comb, $language_service, $language_names, $ewiki_t, - $ewiki_config; - - $o = ""; - $url = ""; - - if ($data["version"]) { - $lang_src = ewiki_guess_lang($data["content"]); - - #-- check if page is already in desired language - if ($ewiki_t["languages"][0] == $lang_src) { - } - else { - - foreach ($ewiki_t["languages"] as $lang_dest) { - - $url = ""; - $comb = "$lang_src|$lang_dest"; - - foreach ($language_service as $SERVICE=>$params) { - - if (in_array($comb, $language_comb[$SERVICE]) || ($SERVICE=="intertran")) { - if ($SERVICE == "babelfish") { - $lp = "&" . $params[1] . "=" . strtr($comb, "|", "_"); - } - elseif ($SERVICE == "google") { - $lp = "&" . $params[1] . "=" . $comb; - } - else { - $from = $language_names[strtok($comb, "|")]; - $to = $language_names[strtok("|")]; - if (!$from || !$to) { - continue; - } - $lp = "&" . $params[1][0] . "=" . $from - . "&" . $params[1][1] . "=" . $to; - } - $url = $params[0] . $lp - . "&" . $params[2] . "=" - . urlencode( ewiki_script($action, $id, "", 0, 0, - ewiki_script_url()) ); - break; - } - } - - #-- add translation link to page - if ($url) { - $ewiki_config["action_links"]["view"][$url] = "TranslateInto" . $ewiki_t["C"][$lang_dest]; - /*--- - $o = "
          " - . "TranslateInto" . $ewiki_t["C"][$lang_dest] - . "\n"; - ---*/ - break; - } - - } - } - } -/*--- - return($o); ----*/ -} - - - -function ewiki_guess_lang(&$data) { - - global $language_detect; - - #-- prepare - $detect = array( - "en"=>0, - "de"=>0, - ); - - #-- separate words in text page - $text = strtr( - " $data ", - "\t\n\r\f_<>\$,.;!()[]{}/", - " " - ); - - #-- search for words in text - foreach ($language_detect as $lang => $word_str) { - foreach (explode(" ", $word_str) as $word) { - switch ($lang[0]) { - case ".": - $word = "$word "; - case "*": - $lang = substr($lang, 1); - break; - default: - $word = " $word "; - } - $l = -1; - while ($l = strpos($text, $word, $l+1)) { - $detect[$lang]++; - } - } - } - - #-- get entry with most counts - $lang = EWIKI_DEFAULT_LANG; - arsort($detect); - $keys = array_keys($detect); - if (array_shift($detect) >= 5) { - $lang = array_shift($keys); - } - - return($lang); -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/action/verdiff.meta b/mods/wiki/plugins/action/verdiff.meta deleted file mode 100644 index 5f9a147bc..000000000 --- a/mods/wiki/plugins/action/verdiff.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: action -priority: bonus -hooks: action -type: action -title: DiffVersions -description: allows to diff any two page versions diff --git a/mods/wiki/plugins/action/verdiff.php b/mods/wiki/plugins/action/verdiff.php deleted file mode 100644 index db64edd3b..000000000 --- a/mods/wiki/plugins/action/verdiff.php +++ /dev/null @@ -1,63 +0,0 @@ -'; - $o .= ''; - $o .= ''; - - $o .= "\n".'' - . " " - . "\n"; - - for ($n=$data["version"]; $n>=1; $n--) { - - $data = ewiki_db::GET($id, $n); - if (EWIKI_DB_F_TEXT == ($data["flags"] & EWIKI_DB_F_TYPE)) { - - $o .= "" - . '' - . '' - . "" - . "" - . "" - . "" - . "\n"; - - } - } - - $o .= "
          from to version mtimesize author
          #$n".strftime("%Y-%m-%d %H:%M",$data["last_modified"])."".strlen($data["content"])."".$data["author"]."
          \n"; - $o .= "\n"; - - } - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/admin/admintrigger.php b/mods/wiki/plugins/admin/admintrigger.php deleted file mode 100644 index 778286d06..000000000 --- a/mods/wiki/plugins/admin/admintrigger.php +++ /dev/null @@ -1,21 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/admin/control.meta b/mods/wiki/plugins/admin/control.meta deleted file mode 100644 index 8497655ed..000000000 --- a/mods/wiki/plugins/admin/control.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: admin -hooks: action -type: action -title: control -description: provides easy to access administration functions per page -priority: deprecated diff --git a/mods/wiki/plugins/admin/control.php b/mods/wiki/plugins/admin/control.php deleted file mode 100644 index 654c0d587..000000000 --- a/mods/wiki/plugins/admin/control.php +++ /dev/null @@ -1,278 +0,0 @@ - 1)) { - - if (is_array($data)) { - $data = "You'll need to be admin. See ewiki_auth() and _PROTECTED_MODE in the README."; - } - $o .= $data; - - } - - #-- page flags --------------------------------------------------------- - elseif (@$_REQUEST["pgc_setflags"]) { - - #-- setted new flags - $new_f = 0; - foreach ($_REQUEST["sflag"] as $n=>$b) { - if ($b) { - $new_f |= (1 << $n); - } - } - #-- administrator may change all flags - if ($ewiki_ring==0) { - $data["flags"] = $new_f; - } - #-- moderators only a few - else { - $data["flags"] = ($data["flags"] & ( ~ EWIKI_DB_F_MODERATORFLAGS)) - | ($new_f & EWIKI_DB_F_MODERATORFLAGS); - } - $data["lastmodified"] = time(); - $data["version"]++; - - if (ewiki_db::WRITE($data)) { - $o .= "Page flags were updated correctly."; - ewiki_log("page flags of '$id' were set to $data[flags]"); - } - else { - $o .= "A database error occoured."; - } - } - - #-- renaming ----------------------------------------------------------- - elseif (@$_REQUEST["pgc_rename"] && strlen($new_id = $_REQUEST["mv_to"])) { - - $old_id = $id; - $report = ""; - - $preg_id = "/". addcslashes($old_id, ".+*?|/\\()$[]^#") ."/" - . ($_REQUEST["mv_cr1"] ? "i" : ""); - - #-- check if new name does not already exist in database - $exists = ewiki_db::GET($new_id); - if ($exists || !empty($exists)) { - return($o .= "Cannot overwrite an existing database entry."); - } - - #-- copy from old name to new name - $max_ver = $data["version"]; - $data = array(); - for ($v=1; $v<=$max_ver; $v++) { - - $row = ewiki_db::GET($old_id, $v); - $row["id"] = $new_id; - $row["lastmodified"] = time(); - $row["content"] = preg_replace($preg_id, $new_id, $row["content"]); - ewiki_scan_wikiwords($row["content"], $links, "_STRIP_EMAIL=1"); - $row["refs"] = "\n\n".implode("\n", array_keys($links))."\n\n"; - $row["author"] = ewiki_author("control/"); - - if (!ewiki_db::WRITE($row)) { - $report .= "error while copying version $v,
          \n"; - - } - } - - #-- proceed if previous actions error_free - if (empty($report)) { - - #-- deleting old versions - for ($v=1; $v<=$max_ver; $v++) { - ewiki_db::DELETE($old_id, $v); - } - - #-- adjust links/references to old page name - if ($_REQUEST["mv_cr0"]) { - - $result = ewiki_db::SEARCH("refs", $old_id); - while ($result && ($row = $result->get())) { - - $row = ewiki_db::GET($row["id"]); - - if (preg_match($preg_id, $row["content"], $uu)) { - - $row["content"] = preg_replace($preg_id, $new_id, $row["content"]); - $row["lastmodified"] = time(); - $row["version"]++; - ewiki_scan_wikiwords($row["content"], $links, "_STRIP_EMAIL=1"); - $row["refs"] = "\n\n".implode("\n", array_keys($links))."\n\n"; - $row["author"] = ewiki_author("control/"); - - if (!ewiki_db::WRITE($row)) { - $report .= "could not update references in ".$row['id'].",
          \n"; - } - else { - $report .= "updated references in ".$row['id'].",
          \n"; - } - } - - } - - } - - $o .= "This page was correctly renamed from '$old_id' to '$new_id'.

          \n$report"; - ewiki_log("page renamed from '$old_id' to '$new_id'", 2); - - } - else { - - $o .= "Some problems occoured while processing your request, therefor the old page still exists:
          \n" . $report; - } - - } - - #-- meta data ----------------------------------------------------------- - elseif (@$_REQUEST["pgc_setmeta"] && ($ewiki_ring==0) && ($set = explode("\n", $_REQUEST["pgc_meta"]))) { - - $new_meta = array(); - foreach ($set as $line) { - if (($line=trim($line)) && ($key=trim(strtok($line, ":"))) && ($value=trim(strtok("\000"))) ) { - $new_meta[$key] = $value; - } - } - - $data["meta"] = $new_meta; - $data["lastmodified"] = time(); - $data["version"]++; - - if (ewiki_db::WRITE($data)) { - $o .= "The {meta} field was updated."; - } - else { - $o .= "A database error occoured."; - } - } - - #-- deletion ----------------------------------------------------------- - elseif (@$_REQUEST["pgc_purge"] && $_REQUEST["pgc_purge1"]) { - - $loop = 3; - do { - $verZ = $data["version"]; - while ($verZ > 0) { - ewiki_db::DELETE($id, $verZ); - $verZ--; - } - } while ($loop-- && ($data = ewiki_db::GET($id))); - - if (empty($data)) { - $o .= "Page completely removed from database."; - ewiki_log("page '$id' was deleted from db", 2); - } - else { - $o .= "Page still here."; - } - } - - #-- function list ------------------------------------------------------- - else { - $o .= '
          ' - . ''; - - #-- flags - $o .= '
          '; - $o .= "

          page flags

          \n"; - foreach ($a_flagnames as $n=>$s) { - $disabled = (($ewiki_ring==1) && !((1<<$n) & EWIKI_DB_F_MODERATORFLAGS)) ? ' disabled="disabled"' : ""; - $checked = $data["flags"] & (1<<$n) ? ' checked="checked"': ""; - $a[$n] = ' ' . $s; - } - $o .= '' . "\n"; - for ($n=0; $n> 2; - $x = $n & 0x03; - if ($x==0) $o .= ""; - $o .= ""; - if ($x==3) $o .= "\n"; - } - $o .= '
          " . $a[4*$y + $x] . "
          '; - $o .= ''; - $o .= "\n


          \n"; - - #-- rename - $o .= '
          '; - $o .= "

          rename page

          \n"; - $o .= 'new page name: ' - . '
          ' - . ' also try to change all references from other pages accordingly ' - . '( and act case-insensitive when doing so) '; - $o .= '
          '; - $o .= "\n


          \n"; - - #-- meta - if (isset($ewiki_ring) && ($ewiki_ring==0)) { - $o .= '
          '; - $o .= "

          meta data

          \n"; - $o .= '\n"; - $o .= '
          '; - $o .= "\n


          \n"; - } - - #-- delete - $o .= '
          '; - $o .= "

          delete page

          \n"; - $o .= ' I\'m sure'; - $o .= '
          '; - $o .= "\n


          \n"; - - $o .= '
          '; - } - - return($o); -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/admin/page_searchandreplace.meta b/mods/wiki/plugins/admin/page_searchandreplace.meta deleted file mode 100644 index 4d5d8696d..000000000 --- a/mods/wiki/plugins/admin/page_searchandreplace.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -category: admin -hooks: page -type: page -page: SearchAndReplace -title: SearchAndReplace -description: allows text search and replacing across all pages -priority: bonus diff --git a/mods/wiki/plugins/admin/page_searchandreplace.php b/mods/wiki/plugins/admin/page_searchandreplace.php deleted file mode 100644 index e17f6cc69..000000000 --- a/mods/wiki/plugins/admin/page_searchandreplace.php +++ /dev/null @@ -1,175 +0,0 @@ - 1)) { - if (is_array($data)) { - $data = "You'll need moderator/administrator privileges to use this."; - } - return($o .= $data); - } - - #-- form ---------------------------------------------------------------- - if (empty($_REQUEST["snr_go"]) && empty($_REQUEST["snr_test"])) { - $url = ewiki_script("", $id); - $o .= ewiki_t(<<
          -
          -search for string
          -
          -this text snippet always matches case-insensitive, used as -first-stage search string; leave it empty to use only the regular -expression matching (slower)
          -look this string up only in
          -
          -and/or with /Perl/i regular expression
          -
          -this is optional, and is anyhow only used as second-stage search -pattern; if used allows to use regex backreferences in the replacement -string field
          -
          -then replace with string
          -
          -can contain backreferences \1 and \$1 if the regex search field was -used
          -
          -   - -
          -
          -
          -The regular expression matching is optional, you'll often only need the -simple string search field and another simple string in the replacement -field. -
          -
          -Please note, that this form allows to initially search for a simple string, -but you can leave this empty and only use a regex search. And as it is a -two stage searching, both patterns can be completely different. -
          -
          -Text replacement always happens in the WikiPages body, even if the simple -search string can be used to search for page names - if you do so, you -certainly need a second regular expression pattern for content replacement. -
          -END - ); - } - else { - $do = $_REQUEST["snr_go"]; - - #-- prepare vars - $search_where = $_REQUEST["snr_search_string_where"]; - $search_string = $_REQUEST["snr_search_string"]; - $search_regex = $_REQUEST["snr_search_regex"]; - $replacement = $_REQUEST["snr_replace"]; - if ($search_string == "*") { - $search_string = ""; - } - $search_string2 = preg_quote($search_string, "/"); - $replacement2 = addcslashes($replacement, "\$"); - - #-- security check in search_regex - if (preg_match('/([\w\s]+)$/', $search_regex, $uu) && strstr($uu[0],"e")) { - ewiki_log("use of regex '$search_regex' could be security circumvention attempt", 1); - return($o . "wrong regex delimiter"); - } - - #-- complain - if (empty($search_string) && empty($search_regex) || empty($replacement)) { - return($o . "too few parameters, needs at least one search and a replacement string"); - } - - #-- initial database string search - if (empty($search_string)) { - $result = ewiki_db::GETALL(array("id", "version", "flags")); - } - else { - $result = ewiki_db::SEARCH($search_where,$search_string); - } - - #-- walk through pages - while ($row=$result->get()) { - - #-- skip binary entries - if (EWIKI_DB_F_TEXT != ($row["flags"] & EWIKI_DB_F_TYPE)) { - continue; - } - $id = $row["id"]; - $save = false; - $row = ewiki_db::GET($id); - - /* - if (!ewiki_auth($id, $row, "edit", ... - ... - */ - - if ($search_regex) { - if (preg_match($search_regex, $row[$search_where], $uu)) { - $save = true; - $row["content"] = preg_replace($search_regex, $replacement, $row["content"]); - } - } - elseif ($search_string) { - if (stristr($row[$search_where], $search_string)) { - $save = true; - $row["content"] = preg_replace("/$search_string2/i", $replacement, $row["content"]); - } - } - - if ($save) { - $o .= "· " . htmlentities($id) - . " matched given search pattern
          \n"; - if ($do) { - $row["lastmodified"] = time(); - $row["author"] = ewiki_author("SearchAndReplace"); - $row["version"]++; - if (ewiki_db::WRITE($row)) { - $o .= "  changed.
          \n"; - } - else { - $o .= "  database store error
          \n"; - $o .= "  " . mysql_error() . "
          \n"; - } - } - } - - }#-- while $result - - if ($do) { - ewiki_log("SearchAndReplace for '$search_strinmg' and '$search_regex' to replace with '$replacement'"); - } - } - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/admin/page_searchcache.meta b/mods/wiki/plugins/admin/page_searchcache.meta deleted file mode 100644 index 0346d895a..000000000 --- a/mods/wiki/plugins/admin/page_searchcache.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: admin -hooks: page -type: page -title: generate SearchCache -description: generates fake text database entries for static/internal pages -priority: deprecated diff --git a/mods/wiki/plugins/admin/page_searchcache.php b/mods/wiki/plugins/admin/page_searchcache.php deleted file mode 100644 index 334d14abd..000000000 --- a/mods/wiki/plugins/admin/page_searchcache.php +++ /dev/null @@ -1,90 +0,0 @@ -
          "; - - $o .= '
          ' - . '' - . '' - . '
          '; - - } - elseif (!ewiki_auth($id, $data, $action, $ring=0, "_FORCE_AUTH=1") || !isset($ewiki_ring) || ($ewiki_ring > 0)) { - - if (is_array($data)) { - $data = "You'll need to be admin. See ewiki_auth() and _PROTECTED_MODE in the README."; - } - $o .= $data; - - } - else { - unset($_REQUEST["generate_cache"]); - - $o .= "generating cache versions from:
            \n"; - - foreach ($ewiki_plugins["page"] as $pid=>$pf) { - -#echo "$pid:"; - - $d = ewiki_db::GET($pid); - if (empty($d) || empty($d["content"])) { - $d = array( - "id" => $pid, - "version" => 1, - "flags" => EWIKI_DB_F_TEXT, - "created" => time(), - "content" => "", - "meta" => "", - "hits" => 0, - "refs" => "", - ); - } - - $d["last_modified"] = time(); - $d["hits"]++; - $d["content"] = $pf($pid, $d, "view"); - - //@ADD - transform back to wikimarkup - // here? - - if (ewiki_db::WRITE($d, true)) { - $o .= "
          • $pid
          • \n"; - } - - unset($d); - } - - $o .= "
          "; - ewiki_log("page search cache was updated", 2); - } - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/appearance/fancy_list_dict.meta b/mods/wiki/plugins/appearance/fancy_list_dict.meta deleted file mode 100644 index ac7be3584..000000000 --- a/mods/wiki/plugins/appearance/fancy_list_dict.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: appearance -title: fancy dictionary-like listing -description: for PageIndex and WordIndex -priority: optional -hooks: list_dict -type: listing diff --git a/mods/wiki/plugins/appearance/fancy_list_dict.php b/mods/wiki/plugins/appearance/fancy_list_dict.php deleted file mode 100644 index 1f205a0c5..000000000 --- a/mods/wiki/plugins/appearance/fancy_list_dict.php +++ /dev/null @@ -1,55 +0,0 @@ - blocks with the first -# letter as block title - - -$ewiki_plugins["list_dict"][0] = "ewiki_fancy_list_dict"; - // ["list_pages"][0] = ... - - - -function ewiki_fancy_list_dict($links) { - - - $o .= '' . "\n"; - - $lfl = false; - - foreach ($links as $line) { - - $nfl = strtoupper(substr($line, strpos($line, ">") + 1)); - $nfl = strtr($nfl, "ÄÖÜß0123456789", "AOUS "); - while ((($nfl[0] < "A") || ($nfl[0] > "Z")) && ($nfl[0] != " ")) { - $nfl = substr($nfl, 1); - } - $nfl = $nfl[0]; - - if ($lfl != $nfl) { - - if ($lfl) { - $o .= "\n"; - } - - $o .= '' . - '\n

          ' . - ($lfl = $nfl) . '

          '; - } - else { - $o .= "
          "; - } - - $o .= $line ; - - } - - $o .= "
          \n"; - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/appearance/listpages_br.meta b/mods/wiki/plugins/appearance/listpages_br.meta deleted file mode 100644 index 206ca6d27..000000000 --- a/mods/wiki/plugins/appearance/listpages_br.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: appearance -title: page
          -lists -hooks: list_pages -type: listing -description: prints out
          -separated lists -priority: extra diff --git a/mods/wiki/plugins/appearance/listpages_br.php b/mods/wiki/plugins/appearance/listpages_br.php deleted file mode 100644 index 138c23980..000000000 --- a/mods/wiki/plugins/appearance/listpages_br.php +++ /dev/null @@ -1,16 +0,0 @@ - - separated lists - # Carsten Senf - - - $ewiki_plugins["list_pages"][] = "ewiki_list_pages_fancy3"; - - - function ewiki_list_pages_fancy3($lines) { - - return join("
          ", $lines); - } - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/appearance/listpages_tbl.meta b/mods/wiki/plugins/appearance/listpages_tbl.meta deleted file mode 100644 index 73dd9f42e..000000000 --- a/mods/wiki/plugins/appearance/listpages_tbl.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: appearance -title: page lists in -hooks: list_pages -type: listing -description: prints out page lists in a table (instead of
            -lists) -priority: rare diff --git a/mods/wiki/plugins/appearance/listpages_tbl.php b/mods/wiki/plugins/appearance/listpages_tbl.php deleted file mode 100644 index 4352bfa80..000000000 --- a/mods/wiki/plugins/appearance/listpages_tbl.php +++ /dev/null @@ -1,22 +0,0 @@ - lists for all the - # internally generated pages - # of course you should customize THIS! - - - $ewiki_plugins["list_pages"][] = "ewiki_list_pages_fancy1"; - - - function ewiki_list_pages_fancy1($lines) { - - $cell_attr = 'bgcolor="#999999"'; - - $o = '
          ' . "\n"; - $o .= "\n\n"; - $o .= "
          " . implode("
          ", $lines) . "
          \n"; - return($o); - } - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/appearance/listpages_ul.meta b/mods/wiki/plugins/appearance/listpages_ul.meta deleted file mode 100644 index a45fbd0bd..000000000 --- a/mods/wiki/plugins/appearance/listpages_ul.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: appearance -title:
            page lists -hooks: list_pages -type: listing -description: traditional page listings use
              for simple unordered lists -priority: optional diff --git a/mods/wiki/plugins/appearance/listpages_ul.php b/mods/wiki/plugins/appearance/listpages_ul.php deleted file mode 100644 index 6d806b717..000000000 --- a/mods/wiki/plugins/appearance/listpages_ul.php +++ /dev/null @@ -1,21 +0,0 @@ - and
            • tags, -# which however annoyed some people and has therefor been replaced in the -# core, and is now banned into this plugin - - -$ewiki_plugins["list_pages"][0] = "ewiki_list_pages_ul"; - - -function ewiki_list_pages_ul($lines=array(), $list_tag="ul") { - - $o = "<" . $list_tag . ">\n"; - $o .= "
            • " . implode("
            • \n
            • ", $lines) . "
            • \n"; - $o .= "\n"; - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/appearance/title_calendar.meta b/mods/wiki/plugins/appearance/title_calendar.meta deleted file mode 100644 index b165e8949..000000000 --- a/mods/wiki/plugins/appearance/title_calendar.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -type: mangle -category: appearance -title: CalendarPageTitles -description: are made non-numeric, more readable and user-friendly -priority: extra -hooks: title_transform, list_transform diff --git a/mods/wiki/plugins/appearance/title_calendar.php b/mods/wiki/plugins/appearance/title_calendar.php deleted file mode 100644 index 1689b91f6..000000000 --- a/mods/wiki/plugins/appearance/title_calendar.php +++ /dev/null @@ -1,78 +0,0 @@ -)(.*?".preg_quote(CALENDAR_NAME_SEP) ." ?\d{8})(.*)#e"," \"$1\".ewiki_calendar_page_title('$2').'$3'",$lines[$index]); - } - - return($lines); -} - -function ewiki_calendar_title_transform($id, &$title, &$go_action){ - - if (ewiki_isCalendarId($id)) { - $title=ewiki_calendar_page_title ($id); - } -} - -#-- title string replacing -function ewiki_print_calendar_title(&$html, $id, $data, $action, $split=EWIKI_SPLIT_TITLE) { - global $ewiki_title; - - if (ewiki_isCalendarId($id)) { - $html=str_replace(">$ewiki_title<", ">".ewiki_calendar_page_title($id,$split)."<", $html); - } -} - -function ewiki_calendar_page_title ($id='', $split=EWIKI_SPLIT_TITLE) { - strlen($id) or ($id = $GLOBALS["ewiki_page"]); - - static $month_names; - if (!isset($month_names)) { - $month_names = explode(" ", ewiki_t("MONTHS")); - } - - if(preg_match(CALENDAR_PAGE_DATE_PARSE_REGEX,$id,$dateParts) ){ - - /*Transform Parent title using plugins */ - $parentId=$dateParts[1]; - - $parentTitle=$parentId; - if ($ewiki_config["split_title"] || $split) { - $parentTitle = ewiki_split_title($parentId); - } - - #-- title mangling - if ($pf_a = $ewiki_plugins["title_transform"]) { - foreach ($pf_a as $pf) { $pf($parentId, $parentTitle, ''); } - } - - $title=ewiki_t("CALENDERENTRYFOR").$parentTitle.": ". $month_names[$dateParts[3]-1]." ".$dateParts[4].", ".$dateParts[2]; - } - return($title); -} -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth-liveuser/LGPL.txt b/mods/wiki/plugins/auth-liveuser/LGPL.txt deleted file mode 100644 index b1e3f5a26..000000000 --- a/mods/wiki/plugins/auth-liveuser/LGPL.txt +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 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. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -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 and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, 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 library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete 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 distribute a copy of this License along with the -Library. - - 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 Library or any portion -of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -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 Library, 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 Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you 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. - - If distribution of 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 satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be 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. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library 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. - - 9. 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 Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -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 with -this License. - - 11. 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 Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library 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 Library. - -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. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library 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. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser 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 Library -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 Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -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 - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "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 -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. 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 LIBRARY 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 -LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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 - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/mods/wiki/plugins/auth-liveuser/PACKAGE.txt b/mods/wiki/plugins/auth-liveuser/PACKAGE.txt deleted file mode 100644 index 05c130c4c..000000000 --- a/mods/wiki/plugins/auth-liveuser/PACKAGE.txt +++ /dev/null @@ -1 +0,0 @@ -http://sourceforge.net/project/showfiles.php?group_id=75510 diff --git a/mods/wiki/plugins/auth-liveuser/README b/mods/wiki/plugins/auth-liveuser/README deleted file mode 100644 index cadcbacb2..000000000 --- a/mods/wiki/plugins/auth-liveuser/README +++ /dev/null @@ -1,206 +0,0 @@ -_______________________________ -eWiki LiveUser Auth/Perm Plugin -¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ -! License - -The required LiveUser library and these plugins are separately licensed under -the Lesser GPL. The copyright on the plugins is held by The Burgiss Group, -LLC. Bugs and change requests may be submitted to the ewiki mailing list, -ewiki@freelists.com. - -! Authors - -The bundled LiveUser PEAR package was developed by Markus Wolff, and -associated contributors . This plugin -was developed at the Burgiss Group by the following -developers: - - * andy fundinger - * alex wan - * jeremy mikola - -__NOTE__: The permissions component of this plugin depends the following -plugin (path reletive from ewiki root): plugins/lib/protmode.php - -! Introduction - -The purpose of this plugin is to provide eWiki with a means of handling -access permissions for all of its pages, based on users and groups. -Permissions are set as a ring level (comparable to eWiki access rings) for a -right and pagename combination. Rights are associated with group names, -which may then contain users. For all intensive purposes, rights and groups -function as a pair of one entity; the right being associated with the page -permissions and the group being associated with users. - -When a user accesses a page, his highest available ring level for the page -is calculated based on all group memberships, and that level is used to -denote what actions may be performed on that page. eWiki actions may be -mapped to one of these base ring levels, so that page permissions may also -be used to govern custom actions for other plugings (to a degree). The -available base levels are as follows: - - * view - * forum (write page comments) - * edit (edit a page) - * manage (advanced editing, such as modifying a page's permissions) - * admin - -There are several rights/groups constructed by the plugin by default, which -have reserved used. These are listed below: - - * NotLoggedIn - * LoggedIn - * LW_Publisher - * LW_Admin - -The NotLoggedIn and LoggedIn groups are used to signify the generic class of -unauthenticated and logged-in users, respectively. The group of NotLoggedIn -is also a superset of the group of LoggedIn users, so that permissions -satisfied by unauthenticated users will also be satisfied by logged-in -users; however, the opposite does not hold. Members of the LW_Publisher that -already have the rights to edit an eWiki page will also be able to make that -page publicly viewable by members of the NotLoggedIn group. Note that a -member of the LW_Publisher group still requires the fundemental edit rights -on a pagename first. Lastly, the LW_Admin group is given access to the -plugin's administration pages by default, allowing a member of this group to -modify page permissions, user accounts, and rights/groups. - -This plugin uses several eWiki plugin hooks. The following eWiki plugin -pagenames are reserved: - - * LogIn - * LogOut - * ChangePassword - * ChangePrefs - * AdminAddUsers (administration interfaces) - * AdminPerms - * AdminPermsReport - * AdminPrefs - * AdminRights - * AdminUsers - -The following authentication hooks are made: - - * $ewiki_plugins['auth_query'][0] for querying logged-in user status - * $ewiki_plugins['auth_perm'][0] for querying a page permission - -In order the handle page permissions, the eWiki edit-page form is appended -with form components to manage the page permissions and toggle the -'published' status of a page, which allows it to be viewed by users that are -not logged in. Two plugin callbacks are added to each of the following -hooks: - - * $ewiki_plugins['edit_form_append'][] - * $ewiki_plugins['edit_save'][] - -The plugin also adds a manage action hook to the array of available page -actions. The action (for text, plugin, and binary pages) hooks are as follows: - - * $ewiki_plugins['action_always']['manage'] - * $ewiki_plugins['action_binary']['manage'] - -! Installation - -The included files (excluding the LiveUser package), should be extracted and -moved to the eWiki plugins directory, or some other directory where eWiki -will include files from. The LiveUser package should then be extracted to the -PEAR directory, or some other path within PHP's include-path list. - -__NOTE__: The above installation instructions for the LiveUser package do not -import LiveUser into PEAR's package list. At the present time, this plugin can -not be guarenteed to work with all versions of LiveUser; therefore, a tested -LiveUser release will be made available for use with this plugin. - -From the directory where the plugin files were extracted, open -liveuser_conf.php and configure the following: - - * prefix for internal table names - * mappings of eWiki actions to perm rings - * public and default perm filters - * log file for deleted users - * LiveUser database connection - -The LiveUser configuration may optionally be edited (documentation may be -found in the LiveUser package), however no changes should be necessary. -Following liveuser_conf.php, open liveuser_setup.php and configure the -following: - - * eWiki database connection - * LiveUser database connection (if needed) - * LiveUser properties, rights, groups, and default page rights and users - -It is not necessary to declare all rights, groups, and users in the setup -file, as the included admin pages may be used to do so after installation; -however, you should ensure that at least one user is added to the admin -group, as shown by example in the setup file. - -Following the configuration of liveuser_conf.php and liveuser_setup.php, the -LiveUser database tables must be created. Within the extracted LiveUser/ -directory, an sql/ directory will contain necessary scripts to build the -LiveUser database. The following files should be executed for this purpose: - - * Auth_DB.sql - * Perm_DB_Complex.sql - -The LiveUser tables should now be properly configured, and now -liveuser_setup.php must be executed to build the remaining database tables -for the plugin. It is suggested that this file be executed from a console -prompt (`php liveuser_setup.php`). It will generate output as it constructs -the database and necessary entities, some of which will be PHP code to be -inserted into liveuser_conf.php, which will define constants of some created -entities. This script is able to be executed safely multiple times if the -generated PHP code is needed again for some reason; however, it will not -generate output about entity creation if those entities already exist. - -For user preferences support, the file liveuser_setup_prefs.php may be -edited and executed (much like liveuser_setup.php).to build user preference -fields and make them available by default. Althougth the functions in -pref_liveuser.php are usable on their own, basic interfaces are available -through the following page names: - - * ChangePrefs - * AdminPrefs - -ChangePrefs, along the lines of ChangePassword, is intended to be used by the -user himself to modify his account. It will allow the user to edit the values -for any preferences that have been toggled 'public', that is, allowed to be -modified by users. The AdminPrefs page will allow an administrator to modify -available fields, along with their default values and public mode. At this time, -there is no interface for the administrator to edit the preferences of users; -therefore, non-public fields are inaccessible through these interfaces, and can -only be employed through the function API. This will be changed in a future release. - -With liveuser_setup.php executed, and its output successfully inserted into -liveuser_conf.php, the only remaining step is to include the plugin from -eWiki's config.php file. One of the following files may be included, -depending on whether simple authentication (login only) or more advanced -permissions (login and rights) are required: - - * auth_liveuser.php OR - * perm_liveuser.php - -If auth_liveuser.php is initially selected and it becomes necessary to -switch to perm_liveuser.php at a later time, it may also be necessary to run -liveuser_setup.php again in order to apply default permissions to all -current pages in the eWiki database, otherwise some pages would have no -permissions assigned and thus be inaccessible. - -__IMPORTANT__: If only auth_liveuser.php is chosen, judgement should be exercised -in properly protecting the liveuser_*_gui.php files, which contain the -admin scripts, from all logged-in users. Without perm_liveuser.php active, -these files cannot be protected by the plugin's permissions system. A -possible solution would be to abort those pages if the handle of the -current user does not match a reserved name. The following pagenames will -be added to the list of eWiki plugin pages for the purpose of administration: - - * AdminAddUsers - * AdminPerms - * AdminPermsReports - * AdminPrefs - * AdminRights - * AdminUsers - -It should be noted that whenever a new right (permission) is created, a -corresponding group should also be created (the option exists) so that they -may be linked together and users may then later be added to that group in -order to inherit the right. diff --git a/mods/wiki/plugins/auth-liveuser/auth_liveuser.meta b/mods/wiki/plugins/auth-liveuser/auth_liveuser.meta deleted file mode 100644 index 698221147..000000000 --- a/mods/wiki/plugins/auth-liveuser/auth_liveuser.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: authentication -title: LiveUser (API/Core) -copyright: Copyright (c) 2003, The Burgiss Group, LLC -priority: rare -type: auth -description: chains the PEAR::LiveUser authentication framework with ewiki diff --git a/mods/wiki/plugins/auth-liveuser/auth_liveuser.php b/mods/wiki/plugins/auth-liveuser/auth_liveuser.php deleted file mode 100644 index fe6471560..000000000 --- a/mods/wiki/plugins/auth-liveuser/auth_liveuser.php +++ /dev/null @@ -1,509 +0,0 @@ - - * @author alex wan - * @author jeremy mikola - * - * Without auth_perm_ring or perm_liveuser this plugin will merely require - * authentication to edit (wherein ring is set to two) and hide all control - * links from users who are not logged in if EWIKI_PROTECTED_MODE_HIDING is set. - * - * A login form will be displayed if you try to edit without logging in. - * - * This plugin opens it's own database and must be included BEFORE the ewiki - * database is opened. - * - * @contributer jeffrey engleman - -added ewiki_check_passwd - */ - -require_once(dirname(__FILE__).'/liveuser_aux.php'); - -define('EWIKI_LOGGEDIN_RING', 1); -define('EWIKI_MIN_DICT_WORD_LENGTH', 3); -//Path to dictionary file, passdict is included for this -//define('EWIKI_PASS_DICT_PATH', '/path/to/dictionary'); -define('EWIKI_PASSWORD_COMPLEXITY', 56); -//Maximum delay before shutting down the system (in seconds) -define('EWIKI_LIVEUSER_LOGIN_SHUTDOWN_DELAY', 30); - -// Set passwords to expire in 180 days, actually expiring passwords requires: -// * a uservars plugin -// * /tools/scripts/passwd_expiration to run daily (not yet released) -// * the /plugins/passwd_expire plugin (not yet released) -define('EWIKI_PASSWD_LIFETIME',180); -/* -log logins for guess rate limiter, table structure should be: - -CREATE TABLE `liveweb_login_log` ( - `auth_user_handle` varchar(32) NOT NULL default '', - `php_session_id` varchar(40) NOT NULL default '', - `ssl_session_id` varchar(16) default '', - `ip_address` varchar(16) NOT NULL default '', - `time` timestamp(14) NOT NULL, - `delay` tinyint(1) NOT NULL default '0', - `success` tinyint(1) NOT NULL default '0', - PRIMARY KEY (`time`,`auth_user_handle`) -) TYPE=MyISAM; - -in the LiveUser database - -if you allow only SSL connections set ssl_session_id to "NOT NULL" - -When enabled a failure to successfully log will result in a die() call. -*/ - -@define('EWIKI_AUTH_DEFAULT_RING', 3); -define('EWIKI_NOT_LOGGEDIN_RING', EWIKI_AUTH_DEFAULT_RING); - -// ewiki callbacks for auth query, login, logout, and changePassword methods -$ewiki_plugins['auth_query'][0] = 'ewiki_auth_query_liveuser'; -$ewiki_plugins['page']['LogIn'] = 'ewiki_page_liveuser_login'; -$ewiki_plugins['page']['LogOut'] = 'ewiki_page_liveuser_logout'; -$ewiki_plugins['page']['ChangePassword'] = 'ewiki_page_liveuser_chpw'; - -/* -Policies for the guess rate limiter, name entry descriptively for alerts: -array( - 'where' => Where clause for interesting records "?" is current username - 'count' => Empty entry, will store count of respondant records when queried - 'threshold' => Minimum records before adding delay - 'coefficient' => delay to add per record - 'alert_mod' => alerts will be sent when count%alert_mod==0 -) -*/ - -//Slow down if 50 bad passwords have been entered this hour. -$liveuser_delay_policies['Hourly_bad_PWs']=array( - 'where' => 'time> DATE_SUB(NOW(), INTERVAL 1 HOUR)', - 'count' => 0, - 'threshold' => 50, - 'coefficient' => 5/120, - 'alert_mod' => 50 -); -//Slow down if 200 bad passwords have been entered today. -$liveuser_delay_policies['Daily_bad_PWs']=array( - 'where' => 'time> DATE_SUB(NOW(), INTERVAL 1 DAY)', - 'count' => 0, - 'threshold' => 200, - 'coefficient' => .0357, - 'alert_mod' => 200 -); -//Send alert if one account gets 10 bad passwords in a day -$liveuser_delay_policies['Acct_bad_PWs']=array( - 'where' => 'time> DATE_SUB(NOW(), INTERVAL 1 DAY) AND auth_user_handle=?', - 'count' => 0, - 'threshold' => 0, - 'coefficient' => 0, - 'alert_mod' => 10 -); - //Who to notify - define('ALERT_RECIPIENTS', 'webmaster@127.0.0.1'); - define('ALERT_SUBJECT',"LU IDS ALERT"); - -/* ignore username and password form data if cancelling a login process */ -/* otherwise calculate and ennact a login delay.*/ -if (isset($_REQUEST['username'])&&!isset($_REQUEST['cancel_login'])){ - $username=$_REQUEST['username']; - $authlog="LOGIN ATTEMPT USERNAME:".$username." cancel_login==".$_REQUEST['cancel_login']; - - liveweb_query_delay_data($liveuser_delay_policies); - //var_dump($liveuser_delay_policies); - - $totalDelay=liveweb_get_total_delay($liveuser_delay_policies); - - //echo(" total delay $totalDelay"); - - if($totalDelay>EWIKI_LIVEUSER_LOGIN_SHUTDOWN_DELAY){ - $liveuserConfig['login']['username'] = ''; - $liveuserConfig['login']['password'] = ''; - }else{ - //using usleep rather than sleep() because sleep() is integer seconds only. - usleep(1000000*$totalDelay); - } - -}else{ - $liveuserConfig['login']['username'] = ''; - $liveuserConfig['login']['password'] = ''; -} - - -/* Setting $liveuserConfig['login']['username'] and $liveuserConfig['login']['password'] -* to '' causes the login to be ignored by the LiveUser system. -* In Liveuser.php during the tryLogin function on line 665, -* it sees the handle is empty. It then tries to login based on a cookie, -* but in line 171 that _options['cookie'] is not set so it goes to line 693 -* sees that _options['login']['username'] and _options['login']['password'] -* are empty, tries to run _options['login']['function'] which is also set to '' -* so it fails out of the if and hits line 715 where it returns false negating the login. -*/ - -// instantiate a LiveUser object from the config array -$liveuser =& LiveUser::factory($liveuserConfig); - -if (isset($_REQUEST['username'])&&!isset($_REQUEST['cancel_login'])){ - if($totalDelay>EWIKI_LIVEUSER_LOGIN_SHUTDOWN_DELAY){ - $liveuser->logout(); - }else{ - //Get data as we would for logging - $loginData=ewiki_liveuser_get_login_data(); - liveuser_loglogin(); - //Tests login, updates $username - if ($username=$liveuser->getHandle()){ - //Clear delay flags with matching handle, php session, ssl session, and ip - // (today only) - $liveuserDB->query(' - UPDATE `liveweb_login_log` set delay=0 - WHERE time> DATE_SUB(NOW(), INTERVAL 1 DAY) - AND auth_user_handle=? AND php_session_id=? - AND ssl_session_id=? AND ip_address=?', - array($username,$loginData['php_session_id'], - $loginData['ssl_session_id'],$loginData['ip_address'])); - }else{//Failed login attempt with logins enabled - $authlog.="LOGIN FAILED USERNAME:".$_REQUEST['username']." PASSWORD:".$_REQUEST['password']; - ewiki_liveuser_IDS_alerts($liveuser_delay_policies,$loginData['auth_user_handle']); - } - } -} - -//Tests login, updates $username NB: $username may or may not have been set above. -if($username=$liveuser->getHandle()) { - //Reset username based on the autheticated username, should be no change. - $GLOBALS['ewiki_author'] = $username; - $GLOBALS['ewiki_auth_user'] = $username; -} else { - $GLOBALS['ewiki_author'] = null; - $GLOBALS['ewiki_auth_user'] = null; - define('EWIKI_AUTO_EDIT',0); -} - -// html page output response messages -$ewiki_t['en']['LOGINSHUTDOWN'] = "

              We're sorry, but logins are temporarily disabled, please try again later.

              "; -$ewiki_t['en']['CANNOTCHANGEPAGE'] = '

              This page cannot be changed. Perhaps you can LogIn and change it then.

              '; -$ewiki_t['en']['NOTLOGGEDIN'] = '

              You are not logged in. You must LogIn to access some features of this site.

              '; -$ewiki_t['en']['LOGGEDINALREADY'] = '

              You are already logged in.

              '; -$ewiki_t['en']['LOGGEDIN'] = '

              You have logged in as '.$GLOBALS['ewiki_author'].'.'; -$ewiki_t['en']['LOGGEDOUT'] = '

              You have been logged out.

              '; -$ewiki_t['en']['LOGINFAILED'] = '

              You supplied an invalid username or password while logging in.

              '; -$ewiki_t['en']['LOGINFORM'] = ' -

              Please identify yourself with a username and a password:

              - -
              - - - - - - - - - - - - - -
              Username:
              Password:
                - - -
              -
              '; - - -$ewiki_t['en']['CHPW_BADNEW_COMPLEXITY']= '

              Your password has been deemed insecure because it did not meet the complexity requirements.

              -

              Suggested Remedies:

              • Increase the length of your new password.
              • Combine upper and lower case letters
              • -
              • Use special characters and numbers.
              '; -$ewiki_t['en']['CHPW_BADNEW_USERNAME']='

              Your password has been deemed insecure because it matches your username too closley.

              Suggested Remedy:

              • Do not use your username -in your password in any way.
              '; -$ewiki_t['en']['CHPW_BADNEW_DICTIONARY']='

              Your password has been deemed insecure because part of it can be found on our list of common passwords.

              Suggested Remedy:

              -
              • Remove all dictionary words from your password.
              • Remove common sequences from your password.
              '; -$ewiki_t['en']['CHPW_BADOLD'] = '

              You have misentered your old password.

              '; -$ewiki_t['en']['CHPW_SUCCESS'] = '

              Your password has been changed.

              '; -$ewiki_t['en']['CHPW_NOMATCH'] = '

              Your new passwords did not match. Please re-enter them.

              '; -$ewiki_t['en']['CHPW_SAMEOLD'] = '

              Your new password is the same as your old password.

              '; -$ewiki_t['en']['CHPW_ERROR'] = '

              An error occurred while attempting to change your password.

              '; -$ewiki_t['en']['CHPW_FORM'] = ' -

              Please enter your old password once and your new password twice in the blanks below:

              - -
              - - - - - - - - - - - - - - - - - -
              Old Password:
              New Password:
              Repeat New Password:
                - - -
              -
              '; -$ewiki_t['en']['PASS_DICTIONARY_READ_ERROR'] = "

              An error was encountered while validating your password.

              "; -/** - * processes login for the current user. - * - * @param mixed id - * @param mixed data - * @return string page output response to login attempt - */ -function ewiki_page_liveuser_login($id, $data) -{ - global $liveuser,$liveuser_delay_policies; - - liveweb_query_delay_data($liveuser_delay_policies); - //var_dump($liveuser_delay_policies); - - $totalDelay=liveweb_get_total_delay($liveuser_delay_policies); - - $o=ewiki_make_title($id, $id, 2); - if($totalDelay > EWIKI_LIVEUSER_LOGIN_SHUTDOWN_DELAY){ - $o.=ewiki_t('LOGINSHUTDOWN'); - return($o); - }else{ - if (isset($_REQUEST['submit_login']) or isset($_REQUEST['submit_login_img_x'])) { - // login form submission, print form response - return $o.($liveuser->isLoggedIn() ? ewiki_t('LOGGEDIN') : ewiki_t('LOGINFAILED').ewiki_t('LOGINFORM')); - } else { - // all other calls, print login status or form output - return $o.($liveuser->isLoggedIn() ? ewiki_t('LOGGEDINALREADY') : ewiki_t('LOGINFORM')); - } - } -} - -/** - * logs out the current user. - * - * @param mixed id - * @param mixed data - * @return string page output for logout message - */ -function ewiki_page_liveuser_logout($id, $data) -{ - global $liveuser; - - $liveuser->logout(); - return ewiki_make_title($id, $id, 2).ewiki_t('LOGGEDOUT'); -} - -/** - * changes current user's password based on form input - * - * @param mixed id - * @param mixed data - * @return mixed - */ -function ewiki_page_liveuser_chpw($id, $data) -{ - global $liveuser, $liveuserAuthAdmin; - - // if form was not submitted, return page output for form - if (!isset($_REQUEST['oldpassword'])) { - return ewiki_make_title($id, $id, 2).ewiki_t('CHPW_FORM'); - } - - // ensure that original password is valid, and that new passwords match - if ($liveuser->getProperty('passwd') != $liveuserAuthAdmin->encryptPW($_REQUEST['oldpassword'])) { - return ewiki_make_title($id, $id, 2).ewiki_t('CHPW_BADOLD').ewiki_t('CHPW_FORM'); - } else if ($_REQUEST['newpassword1'] != $_REQUEST['newpassword2']) { - return ewiki_make_title($id, $id, 2).ewiki_t('CHPW_NOMATCH').ewiki_t('CHPW_FORM'); - } else if ($_REQUEST['newpassword1'] == $_REQUEST['oldpassword']){ - return ewiki_make_title($id, $id, 2).ewiki_t('CHPW_SAMEOLD').ewiki_t('CHPW_FORM'); - } - //$time=getmicrotime(); - $password_status=ewiki_check_passwd($_REQUEST['newpassword1'],$liveuser->getHandle()); - //$end=getmicrotime(); - //echo($end-$time); - if ($password_status!='good passwd') { - if($password_status=='read error'){ - return ewiki_make_title($id, $id, 2).ewiki_t('PASS_DICTIONARY_READ_ERROR'); - } else { - return ewiki_make_title($id, $id, 2).ewiki_t($password_status).''.ewiki_t('CHPW_FORM'); - } - } - - // return success - if ($liveuserAuthAdmin->updateUser($liveuser->getProperty('authUserId'), $liveuser->getHandle(), $_REQUEST['newpassword2']) === true) { - ewiki_set_uservar("passwdstatus", 'good', $GLOBALS['ewiki_auth_user']); - ewiki_set_uservar("passwdexpiredate", time()+(60*60*24*EWIKI_PASSWD_LIFETIME),$GLOBALS['ewiki_auth_user']); - return ewiki_make_title($id, $id, 2).ewiki_t('CHPW_SUCCESS'); - } else { - return ewiki_make_title($id, $id, 2).ewiki_t('CHPW_ERROR'); - } -} - - -/** - * checks if the current user is logged in. this function will alter the output - * parameter if the cancel login form event is being processed. - * - * @param string data page data (not used) - * @param string ewiki_author - * @param int ewiki_ring - * @param int force_query - * @global string ewiki_errmsg returns error message for user on failure - * @return boolean true if the current user is logged in, false otherwise - */ -function ewiki_auth_query_liveuser(&$data, $force_query = 0) -{ - global $liveuser, $ewiki_config, $ewiki_errmsg, $ewiki_ring; - - if ($liveuser->isLoggedIn()) { - $ewiki_ring = EWIKI_LOGGEDIN_RING; - return true; - } else { - if ($force_query){ - if (isset($_REQUEST['cancel_login'])) { - $ewiki_errmsg = ewiki_t('FORBIDDEN'); - } else if (isset($_REQUEST['submit_login'])) { - $ewiki_errmsg = ewiki_t('LOGINFAILED').ewiki_t('LOGINFORM'); - } else { - $ewiki_errmsg = ewiki_t('LOGINFORM'); - } - } - - $liveuser->logout(); - $ewiki_ring = EWIKI_NOT_LOGGEDIN_RING; - - return false; - } -} - -//Gets general data about login for loging etc. -function ewiki_liveuser_get_login_data(){ - global $liveuser; - - $success=$liveuser->isLoggedIn(); - - $requestInfo=array( - 'auth_user_handle' => $_REQUEST['username'], - 'php_session_id' => session_id(), - 'ssl_session_id' => ($uu = $_ENV['SSL_SESSION_ID']?$uu:'SSL not enabled'), - 'ip_address' => $_SERVER['REMOTE_ADDR'], - 'delay' => !$success, - 'success' => $success); - - return($requestInfo); -} - -//logs current login -function liveuser_loglogin(){ - global $liveuserDB; - - if (!isset($_REQUEST['username'])){ - return; - } - - $requestInfo= ewiki_liveuser_get_login_data(); - - //store ip and sslid in session variables so we can check them later. - $_SESSION['loginInfo']['ip_address']=$requestInfo['ip_address']; - $_SESSION['loginInfo']['ssl_session_id']=$requestInfo['ssl_session_id']; - - //var_dump($requestInfo); - - // You must create a new array to pass to this function, passing - // $requestInfo does not work - if($liveuserDB->query('INSERT INTO '.LW_PREFIX.'_login_log (auth_user_handle, '. - 'php_session_id, ssl_session_id,ip_address,delay,success,time) '. - 'VALUES (?, ?, ?, ?, ?, ?, NOW())', - array($requestInfo['auth_user_handle'],$requestInfo['php_session_id'], - $requestInfo['ssl_session_id'],$requestInfo['ip_address'], - $requestInfo['delay'],$requestInfo['success'] ))!=DB_OK) - { - die('Failure in database connection, unable to continue'); - } - //*/ -} - -// Calculates delay, utility function -function liveweb_delay_calc($count, $threshold, $coeff){ - return(max($count-$threshold,0)*$coeff); -} -function liveweb_get_total_delay($liveuser_delay_policies){ - $delay=0; - - foreach($liveuser_delay_policies as $currPolicy){ - $delay += liveweb_delay_calc($currPolicy['count'], $currPolicy['threshold'], $currPolicy['coefficient']); - } - - return($delay); -} - -//Populates 'count' with the number of respondant records -function liveweb_query_delay_data(&$liveuser_delay_policies){ - global $liveuserDB; - - foreach ($liveuser_delay_policies as $polNum => $currPolicy){ - $liveuser_delay_policies[$polNum]['count']=0+$liveuserDB->getOne('SELECT sum(delay) as delay_count from '. - '`'.LW_PREFIX.'_login_log` WHERE '.$currPolicy['where'],array($_REQUEST['username'])); - } -} - -//Sends alerts if need be -function ewiki_liveuser_IDS_alerts($liveuser_delay_policies,$username){ - $send_alert=0; - foreach ($liveuser_delay_policies as $polName => $currPolicy){ - if((++$liveuser_delay_policies[$polName]['count'])%$currPolicy['alert_mod']==0){ - $send_alert=1; - } - } - - if(!$send_alert){ - return; - } - $m_text = ""; - - foreach ($liveuser_delay_policies as $polName => $currPolicy){ - $m_text.="$polName: {$currPolicy['count']}(mod {$currPolicy['alert_mod']})\n"; - } - - ($server = $_SERVER["HTTP_HOST"]) or - ($server = $_SERVER["SERVER_NAME"]); - - $m_text.="$username attempting to login\n"; - - $m_text.= "\n(".EWIKI_PAGE_INDEX." on http://$server/)\n"; - $m_text.= $_SERVER["SERVER_ADMIN"]."\n"; - - //$m_from = EWIKI_NOTIFY_SENDER."@$server"; - $m_from = "Alerts@$server"; - $m_subject = ALERT_SUBJECT; - $m_to = ALERT_RECIPIENTS; - - //echo("mail($m_to, $m_subject, $m_text, 'From: \'$s_2\' <$m_from>\nX-Mailer: ErfurtWiki/'.EWIKI_VERSION);"); - mail($m_to, $m_subject, $m_text, "From: \"$s_2\" <$m_from>\nX-Mailer: ErfurtWiki/".EWIKI_VERSION); - -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_addusers_gui.meta b/mods/wiki/plugins/auth-liveuser/liveuser_addusers_gui.meta deleted file mode 100644 index 6452dd5c0..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_addusers_gui.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: authentication -title: liveuser_addusers_gui -copyright: Copyright (c) 2003, The Burgiss Group, LLC -priority: auto diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_addusers_gui.php b/mods/wiki/plugins/auth-liveuser/liveuser_addusers_gui.php deleted file mode 100644 index 83171424e..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_addusers_gui.php +++ /dev/null @@ -1,146 +0,0 @@ -Invalid form input was provided. Please ensure that the email and group fields are set and not empty.

              '; - $o = ob_get_contents(); - ob_end_clean(); - return $o; - } - - - if (strlen($_POST['text_E-Mail_Address']) > 255) { - echo '

              The email field input is too long. Please ensure that it is 255 characters or less.

              '; - $o = ob_get_contents(); - ob_end_clean(); - return $o; - } - - if(!empty($_POST['username_text'])){ - $username=$_POST['username_text']; - } else { - $username=$_POST['text_E-Mail_Address']; - } - - // ensure user does not already exist - if (($auth_id = liveuser_checkEntity('user', $username)) === false) { - - $pwd=liveuser_generate_password(); - - if (($auth_id = liveuser_addEntity('user', array($username, $pwd))) !== false) { - echo '

              User '.$username.' was inserted into the database.
              The following password has been set for this user: '.$pwd.'

              '; - //set preferences on successful creation - foreach($_POST as $post_key => $post_value){ - if(strstr($post_key, "text_")){ //only work on fields with the text_ prefix - $varname=substr($post_key,5); //remove the text_ prefix - if(!ewiki_set_uservar($varname, $post_value, $username)){ //set appropriate data - echo '

              An error occurred while setting the additional preferences for the user.

              '; - } - } - } - if (is_numeric($group_id = liveuser_checkEntity('group', $_POST['group_list'])) && - $liveuserPermAdmin->addUserToGroup($auth_id, $group_id) === true) { - echo '

              User '.$username.' was added into the group: '.$_POST['group_list'].'

              '; - } else { - echo '

              An error occurred while adding the user to the group: '.$_POST['group_list'].'

              '; - } - } else { - echo '

              An error occurred while creating the user.

              '; - } - } else { - echo '

              User '.$username.' already exists and will not be created or modified.

              '; - } - } - - // show form - ?> -
              -

              Add a User

              - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

              - -
              - \ No newline at end of file diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_aux.meta b/mods/wiki/plugins/auth-liveuser/liveuser_aux.meta deleted file mode 100644 index 0a7d75e0b..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_aux.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: authentication -title: liveuser_aux -copyright: Copyright (c) 2003, The Burgiss Group, LLC -priority: auto diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_aux.php b/mods/wiki/plugins/auth-liveuser/liveuser_aux.php deleted file mode 100644 index 7e2bc63f9..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_aux.php +++ /dev/null @@ -1,601 +0,0 @@ -getOne(' - SELECT liveuser_perm_users.perm_user_id - FROM liveuser_perm_users, liveuser_users - WHERE liveuser_users.auth_user_id = ? AND - liveuser_perm_users.auth_container_name = ? AND - liveuser_users.auth_user_id = liveuser_perm_users.auth_user_id', - array($auth_id, $container_name)); - return (is_numeric($perm_user_id) ? $perm_user_id : false); - } else { - return false; - } -} - -/** - * Allows for duplicate-safe creation of LiveUser entities. The supplied entity - * name must be one of the following: language, application; area; right; group; - * or user. This function expects the following global variables: - * - * $liveuserAuthAdmin (of type LiveUser_Admin_Auth_Container_DB) - * $liveuserPermAdmin (of type LiveUser_Admin_Perm_Container_DB_Complex) - * $liveuserConfig (LiveUser configuration array) - * - * @param string type name of entity type to add - * @param array args array corresponding to argument list of the entity's add method - * @return mixed unique id (integer or string) of added entity on success, false on error - */ -function liveuser_addEntity($type, $args) -{ - global $liveuserAuthAdmin, $liveuserPermAdmin, $liveuserConfig; - - switch ($type) { - // special case, add language, but return 2-letter code instead of numerical id - case 'language': - if (($languageId = liveuser_checkEntity($type, $args[0])) === false) { - $languageId = call_user_func_array(array(&$liveuserPermAdmin,'addLanguage'), $args); - // return 2-letter code for success, false otherwise - return (is_numeric($languageId) ? $args[0] : false); - } - return $args[0]; - break; - // special case, add user to both auth and perm containers - case 'user': - $perm_id = 0; - if (($auth_id = liveuser_checkEntity($type, $args[0])) === false) { - $auth_id = call_user_func_array(array(&$liveuserAuthAdmin,'addUser'), $args); - $perm_id = $liveuserPermAdmin->addUser($auth_id, LIVEUSER_USER_TYPE_ID, null, $liveuserConfig['authContainers'][0]['name']); - } - return (is_numeric($auth_id) && is_numeric($perm_id) ? $auth_id : false); - break; - // common cases, fetch unique name from arguments and proceed - case 'application': - $argName = $args[1]; - break; - case 'area': - $argName = $args[2]; - break; - case 'right': - $argName = $args[2]; - break; - case 'group': - $argName = $args[1]; - break; - // failure case, unknown type - default: - return false; - break; - } - - // common check and create cases where type is: application, area, right, group - if (($entityId = liveuser_checkEntity($type, $argName)) === false) { - $entityId = call_user_func_array(array(&$liveuserPermAdmin,'add'.$type), $args); - } - return (is_numeric($entityId) ? $entityId : false); -} - -/** - * Checks for existing LiveUser entities. The supplied entity name must be one - * of the following: application; area; right; group; user; or language. These - * types will denote that the id parameter is in the form of the entity name. To - * denote that the id parameter is in the form of the numeric id, the suffix - * '_id' should be appended to the type names listed above. Depending on the - * supplied id parameter, this function will search for entities matching the - * numerical id before matching against the string name. All name id values must - * be non-numeric strings. This function expects the following global variables: - * - * $liveuserAuthAdmin (of type LiveUser_Admin_Auth_Container_DB) - * $liveuserPermAdmin (of type LiveUser_Admin_Perm_Container_DB_Complex) - * - * @param string type name of entity type to add - * @param mixed id integer id or unique name of entity to check for depending on type - * @return mixed unique id (integer or string) of entity if it exists, false otherwise - */ -function liveuser_checkEntity($type, $id) -{ - global $liveuserDB, $liveuserConfig, $liveuserAuthAdmin, $liveuserPermAdmin; - - switch ($type) { - // special case, check for existing language and handle 2-character name - case 'language': - case 'language_id': - $languages = $liveuserPermAdmin->getLanguages(); - foreach ($languages as $code => $language) { - if (($type == 'language' && $code == $id && strlen($id) == 2) || - ($type == 'language_id' && $language['language_id'] == $id)) { - return $code; - } - } - return false; - break; - - // special case, check against user entity sets in both auth and perm containers - case 'user': - case 'user_id': - $users = $liveuserAuthAdmin->getUsers(); - $auth_id = null; - foreach ($users as $user) { - if (($type == 'user' && $user['handle'] == $id) || - ($type == 'user_id' && $user['auth_user_id'] == $id)) { - $auth_id = $user['auth_user_id']; - break; - } - } - // no match if user_id is unset, otherwise proceed to check with perm container - if (!isset($auth_id)) { - return false; - } else if ($liveuserDB->getOne('SELECT 1 FROM '.$liveuserConfig['permContainer']['prefix'].'perm_users WHERE auth_user_id = ?', array((int)$auth_id)) == 1) { - return $auth_id; - } else { - return false; - } - break; - - // common cases, check against entity selection - case 'application': - case 'area': - case 'right': - case 'group': - $entities = call_user_func_array(array(&$liveuserPermAdmin, 'get'.$type.'s'), array()); - foreach ($entities as $entity) { - if ($entity['name'] == $id) { - return $entity[$type.'_id']; - } - } - return false; - break; - - case 'application_id': - case 'area_id': - case 'right_id': - case 'group_id': - $entities = call_user_func_array(array(&$liveuserPermAdmin, 'get'.substr($type, 0, -3).'s'), array()); - foreach ($entities as $entity) { - if ($entity[$type] == $id) { - return $entity[$type]; - } - } - return false; - break; - - // failure case, unknown type or no match for entity - default: - return false; - break; - } -} - -/** - * Allows for removal of LiveUser entities. The supplied entity name must be one - * of the following: language, application; area; right; group; or user. These - * types imply that the id parameter is in the form of the entity name. To - * denote the id parameter as an entity numeric id, the suffix '_id' should be - * appended to the names. This function expects the following global variables: - * - * $liveuserAuthAdmin (of type LiveUser_Admin_Auth_Container_DB) - * $liveuserPermAdmin (of type LiveUser_Admin_Perm_Container_DB_Complex) - * - * @param string type name of entity type to remove - * @param mixed id integer id or unique name of entity to remove depending on type - * @return true if the entity existed and was removed, false otherwise - */ -function liveuser_removeEntity($type, $id) -{ - global $liveuserDB, $liveuserConfig, $liveuserAuthAdmin, $liveuserPermAdmin; - - switch ($type) { - // special case, remove user to both auth and perm containers - case 'user': - case 'user_id': - // log removed users with ewiki_log - if (($auth_id = liveuser_checkEntity($type, $id)) !== false && - ($perm_id = liveuser_getPermUserId('user_id', $auth_id)) !== false) { - // fetch authTable names - $authTable = $liveuserConfig['authContainers'][0]['authTable']; - - // backup user preferences and groups of user being removed - $backup['prefs'] = $liveuserDB->getAll('SELECT '.LW_PREFIX.'_prefs_fields.field_name, '.LW_PREFIX.'_prefs_data.field_value - FROM '.LW_PREFIX.'_prefs_fields, '.LW_PREFIX.'_prefs_data - WHERE '.LW_PREFIX.'_prefs_data.user_id = ? AND '.LW_PREFIX.'_prefs_data.field_id = '.LW_PREFIX.'_prefs_fields.field_id', - array((int)$perm_id)); - - // direct sql required to fetch group_define_name - $backup['groups'] = $liveuserDB->getAll('SELECT liveuser_groups.group_define_name - FROM liveuser_groups, liveuser_groupusers - WHERE liveuser_groupusers.perm_user_id = ? AND liveuser_groupusers.group_id = liveuser_groups.group_id', - array((int)$perm_id)); - - // output serialized data to log file - $handle = $liveuserDB->getOne('SELECT handle FROM ! WHERE auth_user_id = ?', - array($authTable, (int)$auth_id)); - ewiki_log('liveuser: removed user: '.$handle.'|'.serialize($backup), 1); - - // remove records of user in auth/perm containers and the user's preferences - if ($liveuserPermAdmin->removeUser($perm_id) !== true) { - return false; - } - if ($liveuserAuthAdmin->removeUser($auth_id) !== true) { - return false; - } - return ($liveuserDB->query('DELETE FROM '.LW_PREFIX.'_prefs_data WHERE '.LW_PREFIX.'_prefs_data.user_id = ?', - array((int)$perm_id)) == DB_OK); - } - return false; - break; - - // common cases, fetch unique name from arguments and proceed - case 'language': - case 'application': - case 'area': - case 'right': - case 'group': - if (($entityId = liveuser_checkEntity($type, $id)) !== false) { - if (call_user_func_array(array(&$liveuserPermAdmin,'remove'.$type), $entityId) !== true) { - return false; - } - return true; - } - return false; - break; - - case 'language_id': - case 'application_id': - case 'area_id': - case 'right_id': - case 'group_id': - if (($entityId = liveuser_checkEntity($type, $id)) !== false) { - if (call_user_func_array(array(&$liveuserPermAdmin,'remove'.substr($type, 0, -3)), $entityId) !== true) { - return false; - } - return true; - } - return false; - break; - - // failure case, unknown type or no match for entity - default: - return false; - break; - } -} - -/** - * Allows for duplicate-safe creation of page permissions. If the permissions - * already exists, the page/right record will be updated, rather than inserted. - * Permissions may be specified as a combination of the page name and right_id, - * or the integer id of the permission may be supplied as the first parameter - * and the right_id parameter omitted. The preserveHigher parameter may be set - * to ensure that existing permissions higher than the permission being set - * are not overwritten, thus making the update have no effect. - * - * @param string type name of entity type to remove - * @param mixed page_id ewiki page name as a string or integer id - * @param int ring ewiki ring level - * @param int right_id LiveUser right id - * @param boolean preserveHigher does not overwrite higher permissions if true - * - * @return boolean true if permission was successfully added or modified, false otherwise - */ -function liveuser_addPerm($page_id, $ring, $right_id = null, $preserveHigher = false) -{ - global $liveuserDB; - - if (($perm_id = liveuser_checkPerm($page_id, $right_id)) !== false) { - if ($preserveHigher) { - return ($liveuserDB->query('UPDATE '.LW_PREFIX.'_perms SET ring = ? WHERE id = ? AND ring > ?', - array((int)$ring, (int)$perm_id, (int)$ring)) == DB_OK); - } else { - return ($liveuserDB->query('UPDATE '.LW_PREFIX.'_perms SET ring = ? WHERE id = ?', - array((int)$ring, (int)$perm_id)) == DB_OK); - } - } else { - return ($liveuserDB->query('INSERT INTO '.LW_PREFIX.'_perms (pagename, ring, right_id) VALUES (?, ?, ?)', - array($page_id, (int)$ring, (int)$right_id)) == DB_OK); - } - return false; -} - -/** - * Checks if a page permission already exists in the database. Permissions - * may be specified as a combination of the page name and right_id, or the - * integer id of the permission may be supplied as the first and only parameter. - * - * @param mixed page_id ewiki page name as a string or integer id - - * @param int right_id LiveUser right id - * - * @return mixed integer identifier if permission exists, false otherwise - */ -function liveuser_checkPerm($page_id, $right_id = null) -{ - global $liveuserDB; - - $perm_id = null; - - if (is_null($right_id)) { - if (is_numeric($page_id)) { - $perm_id = $liveuserDB->getOne('SELECT id FROM '.LW_PREFIX.'_perms WHERE id = ?', - array($page_id)); - } else { - // non-numeric page_id with null right_id, invalid input - return false; - } - } else { - $perm_id = $liveuserDB->getOne('SELECT id FROM '.LW_PREFIX.'_perms WHERE pagename = ? AND right_id = ?', - array($page_id, (int)$right_id)); - } - return (is_numeric($perm_id) ? $perm_id : false); -} - -/** - * Allows for removal of page permissions. Permissions may be specified as a - * combination of the page name and right_id, or the integer id of the permission - * may be supplied as the first and only parameter. The ring_min parameter may - * be used to limit the permissions that will be removed by ensuring that their - * ring level is at least the value given. The default value (0: highest access - * level) would allow all permissions to be removed. - * - * @param mixed page_id ewiki page name as a string or integer id - * @param int right_id LiveUser right id - * @param int ring_min remove only if ring level is >= this value - * - * @return boolean true if permission was successfully removed, false otherwise - */ -function liveuser_removePerm($page_id, $right_id = null, $ring_min = 0) -{ - global $liveuserDB; - - if (($perm_id = liveuser_checkPerm($page_id, $right_id)) !== false) { - return ($liveuserDB->query('DELETE FROM '.LW_PREFIX.'_perms WHERE id = ? AND ring >= ?', - array((int)$perm_id, (int)$ring_min)) == DB_OK); - } - return false; -} - -/** - * Retrieves all permissions for a page. Permissions may be specified as a - * combination of the pagename and right_id, or the integer id of the permission - * may be supplied as the first and only parameter. - * - * @param string pagename ewiki page name as a string - * @param int ring_min retrieve only if ring level is >= this value - * - * @return mixed array of permissions for the page - */ -function liveuser_getPerms($pagename, $ring_min = 0) -{ - global $liveuserDB; - - return $liveuserDB->getAll('SELECT * FROM '.LW_PREFIX.'_perms WHERE pagename = ? AND ring >= ?', - array($pagename, (int)$ring_min)); -} - -/** - * Checks if a group has a right. - * - * @param integer group_id group_id - * @param integer right_id right id - * @return boolean true if group has the right, false otherwise - */ -function liveuser_checkGroupRight($group_id, $right_id) -{ - global $liveuserPermAdmin; - - $groups = $liveuserPermAdmin->getGroups(array('where_group_id' => $group_id, 'with_rights' => true)); - - if (!is_array($groups)) { - return false; - } - - // result of getGroups() is an array [result set] of arrays [groups] - foreach ($groups as $group) { - $rights = $group['rights']; - foreach($rights as $right) { - if ($right['right_id'] == $right_id) { - return true; - } - } - } - return false; -} - -/** - * Checks if a user is a member of a group. - * - * @param integer auth_id auth_id - * @param integer group_id group_id - * @return boolean true if user is in the group, false otherwise - */ -function liveuser_checkGroupUser($group_id, $auth_id) -{ - global $liveuserPermAdmin; - - if (is_numeric($auth_id) && is_numeric($group_id) && - is_numeric($perm_id = liveuser_getPermUserId('user_id', $auth_id))) { - $groups = $liveuserPermAdmin->getGroups(array('where_user_id' => $perm_id, 'where_group_id' => $group_id)); - return (is_array($groups) && !empty($groups)); - } - return false; -} -/* Generates passwords for liveuser_gui and liveuser_addusers_gui*/ -function liveuser_generate_password(){ - $pwd = ''; // to store generated password - $len = rand(LW_PASSWORD_LEN_MIN, LW_PASSWORD_LEN_MAX); // password length - - do{ - // generate random number sequence of ascii characters - for ($i = 0; $i < $len; $i++) { - $num = rand(48, 122); - - if ($num >= ord('a') && $num <= ord('z')) { - $pwd .= chr($num); - } else if ($num >= ord('A') && $num <= ord('Z')) { - $pwd .= chr($num); - } else if ($num >= ord('0') && $num <= ord('9')) { - $pwd .= chr($num); - } else if ($num >= ord('#') && $num <= ord('&')) { - $pwd .= chr($num); - } else if ($num >= ord('?') && $num <= ord('@')) { - $pwd .= chr($num); - } else { - $i--; - } - } - }while(ewiki_check_passwd($pwd)!="good passwd"); - - return($pwd); -} - -function ewiki_calc_complexity($passlen, $groups){ - //checks for password complexity - return intval(log10(pow($groups,$passlen))/log10(2)); -} - -/*Checks to see if the password meets or exceeds a given complexity. - Checks to see if the password is based off of the user name. - Checks to see if the password is or contains a dictionary word. -*/ -function ewiki_check_passwd(&$password, $username=NULL, $skipdict=0){ - $lcase_password=strtolower($password); - $username=strtolower($username); - $possibilities=0; - $a_complexity['[a-z]']=26; //lowercase letters - $a_complexity['[A-Z]']=26; //uppercase letters - $a_complexity['[0-9]']=10; //numbers - $a_complexity['[()<>[\]{}!-.?,\'";:]']=17; //punctuation - $a_complexity['[@#$%^&*_=+\\/|`~ ]']=16; //misc symbols - - $passlen=strlen($password); - //determine the what sets are contained in the password - foreach($a_complexity as $regex => $count){ - //echo("checking $regex "); - if(preg_match("/".$regex."/", $password)){ - //echo("found $regex "); - $possibilities+=$count; - } - } - - $complexity=ewiki_calc_complexity($passlen, $possibilities); - if($complexity $cred){ - //echo("found $word "); - $password = str_replace($word, $cred, $password); - } - //echo(" calculating complexity of $password"); - if(ewiki_calc_complexity(strlen($password),$possibilities)setCurrentLanguage(liveuser_addEntity('language', array('EN', 'English', 'English'))); - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_conf.meta b/mods/wiki/plugins/auth-liveuser/liveuser_conf.meta deleted file mode 100644 index 0af218a37..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_conf.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: authentication -title: liveuser_conf -copyright: Copyright (c) 2003, The Burgiss Group, LLC -priority: auto diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_conf.php b/mods/wiki/plugins/auth-liveuser/liveuser_conf.php deleted file mode 100644 index 439050b1b..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_conf.php +++ /dev/null @@ -1,150 +0,0 @@ - 4, 'forum' => 3, 'edit' => 2, 'manage' => 1, 'admin' => 0); -$liveuserPermRings = array('view' => $liveuserBaseRings['view'], - 'info' => $liveuserBaseRings['view'], - 'links' => $liveuserBaseRings['view'], - 'extodo' => $liveuserBaseRings['view'], - 'expolicy' => $liveuserBaseRings['view'], - 'search' => $liveuserBaseRings['view'], - 'diff' => $liveuserBaseRings['view'], - 'calendar' => $liveuserBaseRings['view'], - 'binary-cache' => $liveuserBaseRings['view'], - 'binary-get' => $liveuserBaseRings['view'], - 'sitemap' => $liveuserBaseRings['view'], - 'like' => $liveuserBaseRings['view'], - 'addpost' => $liveuserBaseRings['forum'], - 'addthread' => $liveuserBaseRings['forum'], - 'edit' => $liveuserBaseRings['edit'], - 'fetchback' => $liveuserBaseRings['edit'], - 'attachments' => $liveuserBaseRings['edit'], - 'wikidump' => $liveuserBaseRings['view'], - 'updformatheader'=> $liveuserBaseRings['manage'], - 'manage' => $liveuserBaseRings['manage'], - 'binary-upload' => $liveuserBaseRings['manage'], - 'admin' => $liveuserBaseRings['admin']); - -/* - * the following arrays will be used to filter displayed permission names when - * editing a page. any permission names not cross-listed in liveuserPublicPerms - * will be kept hidden (and thus cannot be assigned). any permission names - * additionally listed in liveuserDefaultPerms will be selected in the form - * by default. - */ -$liveuserPublicPerms = array('Staff'); -$liveuserDefaultPermsView = array('Staff'); -$liveuserDefaultPermsEdit = array('Staff'); - -/* - * database configuration. the liveuserDSN variable should be set to a valid DSN - * string according to PEAR::DB specifications. - * - * - * (mysql is the type for mysql databases) - */ -$liveuserDSN = 'type://username:password@server/database'; - -/* - * the following array contains liveuser configuration parameters. - */ -$liveuserConfig = array('session' => array('name' => 'PHPSESSID', 'varname' => 'loginInfo'), - 'login' => array('method' => 'post', 'username' => 'username', 'password' => 'password', 'force' => false), - 'logout' => array('destroy' => true), - 'autoInit' => true, - 'authContainers' => array(0 => array('name' => 'eWiki', - 'type' => 'DB', - 'dsn' => $liveuserDSN, - 'loginTimeout' => 0, - 'expireTime' => 43200, - 'idleTime' => 7200, - 'allowDuplicateHandles' => 0, - 'authTable' => 'liveuser_users', - 'passwordEncryptionMode' => 'MD5' - ) - ), - 'permContainer' => array('type' => 'DB_Complex', - 'dsn' => $liveuserDSN, - 'prefix' => 'liveuser_' - ) - ); - -/* - * The following PEAR error handler may be set to globally handle errors generated - * by PEAR classes. It provides debug/backtrace output for user-level PHP errors. - * If used, PHP should be set not to display internal error messages to clients. - * - * @param object err PEAR error object - */ -function _liveuser_error_handler($err) { - $log = $err->toString(); - if(function_exists('debug_backtrace')){ - // remove first step from backtrace (this function call), and parse remaining stack trace - $trace = debug_backtrace(); - array_shift($trace); - foreach ($trace as $step) { - $log .= "\n"; - if (isset($step['file'])) $log .= $step['file'].':'; - if (isset($step['line'])) $log .= $step['line'].' '; - if (isset($step['function'])) { - $log .= $step['function'].'('; - if (isset($step['args'])) { - $args = ''; - foreach ($step['args'] as $arg) { $args .= '\''.$arg.'\','; } - $log .= rtrim($args,','); - } - $log .= ') '; - } - } - } - error_log($log."\n", 0); - exit('

              An internal error has occurred. Please consult the error logs for additional information

              '); -} - -PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, '_liveuser_error_handler'); -$liveuserDB =& DB::connect($liveuserDSN); -$liveuserDB->setFetchMode(DB_FETCHMODE_ASSOC); - -?> diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_perms_gui.meta b/mods/wiki/plugins/auth-liveuser/liveuser_perms_gui.meta deleted file mode 100644 index 5dd321e0f..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_perms_gui.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: authentication -title: liveuser_perms_gui -copyright: Copyright (c) 2003, The Burgiss Group, LLC -priority: auto diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_perms_gui.php b/mods/wiki/plugins/auth-liveuser/liveuser_perms_gui.php deleted file mode 100644 index a41d93d85..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_perms_gui.php +++ /dev/null @@ -1,279 +0,0 @@ -getRights(); - - if (!$readonly) { - // Handle POSTed deletes or updates - foreach ($_POST as $key => $value) { - list($prefix, $id) = explode('_',$key,2); - - if ($prefix == 'chk' && is_numeric($id) && $value == 'on' && isset($_POST['submit_changeperm'])) { - if (liveuser_removePerm($id)) { - echo '

              Permission '.$id.' was successfully deleted.

              '; - } else { - echo '

              Deletion of permission '.$id.' failed.

              '; - } - } - - if ($prefix == 'ring' && is_numeric($id) && $value != '-1' && isset($_POST['submit_changeperm'])) { - if (liveuser_addPerm($id, $value)) { - echo '

              Permission '.$id.' was successfully updated.

              '; - } else { - echo '

              Update of permission '.$id.' failed.

              '; - } - } - } - - // Handle POSTed new rows - if (!empty($_POST['pagename_text']) && !empty($_POST['right_list']) && isset($_POST['submit_addperm'])) { - $livewebperm = liveuser_checkPerm($_POST['pagename_text'], $_POST['right_list']); - - if ($livewebperm === false) { - $livewebperm = liveuser_addPerm($_POST['pagename_text'], $_POST['ring_list'], $_POST['right_list']); - - if ($livewebperm !== false ) { - echo '

              Permission for '.$_POST['pagename_text'].' was successfully created.

              '; - } else { - echo '

              Creation of permission for '.$_POST['pagename_text'].' failed.

              '; - } - } else { - echo '

              Permission for '.$_POST['pagename_text'].' with class '.$_POST['right_list'].' already exists.

              '; - } - } - - // Show Add a new row section - ?> -
              -

              Add a Page Permission

              - ')?> - ')?> - ')?> - -
              - -
              - -
              - -
              - -
              -

              Filter Permissions

              - - - - - -
              - -
              -
              - - -
                 - $letter)).'">'.$letter.' '; - } - - ?> - 0-9 - Other - All -
              -
              - = 'A' && $_REQUEST['letterfilter'] <= 'Z') { - $filter = ' AND UPPER('.LW_PREFIX.'_perms.pagename) LIKE "'.$_REQUEST['letterfilter'].'%"'; - } - - if ($_REQUEST['letterfilter'] == '0-9') { - $filter = ' AND '.LW_PREFIX.'_perms.pagename REGEXP "^[0-9]"'; - } - - if ($_REQUEST['letterfilter'] == 'other') { - $filter = ' AND '.LW_PREFIX.'_perms.pagename REGEXP "^[^0-9A-Za-z]"'; - } - } - - $query .= $filter; - $query .= ' ORDER BY '.LW_PREFIX.'_perms.pagename ASC'; - - if (isset($_REQUEST['pagefilter']) || isset($_POST['classfilter']) || isset($_REQUEST['letterfilter'])) { - $perms = $liveuserDB->getAll($query); - - if (is_array($perms) && !empty($perms)) { - if (!$readonly) { - // Display regular AdminPerms page - ?> -
              - ')?> - ')?> - ')?> -

              Edit Permissions

              - - - - - - - - - - -
              DeletePage NamePermission LevelClass
              - - -
              - -

              View Permissions

              - - - - - - - - - '; - } - } else { - ?> -

              Permissions

              -

              No permissions were found in the database.

              - \ No newline at end of file diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_prefs_gui.meta b/mods/wiki/plugins/auth-liveuser/liveuser_prefs_gui.meta deleted file mode 100644 index 22bf58970..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_prefs_gui.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: authentication -title: liveuser_prefs_gui -copyright: Copyright (c) 2003, The Burgiss Group, LLC -priority: auto diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_prefs_gui.php b/mods/wiki/plugins/auth-liveuser/liveuser_prefs_gui.php deleted file mode 100644 index c2e2c368d..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_prefs_gui.php +++ /dev/null @@ -1,155 +0,0 @@ - $value) { - list($prefix, $id) = explode('_', $key, 2); - - // deleted checked preferences - if ($prefix == 'chk' && is_numeric($id) && $value == 'on') { - if (liveuser_pref_removeField($id)) { - echo '

              Field '.$id.' was successfully deleted

              .'; - } else { - echo '

              An error occurred deleting field '.$id.'

              '; - } - } - - // update preference fields for differing new/old values - if ($prefix == 'public' && is_numeric($id) && ($_POST['origpublic_'.$id] != $value)) { - echo 'old value: '.$_POST['origpublic_'.$id].'new value: '.$value.'
              '; - } - - if ($prefix == 'default' && is_numeric($id) && ($_POST['origdefault_'.$id] != $value)) { - echo 'old value: '.$_POST['origdefault_'.$id].'new value: '.$value.'
              '; - } - } - } - - // Handle POSTed new rows - if (!empty($_POST['prefname_text'])) { - $livewebpref = liveuser_pref_checkField($_POST['prefname_text']); - - if ($livewebpref === false) { - if (!empty($_POST['default_text'])) { - $livewebpref = $_POST['public_chk'] ? liveuser_pref_setField($_POST['prefname_text'], true, $_POST['default_text']) : - liveuser_pref_setField($_POST['prefname_text'], false, $_POST['default_text']); - } else { - $livewebpref = $_POST['public_chk'] ? liveuser_pref_setField($_POST['prefname_text'], true) : - liveuser_pref_setField($_POST['prefname_text'], false); - } - - if ($livewebpref !== false ) { - echo $_POST['prefname_text'].' was inserted into liveweb_prefs_fields...'; - } - } else { - echo $_POST['prefname_text'].' could NOT be inserted into liveweb_prefs_fields...'; - } - } - - echo '

              '; - - // Get list of prefs fields in liveuser system - $results = $liveuserDB->getAll('SELECT * FROM liveweb_prefs_fields'); - - // show form for modifying preferences - if (is_array($results) && !empty($results)) { - ?> - -

              Modify Preference Fields

              -
              PagenamePerm LevelClass
              - - - - - - - - - -
              DeleteIDPreferencePublicDefault Value
              - - - - - -
              - - - - No preference fields were found.

              '; - } - - // show form for adding preferences - ?> -
              -

              Add a Preference Field

              - -
              - -
              - -
              - -
              - \ No newline at end of file diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_rights_gui.meta b/mods/wiki/plugins/auth-liveuser/liveuser_rights_gui.meta deleted file mode 100644 index 6a42f5567..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_rights_gui.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: authentication -title: liveuser_rights_gui -copyright: Copyright (c) 2003, The Burgiss Group, LLC -priority: auto diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_rights_gui.php b/mods/wiki/plugins/auth-liveuser/liveuser_rights_gui.php deleted file mode 100644 index 417919051..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_rights_gui.php +++ /dev/null @@ -1,158 +0,0 @@ - $value) { - list($prefix, $id) = explode('_',$key,2); - - if ($prefix == 'chk' && is_numeric($id) && $value == 'on') { - if (liveuser_removeEntity('right_id', $id)) { - echo '

              Right '.$id.' was successfully deleted.

              '; - } else { - echo '

              Deletion of right '.$id.' failed.

              '; - } - } - } - } - - // handle posted new rights - if (isset($_POST['rightname_text']) && isset($_POST['submit_addright'])) { - $right_id = liveuser_checkEntity('right', $_POST['rightname_text']); - - if ($right_id === false) { - $right_const = 'LU_R_'.strtoupper($_POST['rightname_text']); - $right_id = liveuser_addEntity('right', array(LU_AREA_LIVEWEB, $right_const, $_POST['rightname_text'])); - - if ($right_id !== false) { - echo '

              Right '.$_POST['rightname_text'].' was successfully created.

              '; - } else { - echo '

              Creation of right '.$_POST['rightname_text'].' failed.

              '; - } - } else { - echo '

              Right '.$_POST['rightname_text'].' already exists.

              '; - } - - if (isset($_POST['addgroup']) && $right_id !== false) { - $group_id = liveuser_checkEntity('group', $_POST['rightname_text']); - - if ($group_id === false) { - $group_const = 'LU_G_'.strtoupper($_POST['rightname_text']); - $group_id = liveuser_addEntity('group', array($group_const, $_POST['rightname_text'], null, true)); - - if ($group_id !== false) { - echo '

              Group '.$_POST['rightname_text'].' was successfully created.

              '; - } else { - echo '

              Creation of group '.$_POST['rightname_text'].' failed.

              '; - } - } else { - echo '

              Group '.$_POST['rightname_text'].' already exists.

              '; - } - - if ($group_id !== false) { - // check if group already has the right - if (liveuser_checkGroupRight($group_id, $right_id)) { - echo 'Group '.$_POST['rightname_text'].' already has right '.$_POST['rightname_text'].'.

              '; - } else { - // attempt to assign right to group - if ($liveuserPermAdmin->grantGroupRight($group_id, $right_id, 1) === true) { - echo '

              Right '.$_POST['rightname_text'].' has been assigned to group '.$_POST['rightname_text'].'.

              '; - } else { - echo '

              Assignment of right '.$_POST['rightname_text'].' to group '.$_POST['rightname_text'].' failed.

              '; - } - } - } - } - } - - // Show current table listing of rights - $rights = $liveuserPermAdmin->getRights(); - - if (is_array($rights) && !empty($rights)) { - ?> -
              -

              Edit Rights

              - - - - - - - - - -
              DeleteRight IDRight
              - - -
              - -

              Edit Rights

              -

              No rights were found in the database.

              - -
              -

              Add a Right

              -

              When creating a right, you may choose to create a group with the right, which may then be applied to user accounts. If the right already exists, this form will still attempt to link a group to it. If the group already exists and does not have the right, the right will be assigned.

              - -
              - -
              - -
              - \ No newline at end of file diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_setup.meta b/mods/wiki/plugins/auth-liveuser/liveuser_setup.meta deleted file mode 100644 index 40db9a7e9..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_setup.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: authentication -title: liveuser_setup -copyright: Copyright (c) 2003, The Burgiss Group, LLC -priority: auto diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_setup.php b/mods/wiki/plugins/auth-liveuser/liveuser_setup.php deleted file mode 100644 index 700294771..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_setup.php +++ /dev/null @@ -1,217 +0,0 @@ -setFetchMode(DB_FETCHMODE_ASSOC); -$pagenames = $liveuserWikiDB->getAll('SELECT DISTINCT pagename FROM ewiki'); -$liveuserWikiDB->disconnect(); - -/* - * if necessary, override the database connection in liveuser_conf.php with one - * that has CREATE/DROP rights. comment these lines otherwise. - */ -// $liveuserDB->disconnect(); -// $liveuserDB =& DB::connect('type://username:password@server/database'); - -// create plugin tables -$liveuserDB->query(' - CREATE TABLE IF NOT EXISTS '.LW_PREFIX.'_perms ( - id int(10) unsigned not null auto_increment, - pagename varchar(160) binary not null, - ring tinyint(3) unsigned not null, - right_id int(10) not null, - primary key (id), - unique pagerule (pagename, right_id)) - type=MyISAM;'); - -// liveuser prefs plugin tables -$liveuserDB->query(' - CREATE TABLE IF NOT EXISTS '.LW_PREFIX.'_prefs_data ( - pref_id int(10) unsigned not null auto_increment, - user_id int(10) not null, - field_id int(10) not null, - field_value mediumblob, - primary key (pref_id), - unique prefrule (user_id, field_id)) - type=MyISAM;'); - -$liveuserDB->query(' - CREATE TABLE IF NOT EXISTS '.LW_PREFIX.'_prefs_fields ( - field_id int(10) unsigned not null auto_increment, - field_name varchar(255), - public tinyint(1), - default_value mediumblob, - primary key (field_id), - unique fieldrule (field_name)) - type=MyISAM;'); - -$liveuserDB->query(" - CREATE TABLE IF NOT EXISTS ".LW_PREFIX."_login_log ( - auth_user_handle varchar(32) NOT NULL default '', - php_session_id varchar(40) NOT NULL default '', - ssl_session_id varchar(16) default '', - ip_address varchar(16) NOT NULL default '', - time timestamp(14) NOT NULL, - delay tinyint(1) NOT NULL default '0', - success tinyint(1) NOT NULL default '0', - PRIMARY KEY (time,auth_user_handle) - ) TYPE=MyISAM; "); - - -/* - * the defs array will accumulate all created entities, that should become defined - * constants to be inserted into the main config file. created entities will include - * the language (default English, also set in liveuser_aux.php), application - * name and area (arbitrary values), right and group names, and users. All groups - * should correspond to a particular right of the same name. - */ -$defs = array(); - -$defs['LU_LANG'] = liveuser_addEntity('language', array('EN', 'English', 'English')); -$defs['LU_APP'] = liveuser_addEntity('application', array('LU_APP', 'AppName')); -$defs['LU_AREA'] = liveuser_addEntity('area', array($defs['LU_APP'], 'LU_AREA', 'AppArea')); - -$rights = array( - array($defs['LU_AREA'], 'LU_R_NOTLOGGEDIN', 'NotLoggedIn'), - array($defs['LU_AREA'], 'LU_R_LOGGEDIN', 'LoggedIn'), - array($defs['LU_AREA'], 'LU_R_LW_PUBLISHER', 'LW_Publisher'), - array($defs['LU_AREA'], 'LU_R_LW_ADMIN', 'LW_Admin'), - array($defs['LU_AREA'], 'LU_R_STAFF', 'Staff')); - -foreach ($rights as $right) { - $defs[$right[1]] = liveuser_addEntity('right', $right); -} - -$groups = array( - array('LU_G_LW_PUBLISHER', 'LW_Publisher', null, true), - array('LU_G_LW_ADMIN', 'LW_Admin', null, true), - array('LU_G_STAFF', 'Staff', null, true)); - -foreach ($groups as $group) { - $setup_defs[$group[0]] = liveuser_addEntity('group', $group); - - if (liveuser_checkGroupRight($defs[$group[0]], $defs['LU_R_'.strtoupper($group[1])]) === false) { - $liveuserPermAdmin->grantGroupRight($defs[$group[0]], $defs['LU_R_'.strtoupper($group[1])], 1); - } -} - -// LiveUser plugin pages -liveuser_addPerm('AdminPerms', $liveuserBaseRings['view'], $defs['LU_R_LW_ADMIN']); -liveuser_addPerm('AdminRights', $liveuserBaseRings['view'], $defs['LU_R_LW_ADMIN']); -liveuser_addPerm('AdminAddUsers', $liveuserBaseRings['view'], $defs['LU_R_LW_ADMIN']); -liveuser_addPerm('AdminUsers', $liveuserBaseRings['view'], $defs['LU_R_LW_ADMIN']); -// default list of eWiki plugins -liveuser_addPerm('LogIn', $liveuserBaseRings['view'], $defs['LU_R_NOTLOGGEDIN']); -liveuser_addPerm('Login', $liveuserBaseRings['view'], $defs['LU_R_NOTLOGGEDIN']); -liveuser_addPerm('LogOut', $liveuserBaseRings['view'], $defs['LU_R_LOGGEDIN']); -liveuser_addPerm('Logout', $liveuserBaseRings['view'], $defs['LU_R_LOGGEDIN']); -liveuser_addPerm('ChangePassword', $liveuserBaseRings['view'], $defs['LU_R_LOGGEDIN']); -liveuser_addPerm('ProtectedEmail', $liveuserBaseRings['view'], $defs['LU_R_NOTLOGGEDIN']); -liveuser_addPerm('PowerSearch', $liveuserBaseRings['view'], $defs['LU_R_LOGGEDIN']); -liveuser_addPerm('SearchPages', $liveuserBaseRings['view'], $defs['LU_R_LOGGEDIN']); -liveuser_addPerm('Search', $liveuserBaseRings['view'], $defs['LU_R_LOGGEDIN']); -liveuser_addPerm('PageIndex', $liveuserBaseRings['view'], $defs['LU_R_STAFF']); -liveuser_addPerm('WordIndex', $liveuserBaseRings['view'], $defs['LU_R_STAFF']); -liveuser_addPerm('PageCalendar', $liveuserBaseRings['view'], $defs['LU_R_STAFF']); -liveuser_addPerm('PageYearCalendar', $liveuserBaseRings['view'], $defs['LU_R_STAFF']); -liveuser_addPerm('OrphanedPages', $liveuserBaseRings['view'], $defs['LU_R_STAFF']); -liveuser_addPerm('NewestPages', $liveuserBaseRings['view'], $defs['LU_R_STAFF']); -liveuser_addPerm('MostVisitedPages', $liveuserBaseRings['view'], $defs['LU_R_STAFF']); -liveuser_addPerm('MostOftenChangedPages', $liveuserBaseRings['view'], $defs['LU_R_STAFF']); -liveuser_addPerm('UpdatedPages', $liveuserBaseRings['view'], $defs['LU_R_STAFF']); -liveuser_addPerm('FileUpload', $liveuserBaseRings['view'], $defs['LU_R_STAFF']); -liveuser_addPerm('FileDownload', $liveuserBaseRings['view'], $defs['LU_R_STAFF']); -liveuser_addPerm('AboutPlugins', $liveuserBaseRings['view'], $defs['LU_R_STAFF']); -// ability to create new pages -liveuser_addPerm('[NewPage]', $liveuserBaseRings['manage'], $defs['LU_R_STAFF']); - -// set rights on all existing pagename's -foreach ($pagenames as $pagename) { - liveuser_addPerm($pagename['pagename'], $liveuserBaseRings['manage'], $defs['LU_R_STAFF']); -} - -echo "// add the following lines to liveuser_conf.php\n"; -foreach ($defs as $key => $value) { - echo 'define(\''.$key.'\', '.(is_numeric($value) ? $value : '\''.$value.'\'').");\n"; - define($key,$value); -} - -// default user list -$users = array( - 'user1', - 'user2', - 'user3'); - -// add users (password = username) and set group memberships for default users -foreach ($users as $user) { - if (liveuser_checkEntity('user', $user) === false) { - if (liveuser_addEntity('user', array($user, $user)) !== false) { - echo 'added user '.$user."\n"; - } - - $id = liveuser_checkEntity('user', $user); - if ($id !== false && $liveuserPermAdmin->addUserToGroup($id, $setup_defs['LU_G_STAFF'])) { - echo 'added user '.$user.' to group Staff'."\n"; - } - } -} - -// set special group membership for a user -$user1 = liveuser_checkEntity('user', 'user1'); -if (liveuser_checkGroupUser($setup_defs['LU_G_LW_PUBLISHER'], $user1) === false) { - if ($liveuserPermAdmin->addUserToGroup($user1, $setup_defs['LU_G_LW_PUBLISHER'])) { - echo 'added user user1 to group Publisher'."\n"; - } -} -if (liveuser_checkGroupUser($setup_defs['LU_G_LW_ADMIN'], $user1) === false) { - if ($liveuserPermAdmin->addUserToGroup($user1, $setup_defs['LU_G_LW_ADMIN'])) { - echo 'added user user1 to group Admin'."\n"; - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_setup_prefs.meta b/mods/wiki/plugins/auth-liveuser/liveuser_setup_prefs.meta deleted file mode 100644 index 8400e8615..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_setup_prefs.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: authentication -title: liveuser_setup_prefs -copyright: Copyright (c) 2003, The Burgiss Group, LLC -priority: auto diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_setup_prefs.php b/mods/wiki/plugins/auth-liveuser/liveuser_setup_prefs.php deleted file mode 100644 index 49ca4658b..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_setup_prefs.php +++ /dev/null @@ -1,107 +0,0 @@ - true, - 'FirstName' => true, - 'MiddleName'=> true, - 'LastName' => true, - 'Company' => true, - 'Phone' => true, - 'Address' => true, - 'City' => true, - 'State' => true, - 'ZipCode' => true, - 'Country' => true -); - -$prefs_default_value = array( - 'Country' => 'USA' -); - -$prefs_possible_values = array( - 'State' => array( - 'Alabama', - 'Alaska', - 'Arizona', - 'Arkansas', - 'California', - 'Colorado', - 'Connecticut', - 'Delaware', - 'Florida', - 'Georgia', - 'Hawaii', - 'Idaho', - 'Illinois', - 'Indiana', - 'Iowa', - 'Kansas', - 'Kentucky', - 'Louisiana', - 'Maine', - 'Maryland', - 'Massachusetts', - 'Michigan', - 'Minnesota', - 'Mississippi', - 'Missouri', - 'Montana', - 'Nebraska', - 'Nevada', - 'New Hampshire', - 'New Jersey', - 'New Mexico', - 'New York', - 'North Carolina', - 'North Dakota', - 'Ohio', - 'Oklahoma', - 'Oregon', - 'Pennsylvania', - 'Rhode Island', - 'South Carolina', - 'South Dakota', - 'Tennessee', - 'Texas', - 'Utah', - 'Vermont', - 'Virginia', - 'Washington', - 'West Virginia', - 'Wisconsin', - 'Wyoming' - ) -); - -// iterate through list of prefs and add them as user preference fields -foreach ($prefs as $pref => $public) { - liveuser_pref_setField($pref, $public, $prefs_default_value[$pref], $prefs_possible_values[$pref]); - echo 'Added field '.$pref."\n"; -} - -?> diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_users_gui.meta b/mods/wiki/plugins/auth-liveuser/liveuser_users_gui.meta deleted file mode 100644 index 3e404f8ba..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_users_gui.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: authentication -title: liveuser_users_gui -copyright: Copyright (c) 2003, The Burgiss Group, LLC -priority: auto diff --git a/mods/wiki/plugins/auth-liveuser/liveuser_users_gui.php b/mods/wiki/plugins/auth-liveuser/liveuser_users_gui.php deleted file mode 100644 index b16de1b1b..000000000 --- a/mods/wiki/plugins/auth-liveuser/liveuser_users_gui.php +++ /dev/null @@ -1,557 +0,0 @@ - $value) { - - list($prefix, $id) = explode('_', $key, 2); - - //get password status of current $id - $username=$_POST['origname_'.$id]; - $pwdstatus = ewiki_get_uservar("passwdstatus", NULL, $username); - - // Remove a user - if ($prefix == 'chk' && is_numeric($id) && $value == 'on' && isset($_POST['submit_deleteusers'])) { - if (liveuser_removeEntity('user_id', $id)) { - echo '

              User '.$id.' was successfully removed.

              '; - } else { - echo '

              Removal of user '.$id.' failed.

              '; - } - } - - // Add a user to a group - if ($prefix == 'chk' && is_numeric($id) && $value == 'on' && isset($_POST['submit_adduserstogroup'])) { - if (($group_id = liveuser_checkEntity('group', $_POST['grouplist'])) !== false) { - if (liveuser_checkGroupUser($group_id, $id) === false) { - if ($liveuserPermAdmin->addUserToGroup($id, $group_id)) { - echo '

              User '.$id.' was successfully added to group '.$_POST['grouplist'].'.

              '; - } else { - echo '

              Addition of user '.$id.' to group '.$_POST['grouplist'].' failed.

              '; - } - } else { - echo '

              User '.$id.' is already a member of group '.$_POST['grouplist'].'.

              '; - } - } else { - echo '

              Group '.$_POST['grouplist'].' does not exist.

              '; - } - } - - // Remove a user from a group - if ($prefix == 'chk' && is_numeric($id) && $value == 'on' && isset($_POST['submit_removeusersfromgroup'])) { - if (($group_id = liveuser_checkEntity('group', $_POST['grouplist'])) !== false) { - if ($liveuserPermAdmin->removeUserFromGroup($id, liveuser_checkEntity('group', $_POST['grouplist']))) { - echo '

              User '.$id.' was successfully removed from group '.$_POST['grouplist'].'.

              '; - } else { - echo '

              Removal of user '.$id.' from group '.$_POST['grouplist'].' failed.

              '; - } - } else { - echo '

              Group '.$_POST['grouplist'].' does not exist.

              '; - } - } - - // Change the user name - if ($prefix == 'chname' && is_numeric($id) && !empty($value) && ($_POST['origname_'.$id] != $value) && isset($_POST['submit_changeusers'])) { - $event_log=''; - if (liveuser_checkEntity('user', $value) === false) { - if ($liveuserAuthAdmin->updateUser($id, $value)) { - $event_log.='

              User '.$value.' was successfully updated.

              '; - if(isset($ewiki_plugins['uservars_store'][0])){ - if($ewiki_plugins['uservars_store'][0]($ewiki_plugins['uservars_retrieve'][0]($_POST['origname_'.$id]),$value)){ - $event_log.='

              User data copied to '.$value; - if($ewiki_plugins['uservars_store'][0](array(),$_POST['origname_'.$id])){ - $event_log.= ' and deleted from '.$_POST['origname_'.$id]; - } else { - $event_log.= ' but not deleted from '.$_POST['origname_'.$id]; - } - $event_log.= '.

              '; - } else { - $event_log.= '

              User data copy failed.

              '; - } - } - } else { - $event_log.= '

              Update of user '.$value.' failed.

              '; - } - } else { - $event_log.= '

              Another user with the name '.$value.' already exists in the database. No change has been made.

              '; - } - echo($event_log); - ewiki_log("Attempted to rename ".$_POST['origname_'.$id]." to $value.".$event_log,1); - } - - // Change user variable - if ($prefix == 'chuvar' && is_numeric($id) && !empty($value) && ($_POST['origchuvar_'.$id] != $value) && isset($_POST['submit_changeusers'])) { - if(ewiki_set_uservar($_POST['uvar_fieldname'], $value, $username)){ - echo "

              UserVar ".$_POST['uvar_fieldname']." successfully updated for $username

              "; - } else { - echo "

              Update of UserVar ".$_POST['uvar_fieldname']." for $username failed.

              "; - } - } - - if ($prefix == "radpw" && is_numeric($id) && !empty($value) && isset($_POST['submit_changeusers'])) { - if ($value=="expire" && ($pwdstatus=='good' || is_null($pwdstatus))){ - ewiki_set_uservar("passwdexpiredate", time(),$username); - ewiki_set_uservar("passwdstatus", 'expired', $username); - } elseif($value=="good" && ($pwdstatus=='expired' || is_null($pwdstatus))){ - ewiki_set_uservar("passwdexpiredate", time()+(60*60*24*EWIKI_PASSWD_LIFETIME),$username); - ewiki_set_uservar("passwdstatus", 'good', $username); - } - } - - if ($prefix == 'chkrandpw' && is_numeric($id) && !empty($value) && isset($_POST['submit_changeusers'])) { - $password=liveuser_generate_password(); - - if ($liveuserAuthAdmin->updateUser($id, $_POST['chname_'.$id], $password)) { - ewiki_set_uservar("passwdexpiredate", time()-(60*60*24*EWIKI_PASSWD_LIFETIME),$username); - ewiki_set_uservar("passwdstatus", 'expired', $username); - echo '

              Password for user '.$_POST['chname_'.$id]." was successfully updated to \"$password\" and set to expire in ".EWIKI_PASSWD_LIFETIME."days.

              "; - } else { - echo '

              Update of password for user '.$_POST['chname_'.$id].' failed.

              '; - } - } - - // Change the user's password - if ($prefix == 'chpw' && is_numeric($id) && !empty($value) && isset($_POST['submit_changeusers'])) { - // check for cracklib functions and validate against them if possible - liveuser_admin_users_cracklib_check($_POST['chname_'.$id], $value); - - if ($liveuserAuthAdmin->updateUser($id, $_POST['chname_'.$id], $value)) { - ewiki_set_uservar("passwdexpiredate", time()-(60*60*24*EWIKI_PASSWD_LIFETIME),$username); - ewiki_set_uservar("passwdstatus", 'expired', $username); - echo '

              Password for user '.$_POST['chname_'.$id].' was successfully updated and set to expire in '.EWIKI_PASSWD_LIFETIME.'days.

              '; - } else { - echo '

              Update of password for user '.$_POST['chname_'.$id].' failed.

              '; - } - } - - // Remove a group - if ($prefix == 'chkgroup' && is_numeric($id) && $value == 'on' && isset($_POST['submit_changegroups'])) { - if (liveuser_removeEntity('group_id', $id)) { - echo '

              Group '.$id.' was successfully deleted.

              '; - } else { - echo '

              Deletion of group '.$id.' failed.

              '; - } - } - - // Change group name - if ($prefix == 'chgroupname' && is_numeric($id) && !empty($value) && ($_POST['origgroupname_'.$id] != $value) && isset($_POST['submit_changegroups'])) { - if ($liveuserPermAdmin->updateGroup($id, $value)) { - echo '

              Group '.$value.' was successfully updated.

              '; - } else { - echo 'Update of group '.$value.' failed.

              '; - } - } - } - } - - // Add a user - if (!empty($_POST['username_text']) && !empty($_POST['pw_text']) && isset($_POST['submit_adduser'])) { - if (liveuser_checkEntity('user', $_POST['username_text']) === false) { - // check for cracklib functions and validate against them if possible - liveuser_admin_users_cracklib_check($_POST['chname_'.$id], $value); - - if (liveuser_addEntity('user', array($_POST['username_text'], $_POST['pw_text'])) !== false) { - echo '

              User '.$_POST['username_text'].' was successfully created.

              '; - } else { - echo '

              Creation of user '.$_POST['username_text'].' failed.

              '; - } - } else { - echo '

              User '.$_POST['username_text'].' already exists.

              '; - } - } - - // Add a lot of users and add them into groups - if (!empty($_POST['usernames_text']) && isset($_POST['submit_addusers'])) { - $newusers = explode("\n", $_POST['usernames_text']); - - foreach ($newusers as $newuser) { - $newuser = trim($newuser); - - if (($auth_id = liveuser_checkEntity('user', $newuser)) === false) { - if ($_POST["pwgen_addusers"]=="on"){ - $password=liveuser_generate_password(); - }else{ - $password=$newuser; - } - if (($auth_id = liveuser_addEntity('user', array($newuser, $password))) !== false) { - echo "

              User $newuser was successfully created with password $password.

              "; - } else { - echo '

              Creation of user '.$newuser.' failed.

              '; - } - } else { - echo '

              User '.$newuser.' already exists.

              '; - } - - if ($auth_id !== false && !empty($_POST['usernames_grouplist'])) { - if (($group_id = liveuser_checkEntity('group', $_POST['usernames_grouplist'])) !== false) { - if (liveuser_checkGroupUser($group_id, $auth_id) === false) { - if ($liveuserPermAdmin->addUserToGroup($auth_id, $group_id)) { - echo '

              User '.$newuser.' was successfully added to group '.$_POST['usernames_grouplist'].'.

              '; - } else { - echo '

              Addition of user '.$newuser.' to group '.$_POST['usernames_grouplist'].' failed.

              '; - } - } else { - echo '

              User '.$newuser.' is already a member of group '.$_POST['usernames_grouplist'].'.

              '; - } - } else { - echo '

              Group '.$_POST['usernames_grouplist'].' does not exist.

              '; - } - } - } - } - - // Add a group - if (!empty($_POST['groupname_text']) && isset($_POST['submit_addgroup'])) { - $group_id = liveuser_checkEntity('group', $_POST['groupname_text']); - - if ($group_id === false) { - $group_const = 'LU_G_'.strtoupper($_POST['groupname_text']); - $group_id = liveuser_addEntity('group', array($group_const, $_POST['groupname_text'], null, true)); - - if ($group_id !== false) { - echo '

              Group '.$_POST['groupname_text'].' was successfully created.

              '; - } else { - echo '

              Creation of group '.$_POST['groupname_text'].' failed.

              '; - } - } else { - echo '

              Group '.$_POST['groupname_text'].' already exists.

              '; - } - - if (isset($_POST['addright']) && $group_id !== false) { - $right_id = liveuser_checkEntity('right', $_POST['groupname_text']); - - if ($right_id === false) { - $right_const = 'LU_R_'.strtoupper($_POST['groupname_text']); - $right_id = liveuser_addEntity('right', array(LU_AREA_LIVEWEB, $right_const, $_POST['groupname_text'])); - - if ($right_id !== false) { - echo '

              Right '.$_POST['groupname_text'].' was successfully created.

              '; - } else { - echo '

              Creation of right '.$_POST['groupname_text'].' failed.

              '; - } - } else { - echo '

              Right '.$_POST['groupname_text'].' already exists.

              '; - } - - if ($right_id !== false) { - // check if group already has the right - if (liveuser_checkGroupRight($group_id, $right_id)) { - echo 'Group '.$_POST['groupname_text'].' already has right '.$_POST['groupname_text'].'.

              '; - } else { - // attempt to assign right to group - if ($liveuserPermAdmin->grantGroupRight($group_id, $right_id, 1) === true) { - echo '

              Right '.$_POST['groupname_text'].' has been assigned to group '.$_POST['groupname_text'].'.

              '; - } else { - echo '

              Assignment of right '.$_POST['groupname_text'].' to group '.$_POST['groupname_text'].' failed.

              '; - } - } - } - } - } - - // Show current table listing of pages and permissions - $users = $liveuserAuthAdmin->getUsers(); - $groups = $liveuserPermAdmin->getGroups(); - - - //uservars based controls - if(isset($ewiki_plugins['uservars_search'][0])){ - if(isset($_REQUEST['search_fieldname'])){ //set fieldname variable - $fieldname=$_REQUEST['search_fieldname']; - } - if(strlen($_REQUEST['search_fieldvalue'])){ //set fieldvalue variable - $fieldvalue=$_REQUEST['search_fieldvalue']; - } - if(!empty($fieldname)){ - $userdata = ewiki_search_uservar($fieldname, $fieldvalue); //get data for the given fieldname/fieldvalue combination - - //Remove non-matching users - foreach ($users as $key=>$user) { - if(!isset($userdata[$user['handle']])){ - unset($users[$key]); - } - } - } - - //Display search form - ?> -
              - - - -
              Field Name - -
              Value - -
              - -
              - - -
              -

              Edit Users

              - - - - - - - '); - foreach ($users as $user) { - ?> - - - - - - - - '); - echo(''); - } - echo(""); - } - - ?> -
              SelectUser IDUser Name
              Password [Random]
              Password StatusGroups - - -
              - -
              - - - - encryptPW($user['handle']) == $user['passwd'] ? '
              Password == User Name
              ' : '')?> -
              - Good
              '. - 'Expired
              '; - $expired='Good
              '. - 'Expired
              '; - echo (ewiki_get_uservar("passwdstatus", 'good', $user['handle'])=='good' ? $good : $expired); - echo intval((ewiki_get_uservar("passwdexpiredate", time(), $user['handle'])-time())/(60*60*24))." Days
              "; - ?> -
              - getGroups(array('where_user_id' => $user['auth_user_id'])) as $group) { - echo $group['name'].'
              '; - } - - ?> -
              - - - - -

              -
              - - - '; - } else { - ?> -

              Edit Users

              -

              No users were found in the database.

              - - -

              Add a User

              - -
              - -
              - -
              - -
              -

              Add Multiple Users

              -

              Insert one user name per line. This input will be processed as a - batch, and each user will be created with a password identical to his - user name or a randomly generated password if the "Generate Passwords" - box is checked.

              - - - - - -

              Generate random passwords.

              - -
              - -
              -

              Edit Groups

              - - - - - - - - - -
              DeleteGroup IDGroup Name
              - - -
              - - -
              - -

              Edit Groups

              -

              No groups were found in the database.

              - -
              -

              Add a Group

              -

              When creating a group, you may choose to create a right with the group, which may then be applied to user accounts via the group. If the group already exists, this form will still attempt to link a right to it. If the right already exists and is not associated with the group, it will be assigned to the group.

              - -
              - -
              - -
              - Password for user '.$username.' is not secure, cracklib reports: '.crack_getlastmessage().'.

              '; - } - } - - //Jeff's password checker, copied from auth_liveuser.php - $password_status=ewiki_check_passwd($password,$username); - //$end=getmicrotime(); - //echo($end-$time); - if ($password_status!='good passwd') { - if($password_status=='read error'){ - echo ewiki_t('PASS_DICTIONARY_READ_ERROR'); - } else { - echo ewiki_t($password_status); - } - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth-liveuser/passdict-wget.sh b/mods/wiki/plugins/auth-liveuser/passdict-wget.sh deleted file mode 100755 index 071542b4e..000000000 --- a/mods/wiki/plugins/auth-liveuser/passdict-wget.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -wget -c http://erfurtwiki.sourceforge.net/downloads/contrib-add-ons/passdict diff --git a/mods/wiki/plugins/auth-liveuser/perm_liveuser.meta b/mods/wiki/plugins/auth-liveuser/perm_liveuser.meta deleted file mode 100644 index f36d925d1..000000000 --- a/mods/wiki/plugins/auth-liveuser/perm_liveuser.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: authentication -title: perm_liveuser -copyright: Copyright (c) 2003, The Burgiss Group, LLC -priority: auto diff --git a/mods/wiki/plugins/auth-liveuser/perm_liveuser.php b/mods/wiki/plugins/auth-liveuser/perm_liveuser.php deleted file mode 100644 index afb9ff0ed..000000000 --- a/mods/wiki/plugins/auth-liveuser/perm_liveuser.php +++ /dev/null @@ -1,386 +0,0 @@ - - * @author alex wan - * @author jeremy mikola - */ - -require_once(dirname(__FILE__).'/liveuser_aux.php'); -require_once('plugins/lib/protmode.php'); - -/* - * auth constants must be defined to override auth_liveuser to never validate, - * so that any ring test with $ewiki_plugins['auth_perm'] will fail. - */ -define('EWIKI_LOGGEDIN_RING', max($liveuserPermRings) + 1); -define('EWIKI_NOT_LOGGEDIN_RING', max($liveuserPermRings) + 1); -require_once(dirname(__FILE__).'/auth_liveuser.php'); - -// ewiki callbacks for perm check, and page editing form hooks -$ewiki_plugins['auth_perm'][0] = 'ewiki_auth_perm_liveuser'; -$ewiki_plugins['edit_form_append'][] = 'ewiki_edit_form_append_liveuser_manage'; -$ewiki_plugins['edit_form_append'][] = 'ewiki_edit_form_append_liveuser_publish'; -$ewiki_plugins['edit_save'][] = 'ewiki_edit_save_liveuser_manage'; -$ewiki_plugins['edit_save'][] = 'ewiki_edit_save_liveuser_publish'; -$ewiki_plugins['action_always']['manage'] = 'ewiki_action_manage_liveuser'; -$ewiki_plugins['action_binary']['manage'] = 'ewiki_action_manage_liveuser'; -$ewiki_plugins['binary_handler'][] = 'ewiki_binary_handler_liveuser_setdefault_rights'; - -// html page output response messages -$ewiki_t['en']['MANAGE_TITLE'] = 'Manage This Page'; -$ewiki_t['en']['MANAGE_NEWPAGE'] = '

              The requested page is not available for management.

              '; - -/** - * given a page id and action as input, resolves action to a ring level as - * defined herein, and then queries a table linking liveuser perms/rights with - * ewiki page id and ring combinations. the current user is then checked against - * all possible rights that would satisfy the page id and ring combination. - * this function alters ewiki_ring to the resolved ring value. - * - * @param string page_name page name - * @param mixed data - * @param string action page action - * @param int ewiki_ring ring level corresponding to action (set by reference) - * @param int request_auth - * @return boolean true if current user has access, false otherwise - */ -function ewiki_auth_perm_liveuser($page_name, &$data, $action, $ewiki_ring, $request_auth) -{ - global $liveuser, $liveuserDB, $liveuserPermRings,$ewiki_config; - - // if we are authenticating for the page we are creating - if ($page_name == $ewiki_config["create"] ) { - $page_name = '[NewPage]'; - } - - /* - * checks for an explicit request for admin level rights, requires our top - * level right on such a request, otherwise we select our own ring based on - * the internal action table. - */ - if (($ewiki_ring !== 0) && (array_key_exists($action, $liveuserPermRings))) { - $ewiki_ring = $liveuserPermRings[$action]; - } else { - // for unknown actions, require highest perm level (min numerical value) - $ewiki_ring = min($liveuserPermRings); - } - - // fetch all perms matching page id and ring level - $right_ids = $liveuserDB->getCol('SELECT right_id FROM '.LW_PREFIX.'_perms WHERE pagename = ? AND ring <= ?', 0, - array($page_name, (int)$ewiki_ring)); - - foreach ($right_ids as $right_id) { - - if ($right_id == LU_R_NOTLOGGEDIN) { - return true; - } else if ($right_id == LU_R_LOGGEDIN && $liveuser->isLoggedIn()) { - return true; - } else if ($liveuser->checkRight($right_id) && $liveuser->isLoggedIn()) { - return true; - } - } - - return false; -} - -/** - * the set of all rights in the system must be filtered by the list of all - * publically viewable rights, and the resulting list returned as a series of - * form field selection options. The fourth parameter is used internally to - * hide the permissions for page editing and defaults to true (edit box is shown). - * - * @param string id - * @param mixed data - * @param string action - * @param boolean showEdit shows editing permissions if true, hides if false - * @return string html output for perm selection fields - */ -function ewiki_edit_form_append_liveuser_manage($id, $data, $action, $showEdit = true) -{ - global $liveuserDB, $liveuserBaseRings, $liveuserDefaultPermsView, $liveuserDefaultPermsEdit; - - $o = ''; - $ewiki_ring = false; - - if (!ewiki_auth_perm_liveuser($id, $data, 'manage', $ewiki_ring, 0)) { - return ''; - } - - $liveuserCurrentPermsView = null; - $liveuserCurrentPermsEdit = null; - $selected = false; - - // fetch config default rights for new pages, existing set rights otherwise - if (page_exists($id, $data)) { - $liveuserCurrentPermsView = $liveuserDB->getCol('SELECT right_id FROM '.LW_PREFIX.'_perms WHERE pagename = ? AND ring <= ?', 0, - array($id, $liveuserBaseRings['view'])); - $liveuserCurrentPermsEdit = $liveuserDB->getCol('SELECT right_id FROM '.LW_PREFIX.'_perms WHERE pagename = ? AND ring <= ?', 0, - array($id, $liveuserBaseRings['edit'])); - } - - // fetch the set of public permissions - $rightOptions = liveuser_perm_getPublicPerms(); - - $o .= '

              '; - $o .= '

              '; - - if ($showEdit) { - $o .= '
              '; - $o .= '

              '; - } - - return $o; -} - -/** - * if the current user has permission to publish pages (viewable by those not - * logged in), append the respective checkbox to the edit form. - * - * @param string id - * @param mixed data - * @param string action - * @return string html output for perm selection fields - */ -function ewiki_edit_form_append_liveuser_publish($id, $data, $action) -{ - global $liveuser; - - $o = ''; - - if ($liveuser->checkRight(LU_R_LW_PUBLISHER)) { - // check if permission for anonymous users exists - $published = (liveuser_checkPerm($id, LU_R_NOTLOGGEDIN) !== false); - $o = '

              '; - } - - return $o; -} - -/** - * A binary handler to adjust rights to default on upload or cache - * - * @param string id - * @param mixed data - * @param string action -*/ -function ewiki_binary_handler_liveuser_setdefault_rights($id, &$data, $action) -{ - if ($action == 'save') { - ewiki_liveuser_setdefault_rights($data); - } -} - - -/** - * called on pages that need to have their default rights set - * applied to binary and non-binary pages - * - * @param array save associative array of ewiki page data - * @param action the action by which this page is being reset to default rights - */ -function ewiki_liveuser_setdefault_rights(&$save) -{ - // remove any existing rights - $perms = liveuser_getPerms($save['id']); - foreach ($perms as $perm) { - liveuser_removePerm($save['id'], $perm['right_id']); - } - - if (isset($save['PageType']) && ($save['PageType'] == 'CachedImage')) { - // if a page type is set, get rights based on the PageType - $perms = liveuser_getPerms('['.$save['PageType'].']'); - } else { - // select rights for [NewPage] - $perms = liveuser_getPerms('[NewPage]'); - } - - // duplicate them for the page being created - foreach ($perms as $perm) { - liveuser_addPerm($save['id'], $perm['ring'], $perm['right_id']); - } -} - - -/** - * iterate over posted form data and extract selected liveuser rights to associate - * with view and edit permissions for the current ewiki page id. - * - * @param array save associative array of ewiki form data - */ -function ewiki_edit_save_liveuser_manage(&$save) -{ - global $liveuserBaseRings, $liveuserDefaultPerms; - - // determine what form data is available to be processed - $handleView = isset($_REQUEST['liveuserPermsView']) && is_array($_REQUEST['liveuserPermsView']); - $handleEdit = isset($_REQUEST['liveuserPermsEdit']) && is_array($_REQUEST['liveuserPermsEdit']); - - $ewiki_ring = false; - - // set default rights for new pages - if ($save['version'] == 1) { - ewiki_liveuser_setdefault_rights($save); - } - - // if not authorized to manage this page or form data is unavailable quit out. - if (!ewiki_auth_perm_liveuser($save['id'], $save, 'manage', $ewiki_ring, 0) || !($handleView || $handleEdit)) { - return; - } - // fetch the set of public permissions - $rightOptions = liveuser_perm_getPublicPerms(); - - /* - * clear database of all records for public field options for rings levels - * below edit or view. the minimum removal level (edit or view) will be determined - * based on whether form data for edit permissions was submitted, or just - * form data for view. - */ - if ($handleView || $handleEdit) { - foreach ($rightOptions as $right_id => $name) { - liveuser_removePerm($save['id'], $right_id, ($handleEdit ? $liveuserBaseRings['edit'] : $liveuserBaseRings['view'])); - } - } - - if ($handleView) { - foreach($_REQUEST['liveuserPermsView'] as $right_id) { - if (array_key_exists($right_id, $rightOptions)) { - liveuser_addPerm($save['id'], $liveuserBaseRings['view'], $right_id, true); - } - } - } - - if ($handleEdit) { - foreach($_REQUEST['liveuserPermsEdit'] as $right_id) { - if (array_key_exists($right_id, $rightOptions)) { - liveuser_addPerm($save['id'], $liveuserBaseRings['edit'], $right_id, true); - } - } - } - -} - -/** - * if the current user has permission to publish pages, write the respective - * form data back to the database, thereby allowing a page to be published (with - * viewing rights for users not logged in) or not published. - * - * @param array save associative array of ewiki form data - */ -function ewiki_edit_save_liveuser_publish($save) -{ - global $liveuser, $liveuserBaseRings; - - // alter only if user has publisher right and form field exists - if ($liveuser->checkRight(LU_R_LW_PUBLISHER)) { - if (isset($_REQUEST['liveuserPermsPublish']) && $_REQUEST['liveuserPermsPublish'] == 'checked') { - liveuser_addPerm($save['id'], $liveuserBaseRings['view'], LU_R_NOTLOGGEDIN); - } else { - liveuser_removePerm($save['id'], LU_R_NOTLOGGEDIN); - } - } -} - -function page_exists($id, &$data){ - return(!(empty($data['content'])&& empty($data['meta']) && !array_key_exists($id, $GLOBALS['ewiki_plugins']['page']))); -} - -/** - * this manage action will display a form to edit viewing rights on an internal - * or binary page. the ability to publish (make publicly viewable) is also - * provided. - * - * @param mixed id - * @param mixed data - * @param string action - * @return string html output for perm selection fields - */ -function ewiki_action_manage_liveuser($id, $data, $action) -{ - $o = ''; - - // ignore new pages - if (!page_exists($id, $data)) { - $o .= ewiki_make_title('', ewiki_t('MANAGE_TITLE').' » '.$id.' «'); - $o .= ewiki_t('MANAGE_NEWPAGE'); - return $o; - } - - // handle form submission - if (isset($_REQUEST['submit_manage'])) { - // process view permissions form data - ewiki_edit_save_liveuser_manage($data); - - // process published-status form data - ewiki_edit_save_liveuser_publish($data); - } - - // construct manage form - $o .= ewiki_make_title('', ewiki_t('MANAGE_TITLE').' » '.$id.' «'); - $o .= '
              '; - $o .= ewiki_edit_form_append_liveuser_manage($id, $data, $action, false); - $o .= ewiki_edit_form_append_liveuser_publish($id, $data, $action); - $o .= '
              '; - - return $o; -} - -/** - * fetches a list of all public permissions used in the ewiki page edit form to - * assign view and edit permissions. - * - * @return array set of publically viewable right_id [key] and name [value] pairs - */ -function liveuser_perm_getPublicPerms() -{ - global $liveuser, $liveuserPublicPerms, $liveuserPermAdmin; - - $rights = $liveuserPermAdmin->getRights(); - $publicRights = array(); - foreach ($rights as $right) { - // add only rights whose name exists in the global liveuserPublicPerms array - if (in_array($right['name'], $liveuserPublicPerms)) { - $publicRights[$right['right_id']] = $right['name']; - } - } - - return $publicRights; -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth-liveuser/pref_liveuser.meta b/mods/wiki/plugins/auth-liveuser/pref_liveuser.meta deleted file mode 100644 index 1e2f9425e..000000000 --- a/mods/wiki/plugins/auth-liveuser/pref_liveuser.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: authentication -title: pref_liveuser -copyright: Copyright (c) 2003, The Burgiss Group, LLC -priority: auto diff --git a/mods/wiki/plugins/auth-liveuser/pref_liveuser.php b/mods/wiki/plugins/auth-liveuser/pref_liveuser.php deleted file mode 100644 index 5d261360a..000000000 --- a/mods/wiki/plugins/auth-liveuser/pref_liveuser.php +++ /dev/null @@ -1,254 +0,0 @@ - - * @author alex wan - * @author jeremy mikola - * - * This interface provides functions to save and retrieve user preferences, as - * well as to configure available preference fields. - */ - -require_once(dirname(__FILE__).'/auth_liveuser.php'); -require_once(dirname(__FILE__).'/liveuser_aux.php'); - -$ewiki_plugins['page']['ChangePrefs'] = 'ewiki_page_liveuser_chprefs'; - -/** - * changes user preferences based on form input - * - * @param mixed id - * @param mixed data - * @return mixed - */ -function ewiki_page_liveuser_chprefs($id, $data) -{ - global $liveuser, $liveuserDB; - - // if form was submitted, write - if (isset($_REQUEST['submit_prefs'])) { - return ewiki_t('CHPWFORM'); - } - - ob_start(); - - echo ewiki_make_title($id, $id, 2); - - $results = $liveuserDB->getAll('SELECT * FROM '.LW_PREFIX.'_prefs_fields'); - - foreach ($results as $result) { - if (isset($_REQUEST[$result['field_name']])) { - liveuser_pref_setPref($liveuser->getHandle(), $result['field_name'], $_REQUEST[$result['field_name']]); - } - } - - echo '
              '; - - foreach ($results as $result) { - echo ''; - } - - echo '
              '; - echo ''; - echo '
              '; - - $o = ob_get_contents(); - ob_end_clean(); - - return $o; -} - -/** - * Checks if the specified preference already exists for the specified user. - * - * @param string username user handle - * @param string field_name preference field name - * @return boolean true if preference exists, false otherwise - */ -function liveuser_pref_checkPref($username, $field_name) -{ - global $liveuserDB; - - $user_id = liveuser_getPermUserId($username); - $field_id = $liveuserDB->getOne('SELECT field_id FROM '.LW_PREFIX.'_prefs_fields WHERE field_name = ?', - array($field_name)); - - return (is_numeric($field_id) ? $field_id : false); -} - -/** - * Fetches the specified preference's value for the specified user. - * - * @param string username user handle - * @param string field_name preference field name - * @param boolean useDefault if true, default field value is supplied for non-existent pref, else null is used - * @return string preference field value if set, default value or null otherwise - */ -function liveuser_pref_getPref($username, $field_name, $useDefault = true) -{ - global $liveuserDB; - - $user_id = liveuser_getPermUserId($username); - $field_value = $liveuserDB->getOne(' - SELECT '.LW_PREFIX.'_prefs_data.field_value - FROM '.LW_PREFIX.'_prefs_data, '.LW_PREFIX.'_prefs_fields - WHERE '.LW_PREFIX.'_prefs_data.user_id = ? - AND '.LW_PREFIX.'_prefs_data.field_id = '.LW_PREFIX.'_prefs_fields.field_id - AND '.LW_PREFIX.'_prefs_fields.field_name = ?', - array((int)$user_id, $field_name)); - - if (is_null($field_value) && $useDefault) { - $field_value = $liveuserDB->getOne(' - SELECT default_value - FROM '.LW_PREFIX.'_prefs_fields - WHERE field_name = ?', - array($field_name)); - } - - return $field_value; -} - -/** - * Sets the specified preference's value for the specified user. - * - * @param string username user handle - * @param string field_name preference field name - * @return boolean true if the preference was successfully set, false otherwise - */ -function liveuser_pref_setPref($username, $field_name, $field_value) -{ - global $liveuserDB; - - $user_id = liveuser_getPermUserId($username); - - /* attempt to fetch existing field_id for the field_name, or create a new field if necessary */ - if (($field_id = liveuser_pref_checkField($field_name)) === false && - ($field_id = liveuser_pref_setField($field_name)) === false) { - return false; - } - - $pref_id = $liveuserDB->getOne(' - SELECT pref_id - FROM '.LW_PREFIX.'_prefs_data - WHERE user_id = ? AND field_id = ?', - array((int)$user_id, (int)$field_id)); - - if (isset($pref_id) && is_numeric($pref_id)) { - return ($liveuserDB->query(' - UPDATE '.LW_PREFIX.'_prefs_data - SET field_value = ? - WHERE pref_id = ?', - array($field_value, (int)$pref_id)) == DB_OK); - } else { - return ($liveuserDB->query(' - INSERT INTO '.LW_PREFIX.'_prefs_data (field_value, user_id, field_id) VALUES (?, ?, ?)', - array($field_value, (int)$user_id, (int)$field_id)) == DB_OK); - } -} - -/** - * Checks if the specified preference field already exists. - * - * @param mixed field_name field_name or id of preference field to check for - * @param boolean publicOnly if true, only check against public fields - * @return mixed integer identifier if field exists, false otherwise - */ -function liveuser_pref_checkField($field_name, $publicOnly = false) -{ - global $liveuserDB; - - if (is_numeric($field_name)) { - $field_id = $liveuserDB->getOne(' - SELECT field_id - FROM '.LW_PREFIX.'_prefs_fields - WHERE field_id = ? AND public >= ?', - array((int)$field_name, (int)$publicOnly)); - } else { - $field_id = $liveuserDB->getOne(' - SELECT field_id - FROM '.LW_PREFIX.'_prefs_fields - WHERE field_name = ? AND public >= ?', - array($field_name, (int)$publicOnly)); - } - - return (is_numeric($field_id) ? $field_id : false); -} - -/** - * Removes a field definition and all references in the preferences data table. - * - * @param mixed field_name field name or id of preference field - * @return boolean true if the field was removed successfully, false otherwise - */ -function liveuser_pref_removeField($field_name) -{ - global $liveuserDB; - - if (($field_id = liveuser_pref_checkField($field_name)) === false) { - return false; - } - - if ($liveuserDB->query('DELETE FROM '.LW_PREFIX.'_prefs_data WHERE field_id = ?', - array((int)field_id)) != DB_OK) { - return false; - } - - if ($liveuserDB->query('DELETE FROM '.LW_PREFIX.'_prefs_fields WHERE field_id = ?', - array((int)field_id)) != DB_OK) { - return false; - } -} - -/** - * Sets a field (adds or updates) with the specified properties. - * - * @param mixed field_name field name or id of preference field - * @param boolean public preference field is public if true, private if false - * @param string default_value default field value if user preference is not set - * @param string possible_values possible_values field value for admin to set and user to choose - * @return mixed integer identifier of field if operation was successful, false otherwise - */ -function liveuser_pref_setField($field_name, $public = true, $default_value = null, $possible_values = null) -{ - global $liveuserDB; - - if (($field_id = liveuser_pref_checkField($field_name)) !== false) { - return ($liveuserDB->query(' - UPDATE '.LW_PREFIX.'_prefs_fields - SET public = ?, default_value = ?, possible_values = ? - WHERE field_id = ?', - array((int)$public, $default_value, ($possible_values ? serialize($possible_values) : null), (int)$field_id)) == DB_OK); - } else { - if ($liveuserDB->query(' - INSERT INTO '.LW_PREFIX.'_prefs_fields (field_name, public, default_value, possible_values) - VALUES (?, ?, ?, ?)', - array($field_name, (int)$public, $default_value, ($possible_values ? serialize($possible_values) : null))) != DB_OK) { - return false; - } - return liveuser_pref_checkField($field_name); - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth-liveuser/session_ip_verifier.meta b/mods/wiki/plugins/auth-liveuser/session_ip_verifier.meta deleted file mode 100644 index 1127c19af..000000000 --- a/mods/wiki/plugins/auth-liveuser/session_ip_verifier.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: authentication -hooks: init -type: intercept -title: session_ip_verifier -description: checks to see if the user's ssl_session_id or ip_address has changed -priority: auto diff --git a/mods/wiki/plugins/auth-liveuser/session_ip_verifier.php b/mods/wiki/plugins/auth-liveuser/session_ip_verifier.php deleted file mode 100644 index ee2de83b4..000000000 --- a/mods/wiki/plugins/auth-liveuser/session_ip_verifier.php +++ /dev/null @@ -1,23 +0,0 @@ -logout(); - } - -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth/auth_method_form.meta b/mods/wiki/plugins/auth/auth_method_form.meta deleted file mode 100644 index 003a3ed36..000000000 --- a/mods/wiki/plugins/auth/auth_method_form.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_query -type: auth -title: auth_method_form -description: provides a login
              and uses cookies - this method works not always binary safe and stateless -priority: deprecated -delivers: auth-method diff --git a/mods/wiki/plugins/auth/auth_method_form.php b/mods/wiki/plugins/auth/auth_method_form.php deleted file mode 100644 index b2c4060e5..000000000 --- a/mods/wiki/plugins/auth/auth_method_form.php +++ /dev/null @@ -1,93 +0,0 @@ -, and after verification stores - username and password into a browser Cookie. - - To use this, you'll also need a user database plugin and a ewiki - auth_perm plugin in the _PROTECTED_MODE. - -*/ - - -#-- glue -$ewiki_plugins["auth_query"][0] = "ewiki_auth_query_form"; -define("EWIKI_AUTH_QUERY_SAFE", "eventually"); - - -#-- login form text -$ewiki_t["en"]["LOGIN_QUERY"] = "Please log in to use this function:"; -$ewiki_t["en"]["LOGIN_QUERY_2"] = ""; -$ewiki_t["de"]["LOGIN_QUERY"] = "Bitte log dich ein, um diese Funktion zu verwenden:"; -$ewiki_t["de"]["LOGIN_QUERY_2"] = ""; -#-- text snippet translations -$ewiki_t["de"]["user"] = "Nutzer"; -$ewiki_t["de"]["password"] = "Paßwort"; -$ewiki_t["de"]["login"] = "Einloggen"; - - -#-- code -function ewiki_auth_query_form(&$data, $force_query=0) { - - global $ewiki_plugins, $ewiki_config, $ewiki_errmsg, $ewiki_id, - $ewiki_action, $ewiki_author, $ewiki_ring; - $o = &$ewiki_errmsg; - - #-- get user/pw from POST or COOKIE - if ($_POST["login_user"]) { - $_user = $_REQUEST["login_user"]; - $_pw = $_REQUEST["login_pw"]; - } - elseif ($_COOKIE["ewiki_login"]) { - list($_user,$_pw) = explode(":", base64_decode($_COOKIE["ewiki_login"])); - } - - #-- check password - $_success=0; - if (strlen($_user) && strlen($_pw)) { - $_success = ewiki_auth_user($_user, $_pw); - } - - #-- store login data as Cookie - if ($_success && $_POST["login_user"]) { - setcookie("ewiki_login", base64_encode("$_user:$_pw"), time()+7*24*3600); - } - - #-- login form - if ($force_query && !$_success || ($force_query >= 2)) { - - #-- it's safe to call this plugin for interception of running submits - $_REPOST = ""; - if (defined("EWIKI_AUTH_QUERY_SAFE")) { - foreach($_POST as $i=>$v) { - if ($i=="login_name" || $i=="login_pw") { continue; } - $_REPOST .= ''."\n"; - } - $_REPOST = ''."\n".$_REPOST.''."\n"; - } - - #-- print - $o = '
              '; - } - - #-- end - return($_success); -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth/auth_method_http.meta b/mods/wiki/plugins/auth/auth_method_http.meta deleted file mode 100644 index 57547f988..000000000 --- a/mods/wiki/plugins/auth/auth_method_http.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_query -type: auth -title: auth_method_http -description: provides authentication/login data via HTTP Basic AUTH (recommended login sheme) -conflicts: auth_method_form -delivers: auth-method -priority: extra diff --git a/mods/wiki/plugins/auth/auth_method_http.php b/mods/wiki/plugins/auth/auth_method_http.php deleted file mode 100644 index c78a20bbb..000000000 --- a/mods/wiki/plugins/auth/auth_method_http.php +++ /dev/null @@ -1,81 +0,0 @@ - and has the advantage, that the - authentication infos aren't stored by browsers (unless you use a TCPA- - enabled IE which may of course transmit authentication data to third - parties). - - you'll need: - - EWIKI_PROTECTED_MODE - - plugins/auth_perm_ring.php (or another one) - - plugins/userdb_array.php (or others) - - a binary-safe ewiki/yoursite setup (see the - section on uploads and images in the README) - - You can only load __one__ auth method plugin! - - Note: if you want your Wiki to be accessible to a small group of - people only, then you should favour the http authentication mechanism - of your webserver! This is just a very poor implementation of the HTTP - BASIC AUTH scheme. - (all in here borrowed from the fragments/auth.php) -*/ - - -#-- glue -$ewiki_plugins["auth_query"][0] = "ewiki_auth_query_http"; -define("EWIKI_AUTH_QUERY_SAFE", "always"); - - -#-- text data -$ewiki_t["en"]["RESTRICTED_ACCESS"] = "You must be authenticated to use this part of the wiki."; - - -#-- code -function ewiki_auth_query_http(&$data, $force_query=0) { - - global $ewiki_plugins, $ewiki_errmsg, $ewiki_author, $ewiki_ring; - - #-- fetch user:password - if ($uu = trim($_SERVER["HTTP_AUTHORIZATION"])) { - $auth_method = strtolower(strtok($uu, " ")); - if ($auth_method=="basic") { - $uu = strtok(" ;,"); - $uu = base64_decode($uu); - list($_a_u, $_a_p) = explode(":", $uu, 2); - } - else { - #-- invalid response, ignore - } - } - elseif (strlen($_a_u = trim($_SERVER["PHP_AUTH_USER"]))) { - $_a_p = trim($_SERVER["PHP_AUTH_PW"]); - } - - #-- check password - $_success = ewiki_auth_user($_a_u, $_a_p); - - #-- request HTTP Basic authentication otherwise - if (!$_success && $force_query || ($force_query >= 2)) { - $realm = ewiki_t("RESTRICTED_ACCESS"); - $addmethod = ""; - if ($uu = $ewiki_config["login_notice"]) { - $realm .= " " . $uu; - } - if ($uu = $ewiki_config["http_auth_add"]) { - $addmethod = ", $uu realm=\"$realm\""; - } - header('HTTP/1.1 401 Authentication Required'); - header('Status: 401 Authentication Required'); - header('WWW-Authenticate: Basic realm="'.$realm.'"'.$addmethod); - } - - #-- fin - return($_success); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth/auth_perm_old.meta b/mods/wiki/plugins/auth/auth_perm_old.meta deleted file mode 100644 index c1730b1bb..000000000 --- a/mods/wiki/plugins/auth/auth_perm_old.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_perm -type: auth -config: - EWIKI_ALLOW_OVERWRITE=0|1 - EWIKI_EDIT_AUTHENTICATE=0|1 -title: auth_perm_old -description: this permission system wraps the two older configuration constants -priority: never diff --git a/mods/wiki/plugins/auth/auth_perm_old.php b/mods/wiki/plugins/auth/auth_perm_old.php deleted file mode 100644 index 759e8674d..000000000 --- a/mods/wiki/plugins/auth/auth_perm_old.php +++ /dev/null @@ -1,53 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/auth/auth_perm_ring.meta b/mods/wiki/plugins/auth/auth_perm_ring.meta deleted file mode 100644 index f89483af2..000000000 --- a/mods/wiki/plugins/auth/auth_perm_ring.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_perm -type: auth -title: auth_perm_ring -description: maps wiki actions and page names onto the ring level permission scheme -priority: rare diff --git a/mods/wiki/plugins/auth/auth_perm_ring.php b/mods/wiki/plugins/auth/auth_perm_ring.php deleted file mode 100644 index a8750d506..000000000 --- a/mods/wiki/plugins/auth/auth_perm_ring.php +++ /dev/null @@ -1,68 +0,0 @@ - 3, - "info" => 3, - "links" => 3, - "edit" => 2, - "calendar" => 2, - "upload" => 2, - "view/SecretPage" => 1, - "delete" => 1, - "control" => 0, - "admin" => 0, - "*" => 2, #- anything else requires this ring level - ), - (array)@$ewiki_perm_rings -); - - - -$ewiki_plugins["auth_perm"][0] = "ewiki_auth_handler_ring_permissions"; - - -function ewiki_auth_handler_ring_permissions($id, $data, $action, $required_ring) { - - global $ewiki_plugins, $ewiki_ring, $ewiki_perm_rings; - - if ("ALWAYS_DO_THIS" || ($required_ring===false)) { - - $id = strtolower($id); - $action = strtolower($action); - - foreach ($ewiki_perm_rings as $string => $ring) { - - $string = strtolower($string); - - if (($string == "*") || - ($string == $id) || - ($string == $action) || - ($string == "$action/$id") || - (strtok($string, "/") == $action) ) - { - $required_ring = $ring; - break; - } - - } - - } - - return(($required_ring===false) || isset($ewiki_ring) && ($ewiki_ring <= $required_ring)); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth/auth_perm_unix.meta b/mods/wiki/plugins/auth/auth_perm_unix.meta deleted file mode 100644 index 150387431..000000000 --- a/mods/wiki/plugins/auth/auth_perm_unix.meta +++ /dev/null @@ -1,12 +0,0 @@ -api: ewiki -category: authentication -hooks: action_always, auth_perm, edit_form_append, edit_save -type: auth -config: - EWIKI_USERDB_SYSTEMGROUPS="system/groups" - EWIKI_PERM_UNIX_UMASK=0000 //access rights to strip for new pages - EWIKI_PERM_UNIX_SHAREHOLDERS=1 //group members may revoke rights - EWIKI_PERM_USERSET_FREE=0 //anybody could set the initial owner -title: UNIX-like permissions -description: UNIX filesystem like permission system -priority: rare diff --git a/mods/wiki/plugins/auth/auth_perm_unix.php b/mods/wiki/plugins/auth/auth_perm_unix.php deleted file mode 100644 index d4f040e72..000000000 --- a/mods/wiki/plugins/auth/auth_perm_unix.php +++ /dev/null @@ -1,502 +0,0 @@ - (bitmask)$UnixAccessRights -$ewiki_config["perm_rights_actions"] = array( - - #-- actions - "view" => 4, #=read - "edit" => 2, #=write - "info" => 4, #=read - "links" => 4, #=read - "search" => 1, #=executable - "nop" => 0, #=always yields ok - - #-- pages - "SecretPage" => 16+8, #=special flags (can't be set currently) - - #-- fallback for any other combination: - "*" => 4+1, #=read+executable -); - -#-- also always allowed for ring level 1 users: -$ewiki_config["moderators_may_do"] = array( - "edit", - "view", "info", "links", "search", - "control", -); - - -#-- implementation -function ewiki_auth_perm_unix($id, &$data, $action, $ring=NULL, $force=0) { - - global $ewiki_plugins, $ewiki_config, $ewiki_auth_user, $ewiki_author, $ewiki_ring; - - #-- eventually refetch page $data - if (!$data || (count($data)<5)) { - $data = ewiki_db::GET($id); - } - - #-- pages access rights - ($p_rights = $data["meta"]["rights"]) and isset($p_rights) - or ($p_rights = 0777 ^ EWIKI_PERM_UNIX_UMASK); - - #-- state vars - $effective_rights = 00; // owner/groups/world rights ORed together - $effective_rights |= ($p_rights >> 9); // add high/special bits - - #-- take "world" rights also in account - $effective_rights |= ($p_rights & 0x07); - - #-- user login (???) - # (already done) - - #-- check for authenticated user - if (($user = $ewiki_auth_user) || ($user = $ewiki_author)) { - - #-- if user owns the current page - $p_owner = $data["meta"]["owner"]; - if ($p_owner==$user) { - if ($action=="edit") { - #-- allow to change any permissions on edit page, - # this may still require to load '...?id=edit/CurrentPage' by hand - $effective_rights |= 2; - } - else { - $effective_rights |= ($p_rights >> 6) & 0x07; - } - } - - #-- if user is in one of the mentioned groups - if (ewiki_auth_user_in_groups_str($user, $data["meta"]["groups"])) { - $effective_rights |= ($p_rights >> 3) & 0x07; - } - } - - #-- compare against required permissions for current action or/and page - ($requ = $ewiki_config["perm_rights_actions"]["$action/$page"]) or - ($requ = $ewiki_config["perm_rights_actions"][$page]) or - ($requ = $ewiki_config["perm_rights_actions"][$action]) or - ($requ = $ewiki_config["perm_rights_actions"]["*"]) or - ($requ = 0x0); - $goal = (($effective_rights & $requ) == $requ); - -#$ps=base_convert($p_rights, 10, 2); -#echo "eff=$effective_rights, requ=$requ, p_r=$ps
              \n"; - - #-- advanced comparasions could be added here(?) - /* - ... - */ - - #-- ring permission levels are still here - $goal = $goal - || isset($ewiki_ring) && ($ewiki_ring == 0) // superuser can always do everything - || ($ewiki_ring == 1) && (in_array($action, $ewiki_config["moderators_may_do"])); - - #-- we also take the ring level into account, if one is required - if (isset($ring) && is_int($ring)) { - $goal = $goal && ($ewiki_ring <= $ring); - } - - return($goal); -} - - - - -/* - The following function allows to change access rights via the edit/ - page 'interface' - so using the mysql client and phpserialize() - is not required -*/ - -#-- print page access rights below textarea on edit page -function ewiki_edit_form_append_unix_access_rights($id, &$data, $action) { - - global $ewiki_ring; -$ewiki_ring=0; - - #-- get meta data - $owner = htmlentities($data["meta"]["owner"]); - $groups = htmlentities($data["meta"]["groups"]); - ($rights = $data["meta"]["rights"]) and isset($rights) - or ($rights = 0777 ^ EWIKI_PERM_UNIX_UMASK); - - #-- build checkboxes - $rs = array("", "", "", "", ""); - for ($n=15; $n>=0; $n--) { - $i = (int) ($n/3); - $checked = (($rights >> $n) & 0x1) ? ' checked="checked"' : ""; - $disabled = (($i>=3) && ($ewiki_ring>=2) || ($i>=4) && ($ewiki_ring>=1)) ? ' disabled="disabled"' : ""; - if (!($disabled && ($ewiki_ring>=2))) - $rs[$i] .= ' '; - } - if ($rs[4]) { $rs[4] = "aaa ".$rs[4]; } - if ($rs[3]) { $rs[3] = "mmm ".$rs[3]; } - - #-- output - $o = ewiki_t(<< -_{access rights}  
              - {$rs[4]} - _{owner} - _{groups} - _{world} - {$rs[3]} - rwx {$rs[2]} - rwx {$rs[1]} - rwx {$rs[0]} - -END - ); - return($o); -} - - - -/* - This part stores the changes from the edit/ screen back into the - database, thereby sanitizing the input and rejecting invalid changes. - Only the "owner" has permission to change _all_ settings, but members of - one of the mentioned groups can also change (revoke) access rights for - "groups" and "world". -*/ -#-- adds changed page access rights into {meta} - to get stored into database -function ewiki_edit_save_unix_access_rights(&$save, &$old_data) { - - global $ewiki_auth_user, $ewiki_author, $ewiki_ring, $ewiki_errmsg; - - ($user = $ewiki_auth_user) - or ($user = $ewiki_author) - or ($user = ""); - - #-- get current settings - $new_owner = $p_owner = $save["meta"]["owner"]; - $new_groups = $p_groups = $save["meta"]["groups"]; - ($p_rights = $save["meta"]["rights"]) or ($p_rights = 0777 ^ EWIKI_UNIX_PERM_UMAKS); - $new_rights = $p_rights; - - #-- fetch entered settings - if (true) { - - #-- access rights - $set_rights = 0; - foreach ($_POST["perm_unix_rights"] as $n=>$is) { - if ($is) { - $set_rights = $set_rights | (1<<$n); - } - } - - #-- attempt to set new page owner? - $set_owner = trim($_REQUEST["perm_unix_owner"]); - if (!preg_match("/^[".EWIKI_CHARS."]+$/", $set_owner) && ewiki_auth_user_exists($set_owner)) { - $save = array(); - $ewiki_errmsg = "broken username"; - return; - } - - #-- clean up list of group names - $set_groups = array(); - $uu = strtr($_REQUEST["perm_unix_groups"], EWIKI_USERDB_GROUPDELIMS, " "); - foreach (explode(" ", $uu) as $grp) { - if (strlen($grp) && preg_match("/^[".EWIKI_CHARS."]+$/", $grp) /*&& group_exists()*/ ) { - $set_groups[] = $grp; - } - } - $set_groups = implode(", ", $set_groups); - } - - #-- check if changing settings is allowed - $bad = 0; - if (!$user || ($user!=$p_owner)) { - $bad = $bad || ($p_owner != $set_owner) && !( - (empty($p_owner) && EWIKI_PERM_USERSET_FREE) - || ($set_owner == $user) - ); -# $bad = $bad || ($p_groups != $set_groups); # cannot reliably check this - $bad = $bad || ($p_rights != $set_rights); - } - if ($ewiki_ring == 0) { - $bad = 0; - } -#$bad=0; - - #-- login_query, if something was changed - if (($bad)) { - $uu = 0; - ewiki_auth($uu, $uu, $uu, $uu, 2); - $save = array(); - $ewiki_errmsg = "You cannot change these settings without being logged in."; - return; - } -#echo "pr=$p_rights,sr=$set_rights
              \n"; -#echo "po=$p_owner,so=$set_owner
              \n"; -#echo "bad=$bad
              \n"; -#die("passed"); - - - #-- the owner may change anything - if (($user == $p_owner) || (0 == $ewiki_ring)) { - - #-- new page owner - $new_owner = $set_owner; - - #-- new access rights - $new_rights = $set_rights; - $new_rights |= 000400; // owner can always edit a page - - #-- restricted settings - if ($ewiki_ring == 0) { - // keep all bits - } - elseif ($ewiki_ring == 1) { - $new_rights = (($new_rights) & 007777) | (($p_rights) & 070000); - } - else { - $new_rights = (($new_rights) & 000777) | (($p_rights) & 077000); - } - - #-- groups - $new_groups = $set_groups; - } - -/******** - #-- groups can...(?) - if (!EWIKI_PERM_UNIX_SHAREHOLDERS) { - // no they can't. - } - elseif (ewiki_auth_user_in_groups_str($user, $p_groups) && ($new_rights=$save["meta"]["rights"])) { - #-- this can effectively only remove bits - $new_rights = (077700 & $new_rights) | (000077 & $new_rights & $set_rights); - } -*******/ - - #-- store any changes into database entry - if ($user) { - $save["meta"]["rights"] = $new_rights; - $save["meta"]["owner"] = $new_owner; - $save["meta"]["groups"] = $new_groups; - } - -#print_r($save);die(); -} - - - - -//@FIXME: does not work with all ["auth_userdb"] plugins -//(no workaround, but safe to use with system/UserRegistry or system/passwd) -function ewiki_auth_user_exists($user) { - global $ewiki_plugins; - if ($pf_u = $ewiki_plugins["auth_userdb"]) - foreach ($pf_u as $pf) { - if ($pf($user, '$0$')) { - return(true); - } - } - return(false); -} - - - - -#-- fetch groups for user -function ewiki_auth_get_users_groups($user) { - - #-- get "system/groups" page - $gp = ewiki_db::GET(EWIKI_USERDB_SYSTEMGROUPS); - if (($gp["version"]) && !($gp["flags"] & EWIKI_DB_F_SYSTEM)) { - $gp["flags"] |= EWIKI_DB_F_SYSTEM; - $gp["version"]++; - ewiki_db::WRITE($gp); // secure it as _SYSTEM page - } - - $user_groups = array(); - if (empty($user)) { return($user_groups); } - - #-- go through all the lines in the groups file - if ($list = explode("\n", $gp["content"])) - foreach ($list as $line) { - - #--- quick initial check for string occourence - if (strpos($line, $user)) { - - #-- break line into parts - $line = trim($line); - if ($line[0] == "#") { - continue; - } - if (!($group = strtok($line, ":"))) { - continue; - } - $uu = strtok(":"); #-- this removes the "*:" we don't care - $line = strtok("\000"); - if (strlen($uu) > 1) { $line .= " $uu"; } - - #-- convert delimeters into spaces and lookup $user string - $line = strtr($line, EWIKI_USERDB_GROUPDELIMS, " "); - if (strpos(" {$line} ", " {$user} ")) { - $user_groups[] = $group; - } - } - } - - return($user_groups); -} - - - -/* - Retrieves the list of groups the $user belongs to, and compares against - the list in the $groups list string. -*/ -function ewiki_auth_user_in_groups_str($user, $groups="") { - $p_groups = explode(" ", strtr($groups, EWIKI_USERDB_GROUPDELIMS, " ")); - $user_groups = ewiki_auth_get_users_groups($user); - foreach ($user_groups as $ugrp) { - if (strlen($ugrp) && in_array($ugrp, $p_groups)) { - return(true); - break; - } - } - return(false); -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth/auth_phplib.meta b/mods/wiki/plugins/auth/auth_phplib.meta deleted file mode 100644 index 0eaa7ff31..000000000 --- a/mods/wiki/plugins/auth/auth_phplib.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_query, page -type: auth -config: - EWIKI_PHPLIB_ALLUSERS_PERM="user" - EWIKI_AUTO_EDIT=0 -title: phplib -description: phplib authentication logic -priority: rare diff --git a/mods/wiki/plugins/auth/auth_phplib.php b/mods/wiki/plugins/auth/auth_phplib.php deleted file mode 100644 index 5f2148983..000000000 --- a/mods/wiki/plugins/auth/auth_phplib.php +++ /dev/null @@ -1,305 +0,0 @@ - - * You may also want to add some code to your layout to display the login and logout - links selectively this code is what I use: - * - if($perm->have_perm(EWIKI_PHPLIB_ALLUSERS_PERM)){ - ?> - Welcome
              - » Logout
              - - » Login
              - -*/ - -//There must be one group that includes all valid wiki users, this can be used for -// determing whether to display a login or logout link -define("EWIKI_PHPLIB_ALLUSERS_PERM","user"); - -#-- Connect to login query plugin -#-- Thereby requiring that the user have a name to edit pages -#-- permissions are not required for any particular edit -#-- the user permission is checked below only to see if they are logged in -#-- with an account other than nobody. -$ewiki_plugins["auth_query"][0] = "ewiki_auth_query_phplib"; - -#-- Login/Logout pages -$ewiki_plugins["page"]["LogOut"] = "ewiki_page_phplib_logout"; -$ewiki_plugins["page"]["LogIn"] = "ewiki_page_phplib_login"; -$ewiki_plugins["page"]["ChangePassword"] = "ewiki_page_phplib_chpw"; - - - page_open(array("sess" => "Example_Session", "auth" => "My_Auth", "perm" => "Example_Perm", "user" => "My_User")); - - @$GLOBALS["ewiki_author"]=$auth->auth["uname"]; - - //echo($_REQUEST["cancel_login"]); - if((!$perm->have_perm(EWIKI_PHPLIB_ALLUSERS_PERM))){ - define("EWIKI_AUTO_EDIT",0); - } - -#-- text data -$ewiki_t["en"]["CANNOTCHANGEPAGE"] = "This page cannot be changed. Perhaps you can LogIn to and change it then."; -$ewiki_t["en"]["RESTRICTED_ACCESS"] = "You must be authenticated to use this part of the wiki. If you have an account you can LogIn."; -$ewiki_t["en"]["NOTLOGGEDIN"] = "You are not logged in. You must LogIn to access some features of this site."; -@$ewiki_t["en"]["LOGGEDIN"] = "You have logged in as ".$auth->auth['uname'].". You must LogOut to login again."; -@$ewiki_t["en"]["LOGINFORM"]=' -

              Test for Login

              - -Welcome! - -Please identify yourself with a username and a password:
              - -
              - - - - - - - - - - - - - - -
              Username:
              Password:
                -
              - - - -
              -'; -$ewiki_t["en"]["BADOLDPW"]='You have misentered your old password and been logged out. '. - "Please LogIn again to resume your session."; -$ewiki_t["en"]["PWCHNGD"]='Your password has been changed.'; -$ewiki_t["en"]["NOMATCH"]='Your new password does not match with your retyping of it.'; -$ewiki_t["en"]["CHPWFORM"]=' -

              Change Password:

              - -Please enter your old password once and your new password twice in the blanks below:
              - -
              - - - - - - - - - - - - - - - - - - -
              Old Password:
              New Password:
              Repeat New Password:
                -
              - - - -
              -'; - -function ewiki_page_phplib_chpw($id=0, $data=0) { - global $user; - - if(!isset($_REQUEST['oldpassword'])){ - return(ewiki_t("CHPWFORM")); - }else{ - return($user->changepw($_REQUEST['oldpassword'],$_REQUEST['newpassword1'],$_REQUEST['newpassword2']).ewiki_t("CHPWFORM")); - } - - -} - -function ewiki_page_phplib_login($id=0, $data=0) { - global $auth,$sess,$perm; - - //if we did not just submit user data - if(isset($_REQUEST['username'])){ - if($perm->have_perm(EWIKI_PHPLIB_ALLUSERS_PERM)){ - return( ewiki_t("LOGGEDIN") ); - }else{ - return( ewiki_t("NOTLOGGEDIN") ); - } - } - $auth->unauth(); # We have to relogin, so clear current auth info - $auth->nobody = false; # We are forcing login, so default auth is - # disabled - $auth->auth["uid"] = "form"; - $auth->auth["exp"] = 0x7fffffff; - $auth->auth["refresh"] = 0x7fffffff; - $sess->freeze(); - - return( ewiki_t("LOGINFORM") ); -} - - - -function ewiki_page_phplib_logout($id=0, $data=0) { - global $auth; - - $auth->logout(); - page_close(); -/** - * return( "

              Logout

              - You have been logged in as ".$auth->auth["uname"]." with - ".$auth->auth["perm"]." permission.You have been logged out."); - */ - return( "

              Logout

              You have been logged out."); - } -function ewiki_auth_query_phplib(&$output, $force_query=0) { - - global $auth,$perm,$sess, $ewiki_author, $ewiki_ring; - - if($_REQUEST["cancel_login"]=="Cancel"){ - return(false); - } - - //attempt login if user not in group user - if(!$perm->have_perm(EWIKI_PHPLIB_ALLUSERS_PERM)){ - $auth->unauth(); # We have to relogin, so clear current auth info - $auth->nobody = false; # We are forcing login, so default auth is - # disabled - $auth->auth["uid"] = "form"; - $auth->auth["exp"] = 0x7fffffff; - $auth->auth["refresh"] = 0x7fffffff; - $sess->freeze(); - - $output=ewiki_t("LOGINFORM"); - return(false); - } - - //If we have a valid user (in group user) return sucess - if ($perm->have_perm(EWIKI_PHPLIB_ALLUSERS_PERM)) { - $ewiki_ring=1; // priviliged but ordinary user - } - else { - $ewiki_ring=3; // every other stupid, browse-only access - } - - - //If we have a valid user (in group user) return sucess - return($perm->have_perm(EWIKI_PHPLIB_ALLUSERS_PERM)); -} - -class My_User extends User { - var $classname = "My_User"; - var $register_globals = false; - - var $magic = "Abracadabra"; ## ID seed - var $that_class = "Example_CT_Sql"; ## name of data storage container class - - function changepw($oldpw,$newpw1,$newpw2){ - global $auth; - - if(!$auth->check_login($auth->auth['uname'],$oldpw)){ - $auth->unauth(); # Invalid password, log them out - return(ewiki_t("BADOLDPW")); - }elseif($reason=$this->is_pw_invalid($newpw1)){ - return($reason); - }elseif($newpw1!=$newpw2){ - return(ewiki_t("NOMATCH")); - } - $auth->db->query(sprintf("UPDATE %s SET password='%s'". - " where user_id = '%s' ", - $auth->database_table, - addslashes($newpw1), - addslashes($this->id) - )); - return(ewiki_t("PWCHNGD")); - - - - } - - function is_pw_invalid($pw){ - return($pw==''); - } - -} - - -class My_Auth extends Auth { - var $classname = "My_Auth"; - - var $mode = "log"; ## "log" for login only systems, -# var $classname = "Example_Auth"; - - var $lifetime = 15; - - var $database_class = "DB_Example"; - var $database_table = "auth_user"; - var $nobody = true; - - function auth_loginform() { - global $sess; - global $_PHPLIB; - - include($_PHPLIB["libdir"] . "loginform.ihtml"); - } - function check_login($username,$password){ - $uid = false; - - $this->db->query(sprintf("select user_id, perms ". - " from %s ". - " where username = '%s' ". - " and password = '%s'", - $this->database_table, - addslashes($username), - addslashes($password))); - - while($this->db->next_record()) { - $uid = $this->db->f("user_id"); - $this->auth["perm"] = $this->db->f("perms"); - } - - return $uid; - } - - function auth_validatelogin() { - global $HTTP_POST_VARS; - - if(isset($HTTP_POST_VARS["username"])) { - $this->auth["uname"] = $HTTP_POST_VARS["username"]; ## This provides access for "loginform.ihtml" - } - - - return $this->check_login($HTTP_POST_VARS["username"],$HTTP_POST_VARS["password"]); - - - - } - -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth/password_locks.meta b/mods/wiki/plugins/auth/password_locks.meta deleted file mode 100644 index fe3299eb2..000000000 --- a/mods/wiki/plugins/auth/password_locks.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_perm, edit_form_append, edit_save -type: auth -config: - EWIKI_PROTECTED_MODE=1 -title: PasswordLocking -description: individual pages can be password locked -delivers: auth-method -priority: rare diff --git a/mods/wiki/plugins/auth/password_locks.php b/mods/wiki/plugins/auth/password_locks.php deleted file mode 100644 index f664acb59..000000000 --- a/mods/wiki/plugins/auth/password_locks.php +++ /dev/null @@ -1,119 +0,0 @@ - -function ewiki_auth_login_password(&$data, &$author, &$ring, $force) { - - global $ewiki_errmsg; - static $cookie=0; - - #-- set cookie - if ($pw = $_POST["unlock_password"]) { - if (!$cookie) { - setcookie("unlock_password", $pw, time()+7*24*3600, "/", $_SERVER["SERVER_NAME"]); - $cookie++; - } - } - #-- get cookie - else { - $pw = $_REQUEST["unlock_password"]; - } - - #-- compare - $ok = ($pw == $data["meta"]["password"]); - - #-- print login form - if ($force && !$ok) { - $ewiki_errmsg = ewiki_t( <<_{This page is locked}
        -
        -_{password} -
        - -


        -END - ); - } - - return($ok); -} - - -#-- this separates password-protected pages from all others -function ewiki_auth_perm_password_locks($id, &$data, $action, $ring, $force) { - - $PROTECT = array( - "edit", "delete", "export", "any_other_action", - ); - - #-- only protect pages with passwords for editing - if (in_array($action, $PROTECT)) { - if (empty($data["meta"]["password"])) { - return(true); - } - else { - $ok = ewiki_auth_login_password($data, $ewiki_author, $ewiki_ring, -$force=1); - return($ok); - } - } - #-- strip password here, so it won't display accidently - elseif ($action == "info") { - unset($data["meta"]["password"]); - return(true); - } - #-- pages we don't care - else { - return(true); - // return(NULL); // for tri-state boolean ["auth_perm"] - } -} - - -#-- add password field on edit/ page -function ewiki_edit_field_pwlock($id, &$data, $action) { - $o = ewiki_t('

        _{lock page with} _{password}
        '; - return($o); -} - - -#-- store password into page db entry {meta} field -function ewiki_edit_save_pwlock(&$save, &$old_data) { - - $pw = $_REQUEST["lock_password"]; - if (true) { - - #-- keep in {meta} field - $save["meta"]["password"] = $pw; - - #-- copy it immediately - if ($_REQUEST["unlock_password"] != $pw) { - setcookie("unlock_password", $pw, time()+7*24*3600, "/"); - $_COOKIE["unlock_password"] = $pw; - $_REQUEST["unlock_password"] = $pw; - } - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth/userdb_anonymous.meta b/mods/wiki/plugins/auth/userdb_anonymous.meta deleted file mode 100644 index e7ca255e8..000000000 --- a/mods/wiki/plugins/auth/userdb_anonymous.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_userdb -type: auth -config: - EWIKI_AUTH_ANONYMOUS_RING=2 // permission ring level - EWIKI_AUTH_ANONYMOUS_VERIFY=0 // verify given email address -title: userdb_anonymous -description: allows login using name "anonymous" and email address as password -priority: rare diff --git a/mods/wiki/plugins/auth/userdb_anonymous.php b/mods/wiki/plugins/auth/userdb_anonymous.php deleted file mode 100644 index a1b6904cd..000000000 --- a/mods/wiki/plugins/auth/userdb_anonymous.php +++ /dev/null @@ -1,64 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/auth/userdb_array.meta b/mods/wiki/plugins/auth/userdb_array.meta deleted file mode 100644 index 6fd968c8a..000000000 --- a/mods/wiki/plugins/auth/userdb_array.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_userdb -type: auth -title: userdb_array -description: user database as array, hand edit it in the plugins source -priority: rare diff --git a/mods/wiki/plugins/auth/userdb_array.php b/mods/wiki/plugins/auth/userdb_array.php deleted file mode 100644 index b31ea95db..000000000 --- a/mods/wiki/plugins/auth/userdb_array.php +++ /dev/null @@ -1,42 +0,0 @@ - array("password", $RING_LEVEL=2), - // "user2" => array("sU7oi30Zmf2KTr4", 1), - -); - - -#-- glue -$ewiki_plugins["auth_userdb"][] = "ewiki_auth_user_array"; - -#-- code -function ewiki_auth_user_array($username, $password) { - return($GLOBALS["ewiki_auth_user_array"][$username]); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth/userdb_sql.meta b/mods/wiki/plugins/auth/userdb_sql.meta deleted file mode 100644 index 75850d83a..000000000 --- a/mods/wiki/plugins/auth/userdb_sql.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_userdb -type: auth -title: foreign SQL userdb -description: reuses an existing SQL database user table from foreign CMS -priority: rare diff --git a/mods/wiki/plugins/auth/userdb_sql.php b/mods/wiki/plugins/auth/userdb_sql.php deleted file mode 100644 index d7169126a..000000000 --- a/mods/wiki/plugins/auth/userdb_sql.php +++ /dev/null @@ -1,83 +0,0 @@ -3, "user"=>2, "moderator"=>1, "admin"=>0); - - #-- examples for some common CMS and dynamic web site systems - # PostNuke - //$TABLE="nuke_users"; $COL_USER="pn_name"; $COL_PW="pn_pass"; - //$COL_PRIV=""; - # pSlash - //$TABLE="ps_users"; $COL_USER="uname"; $COL_PW="pass"; - //$COL_PRIV="status"; $MAP_PRIV("member"=>2, "Admin"=>0); - # coWiki - //$TABLE="cowiki_user"; $COL_USER="name"; $COL_PW="passwd"; - //$COL_PRIV=""; - # e107 - //$TABLE="user"; $COL_USER="user_name"; $COL_PW="user_password"; - //$COL_PRIV="user_admin"; $MAP_PRIV(0=>2, 1=>0); - # Geeklog - //$TABLE="gl_user"; $COL_USER="username"; $COL_PW="passwd"; - //$COL_PRIV=""; - - - #-- proceed - $ret = array(); - $username = addslashes($username); # (not really necessary here anymore) - - #-- search username and password - if (($result = $sql_query("select $COL_PW from $TABLE where $COL_USER='$username'")) && ($row = $sql_fetch($result))) { - - #-- return values - $ret[0] = $row[$COL_PW]; - $ret[1] = 2; // default ring level - - #-- fetch privilege level, if there is a table row for it - if ($COL_PRIV && ($result = $sql_query("select $COL_PRIV from $TABLE where $COL_USER='$username'")) && ($row = $sql_fetch($result))) { - $i = $row[$COL_PRIV]; - #-- map priviliege names/values to ewikis' ring level integers - if (isset($i) && isset($MAP_PRIV[$i])) { - $ret[1] = $MAP_PRIV[$i]; - } - } - } - - #-- done - return($ret); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth/userdb_systempasswd.meta b/mods/wiki/plugins/auth/userdb_systempasswd.meta deleted file mode 100644 index a034ab93e..000000000 --- a/mods/wiki/plugins/auth/userdb_systempasswd.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_userdb -type: auth -config: - EWIKI_USERDB_SYSTEMPASSWD="system/passwd" -title: system/passwd -description: user list is kept on system page (only editable by admin) -priority: bonus diff --git a/mods/wiki/plugins/auth/userdb_systempasswd.php b/mods/wiki/plugins/auth/userdb_systempasswd.php deleted file mode 100644 index acb17c05f..000000000 --- a/mods/wiki/plugins/auth/userdb_systempasswd.php +++ /dev/null @@ -1,83 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/auth/userdb_userregistry.meta b/mods/wiki/plugins/auth/userdb_userregistry.meta deleted file mode 100644 index 35a9a78ab..000000000 --- a/mods/wiki/plugins/auth/userdb_userregistry.meta +++ /dev/null @@ -1,11 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_userdb, page -type: page -config: - EWIKI_PAGE_USERREGISTRY="UserRegistry" - EWIKI_USERDB_USERREGISTRY="system/UserRegistry" - EWIKI_REGISTERED_LEVEL=2 // ordinary users -title: UserRegistry -description: people can register themselves as users -priority: bonus diff --git a/mods/wiki/plugins/auth/userdb_userregistry.php b/mods/wiki/plugins/auth/userdb_userregistry.php deleted file mode 100644 index 6172541ef..000000000 --- a/mods/wiki/plugins/auth/userdb_userregistry.php +++ /dev/null @@ -1,279 +0,0 @@ -_{New Account}

      -
      -_{user/login name}
      - -
      -_{password}
      -_{retype}
      -
      - -


      -END - ); - - return($o); // finished here, prevent fallthrough-display of login-form - } - - #-- check password - if ($ue && $user && !ewiki_auth_user($user,$pw)) { - $o .= $_REQUEST["userreg_register"] - ? ewiki_t("USERNAME_ALREADY_USED") - : (ewiki_t("WRONG_PW") . "\n" . ewiki_t("PLEASE_RETRY")); - return($o); - } - - #-- set fallback settings for account creation - if (empty($ue) && $_REQUEST["userreg_store"]) { - $ue = - $_REQUEST["userreg_ue"] = - array( - $pw, - EWIKI_REGISTERED_LEVEL, - "", "", "" - ); - } - - #-- check username - if (preg_match("/[^".EWIKI_CHARS_U.EWIKI_CHARS_L."]/", $user.$pw)) { - $o .= ewiki_t("PW_ONLY_LETTERS") . "\n" . ewiki_t("PLEASE_RETRY"); - return($o); - } - elseif ($name && (strlen($user) < 3)) { - return($o . ewiki_t("USERNAME_MIN")); - } - - #-- save changes ------------------------------------------------------- - if ($_REQUEST["userreg_store"] && $user) { - - #-- new user entry - ($new_ue = $_REQUEST["userreg_ue"]) or ($new_ue = array()); - $new_ue[0] = $pw; - ($new_ue[1] = $ue[1]) or ($new_ue[1] = EWIKI_REGISTERED_LEVEL); - if ($new_pw = $_REQUEST["new_pw"]) { - if ($new_pw == $_REQUEST["new_pw2"]) { - $new_ue[0] = md5($new_pw); - } - else { - $o .= ewiki_t("RETYPE_PW") ."\n
      "; - return($o); - } - } - foreach ($new_ue as $i=>$v) { - $new_ue[$i] = preg_replace("/[^-@._ \w\d".EWIKI_CHARS_L.EWIKI_CHARS_U."]/", " ", $v); - } - - #-- get user db page - ($data = ewiki_db::GET(EWIKI_USERDB_USERREGISTRY)) - or ($data = array( - "id" => EWIKI_USERDB_USERREGISTRY, - "version" => 1, flags => 0, - "created" => time(), "lastmodified" => time(), - "content" => "nobody:*:3::", "meta" => "", - "author" => ewiki_author("$user@$id"), - )); - $data["flags"] |= EWIKI_DB_F_SYSTEM; - $list = explode("\n", $data["content"]); - - #-- update entry - ksort($new_ue); - $new_ue = $user . ":" . implode(":", $new_ue); - $found = 0; - foreach ($list as $i=>$line) { - $line = trim($line); - if (strtok($line, ":") == $user) { - $list[$i] = $new_ue; - $found = 1; - } - } - if (!$found) { - $list[] = $new_ue; - } - - #-- save back - $data["content"] = implode("\n", $list); - $retry = 3; - while ($retry--) { - $data["version"]++; - if ($ok = ewiki_db::WRITE($data)) { - break; - } - } - if ($ok) { - $o .= ewiki_t("Data saved")."\n
      "; - } - else { - $o .= ewiki_t("Error saving")."\n
      "; - ewiki_log("_userdb_userregistry: failed to update db for user $user, retries=$retry", 2); - } - - #-- fallthru to view_settings - $_REQUEST["userreg_login"] = 1; - $ue = ewiki_auth_userdb_userregistry($user); - } - - - #-- view settings ---------------------------------------------------- - if ($_REQUEST["userreg_login"]) { - - #-- edit
      - $o .= ewiki_t(<<< END -

      _{Account Settings}

      - - - -_{change password}
      -_{new password}
      -_{retype}
      -
      -_{optional infos}
      -_{personal WikiPage}
      -_{email address}
      - -
      - -


      -END - ); - } - - #-- print login
      --------------------------------------------- - else { - - $url = ewiki_script("", $id); - $o .= ewiki_t(<<< END - -
      -
      -_{name}   -
      -
      -
      -_{password}
      -
      - -
      -


      -END - ); - } - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth/userdb_xprofile.meta b/mods/wiki/plugins/auth/userdb_xprofile.meta deleted file mode 100644 index a114bb85c..000000000 --- a/mods/wiki/plugins/auth/userdb_xprofile.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -type: auth -category: authentication -title: XUP/XProfile -description: logins against remote XML User Profiles -homepage: http://xprofile.berlios.de/ -depends: libxprofile -x-also-depends-but-this-is-already-hacked-in: session-support -hooks: auth_userdb -funcs: ewiki_auth_userdb_xprofile diff --git a/mods/wiki/plugins/auth/userdb_xprofile.php b/mods/wiki/plugins/auth/userdb_xprofile.php deleted file mode 100644 index fc5a68930..000000000 --- a/mods/wiki/plugins/auth/userdb_xprofile.php +++ /dev/null @@ -1,45 +0,0 @@ -control) { - - #-- validate - if ($xpro->login() ) { - - #-- save data - $_SESSION["ewiki_author"] = $ewiki_author = $xpro->info["nickname"]; - $_SESSION["xprofile"] = $xpro->url; - - return(true); - } - else { - // misuse (already logged by XProfile manager) - ewiki_log("userdb_xprofile: wrong password '...' for remote account on '$username'", 1); - } - } - - return(false); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/auth/users_ldap.meta b/mods/wiki/plugins/auth/users_ldap.meta deleted file mode 100644 index 042c6601e..000000000 --- a/mods/wiki/plugins/auth/users_ldap.meta +++ /dev/null @@ -1,12 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_userdb -type: auth -config: - EWIKI_LDAP_SERVER="ldap.example.com" - EWIKI_LDAP_RDN='cn=$USER,ou=users,dc=example,dc=com' - EWIKI_LDAP_FILTER="" // sn=* ??? - EWIKI_LDAP_RING=2 -title: LDAP users -description: checks login credentials by connecting to LDAP server -priority: rare diff --git a/mods/wiki/plugins/auth/users_ldap.php b/mods/wiki/plugins/auth/users_ldap.php deleted file mode 100644 index 6826b5919..000000000 --- a/mods/wiki/plugins/auth/users_ldap.php +++ /dev/null @@ -1,48 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/auth/you.meta b/mods/wiki/plugins/auth/you.meta deleted file mode 100644 index 629b47889..000000000 --- a/mods/wiki/plugins/auth/you.meta +++ /dev/null @@ -1,12 +0,0 @@ -api: ewiki -category: authentication -hooks: auth_userdb -type: auth -config: - YOUR_PASSWORD="*" - YOUR_LEVEL=0 // 0 = superuser - EWIKI_PROTECTED_MODE=1 - EWIKI_AUTH_DEFAULT_RING=3 // 3 = read/view/browse-only -title: you -description: makes your whole Wiki readonly and editable only with one password -priority: rare diff --git a/mods/wiki/plugins/auth/you.php b/mods/wiki/plugins/auth/you.php deleted file mode 100644 index e013dadb7..000000000 --- a/mods/wiki/plugins/auth/you.php +++ /dev/null @@ -1,37 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/aview/aedit_authorname.meta b/mods/wiki/plugins/aview/aedit_authorname.meta deleted file mode 100644 index ea8122cd8..000000000 --- a/mods/wiki/plugins/aview/aedit_authorname.meta +++ /dev/null @@ -1 +0,0 @@ -type: R diff --git a/mods/wiki/plugins/aview/aedit_authorname.php b/mods/wiki/plugins/aview/aedit_authorname.php deleted file mode 100644 index e03875060..000000000 --- a/mods/wiki/plugins/aview/aedit_authorname.php +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/aview/aedit_deletebutton.js.meta b/mods/wiki/plugins/aview/aedit_deletebutton.js.meta deleted file mode 100644 index ea8122cd8..000000000 --- a/mods/wiki/plugins/aview/aedit_deletebutton.js.meta +++ /dev/null @@ -1 +0,0 @@ -type: R diff --git a/mods/wiki/plugins/aview/aedit_deletebutton.js.php b/mods/wiki/plugins/aview/aedit_deletebutton.js.php deleted file mode 100644 index f47ad0617..000000000 --- a/mods/wiki/plugins/aview/aedit_deletebutton.js.php +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/aview/aedit_log.meta b/mods/wiki/plugins/aview/aedit_log.meta deleted file mode 100644 index ea8122cd8..000000000 --- a/mods/wiki/plugins/aview/aedit_log.meta +++ /dev/null @@ -1 +0,0 @@ -type: R diff --git a/mods/wiki/plugins/aview/aedit_log.php b/mods/wiki/plugins/aview/aedit_log.php deleted file mode 100644 index 7cda26f4b..000000000 --- a/mods/wiki/plugins/aview/aedit_log.php +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/aview/aedit_pageimage.meta b/mods/wiki/plugins/aview/aedit_pageimage.meta deleted file mode 100644 index ea8122cd8..000000000 --- a/mods/wiki/plugins/aview/aedit_pageimage.meta +++ /dev/null @@ -1 +0,0 @@ -type: R diff --git a/mods/wiki/plugins/aview/aedit_pageimage.php b/mods/wiki/plugins/aview/aedit_pageimage.php deleted file mode 100644 index 8a89a5434..000000000 --- a/mods/wiki/plugins/aview/aedit_pageimage.php +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/aview/aedit_templates.meta b/mods/wiki/plugins/aview/aedit_templates.meta deleted file mode 100644 index ea8122cd8..000000000 --- a/mods/wiki/plugins/aview/aedit_templates.meta +++ /dev/null @@ -1 +0,0 @@ -type: R diff --git a/mods/wiki/plugins/aview/aedit_templates.php b/mods/wiki/plugins/aview/aedit_templates.php deleted file mode 100644 index 20f6f085a..000000000 --- a/mods/wiki/plugins/aview/aedit_templates.php +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/aview/backlinks.meta b/mods/wiki/plugins/aview/backlinks.meta deleted file mode 100644 index 777b05ce4..000000000 --- a/mods/wiki/plugins/aview/backlinks.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: aview -title: BackLinks -description: appends the list of pages linking back -priority: rare -hooks: view_append -type: mangle diff --git a/mods/wiki/plugins/aview/backlinks.php b/mods/wiki/plugins/aview/backlinks.php deleted file mode 100644 index f314538cb..000000000 --- a/mods/wiki/plugins/aview/backlinks.php +++ /dev/null @@ -1,24 +0,0 @@ -'.$id.''; - } - ($o) && ($o = "
      Backlinks:
      $o
      \n"); - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/aview/blog.meta b/mods/wiki/plugins/aview/blog.meta deleted file mode 100644 index 8daa1a924..000000000 --- a/mods/wiki/plugins/aview/blog.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: aview -hooks: view_append -type: mangle -title: blog -description: generates wiki-news style summary of the calendar entries -priority: bonus diff --git a/mods/wiki/plugins/aview/blog.php b/mods/wiki/plugins/aview/blog.php deleted file mode 100644 index 1ba78005e..000000000 --- a/mods/wiki/plugins/aview/blog.php +++ /dev/null @@ -1,40 +0,0 @@ -' - .ewiki_wikinews_summary($n_num,$n_len,'/^'.$id.EWIKI_NAME_SEP.'\d{8}$/') - . ''; - $o.='View all log entries.'; - - return($o); -} - - - -?> diff --git a/mods/wiki/plugins/aview/control2.meta b/mods/wiki/plugins/aview/control2.meta deleted file mode 100644 index be4257a24..000000000 --- a/mods/wiki/plugins/aview/control2.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: aview -hooks: view_final -type: mangle -config: - EWIKI_CONTROL_LINE=0 - EWIKI_PRINT_TITLE=1 -title: control2 -description: fancifies (CSS) and moves the control link box to the top -priority: rare diff --git a/mods/wiki/plugins/aview/control2.php b/mods/wiki/plugins/aview/control2.php deleted file mode 100644 index c91e28de9..000000000 --- a/mods/wiki/plugins/aview/control2.php +++ /dev/null @@ -1,53 +0,0 @@ - with info/ link - list($h2, $html) = explode("\n", $html, 2); - - #-- produce control links - $cl = ""; - if (!empty($data["forced_version"])) { - $cl = '$data["forced_version"], "edit"=>"old")). - '">'.ewiki_t("OLDVERCOMEBACK").""; - } - else { - foreach ($ewiki_config["action_links"]["view"] as $action => $title) if (!empty($ewiki_plugins["action"][$action])) { - if (EWIKI_PROTECTED_MODE && (!ewiki_auth($uu, $uu, $action) || EWIKI_PROTECTED_MODE_HIDING && empty($ewiki_ring))) { continue; } - $cl .= ''.$title.' '; - } - } - - if ($data["lastmodified"] >= UNIX_MILLENNIUM) { - $cl .= '
      ' . strftime(ewiki_t("LASTCHANGED"), @$data["lastmodified"]) . ''; - } - - #-- change

      - $h2 = str_replace("

      ", '

      ', $h2); - - #-- output - $html = '
      '. - "$h2\n". - '
      '.$cl.'
      '. - "
      \n". - $html; - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/aview/downloadlist.meta b/mods/wiki/plugins/aview/downloadlist.meta deleted file mode 100644 index 7c3820fc2..000000000 --- a/mods/wiki/plugins/aview/downloadlist.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: aview -title: downloads -description: lists downloads for/on individual pages -priority: bonus -hooks: view_append -type: mangle diff --git a/mods/wiki/plugins/aview/downloadlist.php b/mods/wiki/plugins/aview/downloadlist.php deleted file mode 100644 index d6380c153..000000000 --- a/mods/wiki/plugins/aview/downloadlist.php +++ /dev/null @@ -1,55 +0,0 @@ -

      ' . ewiki_t("ATTACHMENTS") . '

      '; - - $scan = 's:7:"section";' . serialize($id); - $result = ewiki_db::SEARCH("meta", $scan); - - $ord = array(); - while ($row = $result->get()) { - $ord[$row["id"]] = $row["created"]; - } - arsort($ord); - - foreach ($ord as $id => $uu) { - $row = ewiki_db::GET($id); - if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $row, "view")) { - continue; - } - $o .= ewiki_entry_downloads($row, "*"); - } - - return($o); -} - - - - -function ewiki_attachments() { - global $ewiki_title, $ewiki_id; - return(ewiki_view_append_attachments($ewiki_title, array("id"=>$ewiki_id), "view")); -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/aview/fpage_copyright.meta b/mods/wiki/plugins/aview/fpage_copyright.meta deleted file mode 100644 index 18ffb0fd0..000000000 --- a/mods/wiki/plugins/aview/fpage_copyright.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: aview -hooks: page_final -type: mangle -title: fpage_copyright -description: generates a copyright notice -priority: bonus diff --git a/mods/wiki/plugins/aview/fpage_copyright.php b/mods/wiki/plugins/aview/fpage_copyright.php deleted file mode 100644 index 3cf4be407..000000000 --- a/mods/wiki/plugins/aview/fpage_copyright.php +++ /dev/null @@ -1,21 +0,0 @@ -\nCopyright © ".strftime("%B %d, %Y",$data["lastmodified"])." ".ewiki_t("ALLRIGHTSRESERVED")."\n"; - }else { - $o.="
      \nCopyright © ".strftime("2004")." ".ewiki_t("ALLRIGHTSRESERVED")."\n
      "; - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/aview/fpage_logo.meta b/mods/wiki/plugins/aview/fpage_logo.meta deleted file mode 100644 index 43326c85e..000000000 --- a/mods/wiki/plugins/aview/fpage_logo.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -category: aview -hooks: page_final -type: mangle -title: fpage_logo -description: appends an image (logo) to the page -author: Jeffrey Engleman -priority: bonus diff --git a/mods/wiki/plugins/aview/fpage_logo.php b/mods/wiki/plugins/aview/fpage_logo.php deleted file mode 100644 index 280458936..000000000 --- a/mods/wiki/plugins/aview/fpage_logo.php +++ /dev/null @@ -1,17 +0,0 @@ -\n\"".ewiki_t("LOGOALT")."\"/\n\n"; -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/aview/imgappend.meta b/mods/wiki/plugins/aview/imgappend.meta deleted file mode 100644 index bec72bc61..000000000 --- a/mods/wiki/plugins/aview/imgappend.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: aview -title: image appending -description: more quickly appends image to a page -priority: rare -hooks: view_append, action -type: action diff --git a/mods/wiki/plugins/aview/imgappend.php b/mods/wiki/plugins/aview/imgappend.php deleted file mode 100644 index 29f75e993..000000000 --- a/mods/wiki/plugins/aview/imgappend.php +++ /dev/null @@ -1,124 +0,0 @@ - Append an Image
      '; -$ewiki_t["en"]["NO_IMAGEAPPEND"] = "The image uploading succeeded, but the page couldn't get updated. Please try the image upload function on EditThisPage."; - - - - -function ewiki_aview_image_append($id, $data, $action) { - - $URL = ewiki_script("imageappend", $id); - $TXT = ewiki_t("IMAGEAPPEND_FORM0"); - $BTN1 = ewiki_t("UPLOAD_PICTURE_BUTTON"); - - $accept = (defined("EWIKI_IMAGE_ACCEPT") ? ' accept="'.EWIKI_IMAGE_ACCEPT.'">' : ""); - return(<<<___ -
      -
      - $TXT -
      - -
      -
      -___ - ); -} - - - -function ewiki_action_image_append($id, $data, $action) { - - #-- invalid $id value - if (empty($data) || - !$data["version"] || - (EWIKI_DB_F_TEXT != ($data["flags"] & EWIKI_DB_F_TYPE))) - { - $o = ewiki_t("CANNOTCHANGEPAGE"); - } - - #-- temporary upload-file found - elseif ($fa = $_FILES["imagefile"]) { - - #-- guess HTTP meta data - $meta = array( - "X-Content-Type" => $fa["type"], - #"X-Content-Length" => $fa["size"], - ); - if ($s = $fa["name"]) { - $meta["Content-Location"] = $s; - ($p = 0) or - ($p = strrpos($s, "/")) and ($p++) or - ($p = strrpos($s, '\\')) and ($p++); - $meta["Content-Disposition"] = 'inline; filename="'.urlencode(substr($s, $p)).'"'; - } - - #-- proceed an image (reject binary, resize if too large) - $result = ewiki_binary_save_image( - $fa["tmp_name"], // uploaded file location - "", // no predefined $id - "RETURN", // do not die() on error - $meta, // =Content-Location - 0, // =do not accept plain binary - 1 // =care for images - ); - - #-- database rejected file - if (!$result) { - $o = ewiki_t("BIN_NOIMG"); - } - - #-- if picture stored in db - else { - - $loop = 3; - while($loop--) { - - $data = ewiki_db::GET($id); - - $data["version"]++; - $data["content"] = rtrim($data["content"], "\n") . "\n\n" . - "[\"AppendedPicture\"$result]\n\n\n"; - - $result = ewiki_db::WRITE($data); - - if ($result) { - break; - } - - } - - if ($result) { - $o = ewiki_page("view/$id"); - ewiki_log("image appended to '$id'"); - } - else { - $o .= ewiki_t("NO_IMAGEAPPEND"); - } - - } - - } - - #-- no upload-file - else { - $o .= ewiki_t("BIN_NOIMG"); -#"You did not select an image, or something went really wrong during tansmission. Plase go back to the previous page."; - } - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/aview/linktree.meta b/mods/wiki/plugins/aview/linktree.meta deleted file mode 100644 index 5acef8c10..000000000 --- a/mods/wiki/plugins/aview/linktree.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: aview -title: LinkTree -description: shows the paths to the root page (slow) -priority: rare -hooks: view_append -type: mangle -config: - EWIKI_LINKTREE_UL=0 // else a link::list will be printed diff --git a/mods/wiki/plugins/aview/linktree.php b/mods/wiki/plugins/aview/linktree.php deleted file mode 100644 index 1cf059dfe..000000000 --- a/mods/wiki/plugins/aview/linktree.php +++ /dev/null @@ -1,150 +0,0 @@ -$id); - $current = $id; -/* - * $paths["Current"] = "Current"; - * $paths["WorldWideWeb\nWikiWikiWeb\nErfurtWiki"] = "ErfurtWiki"; - */ - - #-- retry until at least one $path is found - while ( (!in_array($dest, $paths)) && ($depth <= 15) && (count($paths)<=100000)) { - - $depth++; - - #-- expand every last path entry - foreach ($paths as $pathkey=>$uu) { - - #-- mk subkey from pathkey - if ($p = strrpos($pathkey, "\n")) { - $lkey = substr($pathkey, $p+1); - } - else { - $lkey = $pathkey; - } - - #-- append tree leafs - if ($walk = $refs[$lkey]) { - foreach ($walk as $add=>$uu) { - $paths[$pathkey."\n".$add] = $add; - } - unset($refs[$lkey]); - } - } - } - - #-- print results - foreach ($paths as $key => $name) { - - $tree = array_reverse(explode("\n", $key)); - $GLOBALS["ewiki_page_sections"] = array(); - - if (($name == $dest) && (count($tree) >= 2)) { - - $GLOBALS["ewiki_page_sections"][] = $tree[1]; - - if (EWIKI_LINKTREE_UL) { - $o .= ewiki_f_tree($tree, 0); - } else { - $o .= ewiki_f_tree2($tree, 0); - } - - } - } - - ($o) && ($o = "\n"); - - - return($o); -} - - -#-- outputs the given pages in a treelist -function ewiki_f_tree(&$pages, $n=1) { - - if ($id = $pages[0]) { - - $o .= "
        "; - $o .= ($n ? "
      • " : "") . - ''.$id.'' . - ($n ? "
      • " : "") . "\n"; - $o .= ewiki_f_tree(array_slice($pages, 1)); - $o .= "
      \n"; - } - - return($o); -} - - -#-- outputs a flat link list -function ewiki_f_tree2(&$pages, $n=1) { - - foreach ($pages as $id) { - $o[] = ''.$id.''; - } - - // "::" instead of "→" may also look nice - return(implode(" → ", $o) . "
      "); -} - - - -#-- build parents array of (reverse) string $refs from the database -function ewiki_f_parent_refs($refs) { - - $pages = array(); - - #-- decode refs - while ($row = $refs->get()) { - $parent = $row["id"]; - foreach (explode("\n", $row["refs"]) as $page) { - - if (strlen($page)) { - $pages[$page][$parent]=1; - } - - //echo("($page,$parent) "); - } - //echo("\n"); - } - - return($pages); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/aview/pagetrail.meta b/mods/wiki/plugins/aview/pagetrail.meta deleted file mode 100644 index e4410eaed..000000000 --- a/mods/wiki/plugins/aview/pagetrail.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: aview -title: page trails -description: << Prev | ParentPage | Next >> -priority: rare -hooks: view_append -type: mangle diff --git a/mods/wiki/plugins/aview/pagetrail.php b/mods/wiki/plugins/aview/pagetrail.php deleted file mode 100644 index 2fe02dadc..000000000 --- a/mods/wiki/plugins/aview/pagetrail.php +++ /dev/null @@ -1,43 +0,0 @@ -> - - Using a pages meta box you can define it to be part of page - section/group ordered by a link list on another page. Use a - meta field of "top:" or "parent:" or "group:" to make the - current page belong to the cluster of pages in a trail. Then - the for and back links will be shown at the bottom. -*/ - - -$ewiki_plugins["view_append"][] = "ewiki_aview_pagetrail"; - -function ewiki_aview_pagetrail($id, &$data, $action) { - - if ($m = $data["meta"]["meta"]) { - - #-- check for parent page - ($top = $m["top"]) - or ($top = $m["parent"]) - or ($top = $m["group"]); - - if ($top) { - $t = ewiki_db::GET($top); - $t = explode("\n", trim($t["refs"])); - - $n = array_search(ewiki_array($top), strtolower($t)); - $prev = $t[$n-1]; - $next = $t[$n+1]; - - $o = "
      << " - . ($prev ? ewiki_link($prev) : "") - . " | " . ewiki_link($top) . " | " - . ($prev ? ewiki_link($prev) : "") . " >%gt;
      \n"; - return($o); - } - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/aview/piclogocntrl.meta b/mods/wiki/plugins/aview/piclogocntrl.meta deleted file mode 100644 index 82ee59d75..000000000 --- a/mods/wiki/plugins/aview/piclogocntrl.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -category: aview -hooks: handler -type: intercept -title: piclogocntrl -description: for selection of a page logo graphic (see fpage_logo) -author: Jeremy Mikola, Andy Fundinger -priority: rare diff --git a/mods/wiki/plugins/aview/piclogocntrl.php b/mods/wiki/plugins/aview/piclogocntrl.php deleted file mode 100644 index 8eefb0670..000000000 --- a/mods/wiki/plugins/aview/piclogocntrl.php +++ /dev/null @@ -1,93 +0,0 @@ -' alt=''> - - to insert the graphic. -*/ -/* -* @author jeremy mikola -* @author andy fundinger (Minor contributions and maintenance) -*/ - - -$ewiki_plugins['edit_save'][] = 'ewiki_edit_save_piclogocntrl'; -$ewiki_plugins['edit_form_append'][] = 'ewiki_edit_form_append_piclogocntrl'; -$ewiki_plugins["handler"][] = 'ewiki_set_pickedlogo'; - -// array lists all available logo files and titles -$piclogocntrlLogos = array( - 'logo1_01.gif' => 'Logo 1', - 'logo2_01.gif' => 'Logo 2', - 'logo3_01.gif' => 'Logo 3', - 'logo4_01.gif' => 'Logo 4'); - -define('DEFAULT_LOGO','BurgissGroup_01.gif'); - -function ewiki_set_pickedlogo($id, $data, $action){ - global $ewiki_config,$piclogocntrlLogos; - - if(isset($ewiki_config['page_logo'])){ - return; - } - - if(!($ewiki_config['page_logo']=$data['meta']['logo'])){ - $ewiki_config['page_logo']=DEFAULT_LOGO; - } - - $ewiki_config['page_logo_alt']=$piclogocntrlLogos[$ewiki_config['page_logo']]; -} - -/** - * Save selected logo value by setting it in the meta field of save data array - * passed by reference. - * - * @param array save associative array of ewiki form data - */ -function ewiki_edit_save_piclogocntrl(&$save, &$old_data) -{ - global $piclogocntrlLogos; - - if (isset($_REQUEST['piclogocntrlSelectLogo']) && array_key_exists($_REQUEST['piclogocntrlSelectLogo'], $piclogocntrlLogos)) { - $save['meta']['logo'] = $_REQUEST['piclogocntrlSelectLogo']; - } -} - -/** - * generates html form output for the logo selection field. - * - * @param mixed id - * @param mixed data - * @param string action - * @return string html output for logo selection fields - */ -function ewiki_edit_form_append_piclogocntrl ($id, $data, $action) -{ - global $piclogocntrlLogos; - - /* - * problem: $data['meta'] is still serialized at this point. it should be - * unserialized and accessible as an array in order to fetch the currently - * selected logo value. - */ - - $o = ' -
      -

      '; - return($o); -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/aview/posts.meta b/mods/wiki/plugins/aview/posts.meta deleted file mode 100644 index fb62df063..000000000 --- a/mods/wiki/plugins/aview/posts.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: aview -priority: rare -hooks: view_append, action, handler, view_final -type: intercept -title: posts -description: appends a class of wiki pages to the bottom (sub or sibling pages) - often used for discussions diff --git a/mods/wiki/plugins/aview/posts.php b/mods/wiki/plugins/aview/posts.php deleted file mode 100644 index 960c43682..000000000 --- a/mods/wiki/plugins/aview/posts.php +++ /dev/null @@ -1,196 +0,0 @@ - "Edit This Post", - "INFOABOUTPOST" => "Information about post", - "COMPVERPOST" => "See Changes" - )); - -#-- entitle actions -$ewiki_config['posts_action_links'] = array_merge(array( - "edit" => "EDITTHISPOST", - "info" => "INFOABOUTPOST", - "diff" => "COMPVERPOST", - -), $ewiki_config['posts_action_links']); - -if (!defined("EWIKI_AUTOVIEW") || EWIKI_AUTOVIEW) { - $ewiki_plugins["view_append"]['view_append_posts'] = "ewiki_view_append_posts"; -} - -$ewiki_t["en"]["POSTS"] = "posts"; -$ewiki_t["en"]["POST"] = "Post: "; -$ewiki_t["en"]["ADDPOST"] = "Add a post"; -$ewiki_t["en"]["TOO_MANY_POSTS"] = 'We are sorry. The maximum number of posts has been exceeded.

      Return to [$id]'; - -$ewiki_config["action_links"]["view"]["addpost"] = $ewiki_t["en"]["ADDPOST"]; - -$ewiki_plugins["action"]["addpost"] = "ewiki_add_post"; -$ewiki_plugins["handler"][] = 'ewiki_adjust_thread_controls'; -$ewiki_plugins["handler"][] = 'ewiki_view_post_parent'; - -define ('EWIKI_POST_SEPARATOR','_POST'); -define("EWIKI_POSTID_PARSE_REGEX",'#(.*)'.preg_quote(EWIKI_POST_SEPARATOR) .'(\d{3})'.'#'); -define ('EWIKI_VIEWPOSTACTION','view'); - -function ewiki_view_post_parent($id, $data, $action){ - global $ewiki_plugins; - - if(!preg_match(EWIKI_POSTID_PARSE_REGEX,$id,$matches)||($action!='view')) - return; - - //Authentication for the new page is handled within this call. - $o=ewiki_page('view/'.$matches[1]); - - //page_final plugins have been run, unset them - unset($ewiki_plugins["page_final"]); - - return($o); -} - -function ewiki_adjust_thread_controls($id, $data, $action){ - global $ewiki_config; - - if($action!='view') - return; - if(!posts_exist()) - return; - - //Move add post action to first position in control links - $temp = $ewiki_config["action_links"]['view']['addpost']; - unset($ewiki_config["action_links"]['view']['addpost']); - $ewiki_config["action_links"]['view'] = array_merge(array('addpost'=>$temp),$ewiki_config["action_links"]['view']); -} - -function ewiki_add_post($id, $data, $action){ - global $ewiki_plugins,$ewiki_config; - - $postNum=getPostCount($id)+1; - $postNum=str_pad($postNum, 3, "0", STR_PAD_LEFT); - - if($postNum>999){ - $o=ewiki_format(ewiki_t("TOO_MANY_POSTS", array("id"=>$id))); - } else { - $id=$id.EWIKI_POST_SEPARATOR.($postNum); - $ewiki_config["create"] = $id; - //echo("Calling edit function $id"); - $o=$ewiki_plugins["action"]["edit"]($id,array("id"=>$id) ,$action); - } - - return($o); -} - -function ewiki_view_append_posts($id, $data, $action) { - global $ewiki_plugins,$ewiki_config; - -## Since this function calls ewiki_page_view it must disable itself when it is called -## I do this by having it set separate view_append and view final actions for posts -## but at a minimum it removes itself - - $std_view_append=$ewiki_plugins["view_append"]; - $std_view_final=$ewiki_plugins["view_final"]; - $std_action_links=$ewiki_config["action_links"]["view"]; - $thread_page_title=$GLOBALS["ewiki_title"]; - - if(!isset($ewiki_config['posts_view_append'])){ - unset($ewiki_plugins["view_append"]['view_append_posts']); - }else{ - $ewiki_plugins["view_append"]=$ewiki_config['posts_view_append']; - } - - if(isset($ewiki_config['posts_view_final'])){ - $ewiki_plugins["view_final"]=$ewiki_config['posts_view_final']; - } - - if(!isset($ewiki_config['posts_action_links'])){ - unset($GLOBALS['ewiki_config']["action_links"]["view"]["addpost"]); - }else{ - $ewiki_config["action_links"]["view"]=$ewiki_config['posts_action_links']; - } - - unset($_REQUEST["thankyou"]); // Prevent thank you message from appearing in the menu - // bar - -/** - * Code for the new database layer */ - $result = ewiki_db::SEARCH("id", $id.'_POST'); - - #sort by post number - $ord = array(); - while ($row = $result->get()) { - if(preg_match('#_POST(\d{3})#', $row["id"],$matches = array())){ - $ord[$matches[1]] = $row['id']; - } - } - asort($ord); - - foreach ($ord as $postNum => $id) { - $GLOBALS["ewiki_title"]=ewiki_t('POST').$postNum; - - $row = ewiki_db::GET($id); - - #-- require auth - if (EWIKI_PROTECTED_MODE) { - if (!ewiki_auth($id, $row, EWIKI_VIEWPOSTACTION, $ring=false, $force=0)) { - continue; - } - } - - $postOut = ewiki_page_view($id, $row, EWIKI_VIEWPOSTACTION); - ewiki_page_css_container($postOut , $id, $row, $oo=EWIKI_VIEWPOSTACTION); - $o.=$postOut ; - } - -## Restore normal actions - $ewiki_plugins["view_append"]= $std_view_append; - $ewiki_plugins["view_final"]= $std_view_final; - $ewiki_config["action_links"]["view"]=$std_action_links; - $GLOBALS["ewiki_title"]=$thread_page_title; - - return("
      ".$o.'
      '); -} - -function isPost($id){ - return(preg_match(EWIKI_POSTID_PARSE_REGEX,$id)); -} -function getPostNumber($id){ - preg_match(EWIKI_POSTID_PARSE_REGEX,$id,$match=array()); - return($match[2]); -} - -function getPostCount($id){ -/** - * Code for the new database layer*/ - #sort by post number - $ord = array(); - - $scan = $id.EWIKI_POST_SEPARATOR; //Should I escape $id here? - $result = ewiki_db::SEARCH("id", $scan); - while ($row = $result->get()) { - preg_match('#_POST(\d{3})#', $row["id"],$matches=array($matches)); - $ord[$row["id"]] = $matches[1]; - } - rsort($ord); - return($ord[0]); -} - -function posts_exist($always=false) { - $id = $GLOBALS["ewiki_id"]; - - $result = $always || ($id) - && ($result = ewiki_db::SEARCH("id", $id.'_POST')) - && ($result->count()); - return( ($id) && ($id != EWIKI_PAGE_CALENDAR) && ($id != EWIKI_PAGE_YEAR_CALENDAR) - && !isPost($id) - && empty($_REQUEST["year"]) && $result ); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/aview/subpages.meta b/mods/wiki/plugins/aview/subpages.meta deleted file mode 100644 index 43f8591e7..000000000 --- a/mods/wiki/plugins/aview/subpages.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: aview -title: SubPages -description: subpages have names similar to the current -priority: rare -hooks: view_append -type: mangle diff --git a/mods/wiki/plugins/aview/subpages.php b/mods/wiki/plugins/aview/subpages.php deleted file mode 100644 index 8a5bfc6d5..000000000 --- a/mods/wiki/plugins/aview/subpages.php +++ /dev/null @@ -1,24 +0,0 @@ -'.ewiki_t($title).":
      "; - $o .= ewiki_list_pages($pages)."\n"; - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/aview/threads.meta b/mods/wiki/plugins/aview/threads.meta deleted file mode 100644 index a49507911..000000000 --- a/mods/wiki/plugins/aview/threads.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -category: aview -priority: rare -hooks: view_append, action -type: action -title: threads -description: lists thread pages (see also posts) -depends: posts diff --git a/mods/wiki/plugins/aview/threads.php b/mods/wiki/plugins/aview/threads.php deleted file mode 100644 index 65fb54fd7..000000000 --- a/mods/wiki/plugins/aview/threads.php +++ /dev/null @@ -1,77 +0,0 @@ -get()) { - if(!isPost($row["id"])){ - $pages[$row["id"]] = ""; - } - } - - if(0!=count($pages)){ - $o = "
      ".ewiki_t('THREADS').":
      "; - $o .= ewiki_list_pages($pages)."
      \n"; - } - - $o .="
      ". - ewiki_t("NEWTHREAD").": ". - "". - "
      "; - - return("
      ".$o.'
      '); -} - - -//Adding a thread is just creating a specially named page. -//We create a blank page and then edit a post off of it -function ewiki_add_thread($id, $data, $action){ - global $ewiki_plugins; - - $id=$id.EWIKI_THREAD_SEPARATOR.$_REQUEST['threadname']; - - $save = array( - "id" => $id, - "version" => 1, - "flags" => '', - "content" => " ", - "author" => ewiki_author(), - "lastmodified" => time(), - "created" => time(), - "meta" => array('isThread'=>'1'), - "hits" => 0, - "refs" => "" - ); - - if (!ewiki_db::WRITE($save)) { - return(ewiki_t("ERRORSAVING")); - } - - return(ewiki_add_post($id, array(), 'addpost')); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/aview/toc.meta b/mods/wiki/plugins/aview/toc.meta deleted file mode 100644 index ed80c73d6..000000000 --- a/mods/wiki/plugins/aview/toc.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: aview -title: TableOfContents -description: is generated automatically from pages headlines -priority: bonus -hooks: format_source, format_final -type: transform -config: - EWIKI_TOC_CAPTION=0 diff --git a/mods/wiki/plugins/aview/toc.php b/mods/wiki/plugins/aview/toc.php deleted file mode 100644 index f5fc334bc..000000000 --- a/mods/wiki/plugins/aview/toc.php +++ /dev/null @@ -1,76 +0,0 @@ -$line) { - - if ($line[0] == "!") { - $n = strspn($line, "!"); - if (($n <= 3) and ($line[$n]==" ")) { - - $text = substr($line, $n); - $toc[$i] = str_repeat(" ", 3-$n) . "·" - .// Had top fix this to make anchor links in the TOC work ' - '' - . trim($text) . ""; - - $src[$i] = str_repeat("!", $n) . $text . " [#line$i]"; - - } - } - } - $src = implode("\n", $src); - - $GLOBALS["ewiki_page_toc"] = &$toc; -} - - -#-- injects toc above page -function ewiki_toc_view_prepend(&$html) { - - global $ewiki_page_toc; - - if (count($ewiki_page_toc) >= 3) { - - $html = "
      \n" - . ( EWIKI_TOC_CAPTION ? '
      '.ewiki_t("toc")."
      \n" : '') - . implode("
      \n", $ewiki_page_toc) . "
      \n" - . $html; - } - - // $ewiki_page_toc = NULL; -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/core.meta b/mods/wiki/plugins/core.meta deleted file mode 100644 index bac27e257..000000000 --- a/mods/wiki/plugins/core.meta +++ /dev/null @@ -1,32 +0,0 @@ -api: PHP -type: api -priority: core -sort: 100 -category: library -title: ewiki core script -description: basic functionality provided by ewiki -fn: ewiki.php -config: - EWIKI_SCRIPT=?id= // all links are constructed with this path prefix - EWIKI_NAME=UnnamedWiki // name of your wiki - EWIKI_PAGE_INDEX=FrontPage // how is the start/default page called - EWIKI_DEFAULT_LANG=en // purely informational - EWIKI_SPLIT_TITLE=0 // inject spaces between parts of WikiWords - EWIKI_PRINT_TITLE=2 // when to display linked headlines - EWIKI_LIST_LIMIT=20 // page lists and searches - EWIKI_CONTROL_LINE=1 // always have action links at bottom of page - EWIKI_ALLOW_HTML=0 // often leads to quirky pages - EWIKI_HTTP_HEADERS=0 // send search engine and user-friendly HTTP headers - EWIKI_NO_CACHE=1 // prevent any caching of pages - EWIKI_AUTO_EDIT=1 // immediately display edit screen if page doesn't exist - EWIKI_EDIT_REDIRECT=1 // quick redirection after edit+save prevents back button problems - EWIKI_CASE_INSENSITIVE=1 // c-i WikiLinks are often more user-friendly - EWIKI_HIT_COUNTING=1 // count visitors for each page - EWIKI_RESOLVE_DNS=1 // disable for faster saving --off-config: - EWIKI_SCRIPT_URL= // absolute URL to wiki wrapper -note: - This file serves as link to the core script. - Don't care. -hooks: database, edit_preview, render, init, init, handler, handler, view_append, view_final, page_final, page_final, edit_form_final, format_block, format_block, format_block, format_block, format_block, page, page, page, page, page, page, action, action_always, action, action, page, action -funcs: ewiki_enlarge, ewiki_page, gettext, ewiki_http_headers, ewiki_etag, ewiki_page_css_container, ewiki_split_title, ewiki_add_title, ewiki_make_title, ewiki_page_view, ewiki_id, ewiki_script, ewiki_script_binary, ewiki_script_url, ewiki_page_links, ewiki_get_backlinks, ewiki_get_links, ewiki_list_pages, ewiki_page_index, ewiki_page_ordered_list, ewiki_page_newest, ewiki_page_updates, ewiki_page_hits, ewiki_page_versions, ewiki_page_search, ewiki_page_info, ewiki_chunked_page, ewiki_page_edit, ewiki_data_update, ewiki_new_data, ewiki_page_edit_form, ewiki_page_edit_form_final_imgupload, ewiki_page_edit_preview, ewiki_control_links, ewiki_control_links_list, ewiki_format, ewiki_format_close_para, ewiki_format_close_tags, ewiki_format_pre, ewiki_format_html, ewiki_format_comment, ewiki_scan_wikiwords, ewiki_render_wiki_links, ewiki_merge_links, ewiki_link_regex_callback, ewiki_link_img, ewiki_stripentities, ewiki_interwiki, ewiki_intermap_walking, ewiki_link, ewiki_binary, ewiki_binary_save_image, ewiki_localization, ewiki_t, ewiki_lowercase, ewiki_log, ewiki_die, ewiki_array_hash, ewiki_in_array, ewiki_array, ewiki_author, ewiki_author_html, ewiki_auth, ewiki_auth_user, ewiki_form, ewiki_eventually_initialize, dbquery_result, ewiki_dbquery_result, ewiki_database, ewiki_database_mysql diff --git a/mods/wiki/plugins/db/any.meta b/mods/wiki/plugins/db/any.meta deleted file mode 100644 index 223562011..000000000 --- a/mods/wiki/plugins/db/any.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: database -hooks: database -type: database -config: - EWIKI_DB_UTF8=0 // convert from/to UTF-8 for your database (PG) - EWIKI_DB_BIN64=0 // cipher any _BINARY entry (PG) -title: anydb -description: provides a SQL database abstraction layer for PostgreSQL and others -priority: auto diff --git a/mods/wiki/plugins/db/any.php b/mods/wiki/plugins/db/any.php deleted file mode 100644 index 1241312f1..000000000 --- a/mods/wiki/plugins/db/any.php +++ /dev/null @@ -1,480 +0,0 @@ -UTF8_ENCODE($id); - $id = anydb_escape_string($id); - if ($version) { - $AND_VERSION = "AND (version=$version)"; - } - $result = anydb_query(" - SELECT * FROM $this->table - WHERE (pagename='$id') $AND_VERSION - ORDER BY version DESC LIMIT 1 - "); - if ($result && ($r = anydb_fetch_array($result, "_ASSOC_ONLY=1"))) { - $r["id"] = $r["pagename"]; - unset($r["pagename"]); - } - if (EWIKI_DB_UTF8) $this->UTF8_DECODE($r); - if (EWIKI_DB_BIN64) $this->BIN64_DECODE($r); - return($r); - } - - - - function WRITE($hash, $overwrite=0) { - if (EWIKI_DB_BIN64) $this->BIN64_ENCODE($hash); - if (EWIKI_DB_UTF8) $this->UTF8_ENCODE($hash); - - #-- overwrite - $id = anydb_escape_string($hash["id"]); - $ver = $hash["version"]; - $current = "FROM $this->table WHERE (pagename='$id') AND (version=$ver)"; - if (($r = anydb_query("SELECT flags $current")) - and anydb_fetch_array($r)) { - if ($overwrite) { - anydb_query("DELETE $current"); - } else { - return; - } - } - - #-- build INSERT command - $hash["pagename"] = $hash["id"]; - unset($hash["id"]); - $sql1 = $sql2 = ""; - foreach ($hash as $index => $value) { - if (is_int($index)) { - continue; - } - $a = ($sql1 ? ', ' : ''); - $sql1 .= $a . $index; - $sql2 .= $a . "'" . anydb_escape_string($value) . "'"; - } - - $result = anydb_query( - "INSERT INTO $this->table ($sql1) VALUES ($sql2)" - ); - return($result ?1:0); - } - - - function HIT($id) { - if (EWIKI_DB_UTF8) $this->UTF8_ENCODE($id); - $id = anydb_escape_string($id); - anydb_query("UPDATE $this->table SET hits=(hits+1) WHERE pagename='$id'"); - } - - - function FIND($list) { - if (EWIKI_DB_UTF8) $this->UTF8_ENCODE($list); - $where = array(); - foreach ($list as $id) { - if (strlen($id)) { - $r[$id] = 0; - $where[] = "(pagename='".anydb_escape_string($id)."')"; - } - } - $where = implode(" OR ", $where); - if (strlen($where)) { $where = "WHERE $where"; } - $result = anydb_query( - "SELECT pagename AS id, meta, flags FROM $this->table $where" - ); - $r = array(); - while ($result && ($row = anydb_fetch_array($result))) { - $id = EWIKI_DB_UTF8 ? utf8_decode($row[0]) : $row[0]; - if ($row["meta"]) { - $r[$id] = $row["meta"]; - $r[$id]["flags"] = $row["flags"]; - } else { - $r[$id] = $row["flags"]; - } - } - if (EWIKI_DB_UTF8) $this->UTF8_DECODE($r); - return($r); - } - - - function GETALL($fields, $mask=0, $filter=0) { - $result = anydb_query("SELECT pagename AS id, flags, version, ". - implode(", ", $fields) . - " FROM $this->table " . - " ORDER BY id, version DESC" - ); - return $this->AS_DBQUERY_RESULT($result, $fields); - } - - - function AS_DBQUERY_RESULT(&$result, $fields) { - $r = new ewiki_dbquery_result($fields); - $last = ""; - if ($result) while ($row = anydb_fetch_array($result)) { - if (EWIKI_DB_UTF8) $this->UTF8_DECODE($row); - $drop = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"]; - if (($last != $drop) && ($last = $drop)) { - if (EWIKI_DB_UTF8) $this->UTF8_DECODE($row); - if (EWIKI_DB_BIN64) $this->BIN64_DECODE($row); - $r->add($row); - } - } - return($r); - } - - - function SEARCH($field, $content, $ci="i", $regex=0, $mask=0, $filter=0) { - global $anydb_type; - if (EWIKI_DB_UTF8) $this->UTF8_ENCODE($content); - // if (EWIKI_DB_BIN64 && ($field=="content") && ($flags&EWIKI_DB_F_BINARY)) $this->BIN64_ENCODE($content); - if ($field != "id") { - $sqlfield = ", $field"; - } - if ($regex) { - if ($GLOBALS["anydb_type"] == ANYDB_MY) { - $regex = "REGEXP"; - } else { - $regex = ($ci ? "~": "~*"); - } - $WHERE = "$field $regex '$content'"; - } - elseif ($ci) { - $content = strtolower($content); - if ($anydb_type == ANYDB_PG && $field == 'id') - $WHERE = "POSITION('$content' IN LOWER(pagename)) > 0"; - else - $WHERE = "POSITION('$content' IN LOWER($field)) > 0"; - } - else { - $WHERE="POSITION('$content' IN $field) > 0"; - } - $content = anydb_escape_string($content); - $result = anydb_query(" - SELECT pagename AS id, version, flags $sqlfield - FROM $this->table - WHERE ($WHERE) - ORDER BY id, version DESC - "); - return $this->AS_DBQUERY_RESULT($result, array($field, "version", "flags")); - } - - - function DELETE($id, $version) { - if (EWIKI_DB_UTF8) $this->UTF8_ENCODE($id); - $id = anydb_escape_string($id); - anydb_query("DELETE FROM $this->table WHERE pagename='$id' AND version=$version"); - } - - - function INIT() { - anydb_query("CREATE TABLE $this->table - ( pagename VARCHAR(160) NOT NULL, - version INTEGER DEFAULT 0 NOT NULL, - flags INTEGER DEFAULT 0, - content TEXT DEFAULT '', - refs TEXT DEFAULT '', - meta TEXT DEFAULT '', - author VARCHAR(100) DEFAULT 'ewiki', - created INTEGER DEFAULT ".time().", - lastmodified INTEGER DEFAULT 0, - hits INTEGER DEFAULT 0 - ) "); - anydb_query(" - ALTER TABLE ONLY $this->table - ADD CONSTRAINT internal_id PRIMARY KEY (pagename, version); - "); - } - - - #-- for charset-aware databases - function UTF8_ENCODE(&$a) { - if (is_array($a)) foreach ($a as $i=>$v) { - $a[$i] = is_array($v) ? $this->UTF8_ENCODE($v) : utf8_encode($v); - } - else { - $a = utf8_encode($a); - } - } - function UTF8_DECODE(&$a) { - if (is_array($a)) foreach ($a as $i=>$v) { - $a[$i] = is_array($v) ? $this->UTF8_DECODE($v) : utf8_decode($v); - } - else { - $a = utf8_decode($a); - } - } - - - #-- only engages if the EWIKI_DB_F_BINARY flag is set - function BIN64_ENCODE(&$a) { - if (!is_array($a)) { - $a = base64_encode($a); - } - elseif ($a["flags"] & EWIKI_DB_F_BINARY) { - $a["content"] = base64_encode($a["content"]); - } - } - function BIN64_DECODE(&$a) { - if (isset($a["content"]) && ($a["flags"] & EWIKI_DB_F_BINARY)) { - $a["content"] = base64_decode($a["content"]); - } - } - - -} - - - - - - - -#---------------------------------------------------------------------------- - - - -if (!function_exists("anydb_connect")) { -############################################################################# -### ### -### anydb access wrapper wrapper ### -### ### -############################################################################# - - -define("ANYDB_PEAR", 21); -define("ANYDB_ADO", 22); -define("ANYDB_DBX", 23); -define("ANYDB_PG", 51); // Postgres -define("ANYDB_MY", 52); // MySQL3.x -define("ANYDB_LI", 53); // SQLite -define("ANYDB_MI", 54); // MySQLi/4 - - -function anydb_connect($host="localhost", $user="", $pw="", $dbname="test", $dbtype="mysql") { - global $anydb_handle; - class_exists("DB") - and ($db = DB::connect("$dbtype://$user:$pw@$host/$dbname")) - and (is_a($db, "db_common")) - and ($db->setFetchMode(DB_FETCHMODE_ASSOC) or true) - or function_exists("newadoconnection") - and ($db = NewAdoConnection($dbtype)) - and ($db->connect($host, $user, $pw, $dbname)) - and ($db->setFetchMode(ADODB_FETCH_ASSOC) or true) - or ($dbtype[0]=="p") and function_exists("pg_connect") - and ($db = pg_connect("dbname=$dbname user=$user password=$pw")) - or function_exists("mysql_connect") - and ($db = mysql_connect($host, $user, $pw)) - and (mysql_query("USE $dbname")) - or function_exists("dbx_connect") - and ($db = dbx_connect($dbtype, $host, $dbname, $user, $pw)) - or ($db = false); - - if ($anydb_handle = $db) { - $charset = EWIKI_DB_UTF8 ? "UTF8" : "ISO-8859-1"; - @anydb_query("SET NAMES '$charset'"); #-- not all databases support this - } - return($db); -} - - -function anydb_handle($db=NULL) { - global $anydb_handle, $anydb_type; - if (!empty($db)) { - $anydb_handle = & $db; - $anydb_type = anydb_type($anydb_handle); - } - return($anydb_handle); -} - - -function anydb_type(&$obj) { - if (is_object($obj)) { - if (is_a($obj, "db_common") || is_a($obj, "db_result")) { - return(ANYDB_PEAR); - } - elseif (is_a($obj, "adoconnection") || is_a($obj, "adorecordset")) { - return(ANYDB_ADO); - } - elseif (is_a($obj, "stdclass")) { - return(ANYDB_DBX); - } - } - elseif (is_resource($obj) && ($type = strtok(get_resource_type($obj), " "))) { - if ($type == "pgsql") { - return(ANYDB_PG); - } - elseif ($type == "mysql") { - return(ANYDB_MY); - } - } -} - - -function anydb_query($sql, $db="") { - global $anydb_type; - $db = anydb_handle($db); - $res = false; - if ($anydb_type == ANYDB_PEAR) { - $res = $db->query($sql); - if (DB::isError($res)) { $res = false; } - } - elseif ($anydb_type == ANYDB_ADO) { - $res = $db->Execute($sql); - } - elseif ($anydb_type == ANYDB_DBX) { - $res = dbx_query($db, $sql, DBX_RESULT_ASSOC); - } - elseif ($anydb_type == ANYDB_PG) { - $res = pg_query($db, $sql); - } - elseif ($anydb_type == ANYDB_MY) { - $res = mysql_query($sql, $db, MYSQL_ASSOC); - } - return($res); -} - - - -function anydb_fetch_array(&$res, $assoc_only=0) { - global $anydb_type; - $anydb_type = anydb_type($res); - $r = false; - if ($anydb_type == ANYDB_PEAR) { - $r = $res->fetchRow(DB_FETCHMODE_ASSOC); - if (is_object($r)) { - $r = false; - } - } - elseif ($anydb_type == ANYDB_ADO) { - $r = $res->FetchRow(); - # $r = obj || false - } - elseif ($anydb_type == ANYDB_DBX) { - $r = array_shift($res->data); - ## $r == obj || 1 || false - } - elseif ($anydb_type == ANYDB_PG) { - $r = pg_fetch_assoc($res); - } - elseif ($anydb_type == ANYDB_MY) { - $r = mysql_fetch_array($res, $db); - } - #-- make numeric indicies, if wanted - $n = 0; - if (!$assoc_only && is_array($r) && count($r)) { - foreach ($r as $i=>$d) { - if (!is_int($i)) { - $r[$n++] = &$r[$i]; - } - } - } - return($r); -} - - - -function anydb_escape_string($s, $db="") { - $db = anydb_handle($db); - $type = anydb_type($db); - if ($type == ANYDB_PEAR) { - $s = $db->quoteString($s); - } - elseif ($type == ANYDB_ADO) { - $s = $db->qStr($s); - if ($s[0] = "'") { - $s = substr($s, 1, strlen($s) - 2); - } - } - elseif ($type == ANYDB_DBX) { - $s = dbx_escape_string($db, (string)$s); - } - elseif ($type == ANYDB_PG) { - $s = pg_escape_string((string)$s); - } - elseif ($type == ANYDB_MY) { - $s = mysql_escape_string((string)$s); - } - else { - $s = addslashes($s); - } - return($s); -} - - -############################################################################# -### ### -############################################################################# -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/db/binary_store.meta b/mods/wiki/plugins/db/binary_store.meta deleted file mode 100644 index d87b56e90..000000000 --- a/mods/wiki/plugins/db/binary_store.meta +++ /dev/null @@ -1,12 +0,0 @@ -api: ewiki -category: database -hooks: binary_store, binary_get -type: database -config: - EWIKI_DB_STORE_DIRECTORY="/tmp" // where to save binary files - EWIKI_DB_STORE_MINSIZE=0 // send smaller files into db - EWIKI_DB_STORE_MAXSIZE=32 <<20 // 32MB max per file (but - EWIKI_DB_STORE_URL="http://example.com/wiki/files/store/" -title: binary_store -description: intercepts binary handling and stores too large blocks into static files -priority: auto diff --git a/mods/wiki/plugins/db/binary_store.php b/mods/wiki/plugins/db/binary_store.php deleted file mode 100644 index 3e0024be5..000000000 --- a/mods/wiki/plugins/db/binary_store.php +++ /dev/null @@ -1,88 +0,0 @@ -= EWIKI_DB_STORE_MINSIZE) && ($meta["size"] <= EWIKI_DB_STORE_MAXSIZE)) { - - #-- generate internal://md5sum - if (empty($id)) { - $md5sum = md5_file($filename); - $id = EWIKI_IDF_INTERNAL . $md5sum . ".$ext"; - ewiki_log("generated md5sum '$md5sum' from file content"); - } - - #-- move file to dest. location - $dbfname = EWIKI_DB_STORE_DIRECTORY."/".rawurlencode($id); - if (@rename($filename, $dbfname) || copy($filename, $dbfname) && unlink($filename)) { - $filename = ""; - $meta["binary_store"] = 1; - return(true); - } - else { - ewiki_log("file store error with '$dbfname'", 0); - } - } - - return(false); -} - - -#-- download -function ewiki_binary_store_get_file($id, &$meta) { - - if (@$meta["binary_store"]) { - - #-- check for file - $dbfname = EWIKI_DB_STORE_DIRECTORY."/".rawurlencode($id); - if (file_exists($dbfname)) { - readfile($dbfname); - return(true); - } - else { - return(false); - } - } - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/db/dba.meta b/mods/wiki/plugins/db/dba.meta deleted file mode 100644 index 5b7a492df..000000000 --- a/mods/wiki/plugins/db/dba.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: database -hooks: database -type: database -config: - EWIKI_DBA="/tmp/mywiki.flatfile" // or use extension .db2 - EWIKI_DBFILES_GZLEVEL=0 // if you want .inifile format (this is not binary safe - also disable image upload then!) -title: dba -description: utilizes PHPs "dba" extension as database backend -priority: auto diff --git a/mods/wiki/plugins/db/dba.php b/mods/wiki/plugins/db/dba.php deleted file mode 100644 index 03b1680ef..000000000 --- a/mods/wiki/plugins/db/dba.php +++ /dev/null @@ -1,212 +0,0 @@ -handle = ewiki_database_dba::CONNECT(EWIKI_DBA); - } - - - - function GET($id, $version=false) { - if (!$version && !($version = $this->LASTVER($id))) { - return; - } - if ($r = dba_fetch("$id.$version", $this->handle)) { - if ($uu = gzuncompress($r)) { - $r = $uu; - unset($uu); - } - if ($r = unserialize($r)) { - return($r); - } - } - } - - - function WRITE($hash, $overwrite=0) { - $key = $hash["id"].".".$hash["version"]; - $ex = dba_exists($key, $this->handle); - if (!$overwrite && $ex) { - return; - } - $hash = serialize($hash); - if ($this->gz) { - $hash = gzcompress($hash, $this->gz); - } - if ($ex) { - $r = dba_replace($key, $hash, $this->handle); - } else { - $r = dba_insert($key, $hash, $this->handle); - } - return($r); - } - - - function HIT($id) { - $key = "$id.1"; - if ($r = unserialize(gzuncompress(dba_fetch($key, $this->handle)))) { - $r["hits"] += 1; - dba_replace($key, gzcompress(serialize($r), $this->gz), $this->handle); - } - } - - - function FIND($list) { - $r = array(); - foreach ($list as $id) { - if (dba_exists("$id.1", $this->handle) || $this->LASTVER($id)) { - $r[$id] = 1; - if (EWIKI_DBFF_ACCURATE) { - $row = $this->GET($id); - if ($row["meta"]) { - $r[$id] = $row["meta"]; - $r[$id]["flags"] = $row["flags"]; - } else { - $r[$id] = $row["flags"]; - } - } - } - } - return($r); - } - - - function GETALL($fields, $mask=0, $filter=0) { - $r = new ewiki_dbquery_result($fields); - foreach ($this->ALLFILES() as $id) { - $row = $this->GET($id); - $r->add($row); - } - return($r); - } - - - function SEARCH($field, $content, $ci="i", $regex=0, $mask=0, $filter=0) { - if ($ci && !$regex) { - $content = strtolower($content); - } - $r = new ewiki_dbquery_result(array($field)); - foreach ($this->ALLFILES() as $id) { - $page = ewiki_db::GET($id); - if ($regex) { - $check = preg_match("\007$content\007$ci", $page[$field]); - } - elseif ($ci) { - $check = strpos(strtolower($page[$field]), $content)!==false; - } - else { - $check = strpos($page[$field], $content)!==false; - } - if ($check) { - $r->add($page); - } - } - return($r); - } - - - function DELETE($id, $version) { - dba_delete("$id.$version", $this->handle); - } - - - function INIT() { - if (!$this->handle) { - die("dba database not writable!\n"); - } - } - - -//@FIXME: uh, oh, bad -// but everything else would be VERY VERY slow - function LASTVER($id) { - $n = 1; - while (dba_exists("$id.$n", $this->handle)) { - $n++; - } - return(--$n); - } - - - function ALLFILES() { - $id = dba_firstkey($this->handle); - while ($id != false) { - $p = strrpos($id, "."); - $id = substr($id, 0, $p); - $r[$id] = $id; - $id = dba_nextkey($this->handle); - } - $r = array_values($r); - return($r); - } - - - #-- open dba connection - function CONNECT($dba_file) { - $avail = array_reverse(dba_handlers()); - $try = substr($dba_file, strrpos($dba_file, ".") + 1); - $try = array_merge(array($try, "gdbm", "db7", "db3", "db2", "flatfile", "db6", "db4", "db5", "ndbm", "dbm"), $avail); - $handle = false; - foreach ($try as $dba_handler) { - if (in_array($dba_handler, $avail)) { - foreach (array("w", "c", "n") as $mode) { - if ($handle = dba_open($dba_file, $mode, $dba_handler)) { -#echo "USING($dba_handler), "; - if ($mode != "w") { - dba_close($handle); - $handle = dba_open($dba_file, "w", $dba_handler); - } - break 2; - } - } - } - } - return($handle); - } - - -} // end of class - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/db/dzf2.meta b/mods/wiki/plugins/db/dzf2.meta deleted file mode 100644 index 43bd23b31..000000000 --- a/mods/wiki/plugins/db/dzf2.meta +++ /dev/null @@ -1,12 +0,0 @@ -api: ewiki -category: database -hooks: database -type: database -config: - EWIKI_DBFILES_DIRECTORY="pages/" // like with plugins/db/flat_files - EWIKI_DBFF_ACCURATE=1 // makes FIND call return image sizes - DZF2_HIT_COUNTING=1 // enables hit-counting - EWIKI_CASE_INSENSITIVE=true // this is hard-coded in here, so don't disable or everything would break -title: dzf2 -description: faster file database with deep directory structure, compression, caching, and it's case-insensitive like the SQL backends -priority: auto diff --git a/mods/wiki/plugins/db/dzf2.php b/mods/wiki/plugins/db/dzf2.php deleted file mode 100644 index b30daf02f..000000000 --- a/mods/wiki/plugins/db/dzf2.php +++ /dev/null @@ -1,311 +0,0 @@ -LASTVER($id))) { - return; - } - #-- read file - $dbfile = $this->FN("$id.$version"); - $lock = fopen($dbfile, "rb"); - flock($lock, LOCK_SH); - if ($f = @gzopen($dbfile, "rb")) { - $r = unserialize(gzread($f, 1<<21)); - gzclose($f); - } - flock($lock, LOCK_UN); - fclose($lock); - if ($r && DZF2_HIT_COUNTING) { - if ($f = @fopen($this->FN("$id.hits"), "rb")) { - $r["hits"] = trim(fread($f, 10)); - fclose($f); - } - } - return($r); - } - - - function WRITE($hash, $overwrite=0) { - $id = $hash["id"]; - $version = $hash["version"]; - $dbfile = $this->FN("$id.$version"); - if (!$overwrite && file_exists($dbfile)) { - return; - } - #-- read-lock - if (file_exists($dbfile)) { - $lock = fopen($dbfile, "rb"); - flock($lock, LOCK_EX); - } - #-- open file for writing, secondary lock - if ($f = gzopen($dbfile, "wb".$this->gz)) { - if (!lock) { - flock($f, LOCK_EX); - } - $r = gzwrite($f, serialize($hash)); - gzclose($f); - $this->SETVER($id, $version); - $this->CACHE_ADD($id, $version); - return(1); - } - #-- dispose lock - if ($lock) { - flock($lock, LOCK_UN); - fclose($lock); - } - return(0); - } - - - function FIND($list) { - $r = array(); - foreach ($list as $id) { - $fn = $this->FN($id); - if (file_exists($fn)) { - $r[$id] = 1; - if (EWIKI_DBFF_ACCURATE && (strpos($id, ":") || strpos($id, "."))) { - $uu = $this->GET($fn); - if ($uu["meta"]) { - $r[$id] = $uu["meta"]; - $r[$id]["flags"] = $uu["flags"]; - } else { - $r[$id] = $uu["flags"]; - } - } - } - } - return($r); - } - - - function GETALL($fields, $mask=0, $filter=0) { - $r = new ewiki_dbquery_result($fields); - $r->entries = $this->ALL(); - return($r); - } - - - function SEARCH($field, $content, $ci="i", $regex=0, $mask=0, $filter=0) { - if ($ci && !$regex) { - $content = strtolower($content); - } - $r = new ewiki_dbquery_result($args); - - #-- fast title search - if (!$mask && ($field == "id")) { - foreach ($this->ALL() as $id) { - if ($regex && preg_match("\007$content\007$ci", $id) - or $ci && strpos(strtolower($id), $content) - or !$ci && strpos($id, $content) ) - { - $this->entries[] = $id; - } - } - } - #-- must load all files from disk - else { - foreach ($this->ALL() as $id) { - $row = ewiki_database_dzf2::GET($id); - if ($mask && ($filter != ($row["flags"] & $mask))) { - continue; - } - if ($regex && preg_match("\007$content\007$ci", $row[$field]) - or $ci && strpos(strtolower($row[$field]), $content) - or !$ci && strpos($row[$field], $content) ) - { - $r->add($row); - } - } - } - return($r); - } - - - function DELETE($id, $version) { - $fn = $this->FN($id); - unlink("$fn.$version"); - if (!$this->LASTVER($id)) { - @unlink("$fn"); - @unlink("$fn.hits"); - $this->ALL("_PURGE"); - } - } - - - function INIT() { - if (!is_writeable($this->dir) || !is_dir($this->dir)) { - mkdir($this->dir) - or die("\nERROR in ewiki/db/dzf2: 'database' directory '$this->dir' is not world-writable (do the chmod 777 thing)!\n"); - } - for ($c=97; $c<=122; $c++) { @mkdir($this->dir.'/'.chr($c)); } - for ($c=48; $c<=57; $c++) { @mkdir($this->dir.'/'.chr($c)); } - @mkdir($this->dir."/@"); - } - - - - #---------------------------------------------------------- internal --- - - function FN($id) { - $id = ewiki_lowercase($id); - $c0 = $id[0]; - if (($c0>="a") && ($c0<="z") || ($c0>="0") && ($c0<="9")) { - $letter = $c0; - } - else { - $letter = "@"; - } - return( $this->dir . "/$letter/" . rawurlencode($id) ); - } - - function LASTVER($id, $count_through=0) { - $ver = NULL; - $fn = $this->FN($id); - if (file_exists($fn) && ($f = fopen($fn, "rb"))) { - $ver = 0 + trim(fgets($f, 10)); - fclose($f); - } - return($ver); - } - - function SETVER($id, $version) { - $fn = $this->FN($id); - if ($f = fopen($fn, "wb")) { - fwrite($f, "$version", 10); - fclose($f); - } - else { - echo "\nERROR in ewiki/db/dzf2: could not write version cache file for '$id'\n"; - } - } - - // reads page list cache file - function ALL($rewrite=0) { - $CACHE = $this->dir."/CACHE"; - - #-- generate cache - if (!file_exists($CACHE) || $rewrite) { - $r = $this->ALL_WALK(); - if ($f = fopen($fn, "wb")) { - flock($f, LOCK_EX); - fwrite($f, "00000027_ewiki_DZF2_database_CACHE_FILE (do not edit!)\n" - . implode("\n", $r) . "\n"); - flock($f, LOCK_UN); - } - } - #-- read - elseif ($f = fopen($CACHE, "r")) { - flock($f, LOCK_SH); - $r = explode("\n", fread($f, 1<<21)); - flock($f, LOCK_UN); - unset($r[0]); // header - array_pop($r); - } - $f and fclose($f); - - return($r); - } - - // adds one entry to the cache file - function CACHE_ADD($id, $version) { - $CACHE = $this->dir."/CACHE"; - if (($version >= 1) && ($f = fopen($CACHE, "ab"))) { - flock($f, LOCK_EX); - fwrite($f, ewiki_lowercase($id) . "\n"); - flock($f, LOCK_UN); - fclose($f); - } - } - - // scans through all dirs to detect existing pages - function ALL_WALK() { - $r = array(); - $main = opendir($this->dir); - while ($sub = readdir($main)) { - if ((strlen($sub)==1) && ($sub[0]!=".") && is_dir($this->dir."/$sub")) { - $sub = $this->dir . "/" . $sub; - $dh = opendir($sub); - while ($fn = readdir($dh)) { - if (($fn[0] != ".") && (strpos($fn, ".hits") != strlen($fn)-5)) { - $fs = filesize($sub ."/". $fn); - if ($fs && ($fs < 10)) { - $r[] = rawurldecode($fn); - } } } - } - } - return($r); - } - - - function HIT($id, $add=+1) - { - if (!DZF2_HIT_COUNTING) { - return; - } - $dbfile = $this->FN($id) . ".hits"; - - #-- open, read - if ($fr = @fopen($dbfile, "r")) { - flock($fr, LOCK_SH); - $r = trim(fgets($fr, 10)); - } - else { - $r = 0; - } - #-- update - if ($add) { - if ($fr) { - flock($fr, LOCK_EX); - } - $r += $add; - $fw = fopen($dbfile, "w"); - fwrite($fw, "$r"); - fclose($fw); - } - #-- close, return value - if ($fr) { - flock($fr, LOCK_UN); - fclose($fr); - } - return($r); - } - - -} // end of class - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/db/ext_multi.meta b/mods/wiki/plugins/db/ext_multi.meta deleted file mode 100644 index 5adbf2d34..000000000 --- a/mods/wiki/plugins/db/ext_multi.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: database -hooks: database -type: database -config: - EWIKI_MULTIDB_GUESS=0 // which database to use for WRITE calls, if disabled this will always fallback to the first backend -title: ext_multi -description: allows to join multiple database backends -priority: never diff --git a/mods/wiki/plugins/db/ext_multi.php b/mods/wiki/plugins/db/ext_multi.php deleted file mode 100644 index 0d6cf0b24..000000000 --- a/mods/wiki/plugins/db/ext_multi.php +++ /dev/null @@ -1,109 +0,0 @@ -all[] = & new ewiki_database_anydb(); - $ewiki_db->all[] = & new ewiki_database_dzf2(); - !> - - If you only load the plugins, the order may not be preserved, so that - new page entries go to the wrong backend (typically the first was the - active/main database). -#this should be configureable! - - If you also want subwiki support, then you should load that plugin - after _this_ one. -#both features could be merged - -*/ - -define("EWIKI_MULTIDB_GUESS", 0); // which database to use for WRITE calls, if disabled this will always fallback to the first backend - - -#-- registration -$ewiki_plugins["database"][0] = "ewiki_database_multi"; - - -#-- backend wrapper -class ewiki_database_multi { - - var $all = array(); - - function ewiki_database_multi($auto=true) { - if ($auto) { - foreach (get_declared_classes() as $classname) { - if ((strpos($name, "ewiki_database_") === 0) && !strpos($name, "_multi")) { - $this->all = & new $classname; - } } } - } - - - function GET($id, $version=false) { - for ($i=0; $iall); $i++) { - $r = $this->all[$i]->GET($id, $version); - if ($r) { - $r["db"] = $i; - return $r; - } - } - } - - - function WRITE($hash, $overwrite=0) { - $i = $hash["db"]; - if (!$i) { - $i = 0; - } - return $this->all[$i]->WRITE($hash, $overwrite); - } - - - function HIT($id) { - } - - - function FIND($list) { - } - - - function GETALL($fields, $mask=0, $filter=0) { - } - - - function SEARCH($field, $content, $ci="i", $regex=0, $mask=0, $filter=0) { - } - - - function DELETE($id, $version) { - } - - - function INIT() { - for ($i=0; $iall); $i++) { - $this->all[$i]->INIT(); - } - } - - - function WHICH($id) { - - } - - -} // end of class - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/db/ext_subwiki.meta b/mods/wiki/plugins/db/ext_subwiki.meta deleted file mode 100644 index 1e85fd2a1..000000000 --- a/mods/wiki/plugins/db/ext_subwiki.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: database -hooks: init -type: intercept -config: - SUBWIKI_SEPARATOR=":" -title: ext_subwiki -description: fragments your database into multiple wikis without touching the backend (not recommended) -priority: never diff --git a/mods/wiki/plugins/db/ext_subwiki.php b/mods/wiki/plugins/db/ext_subwiki.php deleted file mode 100644 index c2470fee4..000000000 --- a/mods/wiki/plugins/db/ext_subwiki.php +++ /dev/null @@ -1,121 +0,0 @@ -db = & $backend; - } - - - function GET($id, $version=false) { - global $subwiki; - $id = $subwiki . $this->dot . $id; - $r = $this->db->GET($id, $version); - if ($r) { - $r["id"] = substr($r["id"], strlen($subwiki) + 1); - } - return($r); - } - - - function HIT($id) { - $id = $GLOBALS["subwiki"] . $this->dot . $id; - return $this->db->HIT($id); - } - - - function DELETE($id, $version=false) { - $id = $GLOBALS["subwiki"] . $this->dot . $id; - return $this->db->DELETE($id, $version); - } - - - function WRITE($hash, $overburn=0) { - $hash["id"] = $GLOBALS["subwiki"] . $this->dot . $hash["id"]; - return $this->db->WRITE($hash, $overburn); - } - - - function INIT() { - $this->db->INIT(); - } - - - function FIND($list) { - global $subwiki; - if ($subwiki) { - $n = strlen($subwiki); - foreach ($list as $i=>$s) { - $list[$i] = $subwiki . $dot . $s; - } - $e = $this->db->FIND($list); - $r = array(); - foreach ($e as $s=>$x) { - $r[substr($s, $n+1)] = $x; - } - return($r); - } - return $this->db->FIND($list); - } - - - function SEARCH($field, $content, $ci=1, $regex=0, $mask=0, $filter=0) { - - $r = $dbf($func, $args, $f1, $f2); - foreach ($r->entries as $i=>$d) { - if (is_array($d) && (0==strncmp($d["id"], $subwiki, $n))) { - $r->entries[$i]["id"] = substr($d["id"], $n+1); - } - elseif (is_string($d) && (0==strncmp($d, $subwiki, $n))) { - $r->entries[$i] = substr($d, $n+1); - } - else { - unset($i); - } - } - } - - function GETALL($fields, $mask=0, $filter=0) { - } - - - -} // end of class - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/db/fast_files.meta b/mods/wiki/plugins/db/fast_files.meta deleted file mode 100644 index 26a612a75..000000000 --- a/mods/wiki/plugins/db/fast_files.meta +++ /dev/null @@ -1,5 +0,0 @@ -depends: flat_files -priority: deprecated -type: R -title: FastFiles -description: (wrapper around real FlatFiles script) diff --git a/mods/wiki/plugins/db/fast_files.php b/mods/wiki/plugins/db/fast_files.php deleted file mode 100644 index 1231e6587..000000000 --- a/mods/wiki/plugins/db/fast_files.php +++ /dev/null @@ -1,9 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/db/flat_files.meta b/mods/wiki/plugins/db/flat_files.meta deleted file mode 100644 index a96bae4ee..000000000 --- a/mods/wiki/plugins/db/flat_files.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: database -hooks: database -type: database -config: - EWIKI_DB_FAST_FILES=0 - EWIKI_DBFF_ACCURATE=0 -title: FlatFiles -description: this backend uses RFC822-style text files for storing pages, binary-safe, but page names are never case-insensitive on Unix -priority: auto diff --git a/mods/wiki/plugins/db/flat_files.php b/mods/wiki/plugins/db/flat_files.php deleted file mode 100644 index cf0056b1f..000000000 --- a/mods/wiki/plugins/db/flat_files.php +++ /dev/null @@ -1,264 +0,0 @@ -"); - - -#-- choose flat file format -define("EWIKI_DB_FAST_FILES", 0); -define("EWIKI_DBFF_ACCURATE", 0); - - -#-- plugin registration -$ewiki_plugins["database"][0] = "ewiki_database_files"; - - -#-- backend -class ewiki_database_files { - - function ewiki_database_files() { - } - - - function GET($id, $version=false) { - - if (!$version && !($version = $this->LASTVER($id))) { - return; - } - #-- read file - $dbfile = $this->FN("$id.$version"); - if ($f = @gzopen($dbfile, "rb")) { - $dat = gzread($f, 1<<21); - gzclose($f); - } - - #-- decode - if ($dat && (substr($dat, 0, 2) == "a:")) { - $r = unserialize($dat); - } - if (empty($r)) { - $r = array(); - $p = strpos($dat, "\012\015\012"); - $p2 = strpos($dat, "\012\012"); - if ((!$p2) || ($p) && ($p < $p2)) { - $p = $p + 3; - } - else { - $p = $p2 + 2; - } - $r["content"] = substr($dat, $p); - $dat = substr($dat, 0, $p); - - foreach (explode("\012", $dat) as $h) { - if ($h = trim($h)) { - $r[trim(strtok($h, ":"))] = str_replace(EWIKI_DBFILES_NLR, "\n", trim(strtok("\000"))); - } - } - } - return($r); - } - - - function WRITE($hash, $overwrite=0) { - - #-- which file - $dbfile = $this->FN($hash["id"].".".$hash["version"]); - if (!$overwrite && file_exists($dbfile)) { - return(0); - } - - #-- write - if (EWIKI_DB_FAST_FILES) { - $val = serialize($hash); - if (($f = gzopen($dbfile, "wb".EWIKI_DBFILES_GZLEVEL))) { - gzwrite($f, $val); - gzclose($f); - } - return(1); - } - else { - $headers = ""; - foreach ($hash as $hn=>$hv) if ($hn != "content") { - $headers .= $hn . ": " . str_replace("\n", EWIKI_DBFILES_NLR, $hv) . "\015\012"; - } - if ($f = fopen($dbfile, "wb")) { - flock($f, LOCK_EX); - fputs($f, $headers . "\015\012" . $hash["content"]); - flock($f, LOCK_UN); - fclose($f); - return(1); - } - } - } - - - function HIT($id) { - if (EWIKI_DB_FAST_FILES) { - $dbfile = $this->FN("$id.1"); - if ($f = gzopen($dbfile, "rb")) { - $r = unserialize(gzread($ff, 1<<21)); - gzclose($f); - if ($r) { - $r["hits"] += 1; - if ($f = gzopen($dbfile, "wb".EWIKI_DBFILES_GZLEVEL)) { - gzwrite($fp, serialize($r)); - gzclose($fp); - } } } } - } - - - function FIND($list) { - $existing = array_flip($this->ALLFILES()); - $r = array(); - foreach ($list as $id) { - $dbfile = $this->FN($id, 0); - $r[$id] = isset($existing[$dbfile]) ?1:0; - if (EWIKI_DBFF_ACCURATE && $r[$id] && strpos($id, "://")) { - $uu = $this->GET($id); - if ($uu["meta"]) { - $r[$id] = unserialize($uu["meta"]); - $r[$id]["flags"] = $uu["flags"]; - } else { - $r[$id] = $uu["flags"]; - } - } - } - return($r); - } - - - function GETALL($fields, $mask=0, $filter=0) { - $r = new ewiki_dbquery_result($fields); - foreach ($this->ALLFILES() as $id) { - $r->entries[] = $id; - } - return($r); - } - - - function SEARCH($field, $content, $ci="i", $regex=0, $mask=0, $filter=0) { - $r = new ewiki_dbquery_result(array($field)); - $strsearch = $ci ? "stristr" : "strpos"; - foreach ($this->ALLFILES() as $id) { - $row = $this->GET($id); - if ($mask && ($filter == $row["flags"] & $mask)) { - continue; - } - $match = - !$regex && ($strsearch($row[$field], $content)!==false) - || $regex && preg_match("\007$content\007$ci", $row[$field]); - if ($match) { - $r->add($row); - } - } - return($r); - } - - - function DELETE($id, $version) { - $fn = $this->FN("$id.$version"); - @unlink($fn); - } - - function INIT() { - if (!is_writeable(EWIKI_DBFILES_DIRECTORY) || !is_dir(EWIKI_DBFILES_DIRECTORY)) { - mkdir(EWIKI_DBFILES_DIRECTORY) - or die("db_flat_files: »database« directory '".EWIKI_DBFILES_DIRECTORY."' is not writeable!\n"); - } - } - - - - #-- db plugin internal ---------------------------------------------- - - function FN($id, $prepend_path=1) { - $fn = EWIKI_DBFILES_ENCODE ? urlencode($id) : strtr($id, '/:', '\\:'); - if ($prepend_path) { - $fn = EWIKI_DBFILES_DIRECTORY.DIRECTORY_SEPARATOR . $fn; - } - return($fn); - } - - - function ID($fn) { - $id = EWIKI_DBFILES_ENCODE ? urldecode($fn) : strtr($fn, '\\:', '/:'); - return($id); - } - - - function LASTVER($id) { - $find = $this->FN($id, 0); - $find_n = strlen($find); - $n = 0; - if ($find_n) { - $dh = opendir(EWIKI_DBFILES_DIRECTORY); - while ($fn = readdir($dh)) { - if ( (strpos($fn, $find) === 0) && //@FIXME: empty delimiter - ($dot = strrpos($fn, ".")) && ($dot == $find_n) && - ($uu = substr($fn, ++$dot)) && ($uu > $n) ) - { - $n = $uu; - } - } } - return($n); - } - - - function ALLFILES() { - $r = array(); - $dh = opendir(EWIKI_DBFILES_DIRECTORY); - $n = 0; - while ($fn = readdir($dh)) { - if (is_file(EWIKI_DBFILES_DIRECTORY . "/" . $fn)) { - $id = $this->ID($fn); - if (($dot = strrpos($id, ".")) && (substr($id, $dot+1) >= 1)) { - $file = substr($id, 0, $dot); - $r[] = $file; - } - if ($n++ > 1000) { - $n = 0; - $r = array_unique($r); - } - } - } - closedir($dh); - $r = array_unique($r); - return($r); - } - - -} // end of class ewiki_database_files - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/db/mysql.meta b/mods/wiki/plugins/db/mysql.meta deleted file mode 100644 index 4390b16b9..000000000 --- a/mods/wiki/plugins/db/mysql.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -type: virtual -category: database -priority: required -title: MySQL -description: built-in database backend -config: - EWIKI_DB_TABLE_NAME=ewiki // SQL database table diff --git a/mods/wiki/plugins/db/oldapi.meta b/mods/wiki/plugins/db/oldapi.meta deleted file mode 100644 index 4d5cb0f4b..000000000 --- a/mods/wiki/plugins/db/oldapi.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: database -title: old API -description: wrapper for old database backend API -priority: never -type: functions diff --git a/mods/wiki/plugins/db/oldapi.php b/mods/wiki/plugins/db/oldapi.php deleted file mode 100644 index 9b04e6823..000000000 --- a/mods/wiki/plugins/db/oldapi.php +++ /dev/null @@ -1,67 +0,0 @@ -pf = "old_db_function_name"; - - You can probably also use this file as template for converting your - database backend to the new scheme. -*/ - - -#-- enable it -if (!isset($ewiki_db) && isset($ewiki_plugins["database"])) { - $ewiki_db = new ewiki_database_compat($ewiki_plugins["database"][0]); -} - - -#-- compatibility wrapper -class ewiki_database_compat { - - var $pf; - - function ewiki_database_compat($pf) { - $this->pf = $pf; - } - - function GET($id, $version=false) { - return $this->pf("GET", array("id"=>$id, "version"=>$version)); - } - - function WRITE($data, $overwrite=0) { - $FUNC = $overwrite ? "OVERWRITE" : "WRITE"; - return $this->pf($FUNC, $data); - } - - function HIT($id) { - return $this->pf("HIT", $id); - } - - function FIND($list) { - return $this->pf("FIND", $list); - } - - function GETALL($fields) { - return $this->pf("GETALL", $fields); - } - - function SEARCH($field, $content, $ci=1, $regex=0, $mask=0, $filter=0) { - return $this->pf("SEARCH", array($field=>$content)); - } - - function DELETE($id, $version) { - return $this->pf("DELETE", array("id"=>$id, "version"=>$version)); - } - - function INIT() { - return $this->pf("INIT", array()); - } - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/db/phpwiki13.meta b/mods/wiki/plugins/db/phpwiki13.meta deleted file mode 100644 index a6349c913..000000000 --- a/mods/wiki/plugins/db/phpwiki13.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: database -hooks: database -type: database -config: - PHPWIKI13_WRITEACCESS=0 -title: phpwiki13 -description: can access PhpWiki 1.3.x MySQL databases -priority: never diff --git a/mods/wiki/plugins/db/phpwiki13.php b/mods/wiki/plugins/db/phpwiki13.php deleted file mode 100644 index f31b227e5..000000000 --- a/mods/wiki/plugins/db/phpwiki13.php +++ /dev/null @@ -1,260 +0,0 @@ - $row["pagename"], - "version" => $row["version"], - "content" => $row["content"], - "author" => $dec2["author"], - "lastmodified" => $row["mtime"], - "hits" => $row["hits"], - "flags" => EWIKI_DB_F_TEXT, - "created" => $created, - "refs" => "\n", - "meta" => $dec1 - ); - - #-- get flags - if ($dec1["locked"]=="yes") { - $r["flags"] |= EWIKI_DB_F_READONLY; - } - if (is_int($flags = $dec1["flags"])) { - $r["flags"] = $flags; - } - unset($r["meta"]["flags"]); - unset($r["meta"]["created"]); - unset($r["meta"]["locked"]); - // $r["meta"] = serialize($r["meta"]); // must be serialized() in inner ewiki_db:: layer - - #-- fetch $refs[] - $num_id = $row["id"]; - if ($result = mysql_query("SELECT p2.pagename FROM link - LEFT JOIN page p1 ON (link.linkfrom=p1.id) - LEFT JOIN page p2 ON (p2.id=link.linkto) - WHERE p1.id=$num_id")) - { - while ($row = mysql_fetch_array($result)) { - $r["refs"] .= $row["pagename"] . "\n"; - } - } - return($r); - } - - } - - - #-- better don't use this! - function WRITE($hash, $overwrite=0) { - if (!PHPWIKI13_WRITEACCESS) { - die("The plugins/db_phpwiki13 interface is meant for READ ONLY access to PhpWiki databases. To enable write access you first need to set the PHPWIKI13_WRITEACCESS configuration constant. But beware that this may make your database inconsistent and thus could prevent PhpWiki to reuse it afterwards.!
      \n"); - } - - #-- make all ewiki page vars available in local/func var scope - extract($hash); - - #-- get existing or new $num_id - $id = addslashes($id); - $num_id = $this->NUM_ID($id); - - #-- split data into parts - $meta = unserialize($meta); - ($markup = $meta["markup"]) or ($markup = 2); - unset($meta["markup"]); - $versiondata = array( - "markup" => $markup, - "author" => $author, - "author_id" => $author, - ); - $versiondata = addslashes(serialize($versiondata)); - - $pagedata = $meta; - $pagedata["created"] = $created; - $pagedata["flags"] = $flags; - if ($flags & EWIKI_DB_F_READONLY) { - $pagedata["locked"] = "yes"; - } - $pagedata = addslashes(serialize($pagedata)); - - #-- save content - $content = addslashes($content); - $result = - mysql_query("INSERT INTO version (id, version, mtime, minor_edit, content, versiondata) VALUES ($num_id, $version, $lastmodified, 0, '$content', '$versiondata')") - && - mysql_query("UPDATE recent SET latestversion=$version WHERE id=$num_id") - && - mysql_query("UPDATE page SET pagedata='$pagedata' WHERE id=$num_id") - && - mysql_query("REPLACE INTO nonempty (id) VALUES ($num_id)"); - if (!$result) { - return; - } - - #-- encode $refs[] into relational database - mysql_query("DELETE FROM link WHERE linkfrom=$num_id"); - $refs = explode("\n", trim($refs)); - foreach ($refs as $pagename) { - $pagename = addslashes($pagename); - $row = mysql_fetch_array(mysql_query("SELECT id FROM page WHERE pagename='$pagename'")); - if ($to = $row["id"]) { - mysql_query($sql="REPLACE INTO link (linkfrom, linkto) VALUES ($num_id, $to)"); - } - } - - return(true); - } - - - function NUM_ID($id) { - if (($result = mysql_query("SELECT id FROM page WHERE pagename='$id'")) - and ($row = mysql_fetch_array($result)) ) { - $num_id = $row["id"]; - } - else { - $result = mysql_query("SELECT id FROM page ORDER BY id DESC"); - $row = mysql_fetch_array($result); - if ($num_id = $row["id"]) { - $num_id++; - if (! ($result = mysql_query("INSERT INTO page (id, pagename, hits, pagedata) VALUES ($num_id, '$id', 0, '')")) ) { - die("db_phpwiki13: could not create new num_id for page\n"); - } - } - else { - die("db_phpwiki13: could not fetch num_id for page\n"); - } - } - return($num_id); - } - - function HIT($id) { - $id = mysql_escape_string($id); - mysql_query("UPDATE page SET hits=(hits+1) WHERE pagename='$id'"); - } - - - #-- returns: array("WikiPage"=>exists) - function FIND($list) { - $r = array(); - $sql = ""; - foreach (array_values($list) as $id) if (strlen($id)) { - $r[$id] = 0; - $sql .= ($sql ? " OR " : "") . - "(pagename = '" . mysql_escape_string($id) . "')"; - } - $result = mysql_query($sql = "SELECT pagename, pagedata AS meta FROM page WHERE $sql"); - while ($result && ($row = mysql_fetch_array($result))) { - $r[$row["pagename"]] = $row["meta"] ? unserialize($row["meta"]) : 1; - } - return($r); - } - - - function GETALL($fields, $mask=0, $filter=0) { - $r = new ewiki_dbquery_result($fields); - foreach ($this->ALLFILES() as $id) { - $row = $this->GET($id); - $r->add($row); - } - return($r); - } - - - function SEARCH($field, $content, $ci="i", $regex=0, $mask=0, $filter=0) { - $r = new ewiki_dbquery_result(array($field)); - if ($ci && !$regex) { - $content = strtolower($content); - } - foreach ($this->ALLFILES() as $id) { - $row = $this->GET($id); - if ($regex) { - $match = preg_match("\007$content\007$ci", $row[$field]); - } - elseif ($ci) { - $match = false !== strpos(strtolower($row[$field]), $content); - } - else { - $match = false !== strpos($row[$field], $content); - } - if ($match) { - $r->add($row); - } - } - return($r); - } - - -# function DELETE($id, $version) { -# die("This interface would probably garbage your PhpWiki v1.3 database, so your issued 'DELETE' action will not be executed."); -# } - - function OTHER() { - die("Not all features can be used with PhpWiki v1.3 databases."); - } - - function INIT() { - die("You cannot create a PhpWiki v1.3 database using this plugin! Please use the default database structure of ErfurtWiki, you're better off with it!"); - } - - - - #---------------------------------------------------------- internal --- - - function ALLFILES() { - $r = array(); - $result = mysql_query("SELECT pagename AS id FROM nonempty - NATURAL LEFT JOIN page"); - if ($result) while ($row = mysql_fetch_array($result)) { - $r[] = $row["id"]; - } - return($r); - } - - -} // end of class - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/db/read_pmwiki1.meta b/mods/wiki/plugins/db/read_pmwiki1.meta deleted file mode 100644 index c4a58b4e6..000000000 --- a/mods/wiki/plugins/db/read_pmwiki1.meta +++ /dev/null @@ -1,11 +0,0 @@ -api: ewiki -category: database -hooks: database -type: database -config: - SUBWIKI_SEPARATOR="." - PMWIKI_DB_DIRS="../pmwiki/wiki.d/:../pmiki/wikilib.d/" - PMWIKI_GROUP="Main" -title: read_pmwiki1 -description: used for importing PmWikis page data files -priority: never diff --git a/mods/wiki/plugins/db/read_pmwiki1.php b/mods/wiki/plugins/db/read_pmwiki1.php deleted file mode 100644 index 69ee0d75a..000000000 --- a/mods/wiki/plugins/db/read_pmwiki1.php +++ /dev/null @@ -1,261 +0,0 @@ -dirs = explode(":", $dirs); - $this->group = $group; - } - - - #-- retrieve/decode pages - function GET($id, $version=false) { - - static $last_id, $last; - $diffs = array(); - $other = array(); - - #-- speedy access - if ($id == $last_id) { - - list($hash, $diffs, $other) = $last; - - } - #-- generic read - elseif ( ($fn = $this->FN($id)) && ($f = fopen($fn, "r")) ) - { - $hash = array(); - $nl = "\n"; - do { - - #-- read line per line - $line = fgets($f, 1<<18); // 256K - if ($l = strpos($line, "=")) { - $field = trim(substr($line, 0, $l)); - $line = rtrim(substr($line, $l+1), "\n"); - } - else { - // broken file? - $field = ":eof:"; - continue; - } - - #-- special field - if ($field == "newline") { - $nl = $line; - } - #-- old revision fields - elseif (strpos($field, ":")) { - list($fi,$n1,$n2,$n3) = explode(":", $field); - if ($n2) { - $diffs[$n2] = $line; - } - else { - $other[$fi][$n1] = $line; - } - } - #-- ordinary entries - else { - switch ($field) { - case "text": - $hash["content"] = $line; - break; - case "name": - if ($l = strpos($line, ".")) { - $l = substr($line, $l+1); - } - $hash["id"] = $line; - break; - case "time": - $hash["lastmodified"] = $line; - break; - case "host": - if (empty($hash["author"])) { - $hash["author"] = $line; - } - else { - $hash["author"] .= " ($line)"; - } - break; - case "author": - if (empty($hash["author"])) { - $hash["author"] = $line; - } - else { - $hash["author"] = $line . " ($hash[author])"; - } - break; - case "rev": - $hash["version"] = $line; - break; - default: - if ($field=="agent") { - $field = "user-agent"; - } - $hash["meta"][$field] = $line; - } - } - - } while (!feof($f)); - fclose($f); - - $last_id = $id; - $last = array($hash, $diffs, $other); - - }// read-in - - - #-- validity check - if ($hash["lastmodified"] && $hash["version"]) { - - #-- guess missing information - $hash["created"] = filectime($fn); - $uu = array_flip(array_keys($diffs)); - $last_diff_time = each($uu); -// $hash["created"] = $last_diff_time; - $hash["hits"] = 0; - $hash["flags"] = EWIKI_DB_F_TEXT; - $hash["refs"] = "\n\n"; - $hash["meta"] = (array)$hash["meta"]; - - #-- if prev version requested - if ($version && ($hash["version"] > $version)) { - - #-- apply patches until it matches requested {version} - foreach ($diffs as $mtime=>$rpatch) { - if ($hash["version"] == $version) { - break; - } - - $hash["author"] = trim( - $others[$mtime]["author"] . ' ('.$others[$mtime]["host"].')' - ); - $hash["content"] = $this->PATCH($hash["content"], $rpatch); - $hash["version"]--; - } - - if ($version < $hash["version"]) { - $hash = false; - } - } - - } - else { - $hash = NULL; - } - - return($hash); - } - - - #-- works - function GETALL($fields, $mask=0, $filter=0) { - $r = new ewiki_dbquery_result($fields); - foreach ($this->LS() as $fn) { - if ($data = $this->GET($fn)) { - $r->add($data); - } - } - return $r; - } - - - #-- stub - function HIT($id) { - } - - - #-- works - function FIND($list) { - $r = array(); - $ls = $this->LS(); - foreach ($list as $id) { - $r[$id] = in_array($id, $ls); - } - return $r; - } - - - #-- search for given filename - function FN($base_id) { - $grp = $this->group; - $dot = SUBWIKI_SEPARATOR; - foreach ($this->dirs as $dir) { - if (file_exists($fn = "$dir/$grp$dot$base_id")) { - return $fn; - } - } - } - - #-- returns list of all existing files - function LS() { - $cmp = $this->group . SUBWIKI_SEPARATOR; - $ncmp = strlen($cmp); - $r = array(); - foreach ($this->dirs as $dir) if ($dh = opendir($dir)) { - while ($fn = readdir($fn)) if (!is_dir($fn)) { - if (strncmp($fn, $cmp, $ncmp) == 0) { - $r[] = substr($fn, $ncmp); - } - } - closedir($dh); - } - return $r; - } - - #-- for decoding older versions - function PATCH($content, $rpatch) { - $f1 = EWIKI_TMP."/ewiki-pmwiki-db-import-".crc32($content)."-".time(); - $f2 = $f1 . ".patch"; - fwrite($f = fopen($f1, "w"), $content) && fclose($f); - fwrite($f = fopen($f2, "w"), $rpatch) && fclose($f); - `patch $f1 $f2`; - $content = fread($f = fopen($f1, "r"), 1<<18); fclose($f); - unlink($f1); - unlink($f2); - return $content; - } - - -} // end of class - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/db/rpc.meta b/mods/wiki/plugins/db/rpc.meta deleted file mode 100644 index f6b0c26a8..000000000 --- a/mods/wiki/plugins/db/rpc.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: database -config: - EWIKI_DB_LOCK=0 - EWIKI_DB_RPC="http://name:pw@rpc.example.com/ewiki/z-db.php" -title: PHP-RPC -description: remote ewiki databases -priority: never -type: database diff --git a/mods/wiki/plugins/db/rpc.php b/mods/wiki/plugins/db/rpc.php deleted file mode 100644 index e0f3b4ad0..000000000 --- a/mods/wiki/plugins/db/rpc.php +++ /dev/null @@ -1,66 +0,0 @@ - "password"); - include("fragments/funcs/auth.php"); - // define("EWIKI_DB_LOCK", 0); - phprpc_server(array("ewiki_db")); - ?> - - Give this a name of "z-db.php" or so, and give its absolute URL in - the EWIKI_DB_RPC constant here. You must load plugins/lib/phprpc.php - of course. -*/ - -define("EWIKI_DB_RPC", "http://name:pw@rpc.example.com/ewiki/z-db.php"); - - -class ewiki_database_rpc { - - function ewiki_ddatabase_rpc($url=EWIKI_DB_RPC) { - $this->api = $url; - } - - - function GET($id, $version) { - return phprpc($this->url, "ewiki_db::GET", array($id, $version)); - } - - function WRITE($hash, $overwrite) { - return phprpc($this->url, "ewiki_db::WRITE", array($hash, $overwrite)); - } - - function HIT($id) { - // stub - } - - function FIND($list) { - return phprpc($this->url, "ewiki_db::FIND", array($list)); - } - - function GETALL($fields, $msk, $filt) { - return phprpc($this->url, "ewiki_db::GETALL", array($fields, $msk, $filt)); - } - - function SEARCH($field, $content, $ci, $regex, $mask, $filter) { - return phprpc($this->url, "ewiki_db::SEARCH", array($field, $content, $ci, $regex, $mask, $filter)); - } - - function DELETE($id, $version) { - return phprpc($this->url, "ewiki_db::DELETE", array($id, $version)); - } - - function INIT() { - return phprpc($this->url, "ewiki_db::INIT", array()); - } - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/db/zip.meta b/mods/wiki/plugins/db/zip.meta deleted file mode 100644 index d603aaa43..000000000 --- a/mods/wiki/plugins/db/zip.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: database -hooks: database -type: database -config: - EWIKI_DB_ZIP="/tmp/database.zip" -title: zip -description: (fun plugin!) can read and write text pages from/into .zip files -priority: never diff --git a/mods/wiki/plugins/db/zip.php b/mods/wiki/plugins/db/zip.php deleted file mode 100644 index 4e07560fc..000000000 --- a/mods/wiki/plugins/db/zip.php +++ /dev/null @@ -1,151 +0,0 @@ -/dev/null"; - - - function ewiki_db_zip() { - } - - - function GET($id, $version=false) { - $fn = $this->FN($id); - if (!$version) { - $version = 0 + trim(`$this->util_get $this->zip $fn $this->QUIET`); - } - if ($version) { - $fn .= ".$version"; - $r = `$this->util_get $this->zip $fn `; - $r = unserialize($r); - } - return($r); - } - - - function WRITE($hash, $overwrite=0) { - $fn = "$this->tmp/" . $this->FN($hash["id"]); - $fn2 = "$fn." . $hash["version"]; - if ($f = fopen($fn2, "w")) { - fwrite($f, serialize($hash)); // unsafe, to say mildly - fclose($f); - if ($f = fopen($fn, "w")) { - fwrite($f, $hash["version"]); - fclose($f); - #-- add to zip - $r = `$this->util_add $this->zip $fn2 $fn $this->QUIET`; - $r = !$r; - @unlink($fn); - } - @unlink($fn2); - } - return($r); - } - - - function HIT($id) { - // nop - } - - - function FIND($list) { - $r = array(); - foreach ($list as $id) if ($id) { - $r[$id] = 0; - $fn = $this->FN($id); - if ($ver = `$this->util_get $this->zip $fn $this->QUIET`) { - $r[$id] = 1; - } - } - return($r); - } - - - function GETALL($fields, $mask=0, $filter=0) { - $r = new ewiki_dbquery_result($fields); - foreach (explode("\n", `$this->util_un -l $this->zip | cut -b 29-290`) as $id) { - if (!strpos($id, ".") || !preg_match('/\.\d+$/', $id)) { - $r->entries[] = rawurldecode($id); - } - } - return($r); - } - - - function SEARCH($field, $content, $ci="i", $regex=0, $mask=0, $filter=0) { - $r = new ewiki_dbquery_result($args); - if ($ci && !$regex) { - $content = strtolower($content); - } - $ALL = $this->GETALL(array($field), $mask, $filter); - while ($row = $ALL->get()) { - if ($regex) { - $match = preg_match("\007$content\007$ci", $row["field"]); - } - elseif ($ci) { - $match = strpos(strtolower($row[$field]), $content) !== false; - } - else { - $match = strpos($row[$field], $content) !== false; - } - if ($match) { - $r->add($row); - } - } - return($r); - } - - -# function DELETE($id, $version) { -# } - - - function INIT() { - if (!file_exists($this->zip) || !filesize($this->zip)) { - $f = fopen($this->zip, "wb"); - fwrite($f, "PK\005\006".str_repeat("\000", 18)); - fclose($f); - } - if (!is_writeable($this->zip)) { - echo "error db_zip: $this->zip is not writeable!\n"; - } - } - - - function FN($id) { - $id = ewiki_lowercase($id); - return(rawurlencode($id)); - } - - -} // end of class - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/debug/verbose.meta b/mods/wiki/plugins/debug/verbose.meta deleted file mode 100644 index 9429f6a17..000000000 --- a/mods/wiki/plugins/debug/verbose.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: PHP -tyep: intercept -category: fragments -title: verbose -description: PHP error handler for verbose debug messages -priority: deprecated -type: intercept diff --git a/mods/wiki/plugins/debug/warn_utf8.meta b/mods/wiki/plugins/debug/warn_utf8.meta deleted file mode 100644 index 89e262ea9..000000000 --- a/mods/wiki/plugins/debug/warn_utf8.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: fragments -hooks: edit_hook -type: intercept -title: warn_utf8 -description: check for UTF-8 in incoming URLs (broken browsers) -priority: deprecated diff --git a/mods/wiki/plugins/debug/warn_utf8.php b/mods/wiki/plugins/debug/warn_utf8.php deleted file mode 100644 index 3bb906126..000000000 --- a/mods/wiki/plugins/debug/warn_utf8.php +++ /dev/null @@ -1,33 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/debug/xerror.meta b/mods/wiki/plugins/debug/xerror.meta deleted file mode 100644 index 02bfa07fc..000000000 --- a/mods/wiki/plugins/debug/xerror.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: PHP -type: intercept -category: fragments -title: xerror -description: sends all detected errors as HTTP headers (and not intermingled with page text) -priority: deprecated diff --git a/mods/wiki/plugins/debug/xerror.php b/mods/wiki/plugins/debug/xerror.php deleted file mode 100644 index 9a00a084c..000000000 --- a/mods/wiki/plugins/debug/xerror.php +++ /dev/null @@ -1,50 +0,0 @@ - "PARSE ERROR", - E_ERROR => "ERROR", - E_WARNING => "WARNING", - E_NOTICE => "NOTICE", - E_STRICT => "STRICT", - E_USER_ERROR => "USER ERROR", - E_USER_WARNING => "USER WARNING", - E_USER_NOTICE => "USER NOTICE", - ); - ($errtype = $error_types[$errno]) or ($errtype = "UNDEF ERROR"); - - #-- check for @ and disabled errors - $emask = get_cfg_var("error_reporting"); - if (! ($emask & $errno)) { - return; - } - - #-- output - $msg = strtr($msg, "\r\n\t\f", " "); - $msg = "$errtype: $msg in $file, line #$line"; - if (headers_sent()) { - print "\n\n"; - } - else { - $no = crc32($msg); - $no = ($no & 0xFFFF) ^ ($no >> 16); - header("X-Error-$no: $msg"); - if ($errno == E_FATAL) { header("Status: 500 Something bad happened"); } - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/authorname.meta b/mods/wiki/plugins/edit/authorname.meta deleted file mode 100644 index 2ff8838bc..000000000 --- a/mods/wiki/plugins/edit/authorname.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: edit -priority: extra -hooks: edit_form_append -type: input -title: set AuthorName freely -description: adds an input box for a free-form author name below the edit/ page diff --git a/mods/wiki/plugins/edit/authorname.php b/mods/wiki/plugins/edit/authorname.php deleted file mode 100644 index dc0fca641..000000000 --- a/mods/wiki/plugins/edit/authorname.php +++ /dev/null @@ -1,42 +0,0 @@ - -$ewiki_plugins["edit_form_append"][] = "ewiki_aedit_authorname"; -function ewiki_aedit_authorname($id, &$data, $action) { - - $var = EWIKI_UP_AUTHOR_NAME; - return(ewiki_t(<<< EOT -
      - _{set the AuthorName to} -
      -EOT - )); -} - - -#-- store as cookie (for 1 month) -if ($uu = @$_REQUEST[EWIKI_UP_AUTHOR_NAME]) { - $uu = trim($uu); - if (!strpos($uu, "://")) { - $ewiki_author = $uu; - } - if ($_COOKIE[EWIKI_UP_AUTHOR_NAME] != $ewiki_author) { - setcookie(EWIKI_UP_AUTHOR_NAME, $ewiki_author, time()+2500000); - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/deletebutton.js.meta b/mods/wiki/plugins/edit/deletebutton.js.meta deleted file mode 100644 index 4224ce59a..000000000 --- a/mods/wiki/plugins/edit/deletebutton.js.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -type: input -category: edit -hooks: edit_form_append -title: DeleteBotton.js -description: appends a "Delete Page" button to the edit/ page (JavaScript only) -priority: rare diff --git a/mods/wiki/plugins/edit/deletebutton.js.php b/mods/wiki/plugins/edit/deletebutton.js.php deleted file mode 100644 index fb8872b42..000000000 --- a/mods/wiki/plugins/edit/deletebutton.js.php +++ /dev/null @@ -1,26 +0,0 @@ - -END; -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/flags.meta b/mods/wiki/plugins/edit/flags.meta deleted file mode 100644 index 2c5e6d777..000000000 --- a/mods/wiki/plugins/edit/flags.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: edit -hooks: edit_form_append, edit_save -type: input -title: flags -description: provides users the ability to set certain page flags on editing -priority: rare diff --git a/mods/wiki/plugins/edit/flags.php b/mods/wiki/plugins/edit/flags.php deleted file mode 100644 index 6c2881551..000000000 --- a/mods/wiki/plugins/edit/flags.php +++ /dev/null @@ -1,44 +0,0 @@ - "minor edit", - EWIKI_DB_F_HIDDEN => "hidden page", -# EWIKI_DB_F_HTML => "html is allowed", -); -$ewiki_plugins["edit_form_append"][] = "ewiki_edit_user_flags"; -$ewiki_plugins["edit_save"][] = "ewiki_edit_save_user_flags"; - -$ewiki_t["de"]["minor edit"] = "kleine Änderung"; -$ewiki_t["de"]["hidden page"] = "versteckte Seite"; - - -function ewiki_edit_save_user_flags(&$save, &$old) { - global $ewiki_config; - - foreach ($ewiki_config["user_flags"] as $FLAG=>$str) { - $save["flags"] = $save["flags"] & (0xFFFF ^ $FLAG) - | ($_REQUEST["page_user_flag"][dechex($FLAG)] ? $FLAG : 0x00); - } -} - - -function ewiki_edit_user_flags($id, &$data, $action) { - global $ewiki_config; - - $o = ""; - foreach ($ewiki_config as $FLAG => $str) { - $o .= '
      ' . "\n"; - } - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/helptext.meta b/mods/wiki/plugins/edit/helptext.meta deleted file mode 100644 index d3692391e..000000000 --- a/mods/wiki/plugins/edit/helptext.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: edit -hooks: edit_hook -type: mangle -title: helptext -description: appends an info text to the edit/ page -priority: bonus diff --git a/mods/wiki/plugins/edit/helptext.php b/mods/wiki/plugins/edit/helptext.php deleted file mode 100644 index 000c01529..000000000 --- a/mods/wiki/plugins/edit/helptext.php +++ /dev/null @@ -1,26 +0,0 @@ -", $l); - $help = substr($help, $l + 1); - } - $ewiki_t["en"]["EDIT_FORM_2"] = $help; - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/limitlinks.meta b/mods/wiki/plugins/edit/limitlinks.meta deleted file mode 100644 index 19f65cc84..000000000 --- a/mods/wiki/plugins/edit/limitlinks.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: spam -hooks: edit_save -type: intercept -config: - EWIKI_LIMIT_LINKS=5 -title: limitlinks -description: disallows adding more than a certain number of external links to a page (very useful) -priority: optional diff --git a/mods/wiki/plugins/edit/limitlinks.php b/mods/wiki/plugins/edit/limitlinks.php deleted file mode 100644 index e6d24f743..000000000 --- a/mods/wiki/plugins/edit/limitlinks.php +++ /dev/null @@ -1,39 +0,0 @@ -
      If you're a bored link spammer, this is message is for you:
      *hehe*, *laugh*
      Happy Death!"; - - -function ewiki_edit_save_limit_adding_external_links(&$save, &$old) { - global $ewiki_errmsg; - - #-- count - preg_match_all('°(http://[^\s*<>"\'\[\]\#]+)°', $old["content"], $old_urls); - preg_match_all('°(http://[^\s*<>"\'\[\]\#]+)°', $save["content"], $save_urls); - $added_urls = array_diff($save_urls[1], $old_urls[1]); - - #-- engage trap - if (count($added_urls) > EWIKI_LIMIT_LINKS) { - - #-- abort saving with an error message - $save = array(); - $ewiki_errmsg = ewiki_t("LINK_ADDING_LIMITED"); - return(false); - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/lock.meta b/mods/wiki/plugins/edit/lock.meta deleted file mode 100644 index 785475eb4..000000000 --- a/mods/wiki/plugins/edit/lock.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: edit -hooks: edit_hook -type: intercept -title: concurrent edit locks -description: creates lock files (time out) to prevent concurrent edits -priority: rare diff --git a/mods/wiki/plugins/edit/lock.php b/mods/wiki/plugins/edit/lock.php deleted file mode 100644 index 05e1b0dfb..000000000 --- a/mods/wiki/plugins/edit/lock.php +++ /dev/null @@ -1,71 +0,0 @@ - time()) { - $o = ewiki_t("

      _{Warning}:" - . " _{This page is currently being edited by someone else}," - . " _{and therefore locked currently}." - . " " - . '

      ' - . '' - . '' - . '
      ' - . "

      \n"); - } - elseif ($time) { - // unlink($lockfile); - touch($lockfile); - } - else { - touch($lockfile); - } - } - - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/log.meta b/mods/wiki/plugins/edit/log.meta deleted file mode 100644 index e56915773..000000000 --- a/mods/wiki/plugins/edit/log.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: edit -priority: extra -hooks: edit_form_append, edit_save -type: input -title: ChangeLog -description: input to the changelog input box on the edit/ screen will be shown on RecentChanges diff --git a/mods/wiki/plugins/edit/log.php b/mods/wiki/plugins/edit/log.php deleted file mode 100644 index 1af4b406e..000000000 --- a/mods/wiki/plugins/edit/log.php +++ /dev/null @@ -1,37 +0,0 @@ - -$ewiki_plugins["edit_form_append"][] = "ewiki_aedit_changelog"; -function ewiki_aedit_changelog($id, &$data, $action) { - - $var = EWIKI_UP_CHANGELOG; - $val = $_REQUEST[EWIKI_UP_CHANGELOG]; - return(ewiki_t(<<< EOT -
      - _{CHANGELOG}:
      -
      -EOT - )); -} - - -#-- save into db {meta} field -$ewiki_plugins["edit_save"][] = "ewiki_edit_save_changelog"; -function ewiki_edit_save_changelog(&$save, &$old_data) { - $log = trim($_REQUEST[EWIKI_UP_CHANGELOG]); - $save["meta"]["log"] = $log; -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/minor.meta b/mods/wiki/plugins/edit/minor.meta deleted file mode 100644 index 9a550a5a6..000000000 --- a/mods/wiki/plugins/edit/minor.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: edit -hooks: edit_form_append, edit_save -type: input -title: minor edits -description: provides a [x]-minor-edit checkbox -priority: deprecated diff --git a/mods/wiki/plugins/edit/minor.php b/mods/wiki/plugins/edit/minor.php deleted file mode 100644 index 4d054ae76..000000000 --- a/mods/wiki/plugins/edit/minor.php +++ /dev/null @@ -1,27 +0,0 @@ -
      ' . "\n"; -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/msg.meta b/mods/wiki/plugins/edit/msg.meta deleted file mode 100644 index a6ee0c3da..000000000 --- a/mods/wiki/plugins/edit/msg.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: edit -hooks: edit_form_final -type: mangle -title: custom edit message -description: allows customized messages to show up when editing a page -priority: bonus diff --git a/mods/wiki/plugins/edit/msg.php b/mods/wiki/plugins/edit/msg.php deleted file mode 100644 index 7bc62ab68..000000000 --- a/mods/wiki/plugins/edit/msg.php +++ /dev/null @@ -1,18 +0,0 @@ -$msg\n" - . $o; - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/pageimage.meta b/mods/wiki/plugins/edit/pageimage.meta deleted file mode 100644 index c3d1ad771..000000000 --- a/mods/wiki/plugins/edit/pageimage.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: edit -title: pageimage -description: allows selecting a page image graphic -priority: rare -type: input diff --git a/mods/wiki/plugins/edit/pageimage.php b/mods/wiki/plugins/edit/pageimage.php deleted file mode 100644 index f0b8b0970..000000000 --- a/mods/wiki/plugins/edit/pageimage.php +++ /dev/null @@ -1,101 +0,0 @@ - -* @based on aview_piclogocntrl.php and page_imagegallery.php -*/ - -require_once('plugins/page/imagegallery.php'); -define('EWIKI_PAGE_LOGOCNTRL_GALLERY','HeaderGallery'); - -$ewiki_plugins['edit_form_append'][] = 'ewiki_edit_form_append_pageimgcntrl'; -$ewiki_plugins['edit_save'][] = 'ewiki_edit_save_pageimgcntrl'; -$ewiki_plugins['view_final'][] = 'ewiki_add_title_image'; - -function ewiki_add_title_image(&$html, $id, &$data, $action) { - if(!isset($data['meta']['pageimage']) || ($data['meta']['pageimage'] == '') ){ - return; - } - $imagename=$data['meta']['pageimage']; - $image=ewiki_database('GET',$imagename); - if((EWIKI_PROTECTED_MODE) &&!ewiki_auth($imagename, $image, "binary-get")){ - return; - } - - #-- height, width - $x = $image['meta']["width"]; - $y = $image['meta']["height"]; - - #-- print a/img tag - $o .= ''. "\n"; - - $html=preg_replace('/

      /','

      ' . $o,$html,1); - -} - -/** - * Save selected pageimage value by setting it in the meta field of save data array - * passed by reference. - * - * @param array save associative array of ewiki form data - */ -function ewiki_edit_save_pageimgcntrl(&$save){ - if (isset($_REQUEST['pageimagecntrl']) ) { - if($_REQUEST['pageimagecntrl']==-1){ - unset($save['meta']['pageimage']); - }else{ - $imageExist=ewiki_database('FIND',array($_REQUEST['pageimagecntrl'])); - //var_dump($imageExist); - if($imageExist[$_REQUEST['pageimagecntrl']]) - $save['meta']['pageimage'] = $_REQUEST['pageimagecntrl']; - } - } -} - -function ewiki_edit_form_append_pageimgcntrl ($id, $data, $action){ - global $ewiki_config; - - #-- fetch and asort images - $sorted = array(); - $result = ewiki_db::GETALL(array("flags", "created", "meta")); - while ($row = $result->get()) { - if ((($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_BINARY) - && (strpos($row['meta']['Content-Type'], 'image/') === 0)) { - if(isset($ewiki_config['image-galleries'][EWIKI_PAGE_LOGOCNTRL_GALLERY])){ - foreach($ewiki_config['image-galleries'][EWIKI_PAGE_LOGOCNTRL_GALLERY]as $field=>$value){ - if($row['meta'][$field]!=$value){ - continue (2); - } - } - } - if (!EWIKI_PROTECTED_MODE || (EWIKI_PROTECTED_MODE_HIDING <= .5)|| ewiki_auth($row["id"], $uu, "binary-get")) { - $sorted[$row["id"]] = substr($row['meta']["Content-Location"].' ('.$row["id"].')',0,70); - //echo("adding ".$row["id"].", ".$sorted[$row["id"]]."
      "); - } - } - } - arsort($sorted); - - #-- start selector - $o = ' -
      - \n"; - - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/plog.meta b/mods/wiki/plugins/edit/plog.meta deleted file mode 100644 index 3a2af05ba..000000000 --- a/mods/wiki/plugins/edit/plog.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -type: R -category: edit -title: IntComm:PersonalLogServer -description: sends notifications to users plog server -priority: deprecated diff --git a/mods/wiki/plugins/edit/requirespassword.meta b/mods/wiki/plugins/edit/requirespassword.meta deleted file mode 100644 index c393a451b..000000000 --- a/mods/wiki/plugins/edit/requirespassword.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: edit -hooks: edit_hook, edit_save -type: intercept -config: - EWIKI_ADMIN_PW="password" -title: requirespassword -description: lightweight alternative to powering up the _PROTECTED_MODE -priority: rare diff --git a/mods/wiki/plugins/edit/requirespassword.php b/mods/wiki/plugins/edit/requirespassword.php deleted file mode 100644 index 1262feb53..000000000 --- a/mods/wiki/plugins/edit/requirespassword.php +++ /dev/null @@ -1,26 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/edit/spam_block.meta b/mods/wiki/plugins/edit/spam_block.meta deleted file mode 100644 index 31e1bcc8a..000000000 --- a/mods/wiki/plugins/edit/spam_block.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: spam -hooks: edit_save -type: intercept -config: - EWIKI_PAGE_BLOCKED="BlockedLinks" -title: BlockedLinks -description: rejects editing attempts with blocked URL patterns (page BlockedLinks) -priority: rare diff --git a/mods/wiki/plugins/edit/spam_block.php b/mods/wiki/plugins/edit/spam_block.php deleted file mode 100644 index edddf667d..000000000 --- a/mods/wiki/plugins/edit/spam_block.php +++ /dev/null @@ -1,109 +0,0 @@ -"\'\[\]\#]+)°', $save["content"], $save_urls); - preg_match_all('°(http://[^\s*<>"\'\[\]\#]+)°', $old_data["content"], $old_urls); - - $added_urls = array_diff($save_urls[1], $old_urls[1]); - if ($added_urls) { - foreach ($added_urls as $i=>$url) { - - #-- test against BannedLinks, then deface (filter page) URL - if (ewiki_blocked_link($url, $BLOCK)) { - $block = true; - unset($added_urls[$i]); - } - } - $old = $i + 1; - } - - #-- if matched - if ($block) { - #-- add new URLs to our BannedLinks page - if ($new = count($added_urls)) { - $content = ""; - foreach ($added_urls as $d) { - $d = preg_replace('#^.+//(?:www\.)?#', '', $d); - $d = preg_replace('#^([^/]+)(/.*)?$*', '$1', $d); - if ($d) { - $content .= "\n* [$d] (auto-added by spam attack on [$ewiki_id])"; - } - } - if ($content) { - ewiki_db::APPEND($BLOCK, $content); - } - $date = strftime("%c", time()); - ewiki_append_to_page("SpamLog", "\n* spam attack on [$ewiki_id] from $_SERVER[REMOTE_ADDRESS]:$_SERVER[REMOTE_PORT] ($_SERVER[HTTP_USER_AGENT]) happend at $date, around {$new} of the {$old} added URLs were already on BlockedLinks"); - } - - #-- error reporting method for ["edit_save"] - $save = array(); - $ewiki_errmsg = ewiki_t("BLOCKED_URL"); - return(false); - } -} - - - -function ewiki_blocked_link($href, $LinkPage=EWIKI_PAGE_BLOCKED) { - global $ewiki_config, $ewiki_plugins; - - if (! ($href = trim(strtolower(urldecode($href)))) ) { - return; - } - - #-- buffer list of banned urls - if (!isset($ewiki_config[$LinkPage])) { - $data = ewiki_db::GET($LinkPage); - $ewiki_config[$LinkPage] = trim(strtolower($data["refs"])); - } - - #-- check for entry - if ($b = &$ewiki_config[$LinkPage]) { - if (strpos($b, $href) !== false) { // quick string check - return(true); - } - foreach (explode("\n", $b) as $bad) { // use as patterns - if (strlen($bad) && (strpos($href, $bad) !== false)) { - return(true); - } - } - } - - #-- advanced - if ($pf_a = $ewiki_plugins["ban_lookup"]) { - foreach ($pf_a as $pf) { - if ($pf($href)) { - return(true); - } - } - } - - return(false); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/spam_deface.meta b/mods/wiki/plugins/edit/spam_deface.meta deleted file mode 100644 index 70f971d41..000000000 --- a/mods/wiki/plugins/edit/spam_deface.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: edit -hooks: edit_save -type: intercept -config: - ZERO_PAGERANK="http://www.google.com/url?sa=D&q=" - EWIKI_PAGE_BANNED="BannedLinks" -title: BannedLinks defacement -description: defaces all URLs which match patterns from "BannedLinks" page -priority: rare diff --git a/mods/wiki/plugins/edit/spam_deface.php b/mods/wiki/plugins/edit/spam_deface.php deleted file mode 100644 index ba9664a2c..000000000 --- a/mods/wiki/plugins/edit/spam_deface.php +++ /dev/null @@ -1,77 +0,0 @@ -"\'\[\]\#]+)°', $old["content"], $old_urls); - preg_match_all('°(http://[^\s*<>"\'\[\]\#]+)°', $save["content"], $save_urls); - - $added_urls = array_diff($save_urls[1], $old_urls[1]); - if ($added_urls) { - foreach ($added_urls as $url) { - - #-- test against BannedLinks, then deface (filter page) URL - if (ewiki_banned_link($url)) { - $save["content"] = str_replace($url, ZERO_PAGERANK.urlencode($url), $save["content"]); - } - } - } -} - - -function ewiki_banned_link($href) { - global $ewiki_config, $ewiki_plugins; - - #-- buffer list of banned urls - if (!isset($ewiki_config["banned"])) { - $data = ewiki_db::GET(EWIKI_PAGE_BANNED); - $ewiki_config["banned"] = trim(strtolower($data["refs"])); - } - - #-- check for entry - if ($b = &$ewiki_config["banned"]) { - $href = strtolower(urldecode($href)); - if (strpos($b, $href) !== false) { // quick string check - return(true); - } - foreach (explode("\n", $b) as $bad) { // use as patterns - if (strpos($href, $bad) !== false) { - return(true); - } - } - } - - #-- advanced - if ($pf_a = $ewiki_plugins["ban_lookup"]) { - foreach ($pf_a as $pf) { - if ($pf($href)) { - return(true); - } - } - } - - return(false); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/templates.meta b/mods/wiki/plugins/edit/templates.meta deleted file mode 100644 index 2fa589cc8..000000000 --- a/mods/wiki/plugins/edit/templates.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: edit -priority: extra -hooks: edit_form_final, edit_hook -type: intercept -title: templates -description: on creating a new page, users will be left the choice to load a "...Template" page diff --git a/mods/wiki/plugins/edit/templates.php b/mods/wiki/plugins/edit/templates.php deleted file mode 100644 index 02f9890cd..000000000 --- a/mods/wiki/plugins/edit/templates.php +++ /dev/null @@ -1,54 +0,0 @@ - list, whenever a new page was to be - created. -*/ - - -$ewiki_plugins["edit_form_final"][] = "ewiki_aedit_templates"; -$ewiki_plugins["edit_hook"][] = "ewiki_edit_load_template"; - - -function ewiki_aedit_templates(&$html, $id, &$data, $action) -{ - if (!$data["content"]) { - - #-- search template pages - $list = array(); - $result = ewiki_db::SEARCH("id","Template"); - while ($row = $result->get(0, 0x21, EWIKI_DB_F_TEXT)) { - if (preg_match('/Template$/', $row["id"])) { - $list[] = $row["id"]; - } - } - - #-- add list - if ($list) { - $o = '
      ' - . '' - . ' ' - . '
      '; - - #-- output - $html = $o . $html; - } - } -} - - -function ewiki_edit_load_template($id, &$data, $action) -{ - if ($id = $_REQUEST["load_template"]) { - $d2 = ewiki_db::GET($id); - $data["content"] = $d2["content"]; - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/edit/upload.meta b/mods/wiki/plugins/edit/upload.meta deleted file mode 100644 index 3bb94f675..000000000 --- a/mods/wiki/plugins/edit/upload.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: edit -title: upload -description: shows an upload-from-file
      field on empty (non-existant) pages -type: R -priority: rare diff --git a/mods/wiki/plugins/edit/warn.meta b/mods/wiki/plugins/edit/warn.meta deleted file mode 100644 index 102b3cb3d..000000000 --- a/mods/wiki/plugins/edit/warn.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: edit -hooks: edit_form_final -type: mangle -title: warn conncurrent edits -description: shows a warning messages for concurrent edits -priority: optional diff --git a/mods/wiki/plugins/edit/warn.php b/mods/wiki/plugins/edit/warn.php deleted file mode 100644 index edbfa9b98..000000000 --- a/mods/wiki/plugins/edit/warn.php +++ /dev/null @@ -1,49 +0,0 @@ - time()) { - $o = ewiki_t("

      _{Warning}:" - . " _{This page is currently being edited by someone else}." - . " _{If you start editing now, your changes may get lost}." - . "

      \n") - . $o; - } - elseif ($time) { - // unlink($lockfile); - touch($lockfile); - } - else { - touch($lockfile); - } - -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/email_protect.meta b/mods/wiki/plugins/email_protect.meta deleted file mode 100644 index cc82ab8e2..000000000 --- a/mods/wiki/plugins/email_protect.meta +++ /dev/null @@ -1,12 +0,0 @@ -api: ewiki -type: page -hooks: page, link_url, edit_hook, page_final -funcs: ewiki_email_protect_enctext, ewiki_email_protect_link, ewiki_email_protect_edit_hook, ewiki_email_protect_form, ewiki_email_protect_encode, str_rot17, ewiki_email_protect_feedbots, nat_rand -page: ProtectedEmail -category: feature -title: ProtectedEmailAdresses -description: hides email addresses with intermediate formular pages -config: - EWIKI_PAGE_EMAIL=ProtectedEmail // page name - EWIKI_EMAILPROT_UNLOCK=1|0 // unlock protection, once human verified -priority: important diff --git a/mods/wiki/plugins/email_protect.php b/mods/wiki/plugins/email_protect.php deleted file mode 100644 index 334d8ee76..000000000 --- a/mods/wiki/plugins/email_protect.php +++ /dev/null @@ -1,329 +0,0 @@ - before the real email address gets shown on a page. It seems - # impossible to me that there are already all that intelligent spambots - # available, which can automatically fill out a to access the - # following page. Also bots are unlikely to ever perform POST requests, - # because this would damage too many web interfaces. - # The 'cipher' method is really unimportant, when it comes to tricking - # automated harvesters. - # - # Additionally it generates faked/trap email addresses to annoy the - # marketing mafia. - - - #-- change these from time to time: - define("EWIKI_PAGE_EMAIL", "ProtectedEmail"); - define("EWIKI_EMAILPROT_UNLOCK", 1); - define("EWIKI_UP_ENCEMAIL", "encoded_email"); - define("EWIKI_UP_NOSPAMBOT", "i_am_no_spambot"); - define("EWIKI_UP_REQUESTLV", "rl"); - define("EWIKI_FAKE_EMAIL_LOOP", 8); - $ewiki_config["feedbots_tarpits"] = "@spamassassin.taint.org,@123webhosting.org,@e.mailsiphon.com,@heypete.com,@ncifcrf.gov"; - $ewiki_config["feedbots_badguys"] = "@riaa.com,@whitehouse.gov,@aol.com,@microsoft.com"; - @$ewiki_config["ua"] .= " EmailProtect/2.1"; - - #-- text, translations - $ewiki_t["en"]["PROTE0"] = "Protected Email Address"; - $ewiki_t["en"]["PROTE1"] = "The email address you've clicked on is protected by this form, so it won't get found by spambots (automated search engines, which crawl the net for addresses just for the entertainment of the marketing mafia)."; - $ewiki_t["en"]["PROTE2"] = "The page you're going to edit contains at least one email address. To protect it we must ensure that no spambot reaches the edit box (with the email address in cleartext)."; - $ewiki_t["en"]["PROTE4"] = "I'm no spambot, really!"; - $ewiki_t["en"]["PROTE5"] = "generate more faked email addresses"; - $ewiki_t["en"]["PROTE6"] = "the email address you've clicked on is:"; - $ewiki_t["en"]["PROTE7"] = "spammers, please eat these:"; - - $ewiki_t["de"]["PROTE0"] = "Geschützte EMail-Adresse"; - $ewiki_t["de"]["PROTE1"] = "Die EMail-Adresse, die du angeklickt hast, wird durch dieses Formular vor spambots (automatisierte Suchwerkzeuge, die das Netz zur Freude der MarketingMafia nach Adressen abgrasen) beschützt."; - $ewiki_t["de"]["PROTE2"] = "Die Seite, die du ändern willst, enthält momentan wenigstens eine EMail-Adresse. Um diese zu schützen müssen wir sicherstellen, daß kein Spambot an die Edit-Box kommt (weil dort die Adresse ja im Klartext steht)."; - $ewiki_t["de"]["PROTE4"] = "Ich bin wirklich kein Spambot!"; - $ewiki_t["de"]["PROTE5"] = "noch mehr fingierte Adressen anzeigen"; - $ewiki_t["de"]["PROTE6"] = "die EMail-Adresse die du angeklickt hast lautet:"; - $ewiki_t["de"]["PROTE7"] = "Liebe Spammer, bitte freßt das:"; - - #-- plugin glue - $ewiki_plugins["page"][EWIKI_PAGE_EMAIL] = "ewiki_email_protect_form"; - if (!EWIKI_EMAILPROT_UNLOCK || !@$_COOKIE[EWIKI_UP_NOSPAMBOT]) { - $ewiki_plugins["link_url"][] = "ewiki_email_protect_link"; - $ewiki_plugins["edit_hook"][] = "ewiki_email_protect_edit_hook"; - $ewiki_plugins["page_final"][] = "ewiki_email_protect_enctext"; - } - - - - /* helps protecting addresses on generated/dynamic pages, and - for action pages (diff, info, links, ...) - */ - function ewiki_email_protect_enctext(&$html, $id, $data, $action) { - - global $ewiki_config; - - #-- only activate if _feedbots() wasn't active, for info/ or - # diff/ action or for page plugins - $a_secure = array("info", "diff"); - if (!isset($ewiki_config["@"]) && (in_array($action, $a_secure) || ewiki_array($GLOBALS["ewiki_plugins"]["page"], $id))) { - - $html = preg_replace('/(?:(?:]+href="mailto:)?([-_+\w\d.]+@[-\w\d.]+\.[\w]{2,5})(?:"[^>]*>[-_+\w\d.@]+<\/a>)?)/me', - '"".ewiki_email_protect_encode("\1",0).""', - $html); - } - } - - - /* ewiki_format() callback function to replace mailto: links with - * encoded redirection URLs - */ - function ewiki_email_protect_link(&$href, &$title) { - - if (substr($href, 0, 7) == "mailto:") { - - $href = substr($href, 7); - - $href = ewiki_email_protect_encode($href, 2); - $title = ewiki_email_protect_encode($title, 0); - } - } - - - - /* the edit box for every page must be protected as well - else all - * mail addresses would still show up in the wikimarkup (cleartext) - */ - function ewiki_email_protect_edit_hook($id, &$data, &$hidden_postdata) { - - $hidden_postdata[EWIKI_UP_NOSPAMBOT] = 1; - - if (empty($_REQUEST[EWIKI_UP_NOSPAMBOT]) - && strpos($data["content"], "@") - && preg_match('/\w\w@([-\w]+\.)+\w\w/', $data["content"]) ) - { - $url = ewiki_script("edit", $id); - $o = ewiki_email_protect_form($id, $data, "edit", "PROTE2", $url); - return($o); - } - - if (!empty($_POST[EWIKI_UP_NOSPAMBOT]) && empty($_COOKIE[EWIKI_UP_NOSPAMBOT]) && EWIKI_HTTP_HEADERS) { - setcookie(EWIKI_UP_NOSPAMBOT, "grant_access", time()+7*24*3600, "/"); - } - - } - - - - /* this places a in between the WikiPage with the - * encoded mail address URL and the page with the clearly readable - * mailto: string - */ - function ewiki_email_protect_form($id, $data=0, $action=0, $text="PROTE1", $url="") { - global $ewiki_config; - - $html = "

      " . ewiki_t("PROTE0") . "

      \n"; - - #-- get encoded-email parameter - if ($url || ($email = @$_REQUEST[EWIKI_UP_ENCEMAIL])) { - - #-- check for unlock cookie / post variable - if (empty($_REQUEST[EWIKI_UP_NOSPAMBOT])) { - - if (empty($url)) { - $url = ewiki_script("", EWIKI_PAGE_EMAIL); - } - - $html .= ewiki_t($text) . "


      \n"; - - $html .= ''; - $html .= ''; - foreach (array_merge($_GET, $_POST) as $var=>$value) { - if (($var != "id") && ($var != EWIKI_UP_ENCEMAIL) && ($var != EWIKI_UP_NOSPAMBOT)) { - $html .= ''; - } - } - $html .= '

      '; - $html .= '

      '; - - if (EWIKI_FAKE_EMAIL_LOOP) { - $html .= "\n" . ewiki_t("PROTE7") . "
      \n"; - $html .= ewiki_email_protect_feedbots(); - } - } - - #-- display deciphered email address - else { - $email = ewiki_email_protect_encode($email, -1); - - $html .= ewiki_t("PROTE6") . "
      "; - $html .= '' . $email . ''; - - if (EWIKI_HTTP_HEADERS && empty($_COOKIE[EWIKI_UP_NOSPAMBOT])) { - setcookie(EWIKI_UP_NOSPAMBOT, "grant_access", time()+7*24*3600, "/"); - } - - #-- must disable the page plugin mangling filter manually - $ewiki_config["@"] = 0; // flag value doesn't matter here - } - } - else { - // $html .= "This page makes no sense standalone."; - $html .= "No encoded email address given in parameters."; - } - - return($html); - } - - - - /* security really does not depend on how good "encoding" is, because - * bots cannot automatically guess that one is actually used - */ - function ewiki_email_protect_encode($string, $func) { - - switch ($func) { - - case 0: // garbage shown email address - if (strpos($string, "mailto:") === 0) { - $string = substr($string, 7); - } - while (($rd = strrpos($string, ".")) > strpos($string, "@")) { - $string = substr($string, 0, $rd); - } - $string = strtr($string, "@.-_", "»·±¯"); - break; - - case 1: // encode - $string = str_rot17($string); - $string = base64_encode($string); - break; - - case -1: // decode - $string = base64_decode($string); - $string = str_rot17($string); - break; - - case 2: // url - $string = ewiki_script("", EWIKI_PAGE_EMAIL, - array(EWIKI_UP_ENCEMAIL => ewiki_email_protect_encode($string, 1)) - ); - break; - - } - - return($string); - } - - - - /* this is a non-portable string encoding function which ensures that - * encoded strings can only be decoded when requested by the same client - * or user in the same dialup session (IP address must match) - * feel free to exchange the random garbage string with anything else - */ - function str_rot17($string) { - if (!defined("STR_ROT17")) { - $i = @$_SERVER["SERVER_SOFTWARE"] . - @$_SERVER["HTTP_USER_AGENT"] . - @$_SERVER["REMOTE_ADDR"]; - $i .= 'MxQXF^e-0OKC1\\s{\"?i!8PRoNnljHf65`Eb&A(\':g[D}_|S#~3hG>*9yvdI%<=.urcp/@$ZkqL,TWBw]a;72UzYJ)4mt+ V'; - $f = ""; - while (strlen($i)) { - if (strpos($f, $i[0]) === false) { - $f .= $i[0]; - } - $i = substr($i, 1); - } - define("STR_ROT17", $f); - } - return(strtr($string, STR_ROT17, strrev(STR_ROT17))); - } - - - - /* this function emits some html with random (fake) email addresses - * and spambot traps - */ - function ewiki_email_protect_feedbots($limit=EWIKI_FAKE_EMAIL_LOOP) { - - global $ewiki_config; - - $html = ""; - srand(time()/17-1000*microtime()); - - #-- once _this_ function was called, all @s shall be send as-is - $ewiki_config["@"] = 1; - - #-- spamtraps, and companys/orgs fighting for spammers rights - $domains = explode(",", - $ewiki_config["feedbots_tarpits"]. "," .$ewiki_config["feedbots_badguys"] - ); - $traps = explode(" ", "blockme@relays.osirusoft.com simon.templar@rfc1149.net james.bond@ada-france.org anton.dvorak@ada.eu.org amandahannah44@hotmail.com usenet@fsck.me.uk meatcan2@beatrice.rutgers.edu heystupid@artsackett.com listme@dsbl.org bill@caradoc.org spamtrap@spambouncer.org spamtrap@woozle.org gfy@spamblocked.com listme@blacklist.woody.ch tarpit@lathi.net"); - $word_parts = explode(" ", "er an Ma ar on in el en le ll Ca ne ri De Mar Ha Br La Co St Ro ie Sh Mc re or Be li ra Al la al Da Ja il es te Le ha na Ka Ch is Ba nn ey nd He tt ch Ho Ke Ga Pa Wi Do st ma Mi Sa Me he to Car ro et ol ck ic Lo Mo ni ell Gr Bu Bo Ra ia de Jo El am An Re rt at Pe Li Je She Sch ea Sc it se Cha Har Sha Tr as ng rd rr Wa so Ki Ar Bra th Ta ta Wil be Cl ur ee ge ac ay au Fr ns son Ge us nt lo ti ss Cr os Hu We Cor Di ton Ri ke Ste Du No me Go Va Si man Bri ce Lu rn ad da ill Gi Th and rl ry Ros Sta sh To Se ett ley ou Ne ld Bar Ber lin ai Mac Dar Na ve no ul Fa ann Bur ow Ko rs ing Fe Ru Te Ni hi ki yn ly lle Ju Del Su mi Bl di lli Gu ine do Ve Gar ei Hi vi Gra Sto Ti Hol Vi ed ir oo em Bre Man ter Bi Van Bro Col id Fo Po Kr ard ber sa Con ick Cla Mu Bla Pr Ad So om io ho ris un her Wo Chr Her Kat Mil Tre Fra ig Mel od nc yl Ale Jer Mcc Lan lan si Dan Kar Mat Gre ue rg Fi Sp ari Str Mer San Cu rm Mon Win Bel Nor ut ah Pi gh av ci Don ot dr lt ger co Ben Lor Fl Jac Wal Ger tte mo Er ga ert tr ian Cro ff Ver Lin Gil Ken Che Jan nne arr va ers all Cal Cas Hil Han Dor Gl ag we Ed Em ran han Cle im arl wa ug ls ca Ric Par Kel Hen Nic len sk uc ina ste ab err Or Am Mor Fer Rob Luc ob Lar Bea ner pe lm ba ren lla der ec ric Ash Ant Fre rri Den Ham Mic Dem Is As Au che Leo nna rin enn Mal Jam Mad Mcg Wh Ab War Ol ler Whi Es All For ud ord Dea eb nk Woo tin ore art Dr tz Ly Pat Per Kri Min Bet rie Flo rne Joh nni Ce Ty Za ins eli ye rc eo ene ist ev Der Des Val And Can Shi ak Gal Cat Eli May Ea rk nge Fu Qu nie oc um ath oll bi ew Far ich Cra The Ran ani Dav Tra Sal Gri Mos Ang Ter mb Jay les Kir Tu hr oe Tri lia Fin mm aw dy cke itt ale wi eg est ier ze ru sc My lb har ka mer sti br ya Gen Hay a b c d e f g h i j k l m n o p q r s t u v w x y z"); - $word_delims = explode(" ", "0 1 2 3 3 3 4 5 5 6 7 8 9 - - - - - - - _ _ _ _ _ _ _ . . . . . . ."); - $n_dom = count($domains)-1; - $n_trp = count($traps)-1; - $n_wpt = count($word_parts)-1; - $n_wdl = count($word_delims)-1; - - for ($n = 1; $n < $limit; $n++) { - - // email name part - $m = ""; - while (strlen($m) < rand(3,17)) { - $a = $word_parts[nat_rand($n_wpt)]; - if (!empty($m)) { - $a = strtolower($a); - if (rand(1,9)==5) { - $m .= $word_delims[rand(0,$n_wdl)]; - } - } - $m .= $a; - } - - // add domain - switch ($dom = $domains[rand(0, $n_dom)]) { - - case "@123webhosting.org": - $m = strtr($_SERVER["REMOTE_ADDR"], ".", "-")."-".$_SERVER["SERVER_NAME"]."-".time(); - break; - - default: - } - $m .= $dom; - - $html .= ''.$m.''.",\n"; - } - - $html .= ''.$traps[rand(0, $n_trp)].''; - - if (($rl = 1 + @$_REQUEST[EWIKI_UP_REQUESTLV]) < EWIKI_FAKE_EMAIL_LOOP) { - $html .= ",\n" . '
      ewiki_email_protect_encode($m, 1), - EWIKI_UP_REQUESTLV=>"$rl" - ) - ) . '">' . ewiki_t("PROTE5") . '
      ' . "\n"; - ($rl > 1) && sleep(3); - } - - sleep(1); - return($html); - } - - - - function nat_rand($max, $dr=0.5) { - $x = $max+1; - while ($x > $max) { - $x = rand(0, $max * 1000)/100; - $x = $x * $dr + $x * $x / 2 * (1-$dr) / $max; - } - return((int)$x); - } - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/feature/anacron.meta b/mods/wiki/plugins/feature/anacron.meta deleted file mode 100644 index 88929e5a0..000000000 --- a/mods/wiki/plugins/feature/anacron.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: extension -hooks: init -type: intercept -config: - EWIKI_ANACRON_INTERLEAVE=2*3600 // in seconds - EWIKI_ANACRON_ID="etc/anacron/last-run" // a _SYSTEM entry -title: anacron -description: support code for the tools/cron.d/ utilities -priority: rare diff --git a/mods/wiki/plugins/feature/anacron.php b/mods/wiki/plugins/feature/anacron.php deleted file mode 100644 index 7a83791d0..000000000 --- a/mods/wiki/plugins/feature/anacron.php +++ /dev/null @@ -1,43 +0,0 @@ -= UNIX_MILLENNIUM) - and (time() >= $d["last"] + EWIKI_ANACRON_INTERLEAVE) ) - { - register_shutdown_function("ewiki_anacron_runparts"); - } -} - - -#-- every two hours: starts run-parts -function ewiki_anacron_runparts() { - - // clean up env, because we've been triggered by someone innocent - $_SERVER["REMOTE_ADDR"] = "0.0.0.0"; - $_SERVER["REMOTE_PORT"] = "-"; - $ewiki_author = "ewiki_anacron_runparts"; - - // only works for more or less standard installations - include(EWIKI_BASE_DIR."/tools/cron.d/run-parts.php"); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/feature/announcements.meta b/mods/wiki/plugins/feature/announcements.meta deleted file mode 100644 index ef4ed6b62..000000000 --- a/mods/wiki/plugins/feature/announcements.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -category: extension -hooks: delegator -type: special -title: announcements -description: displays pages from a list rather than the requested page -author: Andy Fundinger -priority: rare diff --git a/mods/wiki/plugins/feature/announcements.php b/mods/wiki/plugins/feature/announcements.php deleted file mode 100644 index fa6628034..000000000 --- a/mods/wiki/plugins/feature/announcements.php +++ /dev/null @@ -1,64 +0,0 @@ - 0); - -function ewiki_announcements($id, $data, $action){ - global $ewiki_plugins, $ewiki_config; - - if(!isset($GLOBALS['ewiki_auth_user'])){ - return; - } - - $notifyDates=ewiki_get_uservar("NotifyDates",FALSE); - - if(!$notifyDates){ - $notifyDates=$ewiki_config["DefaultNotify"]; - }else{ - $notifyDates=unserialize($notifyDates); - } - - foreach($notifyDates as $pageName=>$date){ - $data=ewiki_db::GET($pageName); - - if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($pageName, $data, "view")) { - continue; - } - - if($data['lastmodified']>$date){ - $dispDate=$data['lastmodified']; - $dispPage=$pageName; - break; - } - } - - if(!isset($dispPage)) - return; - - $notifyDates[$dispPage]=$dispDate; - ewiki_set_uservar("NotifyDates",serialize($notifyDates)); - - $o=ewiki_page('view/'.$dispPage); - - //page_final plugins have been run, unset them - unset($ewiki_plugins["page_final"]); - - return($o); - -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/feature/appendcomments.meta b/mods/wiki/plugins/feature/appendcomments.meta deleted file mode 100644 index 00581155e..000000000 --- a/mods/wiki/plugins/feature/appendcomments.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: extension -hooks: edit_hook, edit_save, handler -type: intercept -config: - EWIKI_APPENDONLY_COMMENTSPART="/Comments" -title: appendcomments -description: _APPENDONLY flagged pages can only be appended text as comments -priority: rare diff --git a/mods/wiki/plugins/feature/appendcomments.php b/mods/wiki/plugins/feature/appendcomments.php deleted file mode 100644 index 9e6ea335b..000000000 --- a/mods/wiki/plugins/feature/appendcomments.php +++ /dev/null @@ -1,109 +0,0 @@ -= 2)) { - - #-- fill edit box with contents from "$id/Content" page - $c_id = $id.EWIKI_APPENDONLY_COMMENTSPART; - $data = ewiki_db::GET($c_id); - if (!$data["version"]) { - $data = array( - "id" => $c_id, - "version" => NULL, - "flags" => EWIKI_DB_F_PART|EWIKI_DB_F_TEXT, - "created" => time(), - "lastmodified" => time(), - "hits" => 0, - "meta" => array("parent" => $id), - "content" => "", - "refs" => "", - ); - } - $data["flags"] = EWIKI_DB_F_TEXT; # another ugly workaround - - #-- change "edit" title to "append" - foreach (array_keys($ewiki_t) as $LANG) { - if ($ewiki_t[$LANG]["APPENDTOPAGE"]) { - $ewiki_t[$LANG]["EDITTHISPAGE"] = &$ewiki_t[$LANG]["APPENDTOPAGE"]; - } - } - - } - } -} - - -/* - manages ewiki_edit_page() to store the currently edited /Comments - part back into the correct database entry (and not the main page) -*/ -function ewiki_edit_save_appendcomments(&$save, &$old) { - - if ($old["meta"]["parent"] == $save["id"]) { - if (!EWIKI_PROTECTED_MODE || ($ewiki_ring >= 2)) { - - #-- transform $save entry into "/Comments" page request - $save["id"] = $old["id"]; - $save["flags"] = EWIKI_DB_F_TEXT|EWIKI_DB_F_PART; - $save["created"] = $old["created"]; - $save["hits"] = $old["hits"]; - $save["meta"] = $old["meta"]; - # leaving as is: content, refs, author, lastmodified - - } - } -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/feature/appendonly.meta b/mods/wiki/plugins/feature/appendonly.meta deleted file mode 100644 index 549f332b8..000000000 --- a/mods/wiki/plugins/feature/appendonly.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: extension -priority: bonus -hooks: edit_hook, edit_save -type: intercept -title: appendonly -description: if the _APPENDONLY page flag is set, users can further only append text to it diff --git a/mods/wiki/plugins/feature/appendonly.php b/mods/wiki/plugins/feature/appendonly.php deleted file mode 100644 index 09ac20a88..000000000 --- a/mods/wiki/plugins/feature/appendonly.php +++ /dev/null @@ -1,69 +0,0 @@ -= 2))) { - if ($data["version"] && strlen($data["content"])) { - if (!$_REQUEST["content"] || !$_REQUEST["version"]) { - - #-- only show the editable part in the edit box - $data["content"] = "----\n\n"; - - #-- change "edit" title to "append" - foreach (array_keys($ewiki_t) as $LANG) { - if ($ewiki_t[$LANG]["APPENDTOPAGE"]) { - $ewiki_t[$LANG]["EDITTHISPAGE"] = &$ewiki_t[$LANG]["APPENDTOPAGE"]; - } - } - - } - } - } -} - - - -function ewiki_edit_save_appendonly(&$save, &$old) { - - global $ewiki_ring; - - if ((($old["flags"] & EWIKI_DB_F_ACCESS) == EWIKI_DB_F_APPENDONLY) && (!EWIKI_PROTECTED_MODE || ($ewiki_ring >= 2))) { - if ($old["version"] && ($old_len=strlen($old_str=&$old["content"]))) { - - #-- add newlines and a horizontal bar - $old_str = rtrim($old_str); - if (substr($old_str, $old_len-5, 4) == "----") { - $old_str = rtrim(rtrim($old_str, "-")); - } - $old_str .= "\n\n"; - if (!preg_match("/^\n*----/", $save["content"])) { - $save["content"] = "----\n\n" . $save["content"]; - } - - #-- merge the old not-editable-part with the new append-part - $save["content"] = $old["content"] - . "\n\n" - . $save["content"]; - - } - } -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/feature/appendwrite.meta b/mods/wiki/plugins/feature/appendwrite.meta deleted file mode 100644 index 35d4e60b1..000000000 --- a/mods/wiki/plugins/feature/appendwrite.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: extension -hooks: handler, edit_hook, edit_save -type: intercept -config: - EWIKI_APPENDWRITE_AUTOLOCK=1 -title: appendwrite -description: allows full-write access to only a second part/section of an _APPENDONLY+_WRITEABLE flagged page -priority: rare diff --git a/mods/wiki/plugins/feature/appendwrite.php b/mods/wiki/plugins/feature/appendwrite.php deleted file mode 100644 index 2bdce56a8..000000000 --- a/mods/wiki/plugins/feature/appendwrite.php +++ /dev/null @@ -1,112 +0,0 @@ -= 2))) { - if ($data["version"] && strlen($data["content"]) && !$_REQUEST["content"]) { - if ($end = ewiki_appendwrite_split($data["content"])) { - - #-- only show the editable part in the edit box - $data["content"] = substr($data["content"], $end); - - # change "edit" title to "append" - foreach (array_keys($ewiki_t) as $LANG) { - if ($ewiki_t[$LANG]["APPENDTOPAGE"]) { - $ewiki_t[$LANG]["EDITTHISPAGE"] = &$ewiki_t[$LANG]["APPENDTOPAGE"]; - } - } - } } } -} - - - -/* - merges the not-editable part, with the submitted - changes to the appendonly/writable part -*/ -function ewiki_edit_save_appendwrite(&$save, &$old) { - - global $ewiki_ring; - - if (($old["flags"] & EWIKI_DB_F_APPENDWRITE) && (!EWIKI_PROTECTED_MODE || ($ewiki_ring >= 2))) { - if ($old["version"] && strlen($old["content"])) { - if ($end = ewiki_appendwrite_split($old["content"])) { - - #-- merge the old not-editable-part with the new append-part - $save["content"] = substr($old["content"], 0, $end+1) - . $save["content"]; - - } } } -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/feature/fset_actionurls.meta b/mods/wiki/plugins/feature/fset_actionurls.meta deleted file mode 100644 index bca9c425f..000000000 --- a/mods/wiki/plugins/feature/fset_actionurls.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -type: virtual -category: feature -config: - EWIKI_ACTION_USE_PARAM=2 - EWIKI_ACTION_TAKE_ASIS=0 -title: fset_actionurls -description: will default ewiki to use "?WikiPage&action=view" like URLs -priority: never diff --git a/mods/wiki/plugins/feature/fset_actionurls.php b/mods/wiki/plugins/feature/fset_actionurls.php deleted file mode 100644 index e2e9cc008..000000000 --- a/mods/wiki/plugins/feature/fset_actionurls.php +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/feature/imgfile_naming.meta b/mods/wiki/plugins/feature/imgfile_naming.meta deleted file mode 100644 index 6af49fdee..000000000 --- a/mods/wiki/plugins/feature/imgfile_naming.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: extension -title: imagefile naming -description: beautyfies generated internal:// links -priority: bonus -hooks: binary_store -type: database diff --git a/mods/wiki/plugins/feature/imgfile_naming.php b/mods/wiki/plugins/feature/imgfile_naming.php deleted file mode 100644 index f6b5530ee..000000000 --- a/mods/wiki/plugins/feature/imgfile_naming.php +++ /dev/null @@ -1,70 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/feature/imgresize_gd.meta b/mods/wiki/plugins/feature/imgresize_gd.meta deleted file mode 100644 index 9d383b2b6..000000000 --- a/mods/wiki/plugins/feature/imgresize_gd.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: extension -title: image resizing PHP libgd -description: scales images down, when uploaded on the edit page -priority: default -hooks: image_resize -type: intercept -config: - EWIKI_IMGRESIZE_WIN=0 diff --git a/mods/wiki/plugins/feature/imgresize_gd.php b/mods/wiki/plugins/feature/imgresize_gd.php deleted file mode 100644 index 992b22d03..000000000 --- a/mods/wiki/plugins/feature/imgresize_gd.php +++ /dev/null @@ -1,126 +0,0 @@ - EWIKI_IMAGE_MAXSIZE)) { - - if ($filename == $tmp_rescale) { - $tmp_rescale = tempnam(EWIKI_TMP, "ewiki.img_resize_gd.tmp."); - } - - #-- sizes - $new_x = (int) ($orig_x * $r); - $new_y = (int) ($orig_y * $r); - - #-- new gd image - $tc = function_exists("imageistruecolor") && imageistruecolor($orig_image); - if (!$tc || ($type == "gif")) { - $new_image = imagecreate($new_x, $new_y); - imagepalettecopy($new_image, $orig_image); - } - else { - $new_image = imagecreatetruecolor($new_x, $new_y); - } - - #-- resize action - imagecopyresized($new_image, $orig_image, 0,0, 0,0, $new_x,$new_y, $orig_x,$orig_y); - - #-- special things - if ( ($type == "png") && function_exists("imagesavealpha") ) { - imagesavealpha($new_image, 1); - } - - #-- save - if (function_exists($pf = "image$type")) { - $pf($new_image, $tmp_rescale); - } - else { - return(false); # cannot save in orig format (.gif) - } - - #-- prepare next run - imagedestroy($new_image); - clearstatcache(); - $r *= 0.95; - } - - #-- stop - imagedestroy($orig_image); - - #-- security check filesizes, abort - if (!filesize($filename) || !filesize($tmp_rescale) || (filesize($tmp_rescale) > EWIKI_IMAGE_MAXSIZE)) { - unlink($tmp_rescale); - return($false); - } - - #-- set $mime, as it may have changed (.gif) - $mime = strtok($mime, "/") . "/" . $type; - if (!strstr($filename, ".$type")) { - unlink($filename); - $filename .= ".$type"; - } - - #-- move tmp file to old name - copy($tmp_rescale, $filename); - unlink($tmp_rescale); - return(true); - -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/feature/imgresize_gd2.meta b/mods/wiki/plugins/feature/imgresize_gd2.meta deleted file mode 100644 index ba0f097f8..000000000 --- a/mods/wiki/plugins/feature/imgresize_gd2.meta +++ /dev/null @@ -1,15 +0,0 @@ -api: ewiki -category: extension -hooks: image_resize -type: intercept -config: - EWIKI_IMGRESIZE_WIN=0 - EWIKI_IMAGE_MAX_PIXELS=11000000 //11 megapixels - EWIKI_IMAGE_MAXSIZE=65536 - EWIKI_IMAGE_TOLERANCE=60000 //don't settle for smaller than this during resize - EWIKI_WORK_AREA=640 //width of whitespace or work area within ewiki - EWIKI_IMAGE_MAX_Y=1000 //max y value if picture is "candy cane" - EWIKI_IMAGE_RATIO=10 //maximum acceptable y:x ratio -title: imgresize_gd2 -description: refined algorithm for downscaling uploaded images -priority: bonus diff --git a/mods/wiki/plugins/feature/imgresize_gd2.php b/mods/wiki/plugins/feature/imgresize_gd2.php deleted file mode 100644 index 2bb5fd9fc..000000000 --- a/mods/wiki/plugins/feature/imgresize_gd2.php +++ /dev/null @@ -1,351 +0,0 @@ - EWIKI_IMAGE_MAX_X) - { - return true; - } - - if (filesize($a_fileName) > EWIKI_IMAGE_MAXSIZE) - { - return true; - } - - return false; -} - -function isImageTolerable($a_fileName) -{ - clearstatcache(); - - if (filesize($a_fileName) > EWIKI_IMAGE_MAXSIZE) - { - return false; - } - - if (filesize($a_fileName) < EWIKI_IMAGE_TOLERANCE) - { - return false; - } - - return true; -} - -function getImageStream($filename,$type) -{ - $retval=NULL; - - if ((($type != "gif") && ($type !="jpeg") && ($type !="png") && ($type != "vnd.wap.wbmp"))) - { - return($retval); - } - - if (!function_exists($pf = "imagecreatefrom$type")) - { - return($retval); - } - - $retval = $pf($filename); - - return($retval); -} - -function getInitialResize($orig_image,&$new_x,&$new_y) -{ - getXY($orig_image,$orig_x,$orig_y); - - if ($orig_x <= EWIKI_IMAGE_MAX_X) - //keep original dimesions - { - $new_x=$orig_x; - $new_y=$orig_y; - } - else - //wider than max width, so resize - { - $new_x=EWIKI_IMAGE_MAX_X; - $new_y=(int)((EWIKI_IMAGE_MAX_X*$orig_y)/$orig_x); - } -} - -function doResize($orig_image,$new_x,$new_y,&$type) -{ - $tc = function_exists("imageistruecolor") && imageistruecolor($orig_image); - if (!$tc || ($type == "gif")) - { - $new_image = imagecreate($new_x, $new_y); - $white = imagecolorallocate($new_image,255,255,255); - imagefill($new_image, 0, 0, $white); - imagepalettecopy($new_image, $orig_image); - } - else - { - $new_image = imagecreatetruecolor($new_x, $new_y); - $white = imagecolorallocate($new_image,255,255,255); - imagefill($new_image, 0, 0, $white); - } - - getXY($orig_image,$orig_x,$orig_y); - - #-- resize action - imagecopyresampled($new_image, $orig_image, 0,0, 0,0, $new_x,$new_y, $orig_x,$orig_y); - - $type = "jpeg"; - - return($new_image); -} - -function doSave(&$image,$filename,$type) -{ - if (function_exists($pf = "image$type")) - { - $pf($image,$filename,70); - } - else - { - return(false); # cannot save in orig format - } -} - -function isCandyCane($filename) -{ - clearstatcache(); - - list($width, $height, $type, $attr) = getimagesize($filename); - $ratio = ($height/$width); - $fs = filesize($filename); - - if (($ratio > EWIKI_IMAGE_RATIO) && ($fs > EWIKI_IMAGE_MAXSIZE) && ($height > EWIKI_IMAGE_MAX_Y)) - { - ewiki_log("$filename is a candy cane",3); - return true; - } - return false; -} - -function isMemoryFriendly($filename) -{ - list($width, $height, $type, $attr) = getimagesize($filename); - $pixels = (int)($height*$width); - - if ($pixels > EWIKI_IMAGE_MAX_PIXELS) - { - ewiki_log("$filename at $pixels pixels is too big!",3); - return false; - } - - return true; -} - -function resizeImage(&$filename, &$mime, $return=0) -{ - //start timing - $time_start = getmicrotime(); - - /*** this disallows Win32 ***/ - if ((DIRECTORY_SEPARATOR!="/") && !EWIKI_IMAGERESIZE_WIN || (strpos($mime, "image/")!==0)) - { - return(false); - } - - if (!isMemoryFriendly($filename)) - { - return false; - } - - if (isCandyCane($filename)) - { - return false; - } - - $rescaled_filename = $filename; - - $type = getTypeFromMIME($mime); - - $orig_image = getImageStream($rescaled_filename,$type); - if (!isset($orig_image)) - { - return(false); - } - - getXY($orig_image,$orig_x,$orig_y); - - if (!isResizeNeeded($orig_x, $filename)) - return true; - - getInitialResize($orig_image,$new_x,$new_y); - - $orig_image = doResize($orig_image,$new_x,$new_y,$type); - - $rescaled_filename = tempnam(EWIKI_TMP, "ewiki.img_resize_gd.tmp."); - doSave($orig_image,$rescaled_filename,$type); - - if (isResizeNeeded($new_x, $rescaled_filename)) - //will only take cases that need to be resized - { - ewiki_log("Resize beyond initial resize is needed. Carrying through.",3); - - //set starting points for binary search - $x_max=EWIKI_IMAGE_MAX_X-1; - $x_min=EWIKI_IMAGE_MIN_X; - - //set failsafe break to max number of iterations through the loop - $failsafe = (int)(log($orig_x)+1); - - while (($x_min <= $x_max) && !isImageTolerable($rescaled_filename)) - //the resize while loop - { - ewiki_log("While loop initiated",3); - - //somehow made it to an infinite loop, so get out - if($failsafe < 0) return(false); - - //take a guess at the correct width - $x_guess=(int)(($x_max+$x_min)/2); - - if ($filename == $rescaled_filename) - { - $rescaled_filename = tempnam(EWIKI_TMP, "ewiki.img_resize_gd.tmp."); - } - - #-- sizes - $new_x = (int)($x_guess); - $new_y = (int)(($x_guess*$orig_y)/$orig_x); - - $new_image = doResize($orig_image,$new_x,$new_y,$type); - - doSave($new_image,$rescaled_filename,$type); - - #-- prepare next run - imagedestroy($new_image); - clearstatcache(); - - $failsafe--; - - $ftmp = filesize($rescaled_filename); - ewiki_log("xguess: $x_guess, xmin: $x_min, xmax: $x_max, filesize: $ftmp",3); - - if (filesize($rescaled_filename) < EWIKI_IMAGE_TOLERANCE) - { - $x_min=$x_guess+1; - } - else if (filesize($rescaled_filename) > EWIKI_IMAGE_MAXSIZE) - { - $x_max=$x_guess-1; - } - } - - ewiki_log("While loop ended",3); - - } - - #-- stop - imagedestroy($orig_image); - clearstatcache(); - - #-- security check filesizes, abort - if (!filesize($filename) || !filesize($rescaled_filename) || (filesize($rescaled_filename) > EWIKI_IMAGE_MAXSIZE)) - { - unlink($rescaled_filename); - return($false); - } - - #-- set $mime, as it may have changed (.gif) - $mime = strtok($mime, "/") . "/" . $type; - if (!strstr($filename, ".$type")) - { - unlink($filename); - $filename .= ".$type"; - } - - #-- move tmp file to old name - copy($rescaled_filename, $filename); - unlink($rescaled_filename); - - //end timing - $time_end = getmicrotime(); - $time = $time_end - $time_start; - ewiki_log("$time seconds to perform resizing", 3); - - return(true); -} -?> \ No newline at end of file diff --git a/mods/wiki/plugins/feature/imgresize_magick.meta b/mods/wiki/plugins/feature/imgresize_magick.meta deleted file mode 100644 index bc3032493..000000000 --- a/mods/wiki/plugins/feature/imgresize_magick.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: extension -title: image resizing ImageMagick -description: requires an installed ImageMagick binary on the server -hooks: image_resize -type: intercept -priority: rare diff --git a/mods/wiki/plugins/feature/imgresize_magick.php b/mods/wiki/plugins/feature/imgresize_magick.php deleted file mode 100644 index d4b8a9a99..000000000 --- a/mods/wiki/plugins/feature/imgresize_magick.php +++ /dev/null @@ -1,66 +0,0 @@ - EWIKI_IMAGE_MAXSIZE)) { - - @unlink($tmp_rescale); - copy($filename, $tmp_rescale); - - $n = round($scale * 100); - exec("mogrify -scale $n%x$n% $tmp_rescale"); - - clearstatcache(); - $scale = $scale * 0.95; - $tmp_size = filesize($tmp_rescale); - } - - - #-- return result - if ((filesize($tmp_rescale)) && - (filesize($tmp_rescale) < filesize($filename)) && - (filesize($tmp_rescale) < EWIKI_IMAGE_MAXSIZE)) - { - @unlink($filename); - $filename = $tmp_rescale; - return($true); - } - else { - @unlink($tmp_rescale); - return($false); - } - -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/feature/pingback.meta b/mods/wiki/plugins/feature/pingback.meta deleted file mode 100644 index 91c70baec..000000000 --- a/mods/wiki/plugins/feature/pingback.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: extension -hooks: edit_save, init -type: api -title: PingBack -description: accept and send PingBacks automatically (with auto-discovery) -priority: bonus -homepage: http://www.hixie.ch/specs/pingback/pingback -depends: xmlrpc -version: 0.2 diff --git a/mods/wiki/plugins/feature/pingback.php b/mods/wiki/plugins/feature/pingback.php deleted file mode 100644 index a035b03b4..000000000 --- a/mods/wiki/plugins/feature/pingback.php +++ /dev/null @@ -1,198 +0,0 @@ - to - your site layout script. -*/ - - - -#-- plugin registration -$wikiapi["pingback.ping"] = "ewiki_pingback_rpc"; -$ewiki_plugins["edit_save"][] = "ewiki_pingback_newurls"; -$ewiki_plugins["init"][] = "ewiki_pingback_header"; -@$ewiki_config["ua"] .= " PingBack/0.2"; - - -#-- server part (adding URLs to our pages) ------------------------------- -function ewiki_pingback_rpc($source_url, $target_url) { - global $ewiki_config; - - #-- does the target URL refer to a known WikiPage ? - $id = ewiki_url2id($target_url); - if (!$id) { - xmlrpc_send_response(xmlrpc_error(0x0021, "Could not determine PageName for the given target URL.")); - } - if (!($data = ewiki_db::GET($id))) { - xmlrpc_send_response(xmlrpc_error(0x0020, "The given target page does not exist.")); - } - - - #-- check if the caller really has a link as he claims - ini_set("user_agent", $ewiki_config["ua"]); - if ((strpos($source_url, "http://")===0) && ($test = ewiki_http_asis($source_url, 96256))) { - $test = strtolower($test); - $test_url = strtolower($target_url); - if (!strpos($test, $test_url) - and !strpos($test, htmlentities($test_url))) { - return xmlrpc_error(0x0011, "Sorry, but couldn't find a link to '$target_url' on your given '$source_url' page."); - } - } - else { - return xmlrpc_error(0x0010, "Your given source URL does not exist, could not be retrieved."); - } - - #-- reject other frivolous links - if (preg_match('#^http://[^/]+/?$#', $source_url)) { - return xmlrpc_error(0x0011, "Rejected '$source_url' as frivolous."); - } - #-- check write permissions - if ((EWIKI_DB_F_TEXT != $data["flags"] & EWIKI_DB_F_TYPE) - or ($data["flags"] & EWIKI_DB_F_READONLY)) { - return xmlrpc_error(0x0031, "Sorry, but this page is write-protected or not a system page."); - } - #-- already on page - if (strpos($data["content"], $source_url)) { - return xmlrpc_error(0x0030, "The given link does already exist on this page."); - } - #-- other go-away cases - if (function_exists("ewiki_banned_url") && ewiki_banned_url($source_url) || function_exists("ewiki_blocked_url") && ewiki_blocked_url($source_url)) { - return xmlrpc_error(0x0100, "Your link is unwanted here (registered on BlockedLinks or BannedLinks)."); - } - - #-- else update page - $data["content"] = rtrim($data["content"]) - . "\n* $source_url (PingBack)\n"; - ewiki_db::UPDATE($data); - $data["version"]++; - $ok = ewiki_db::WRITE($data); - - #-- fin response - if ($ok) { - return("Link to '$source_url' was added to page '$id'."); - } - else { - return xmlrpc_error(0x0101, "Seems like a database/writing error occoured."); - } -} - - -#-- page id from absolute URL -function ewiki_url2id($url) { - if (strpos($url, EWIKI_SCRIPT_URL)===0) { - $id = substr($url, strlen(EWIKI_SCRIPT_URL)); - } - elseif ($l = strpos($url, "?id=")) { - $id = strtok(substr($url, $l+4), "&"); - } - elseif ($l = strpos($url, "?")) { - $id = strtok(substr($url, $l+1), "&"); - } - elseif (($l = strrpos($url, "/")) > 10) { - $id = strtok(substr($url, $l+1), "?&."); - } - return($id); -} - - -#-- notify clients that we're also server -function ewiki_pingback_header() { - header("X-PingBack: " . EWIKI_BASE_URL . "z.php"); -} - - - - -#-- client part (notify remote server of added URLs on current site) ----- -function ewiki_pingback_ping($source, $target) { - - #-- detect if $target URL is pingback-enabled, and go - if ($rpc_url = ewiki_pingback_discover($target)) { - - $res = xmlrpc_request($rpc_url, "pingback.ping", array($source, $target)); - // we don't care about the result, do we? - } -} - - -#-- short http request to discover X-Pingback header or tag -function ewiki_pingback_discover($url) { - global $ewiki_config; - - ini_set("user_agent", $ewiki_config["ua"]); - if ((strpos($url, "http://") === 0) && ($data = ewiki_http_asis($url, 4096))) { - if (preg_match('/\nX-Pingback:\s*([^\s,]+)/i', $data, $uu)) { - return($uu[1]); - } - elseif (preg_match('/]+rel=["\']?pingback["\']?[^>]+href=["\']?([^>"\'\s]+)/i', $data, $uu)) { - return($uu[1]); - } - } -} - - -#-- undeciphered GET request -function ewiki_http_asis($url, $maxsize=8192) { - global $ewiki_config; - $c = parse_url($url); - extract($c); - $port = $port ? $port : 80; - $path .= $query ? "?$query" : ""; - if ($f = fsockopen($host, $port, $errno, $errstr, $timeout=5)) { - fwrite($f, "GET $path HTTP/1.0\r\n" - . "Host: $host\r\n" - . "Connection: close\r\n" - . "Accept: text/html, application/xml, text/xml, application/xhtml+xml, text/plain\r\n" - . "User-Agent: $ewiki_config[ua]\r\n" - . "\r\n"); - socket_set_blocking($f, true); - $data = false; - while (!feof($f) && (strlen($data) < $maxsize)) { - $data .= fread($f, $maxsize); - } - fclose($f); - return($data); - } -} - - - -#-- check for newly added urls -function ewiki_pingback_newurls(&$save, &$old) { - - global $ewiki_plugins, $ewiki_config; - - #-- check newly added links - $newlinks = array_diff(explode("\n", trim($save["refs"])), explode("\n", trim($old["refs"]))); - foreach ($newlinks as $link) if (strpos($link, "://")) { - $ewiki_config["pingback"][] = $link; - } - if (@$ewiki_config["pingback"]) { - register_shutdown_function("ewiki_pingback_start"); - } -} - - -#-- registers all previously added URLs -function ewiki_pingback_start() { - - global $ewiki_plugins, $ewiki_config, $ewiki_id; - $source_url = ewiki_script_url("", $ewiki_id); - - foreach ($ewiki_config["pingback"] as $target_url) { - ewiki_pingback_ping($source_url, $target_url); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/feature/refererlog.meta b/mods/wiki/plugins/feature/refererlog.meta deleted file mode 100644 index 3b32f525a..000000000 --- a/mods/wiki/plugins/feature/refererlog.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: extension -hooks: view_final, shutdown -type: mangle -config: - EWIKI_REFERER_NOISE=2 -title: RefererLog -description: inserts validated REFERER urls at the bottom of pages -priority: bonus diff --git a/mods/wiki/plugins/feature/refererlog.php b/mods/wiki/plugins/feature/refererlog.php deleted file mode 100644 index 68a8097a5..000000000 --- a/mods/wiki/plugins/feature/refererlog.php +++ /dev/null @@ -1,166 +0,0 @@ -$s) { - if (strlen($s) <= 17) { - continue; - } - ($r = strpos($s, "?")) or ($r = strrpos($s, "/")); - $s = substr($s, 0, $r - 1); - if (strncmp($url, $s, strlen($s)) == 0) { - $page = substr($url, strlen($r)); - preg_match("°(([".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L."]+){2,}[\w\d]*)°", $page, $uu); - if ($page = $uu[1]) { - return("$moniker:$page"); - } - return(false); - } - } -} - - -#-- simple HTTP requests -function ewiki_http_query($method, $url, $params=0, $req_headers=0, $cookies=0) { - $R = array( - 0 => implode("", file($url)) - ); - return($R); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/feature/spellcheck.meta b/mods/wiki/plugins/feature/spellcheck.meta deleted file mode 100644 index 12d99552b..000000000 --- a/mods/wiki/plugins/feature/spellcheck.meta +++ /dev/null @@ -1 +0,0 @@ -type: R \ No newline at end of file diff --git a/mods/wiki/plugins/feature/spellcheck.php b/mods/wiki/plugins/feature/spellcheck.php deleted file mode 100644 index b5df9399d..000000000 --- a/mods/wiki/plugins/feature/spellcheck.php +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/feature/spellcheck2.meta b/mods/wiki/plugins/feature/spellcheck2.meta deleted file mode 100644 index 12d99552b..000000000 --- a/mods/wiki/plugins/feature/spellcheck2.meta +++ /dev/null @@ -1 +0,0 @@ -type: R \ No newline at end of file diff --git a/mods/wiki/plugins/feature/spellcheck2.php b/mods/wiki/plugins/feature/spellcheck2.php deleted file mode 100644 index a19effc0e..000000000 --- a/mods/wiki/plugins/feature/spellcheck2.php +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/feature/xpi.meta b/mods/wiki/plugins/feature/xpi.meta deleted file mode 100644 index bd2309be5..000000000 --- a/mods/wiki/plugins/feature/xpi.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -type: intercept -hook: init -page: PlugInstall -conflicts: xpi0 -title: XPI (full) -description: easy installation and managment of .xpi (and .jpi) plugins -priority: bonus -category: extension diff --git a/mods/wiki/plugins/feature/xpi.php b/mods/wiki/plugins/feature/xpi.php deleted file mode 100644 index 7c22e6e74..000000000 --- a/mods/wiki/plugins/feature/xpi.php +++ /dev/null @@ -1,424 +0,0 @@ - and installation procedures for .xpi -function ewiki_page_pluginstall($id, $data, $action) { - - global $ewiki_config, $ewiki_plugins; - $jpi_support = function_exists("js_compile") && function_exists("jsa_generate"); - $jpi_access = XPI_EVERYBODY_JPI && $jsi_support; - - #-- title - $o .= ewiki_make_title($id, $id, 2); - $o .= '
      ' - . ''; - - #-- pw, access - $access = 0; - $o .= ewiki_xpi_password($access, $jpi_access); - - - #-- upload & install - if ($access || $jpi_access) { - $o .= '

      .xpi plugin upload

      '; - - #-- if filename received => upload+install - if (($xpi_install_fn = $_REQUEST["install_remote_xpi"]) - or ($_REQUEST["install_xpi"]) - && ($xpi_install_fn = $_FILES["xpi_file"]["tmp_name"]) ) - { - $o .= ewiki_xpi_install($xpi_install_fn, $access, $jsi_access, $jsi_support); - } - #-- or upload - else { - $o .= ewiki_xpi_show_remote_repository(); - $o .= ewiki_xpi_upload_form(); - } - - $o .= '

      '; - } - - - #-- plugin control - $o .= ewiki_xpi_plugin_control_centre(); - - return($o); -} - - - -#-- install given file as .xpi plugin -function ewiki_xpi_install($xpi_install_fn, $access, $jsi_access, $jsi_support) { - ewiki_xpi_load_registry($registry, $registry_hash); - - #-- load (possibly remote) .xpi file - $xpi = ewiki_xpi_read($xpi_install_fn, "rb"); - if (!$xpi) { - return "not a valid .xpi plugin (or wrong/inacceptable xpi plugin type/version)"; - } - if (strlen($xpi["id"]) < 3) { - return "missing .xpi header"; - } - - #-- it's a .jpi plugin - if (($access || $jsi_access) && ($xpi["type"] == "jpi")) { - - #-- compile from JS (WikiScript) into sandboxed PHP - if ($jsi_support) { - $xpi["type"] = "page"; - js_compile($xpi["code"]); - $xpi["code"] = NULL; - $xpi["code"] = jsa_generate(); - } - else { - return "ERROR: cannot handle .jpi plugins without installed JavaScript interpreter"; - } - if ($GLOBALS["js_err"]) { - ewiki_log("failed compiling .jpi plugin '$xpi[id]'", 0); - return "ERROR: broken .jpi plugin!"; - } - - } - #-- else no permission to upload anything - elseif (!$access) { - return "ERROR: You don't have permission to install this type of plugin.

      "; - } - - - #-- proceed with setup - $xpi["state"] = 1; - if (function_exists("php_check_syntax")) { - if (!php_check_syntax($xpi["code"])) { - return "ERROR: plugin code is broken"; - } - } - - #-- create new database entry - $new = ewiki_new_data($xpi["id"], EWIKI_DB_F_SYSTEM|EWIKI_DB_F_EXEC); - $new["content"] = $xpi["code"]; - unset($xpi["code"]); - - - #-- check for old version - if ($access) { - $old = ewiki_db::GET($new["id"]); - if ($old["version"]) { - $new["version"] = $old["version"]+1; - $o .= "(overwriting plugin [version {$old[version]}])
      "; - } - } - - #-- store plugin into database - if (ewiki_db::WRITE($new)) { - ewiki_log("successfully installed .xpi plugin '$xpi[id]'", 0); - $o .= ($xpi["type"] == "page") ? ewiki_link($xpi[id]) : "{$xpi[id]}"; - $o .= " plugin stored. "; - - #-- update .xpi registry - $registry[$xpi["id"]] = $xpi; - $registry_hash["content"] = serialize($registry); - ewiki_data_update($registry_hash); - $registry_hash["version"]++; - ewiki_db::WRITE($registry_hash); - } - else { - $o .= "error saving"; - ewiki_log("error installing .xpi/.jpi plugin '$xpi[id]'", 0); - } - - return($o); -} - - - -#-- check pw, set cookie -function ewiki_xpi_password(&$access, &$jpi_access) { - - #-- check - $o = '\n"; - - return($o); -} - - - -#-- load .xpi plugin registry -function ewiki_xpi_load_registry(&$registry, &$registry_hash) { - $registry_hash = ewiki_db::GET(XPI_DB); - if (!$registry_hash || !($registry_hash["flags"] & EWIKI_DB_F_SYSTEM)) { - $registry_hash = ewiki_new_data(XPI_DB, EWIKI_DB_F_SYSTEM); - $registry_hash["version"] = 0; - $registry = array(); - } - else { - $registry = unserialize($registry_hash["content"]); - } -} - - - -#-- delete + disable plugins -function ewiki_xpi_plugin_control_centre() { - ewiki_xpi_load_registry($registry, $registry_hash); - - #-- title - $o = '

      plugin control

      '; - - #-- delete plugins - if ($access && ($uu = $_REQUEST["xpi_rm"])) { - foreach ($uu as $id=>$del) { - if ($del) { - $id = rawurldecode($id); - $dat = ewiki_db::GET($id); - $vZ = $dat["version"]; - for ($v=1; $v<=$vZ; $v++) { - ewiki_db::DELETE($id, $v); - } - unset($registry[$id]); - $vZ += 0; - $o .= "i: Purged $vZ versions of '$id' and removed xpi registry entry.

      "; - ewiki_log("uninstalled .xpi/.jpi plugin '$id'", 0); - } - } - $_REQUEST["setup_xpi"]=1; - } - - #-- update config settings - if ($_REQUEST["setup_xpi"]) { - - if ($access) { - foreach ($registry as $id=>$uu) { - $registry[$id]["state"] = $_REQUEST["xpi_set"][rawurlencode($id)] ?1:0; - } - - $registry_hash["content"] = serialize($registry); - ewiki_data_update($registry_hash); - $registry_hash["version"]++; - ewiki_db::WRITE($registry_hash); - } - else { - $o .= "You have no privileges to change the status of installed .xpi plugins.
      \n"; - } - } - - #-- enable/disable checkboxes - $o .= ''; - foreach ($registry as $dat) { - $enabled = ($dat["state"]==1); - $hard = ($dat["type"]=="page"); - $title = $hard ? ewiki_link($dat["id"]) : $dat["id"]; - $o .= '' - . '' - . '' - . '' - . '' - . '' - . '' - . ''; - } - $o .= '
      ' . $dat["type"] . '' . $title . '' . htmlentities($dat["description"]) . '' . $dat["author"] . ", " . $dat["license"] . '
      '; - $o .= '
      '; - $o .= '
      '; - - return($o); -} - - - -#-- plugin upload
      -function ewiki_xpi_upload_form() { - $o = 'Warning: before uploading an extension plugin, you should check its source, because you\'ll otherwise may open big security leaks in your installation.




      '; - $o .= 'Or install a plugin from one of the registered plugin directories:
      '; - foreach ($ewiki_config["xpi_dirs"] as $s) { - $o .= '
      '; - } - return($o); -} - - - -#-- show remote .xpi directory -function ewiki_xpi_show_remote_repository() { - if ($url = $_REQUEST["xpidir"]) { - $r = array(); - if ($urls = ewiki_util_getlinks($url, '[^\"\'\>\s]+?\.[jx]pi')) { - foreach ($urls as $fn) { - if ($xpi = ewiki_xpi_read($fn)) { - $xpi["XPI"] = $xpi["code"] = NULL; - if (!$access && $xpi["JPI"]) { - continue; - } - $r[$fn] = $xpi; - } - } - } - $o .= "install .xpi plugins from remote directory
      $url:
      " - . "don't do this, if you don't know the operator of the provided extension plugins (could contain malicious code)
      \n"; - $o .= ''; - foreach ($r as $fn=>$xpi) { - $o .= "\n".'' - . "" - . "" - . "" - . ''; - } - $o .= '
      ' - . '' - . '
      [{$xpi[type]}] {$xpi[id]} {$xpi[version]}{$xpi[description]}
      {$xpi[author]}, {$xpi[license]}

      '; - } - - return($o); -} - - - -#-- open binary .xpi file -function ewiki_xpi_read($fn, $maxsize=0x020000) { - if ($f = gzopen($fn, "rb")) { - $xpi = gzread($f, $maxsize); - gzclose($f); - } - if ($xpi) { - $xpi = unserialize($xpi); - if (($xpi["XPI"]=="0.1") - and (($xpi["engine"]=="ewiki") || ($xpi["type"]=="jpi")) - and $xpi["id"] && $xpi["type"] && $xpi["code"]) { - return($xpi); - } - } -} - - - -#-- read out file names from directory listing in .html format -function ewiki_util_getlinks($url, $regex='.+?') { - $r = array(); - - if ($html = @file($url)) { - $html = implode("", $html); - - $url_b = substr("$url", 0, strrpos($url, "/")); - $url_s = substr("$url", 0, strpos($url, "/", 10)); - - preg_match_all('#]+href=["\']?('.$regex.')["\'\s>]#i', $html, $uu); - foreach ($uu[1] as $fn) { - if ($fn[0] == "/") { - $fn = $url_s . $fn; - } - elseif (strpos($fn, "://")) { - } - else { - $fn = $url_b . "/" . $fn; - } - $r[] = $fn; - } - } - return($r); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/feature/xpi0.meta b/mods/wiki/plugins/feature/xpi0.meta deleted file mode 100644 index 6d3abdc4a..000000000 --- a/mods/wiki/plugins/feature/xpi0.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -type: intercept -hook: init -conflicts: xpi -title: XPI support -description: without the PlugInstall page -priority: rare -category: extension diff --git a/mods/wiki/plugins/feature/xpi0.php b/mods/wiki/plugins/feature/xpi0.php deleted file mode 100644 index 4de6abdac..000000000 --- a/mods/wiki/plugins/feature/xpi0.php +++ /dev/null @@ -1,55 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/filter/f_fixhtml.meta b/mods/wiki/plugins/filter/f_fixhtml.meta deleted file mode 100644 index 0ce946f68..000000000 --- a/mods/wiki/plugins/filter/f_fixhtml.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: filter -title: fiXhtml filter -description: tries to work around various formatting errors, and can even try to convince ewiki to generate valid XHTML -priority: rare -hooks: page_final -type: mangle -config: - EWIKI_XHTML=0 diff --git a/mods/wiki/plugins/filter/f_fixhtml.php b/mods/wiki/plugins/filter/f_fixhtml.php deleted file mode 100644 index f2c20cefd..000000000 --- a/mods/wiki/plugins/filter/f_fixhtml.php +++ /dev/null @@ -1,172 +0,0 @@ - inside
        or even -

        inside

        problems (this should rather be fixed in the ewiki_format - function). So following code is not meant to fix any possible html file, - and it certainly won't make valid html files out of random binary data. - So for full html spec conformance you should rather utilize w3c tidy (by - using your Webservers "Filter" directive). -*/ - - -define("EWIKI_XHTML", 0); -$ewiki_plugins["page_final"][] = "ewiki_html_tag_balancer"; - - -function ewiki_html_tag_balancer(&$html) { - - #-- vars - $html_standalone = array( - "img", "br", "hr", - "input", "meta", "link", - ); - $html_tags = array( - "a", "abbr", "acronym", "address", "applet", "area", "b", "base", - "basefont", "bdo", "big", "blockquote", "body", "br", "button", - "caption", "center", "cite", "code", "col", "colgroup", "dd", "del", - "dfn", "dir", "div", "dl", "dt", "em", "fieldset", "font", "form", - "h1", "h2", "h3", "h4", "h5", "h6", "head", "hr", "html", "i", - "iframe", "img", "input", "ins", "kbd", "label", "legend", "li", - "link", "map", "menu", "meta", "noframes", "noscript", "object", "ol", - "optgroup", "option", "p", "param", "pre", "q", "s", "samp", "script", - "select", "small", "span", "strike", "strong", "style", "sub", "sup", - "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "title", - "tr", "tt", "u", "ul", "var", - #-- H2.0 "nextid", "listing", "xmp", "plaintext", - #-- H3.2 "frame", "frameset", - #-- X1.1 "rb", "rbc", "rp", "rt", "rtc", "ruby", - ); - $close_opened_when = array( - "p", "div", "ul", "td", "table", "tr", - ); - if (!EWIKI_XHTML) { - $html_tags = array_merge( (array) $html_tags, array( - "bgsound", "embed", "layer", "multicol", "nobr", "noembed", - )); - } - - #-- walk through all tags - $tree = array(); - $len = strlen($html); - $done = ""; - $pos = 0; - $loop = 1000; - while (($pos < $len) && $loop--) { - - #-- search next tag - $l = strpos($html, "<", $pos); - $r = strpos($html, ">", $l); - if (($l===false) or ($r===false)) { - # finish - $done .= substr($html, $pos); - break; - } - - #-- copy plain text part - if ($l >= $pos) { - $done .= substr($html, $pos, $l-$pos); - $pos = $l; - } - - #-- analyze current html tag - if ($r >= $pos) { - $pos = $r + 1; - $tag = substr($html, $l + 1, $r - $l - 1); - - #-- split into name and attributes - $tname = strtolower(strtok($tag, " \t\n>")); // LOWERCASING not needed here really - ($tattr = strtok(">")) && ($tattr = " $tattr"); - - // attribute checking could go here - // (here we just assume good output from ewiki core) - // ... - - #-- html comment - if (substr($tname, 0, 3) == "!--") { - $r = strpos($html, "-->", $l+4); - $pos = $r + 3; - $done .= substr($html, $l, $r-$l+3); - continue; - } - - #-- opening tag? - elseif ($tname[0] != "/") { - - #-- standalone tag - if (in_array($tname, $html_standalone)) { - $tattr = rtrim(rtrim($tattr, "/")); - if (EWIKI_XHTML) { - $tattr .= " /"; - } - } - #-- normal tag - else { - if (in_array($tname, $html_tags)) { - #-- ok - } - else { - $tattr .= " class=\"$tname\""; - $tname = "div"; - } - array_push($tree, $tname); - } - - $tag = "$tname$tattr"; - } - #-- closing tag - else { - $tname = substr($tname, 1); - - if (!in_array($tname, $html_tags)) { - $tname= "div"; - } - - #-- check if this is allowed - if (!$tree) { - continue; // ignore closing tag - } - $last = array_pop($tree); - if ($last != $tname) { - - #-- close until last opened block element - if (in_array($tname, $close_opened_when)) { - do { - $done .= ""; - } - while (($last = array_pop($tree)) && ($last!=$tname)); - } - #-- close last, close current, reopen last - else { - array_push($tree, $last); - $done .= "<$last>"; - continue; - } - } - else { - #-- all ok - } - - #-- readd closing-slash to tag name - $tag = "/$tname"; - } - - $done .= "<$tag>"; - } - } - - #-- close still open tags - while ($tree && ($last = array_pop($tree))) { - $done .= ""; - } - - #-- copy back changes - $html = $done; - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/filter/f_msiepng.meta b/mods/wiki/plugins/filter/f_msiepng.meta deleted file mode 100644 index 0a1f203f1..000000000 --- a/mods/wiki/plugins/filter/f_msiepng.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: filter -title: MSIE .png support -description: instructs IE to use an ActiveX imageloader for .png images -hooks: view_final -type: mangle -config: - FIX_MSIE_NULL_GIF="/img/null.gif" -priority: deprecated diff --git a/mods/wiki/plugins/filter/f_msiepng.php b/mods/wiki/plugins/filter/f_msiepng.php deleted file mode 100644 index 5a28705fe..000000000 --- a/mods/wiki/plugins/filter/f_msiepng.php +++ /dev/null @@ -1,31 +0,0 @@ -]*?)\ssrc="([^">]+?png[^>"]*)"([^>]*?>)/i', - '$1 src="'.FIX_MSIE_NULL_GIF.'" style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'$2\', sizingMethod=\'scale\')"$3', - $html - ); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/filter/f_tidy.meta b/mods/wiki/plugins/filter/f_tidy.meta deleted file mode 100644 index 28dbd8e27..000000000 --- a/mods/wiki/plugins/filter/f_tidy.meta +++ /dev/null @@ -1,3 +0,0 @@ -api: ewiki -category: filter -title: f_tidy diff --git a/mods/wiki/plugins/filter/fun_chef.meta b/mods/wiki/plugins/filter/fun_chef.meta deleted file mode 100644 index 27237592e..000000000 --- a/mods/wiki/plugins/filter/fun_chef.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: filter -hooks: view_final -type: mangle -title: fun_chef -description: Code modelled after Joes Hess` description of the 'chef' filter from -priority: never diff --git a/mods/wiki/plugins/filter/fun_chef.php b/mods/wiki/plugins/filter/fun_chef.php deleted file mode 100644 index 7abf8c8c9..000000000 --- a/mods/wiki/plugins/filter/fun_chef.php +++ /dev/null @@ -1,77 +0,0 @@ -([^<>]+)".stripslashes(strhtml_chef("\\1"))."<"', $o); -} - - -function strhtml_chef($text) { - - #-- end of word - $text = preg_replace('/th\b/', 't', $text); - $text = preg_replace('/en\b/', 'ee', $text); - - #-- simple - $text = preg_replace('/the/', 'zhe', $text); - $text = preg_replace('/The/', 'Zhe', $text); - - #-- if not first letter - $text = preg_replace('/(\w)f/', '\\1ff', $text); - $text = preg_replace('/\b(\w+?)i(\w+)\b/', '\\1ee\\2', $text); - - #-- u to oo, o to u - $text = strtr($text, "uo", "ou"); - $text = preg_replace('/o/', 'oo', $text); - #-- first letter o - $text = preg_replace('/\bO(\w)/', 'Oo\\2', $text); - - #-- always (o and u rules) - $text = preg_replace('/au/', 'oo', $text); - $text = preg_replace('/Au/', 'Oo', $text); - - #-- always (not conflicting) - $text = preg_replace('/v/', 'f', $text); - $text = preg_replace('/V/', 'F', $text); - $text = preg_replace('/w/', 'v', $text); - $text = preg_replace('/W/', 'V', $text); - $text = preg_replace('/an/', 'un', $text); - $text = preg_replace('/An/', 'Un', $text); -// $text = preg_replace('/en/', 'un', $text); // for bug emulation - - #-- begin of word - $text = preg_replace('/\be/', 'i', $text); - $text = preg_replace('/\bE/', 'I', $text); - - #-- not last letter - $text = preg_replace('/[Aa](\w)/', 'e\\1', $text); - - #-- all following must take into account previous garbaging, and revert - # as needed - - #-- simple - $text = preg_replace('/(tion|teeun)/', 'shun', $text); - - #-- end of word - $text = preg_replace('/(?\nBork Bork Bork!
        \n", $text); - - return($text); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/filter/fun_screamomatic.meta b/mods/wiki/plugins/filter/fun_screamomatic.meta deleted file mode 100644 index 802135afd..000000000 --- a/mods/wiki/plugins/filter/fun_screamomatic.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: filter -title: scream-o-matic -description: uppercases all pages contents, if a user enters too much uppercase on a page -priority: never -hooks: edit_save, page_final -type: mangle diff --git a/mods/wiki/plugins/filter/fun_screamomatic.php b/mods/wiki/plugins/filter/fun_screamomatic.php deleted file mode 100644 index 27e1ff0f3..000000000 --- a/mods/wiki/plugins/filter/fun_screamomatic.php +++ /dev/null @@ -1,39 +0,0 @@ - $old_screaming) { - setcookie(EWIKI_UP_SCREAMOMATIC, "true", time()+7*24*3600, "/"); - } -} - - -function ewiki_page_final_fun_screamomatic(&$html, $id, &$data, $action) { - if ($_COOKIE[EWIKI_UP_SCREAMOMATIC]) { - $html = preg_replace('/>([^<>]+)".strtoupper(stripslashes("\\1"))."<"', $html); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/filter/fun_upsidedown.meta b/mods/wiki/plugins/filter/fun_upsidedown.meta deleted file mode 100644 index 52742c231..000000000 --- a/mods/wiki/plugins/filter/fun_upsidedown.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: filter -hooks: view_final, handler -type: mangle -title: fun_upsidedown -description: ripped from the debian text filters package -priority: never diff --git a/mods/wiki/plugins/filter/fun_upsidedown.php b/mods/wiki/plugins/filter/fun_upsidedown.php deleted file mode 100644 index d606b68df..000000000 --- a/mods/wiki/plugins/filter/fun_upsidedown.php +++ /dev/null @@ -1,80 +0,0 @@ -([^<>]+)".htmlentities((str_upsidedown(stripslashes("\\1"))))."<"', $o); -} - - -#-- this does the string transformation for plain ASCII text -function str_upsidedown($text) { - - $text = explode("\n", $text); - foreach ($text as $i=>$line) { - - $line = strrev($line); - $line = str_replace('"', "''", $line); - $line = strtolower($line); - - $line = strtr($line, - "abcdefghijklmnopqrstuvwxyz 123456789 ,!?¯_ []{}<> .'' ", - "eq)paj6y!fk7wuodbJsfn^mxhz l2Eh59L86 `i¿_¯ ][}{>< ',, " - ); - - $line = str_replace("k", ">|", $line); - $text[$i] = $line; - - } - $text = implode("\n", $text); - - return($text); -} - - -#-- reversal -function decode_upsidedown($text) { - $text = explode("\n", $text); - foreach ($text as $i=>$line) { - $line = str_replace(">|", "k", $line); - $line = strtr($line, - "eq)paj6y!fk7wuodbJsfn^mxhz l2E59L8 `i%_¯ ][}{>< ',, ", - "abcdefghijklmnopqrstuvwxyz 1235678 ,!?¯_ []{}<> .'' " - ); - $line = str_replace("''", '"', $line); - $line = strrev($line); - $text[$i] = $line; - } - $text = implode("\n", $text); - return($text); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/filter/fun_wella.meta b/mods/wiki/plugins/filter/fun_wella.meta deleted file mode 100644 index 32079e5d7..000000000 --- a/mods/wiki/plugins/filter/fun_wella.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: filter -hooks: view_final -type: mangle -title: fun_wella -description: adds some CSS to "beautify" the wiki page output -priority: never diff --git a/mods/wiki/plugins/filter/fun_wella.php b/mods/wiki/plugins/filter/fun_wella.php deleted file mode 100644 index 6ebffb603..000000000 --- a/mods/wiki/plugins/filter/fun_wella.php +++ /dev/null @@ -1,47 +0,0 @@ - '. - ' '; - break; - - default: - $o .= ' '; - break; - } - } - - $o .= '
        '; - $html = "$o$html"; -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/filter/search_highlight.meta b/mods/wiki/plugins/filter/search_highlight.meta deleted file mode 100644 index 5c1fe9b25..000000000 --- a/mods/wiki/plugins/filter/search_highlight.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: filter -title: search term highlighting -description: encolours the words from a previous search that led to the current page (links from PowerSearch or Google) -priority: extra -hooks: page_final -type: mangle diff --git a/mods/wiki/plugins/filter/search_highlight.php b/mods/wiki/plugins/filter/search_highlight.php deleted file mode 100644 index 354271f7b..000000000 --- a/mods/wiki/plugins/filter/search_highlight.php +++ /dev/null @@ -1,101 +0,0 @@ - $word) { - - if (empty($word)) { - continue; - } - - while ($l = strpos(strtolower($o), strtolower($word), $l)) { - - #-- check for html-tags - $t0 = strpos($o, "<", $l); - $t1 = strpos($o, ">", $l); - $found = substr($o, $l, strlen($word)); - if ((!$t0) || ($t0 < $t1)) { - - $repl = '' . $found . ''; - $o = substr($o, 0, $l) - . $repl - . substr($o, $l + strlen($word)); - - $l += strlen($repl); - } - - $l++; // advance strpos - } - - } // foreach(word) - - } - - } // if(q) - -} // func - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/init.php b/mods/wiki/plugins/init.php deleted file mode 100644 index 6047e2728..000000000 --- a/mods/wiki/plugins/init.php +++ /dev/null @@ -1,123 +0,0 @@ -WikiSetupWizard

        \n"; - $o .= "You don't have any pages in your Wiki yet, so we should try to read-in the default ones from init-pages/ now.

        "; - - $o .= '"now")).'">[InitializeWikiDatabase]'; - $o .= "   "; - $o .= '"this")).'">[NoThanks]'; - $o .= "

        "; - - #-- analyze and print settings and misconfigurations - $pf_db = $ewiki_plugins["database"][0]; - $db = substr("_$pf_db", strrpos($pf_db, "_") + 1); - $o .= ''; - $o .= '"; - - $o .= '"; - $o .= "
        DatabaseBackend'; - $o .= "" . $db . "
        "; - if (($db == "files") || strstr($db, "f2")) { - $o .= "_DBFILES_DIR='" . EWIKI_DBFILES_DIRECTORY . "'"; - if (strpos(EWIKI_DBFILES_DIRECTORY, "tmp")) { - $o .= "
        Warning: Storing your pages into a temporary directory is not what you want (there they would get deleted randomly), except for testing purposes of course. See the README."; - } - } - else { - $o .= "(looks ok)"; - } - $o .= "
        WikiSoftwareewiki '.EWIKI_VERSION."
        "; - - #-- more diagnosis - if (ini_get("magic_quotes")) { - $o.= "Warning: Your PHP interpreter has enabled the ugly and outdated 'magic_quotes'. This will lead to problems, so please ask your provider to correct it; or fix it yourself with .htaccess settings as documented in the README. Otherwise don't forget to include() the fragments/strip_wonderful_slashes.php (it's ok to proceed for the moment).

        "; - } - if (ini_get("register_globals")) { - $o.= "Security warning: The horrible 'register_globals' setting is enabled. Without always using fragments/strike_register_globals.php or letting your provider fix that, you could get into trouble some day.

        "; - } - - return('
        ' . $o . '
        '); - } - - - #-- actually initialize the database - else { - ewiki_db::INIT(); - if ($dh = @opendir($path=EWIKI_INIT_PAGES)) { - while ($filename = readdir($dh)) { - if (preg_match('/^(['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+\w*)+/', $filename)) { - $found = ewiki_db::FIND(array($filename)); - if (! $found[$filename]) { - $content = implode("", file("$path/$filename")); - ewiki_scan_wikiwords($content, $ewiki_links, "_STRIP_EMAIL=1"); - $refs = "\n\n" . implode("\n", array_keys($ewiki_links)) . "\n\n"; - $save = array( - "id" => "$filename", - "version" => "1", - "flags" => "1", - "content" => $content, - "author" => ewiki_author("ewiki_initialize"), - "refs" => $refs, - "lastmodified" => filemtime("$path/$filename"), - "created" => filectime("$path/$filename") // (not exact) - ); - ewiki_db::WRITE($save); - } - } - } - closedir($dh); - ewiki_log("initializing database", 0); - } - else { - return("ewiki error: could not read from directory ". realpath($path) ."
        \n"); - } - - #-- try to view/ that newly inserted page - if ($data = ewiki_db::GET($id)) { - $action = "view"; - } - - #-- let ewiki_page() proceed as usual - return(""); - } - } - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/input_trimming.meta b/mods/wiki/plugins/input_trimming.meta deleted file mode 100644 index cf36ef606..000000000 --- a/mods/wiki/plugins/input_trimming.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -type: intercept -hooks: init -funcs: ewiki_input_truncate, ewiki_check_input, ewiki_reset_key, ewiki_set_globals -title: InputTrimming -description: secures HTTP input by truncation and unsetting of unknown variables -author: Jeffrey Engleman -category: feature -priority: recommended diff --git a/mods/wiki/plugins/input_trimming.php b/mods/wiki/plugins/input_trimming.php deleted file mode 100644 index 94bfc9e2c..000000000 --- a/mods/wiki/plugins/input_trimming.php +++ /dev/null @@ -1,217 +0,0 @@ - array(INPUTNAME => INPUTLENGTH, INPUT2NAME => INPUT2LENGTH)); -//special PAGENAME entries include: -//_AllPages: handles submits that can appear on all pages e.g. username and password -//_Binary: handles submits that appear on binary pages e.g. internal://.... -//_Edit: handles submits from pages prefixed with edit/ and updateformatheader/ -$ewiki_input_limits=array( -"_AllPages" => array("username" => EWIKI_USERNAME_LENGTH, "password" => EWIKI_PASSWORD_LENGTH, "submit_login_img_x" => 2, - "submit_login_img_y" => 2, "submit_login" => 5, "thankyou" => 1, "id" => 160, "page" => 160, "PHPSESSID" => 32, - "i_am_no_spambot" => 12, "new_filename" => 160, "comment" => 1600000, "section" => 160, "year" => 4,"version" => 3, - EWIKI_UP_PAGENUM => EWIKI_UP_PAGE_LENGTH,EWIKI_UP_PAGEEND => EWIKI_UP_PAGE_LENGTH), -"_Binary" => array("binary" => 160), -"_Manage" => array("submit_manage" => 0, "liveuserPermsView" => 10,"liveuserPermsPublish" => 10), -"_Email" => array("email_address" => 340, "email_text" => 255,"not_first_time" => 1,"email_page" => 1), -"_Edit" => array("piclogocntrlSelectLogo" => 160, "pageimagecntrl" => 160, "encoded_email" => 0, "go" => 0, "preview" => 7, - "content" => 1677215 , "save" => 4, "liveuserPermsView" => 10, "liveuserPermsEdit" => 10, - "liveuserPermsPublish" => 10), -"WikiDump" => array("dump_id" => 160, "download_tarball" => 17, "dump_images" => 1, "dump_fullhtml" => 1, "dump_virtual" => 1, - "dump_depth" => 3, "dump_arclevel" => 1, "dump_arctype" => 3), -"ExAllTodo" => array("q" => 16), -"ExAllPolicy" => array("q" => 16), -"Search" => array("Submit_x" => 2, "Submit_y" => 2, "q" => 50, "where" => 7), -"SearchPages" => array("q" => 50), -"PowerSearch" => array("q" => 50, "where" => 7), -"AdminAddUsers" => array("username_text" => EWIKI_USERNAME_LENGTH, "text_E-Mail_Address" => EWIKI_USERNAME_LENGTH, - "group_list" => EWIKI_GROUPNAME_LENGTH, "submit_addusers" => 1, "text_" => 255), -"AdminPerms" => array("submit_changeperm" => 14, "ring_" => 3, "chk_" => 2, "letterfilter" => 5, "pagefilter" => 160,"classfilter" => 10, - "submit_filterperm" => 6, "pagename_text" => 160, "ring_list" => 3, "right_list" => 3, "submit_addperm" => 17), -"AdminPermsReport" => array("letterfilter" => 5, "pagefilter" => 160, "classfilter" => 10, "submit_filterperm" => 6), -"AdminRights" => array("chk_" => 2, "submit_changerights" => 14, "rightname_text" => 50, "addgroup" => 2, "submit_addright" => 9), -"AdminUsers" => array("chname_" => EWIKI_USERNAME_LENGTH, "origname_" => EWIKI_USERNAME_LENGTH, "usernames_text" => EWIKI_USERNAME_LENGTH*10, - "username_text" => EWIKI_USERNAME_LENGTH, "pw_text" => EWIKI_PASSWORD_LENGTH, "search_fieldname" => EWIKI_FIELDNAME_LENGTH, - "chgroupname_" => EWIKI_GROUPNAME_LENGTH, "usernames_grouplist" => EWIKI_GROUPNAME_LENGTH, - "grouplist" => EWIKI_GROUPNAME_LENGTH, "groupname_text" => EWIKI_GROUPNAME_LENGTH,"origgroupname_" => EWIKI_GROUPNAME_LENGTH, - "uvar_fieldname" => EWIKI_FIELDNAME_LENGTH,"chpw_" => EWIKI_PASSWORD_LENGTH,"grouplist" => EWIKI_GROUPNAME_LENGTH, - "submit_removeusersfromgroup" => 15, "radpw_" => 6,"chkgroup_" => 2, "chk_" => 2, "submit_deleteusers" => 16, - "submit_changegroups" => 14, "submit_adduser" => 8, "chuvar_" => 255, "origchuvar_" => 255, "search_fieldvalue" => 255, - "submit_searchaccount" => 6, "submit_addusers" => 9,"pwgen_addusers" =>2,"addright" => 2, "submit_addgroup" => 9, - "submit_adduserstogroup" => 12, "chkrandpw_"=> 2,"submit_changeusers" => 14), -"AdminFullUser" => array("accountname_text" => EWIKI_USERNAME_LENGTH,"new_accountfield" => EWIKI_FIELDNAME_LENGTH, "submit_viewaccount" => 9, - "chk_" => 2, "text_" => 255, "submit_changeaccount" => 14,"submit_clearuservars" => 14, "new_accountfieldvalue" => 255, - "submit_accountaddfield" => 9,"batch_fieldnames" => 1649, "batch_fieldvalues" => 12799, "submit_batchfields" => 10, - "submit_batchusers" => 10, "bulk_items" => 1677215, "submit_bulkset" => 11, "batch_usernames" => 1649), -"UserInfo" => array("submit_changeaccount" => 14, "text_" => 255), -"AdminSearchAccounts" => array("search_fieldname" => EWIKI_FIELDNAME_LENGTH, "chk_" => EWIKI_FIELDNAME_LENGTH, "search_fieldvalue" => 255, - "submit_searchaccount" => 6,"text_" => 255, "submit_changeaccount" => 14, "submit_clearuservars" => 15), -"ChangePassword" => array("oldpassword" => EWIKI_PASSWORD_LENGTH, "newpassword1" => EWIKI_PASSWORD_LENGTH, "newpassword2" => EWIKI_PASSWORD_LENGTH, - "submit" => 15), -"TextUpload" => array("textfile_overwrite_pages" => 1, "textfile_assume_text" => 1, "textfile_noext_is_text" => 1, - "textfile_brute_force" => 1, "textfile_brute_force" => 1, "textfile_saveas" => 160, - "textfile_strip_ext" => 1, "upload_text_file" => 300), -"ProtectedEmail" => array("encoded_email" => 340), -"Login" => array("cancel_login" => 6)); - -$ewiki_plugins["init"][-4] = "ewiki_input_truncate"; - -function ewiki_input_truncate(){ - global $ewiki_input_limits, $ewiki_plugins; - - //get and trim current page id - $id=substr(ewiki_id(), 0, $ewiki_input_limits['_AllPages']['id']); - - if ($delim = strpos($id, EWIKI_ACTION_SEP_CHAR)) { - $action = substr($id, 0, $delim); - $id = substr($id, $delim + 1); - } - - foreach($_REQUEST as $key => $value){ //loop through the $_REQUEST variable - $input_value=trim($value); //trim value - - $ewiki_input_key=$key; - $ewiki_input_id=ewiki_check_input($id, $ewiki_input_key, $action); - if(!strlen($ewiki_input_id)){ - $ewiki_input_key=ewiki_reset_key($id, $key); - $ewiki_input_id=ewiki_check_input($id, $ewiki_input_key, $action); - } - if(!strlen($ewiki_input_id)){ - ewiki_log('Unhandled submit: Page: "'.$id.'" Key: "'.$key.'" Value: "'.$value.'" \n', 1); - ewiki_set_globals($key); - } - - if(is_array($input_value)){ - //loop through the input array - foreach($input_value as $array_input_key => $array_input_value){ - $input_value=trim($array_input_value); //redefine input_value with the array value - //check to see if its longer than allowed - if(strlen($input_value)>$ewiki_input_limits[$ewiki_input_id][$ewiki_input_key]){ - //its too long truncate it... - ewiki_set_globals($key, substr($input_value, 0, $ewiki_input_limits[$ewiki_input_id][$ewiki_input_key]), $array_input_key); - } - } - } - - //if the input length is longer than its supposed to be trim it. - elseif((strlen($input_value)>$ewiki_input_limits[$ewiki_input_id][$ewiki_input_key]) && isset($ewiki_input_limits[$ewiki_input_id][$ewiki_input_key])){ - ewiki_log("Trimming: Key: $ewiki_input_key Id: $ewiki_input_id to length: ".$ewiki_input_limits[$ewiki_input_id][$ewiki_input_key]); - ewiki_set_globals($key, substr($input_value, 0, $ewiki_input_limits[$ewiki_input_id][$ewiki_input_key])); - } - } -} - -function ewiki_check_input($id, $ewiki_input_key, $action){ - global $ewiki_input_limits; - //determines what type of page we are running on and sets the ewiki_input_id variable accordingly - //check to see if our key matches up with an input for this specific page - if(isset($ewiki_input_limits[$id][$ewiki_input_key])){ - //some inputs are arrays themselves this handles that. - return $id; - //else check to see if it's a global input - } elseif(isset($ewiki_input_limits["_AllPages"][$ewiki_input_key])){ - return "_AllPages"; - //$maxlen=$ewiki_input_limits["_AllPages"][$ewiki_input_key]; - //else check to see if its a binary input - } elseif(isset($ewiki_input_limits["_Binary"][$ewiki_input_key]) && strstr($action, "binary")){ - return "_Binary"; - //$maxlen=$ewiki_input_limits["_Binary"][$ewiki_input_key]; - //else check to see if its an edit input - } elseif(isset($ewiki_input_limits["_Email"][$ewiki_input_key]) && ($action=="emailpage")){ - return "_Email"; - //$maxlen=$ewiki_input_limits["_Edit"][$ewiki_input_key]; - } elseif(isset($ewiki_input_limits["_Edit"][$ewiki_input_key]) && ($action=="edit" || $action=="updateformatheader")){ - return "_Edit"; - //$maxlen=$ewiki_input_limits["_Edit"][$ewiki_input_key]; - } elseif(isset($ewiki_input_limits["_Manage"][$ewiki_input_key]) && ($action=="manage")){ - return "_Manage"; - //no more input types. fail. - } else { - return ""; - } -} - -//Resets a key to a substring of itself to handle iteratively generated inputs. -function ewiki_reset_key($id, $key){ - global $ewiki_input_limits; - //handles multiple elements with the same prefix *_ and a numerical suffix - if(preg_match("/(\D+_)(\d+)/", $key, $matches)){ - //redefine the input key as the prefix of these elements *_ - return $matches[1]; - //handles multiple elements with the same prefix *_ and a non numeric suffix - } elseif(preg_match("/([a-zA-Z]+_)(.*)/", $key, $matches) && !isset($ewiki_input_limits[$id][$key]) && !isset($ewiki_input_limits["_AllPages"][$key])){ - return $matches[1]; - } else { - return ""; //used to match the request key to the ewiki_input_limits array - } -} - -/**ewiki_set_globals sets or clears global HTTP variables as requested - * - * @param string key - * @param string $newval - */ -function ewiki_set_globals($key, $newval="", $key2=""){ - for($i=1;$i<=4;$i++){ - switch ($i){ - case 1: //process $_REQUEST - if($newval=="" && $key2==""){ - unset($_REQUEST[$key]); - } elseif($newval=="" && $key2!=""){ - unset($_REQUEST[$key][$key2]); - } elseif($key2=="") { - $_REQUEST[$key]=$newval; - } else { - $_REQUEST[$key][$key2]=$newval; - } - break; - case 2: //process $_POST - if($newval=="" && $key2==""){ - unset($_POST[$key]); - } elseif($newval=="" && $key2!=""){ - unset($_POST[$key][$key2]); - } elseif($key2=="") { - $_POST[$key]=$newval; - } else { - $_POST[$key][$key2]=$newval; - } - break; - case 3: //process $_GET - if($newval=="" && $key2==""){ - unset($_GET[$key]); - } elseif($newval=="" && $key2!=""){ - unset($_GET[$key][$key2]); - } elseif($key2=="") { - $_GET[$key]=$newval; - } else { - $_GET[$key][$key2]=$newval; - } - break; - case 4: //process $_COOKIE - if($newval=="" && $key2==""){ - unset($_COOKIE[$key]); - } elseif($newval=="" && $key2!=""){ - unset($_COOKIE[$key][$key2]); - } elseif($key2=="") { - $_COOKIE[$key]=$newval; - } else { - $_COOKIE[$key][$key2]=$newval; - } - break; - } - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/interwiki/editable.meta b/mods/wiki/plugins/interwiki/editable.meta deleted file mode 100644 index 634b51148..000000000 --- a/mods/wiki/plugins/interwiki/editable.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -title: PublicallyEditableIntermap -description: eases extension of the InterWiki prefix/moniker list -priority: bonus -hooks: init, page -type: page diff --git a/mods/wiki/plugins/interwiki/editable.php b/mods/wiki/plugins/interwiki/editable.php deleted file mode 100644 index 4406402b0..000000000 --- a/mods/wiki/plugins/interwiki/editable.php +++ /dev/null @@ -1,108 +0,0 @@ -$moni) { - if (!isset($inter[$moni])) { - $inter[$moni] .= $uu[2][$i]; - } - } } - /* - WONT_WORK - $refs = explode("\n", trim($data["refs"])); - for ($n=1; $n -
        - - :: -
        - - -EOT - ); - - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/interwiki/intermap.meta b/mods/wiki/plugins/interwiki/intermap.meta deleted file mode 100644 index 62ba17cbb..000000000 --- a/mods/wiki/plugins/interwiki/intermap.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: hypertext -title: InterMap -description: enlarges the list of knwon InterWiki: monikers -priority: extra -type: variables diff --git a/mods/wiki/plugins/interwiki/intermap.php b/mods/wiki/plugins/interwiki/intermap.php deleted file mode 100644 index 246e9b2ce..000000000 --- a/mods/wiki/plugins/interwiki/intermap.php +++ /dev/null @@ -1,113 +0,0 @@ - "http://news.alife.org/wiki/index.php?", - "AbbeNormal" => "http://www.ourpla.net/cgi-bin/pikie.cgi?", - "AcadWiki" => "http://xarch.tu-graz.ac.at/autocad/wiki/", - "Acronym" => "http://www.acronymfinder.com/af-query.asp?String=exact&Acronym=", - "Advogato" => "http://www.advogato.org/", - "AndStuff" => "http://andstuff.org/wiki.php?", - "Dictionary" => "http://www.dictionary.com/cgi-bin/dict.pl?term=", - "BcWireless" => "http://www.bcwireless.net/wiki-moinmoin/moin.cgi/", - "Annotation" => "http://bayle.stanford.edu/crit/nph-med.cgi/", - "AnnotationWiki"=> "http://www.seedwiki.com/page.cfm?wikiid=368&doc=", - "AwarenessWiki" => "http://taoriver.net/aware/", - "BenefitsWiki" => "http://www.benefitslink.com/cgi-bin/wiki.cgi?", - "BrainBench" => "http://www.brainbench.com/transcript.jsp?pid=", - "BridgesWiki" => "http://c2.com/w2/bridges/", - "C2find" => "http://c2.com/cgi/wiki?FindPage&value=", - "CLiki" => "http://www.telent.net/cliki/", - "Cache" => "http://www.google.com/search?q=cache:", - "CmWiki" => "http://www.ourpla.net/cgi-bin/wiki.pl?", - "CreationMatters"=> "http://www.ourpla.net/cgi-bin/wiki.pl?", - "DejaNews" => "http://www.deja.com/=dnc/getdoc.xp?AN=", - "DocBook" => "http://docbook.org/wiki/moin.cgi/", - "DolphinWiki" => "http://www.object-arts.com/wiki/html/Dolphin/", - "DseWiki" => "http://www.wikiservice.at/dse/wiki.cgi?", - "ErfurtWiki" => "http://erfurtwiki.sourceforge.net/?id=", - "EfnetCeeWiki" => "http://wiki.rm-f.net/moin.cgi/", - "EfnetCppWiki" => "http://purl.net/wiki/cpp/", - "EfnetPythonWiki"=> "http://purl.net/wiki/python/", - "EfnetXmlWiki" => "http://purl.net/wiki/xml/", - "EljWiki" => "http://elj.sourceforge.net/phpwiki/index.php/", - "EmacsWiki" => "http://www.emacswiki.org/cgi-bin/wiki.pl?", - "FOLDOC" => "http://foldoc.doc.ic.ac.uk/foldoc/foldoc.cgi?query=", - "Foldoc" => "http://www.foldoc.org/foldoc/foldoc.cgi?", - "FoxWiki" => "http://fox.wikis.com/wc.dll?Wiki~", - "FreeBSDman" => "http://www.FreeBSD.org/cgi/man.cgi?apropos=1&query=", - "FreshMeat" => "http://freshmeat.net/", - "FreeNetworks" => "http://www.freenetworks.org/index.cgi/", - "Google" => "http://www.google.com/search?q=", - "GoogleGroups" => "http://groups.google.com/groups?q=", - "HammondWiki" => "http://www.dairiki.org/HammondWiki/index.php3?", - "Haribeau" => "http://wiki.haribeau.de/cgi-bin/wiki.pl?", - "IAWiki" => "http://www.IAwiki.net/", - "IMDB" => "http://us.imdb.com/Title?", - "ISBN" => "http://www.amazon.com/exec/obidos/ISBN=", - "JargonFile" => "http://sunir.org/apps/meta.pl?wiki=JargonFile&redirect=", - "JiniWiki" => "http://www.cdegroot.com/cgi-bin/jini?", - "JspWiki" => "http://www.ecyrd.com/JSPWiki/Wiki.jsp?page=", - "JuraWiki" => "http://jurawiki.de/", - "KnowHow" => "http://www2.iro.umontreal.ca/~paquetse/cgi-bin/wiki.cgi?", - "LegoWiki" => "http://www.object-arts.com/wiki/html/Lego-Robotics/", - "LinuxWiki" => "http://linuxwiki.de/", - "MathSongsWiki" => "http://SeedWiki.com/page.cfm?wikiid=237&doc=", - "MbTest" => "http://www.usemod.com/cgi-bin/mbtest.pl?", - "MeatBall" => "http://www.usemod.com/cgi-bin/mb.pl?", - "UseMod" => "http://www.usemod.com/cgi-bin/wiki.pl?", - "MetaWiki" => "http://sunir.org/apps/meta.pl?", - "MoinMaster" => "http://moinmaster.wikiwikiweb.de/", - "MoinMoin" => "http://moinmoin.wikiwikiweb.de/", - "MoinPurl" => "http://purl.net/wiki/moin/", - "MuWeb" => "http://www.dunstable.com/scripts/MuWebWeb?", - "OpenWiki" => "http://openwiki.com/?", - "OrgPatterns" => "http://www.bell-labs.com/cgi-user/OrgPatterns/OrgPatterns?", - "PPR" => "http://c2.com/cgi/wiki?", - "PangalacticOrg"=> "http://www.pangalactic.org/Wiki/", - "PersonalTelco" => "http://www.personaltelco.net/index.cgi/", - "PhpWiki" => "http://phpwiki.sourceforge.net/phpwiki/index.php3?", - "PhpFunction" => "http://www.php.net/manual/en/function.", - "PhpManual" => "http://www.php.net/manual-lookup.php?pattern=", - "Pikie" => "http://pikie.darktech.org/cgi/pikie?", - "PolitizenWiki" => "http://www.politizen.com/wiki.asp?", - "PurlNet" => "http://purl.oclc.org/NET/", - "PyWiki" => "http://www.voght.com/cgi-bin/pywiki?", - "KmWiki" => "http://www.voght.com/cgi-bin/pywiki?", - "PythonInfo" => "http://www.python.org/cgi-bin/moinmoin/", - "PythonWiki" => "http://www.pythonwiki.de/", - "RFC" => "http://www.ietf.org/rfc/rfc", - "SVGWiki" => "http://www.protocol7.com/svg-wiki/default.asp?", - "SeaPig" => "http://www.seapig.org/", - "SeattleWireless"=> "http://seattlewireless.net/?", - "SenseisLibrary"=> "http://senseis.xmp.net/?", - "SourceForge" => "http://sourceforge.net/", - "Squeak" => "http://minnow.cc.gatech.edu/squeak/", - "StrikiWiki" => "http://ch.twi.tudelft.nl/~mostert/striki/teststriki.pl?", - "TMwiki" => "http://www.EasyTopicMaps.com/?page=", - "TWiki" => "http://twiki.sourceforge.net/cgi-bin/view/", - "TwikiOrg" => "http://twiki.org/cgi-bin/view/", - "TamTam" => "http://boo.mi2.hr:10000/TamTam/", - "Tavi" => "http://tavi.sourceforge.net/index.php?", - "Thinki" => "http://www.thinkware.se/cgi-bin/thinki.cgi/", - "TwistedWiki" => "http://purl.net/wiki/twisted/", - "VisualWorks" => "http://wiki.cs.uiuc.edu/VisualWorks/", - "WebDevWikiNL" => "http://www.promo-it.nl/WebDevWiki/index.php?page=", - "Why" => "http://clublet.com/c/c/why?", - "Wiki" => "http://c2.com/cgi/wiki?", - "WikiPedia" => "http://www.wikipedia.com/wiki.cgi?", - "WikiPediaOld" => "http://www.wikipedia.com/wiki.phtml?title=", - "ZWiki" => "http://www.zwiki.org/", - "Faqs" => "http://www.faqs.org/rfcs/rfc", - "Thesaurus" => "http://www.thesaurus.com/cgi-bin/search?config=roget&words=" -)); - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/interwiki/intermaptxt.meta b/mods/wiki/plugins/interwiki/intermaptxt.meta deleted file mode 100644 index dcd349391..000000000 --- a/mods/wiki/plugins/interwiki/intermaptxt.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: hypertext -title: intermaptxt -description: loads InterWiki URLs and monikers from a standard 'intermap.txt' file (slower) -priority: bonus -type: data diff --git a/mods/wiki/plugins/interwiki/intermaptxt.php b/mods/wiki/plugins/interwiki/intermaptxt.php deleted file mode 100644 index 9cf204d5f..000000000 --- a/mods/wiki/plugins/interwiki/intermaptxt.php +++ /dev/null @@ -1,18 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/interwiki/linkdb.meta b/mods/wiki/plugins/interwiki/linkdb.meta deleted file mode 100644 index e69de29bb..000000000 diff --git a/mods/wiki/plugins/interwiki/metadb-wget.sh b/mods/wiki/plugins/interwiki/metadb-wget.sh deleted file mode 100755 index 36b6d086b..000000000 --- a/mods/wiki/plugins/interwiki/metadb-wget.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -# This script fetches the MetaWiki database file from our downloads/ dir -URL_DOWN="http://erfurtwiki.sourceforge.net/downloads/contrib-add-ons/metadb" -URL_MIRR="http://ewiki.berlios.de/metadb" -URL_ORIG="http://sunir.org/meatball/MetaWiki/metadb" - -#-- switch to ewiki base, make EWIKI_VAR directory -cd `dirname $0` -cd ../.. -[ ! -e var ] && mkdir var && chmod 763 var - -#-- download -wget -N $URL_MIRR -O var/metadb || \ -wget -N $URL_DOWN -O var/metadb || \ -wget -N $URL_ORIG -O var/metadb || \ -echo "ERROR fetching latest 'metadb' file" - -#-- compress -gzip -7 var/metadb - diff --git a/mods/wiki/plugins/interwiki/metadb.meta b/mods/wiki/plugins/interwiki/metadb.meta deleted file mode 100644 index 1e63a3ae5..000000000 --- a/mods/wiki/plugins/interwiki/metadb.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -category: hypertext -config: - EWIKI_METADB_FN="metadb" -title: metadb -description: utility and access code for NearLinks, SisterPages, ... -type: functions -priority: auto diff --git a/mods/wiki/plugins/interwiki/metadb.php b/mods/wiki/plugins/interwiki/metadb.php deleted file mode 100644 index 079e30605..000000000 --- a/mods/wiki/plugins/interwiki/metadb.php +++ /dev/null @@ -1,73 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/interwiki/metawiki.meta b/mods/wiki/plugins/interwiki/metawiki.meta deleted file mode 100644 index e69de29bb..000000000 diff --git a/mods/wiki/plugins/interwiki/near.meta b/mods/wiki/plugins/interwiki/near.meta deleted file mode 100644 index c4fd3babc..000000000 --- a/mods/wiki/plugins/interwiki/near.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -hooks: format_prepare_linking -type: link -title: NearPages -description: tries to link locally non-existant page in any other Wiki -priority: bonus diff --git a/mods/wiki/plugins/interwiki/near.php b/mods/wiki/plugins/interwiki/near.php deleted file mode 100644 index 433f40562..000000000 --- a/mods/wiki/plugins/interwiki/near.php +++ /dev/null @@ -1,41 +0,0 @@ -$state) { - if (!$state) { - $nf[] = $id; - } - } - - #-- load metadb, inject URLs into $ewiki_links - if (count($nf) && ewiki_metadb::LOAD()) { - $nf = ewiki_metadb::FIND($nf); - foreach ($nf as $id=>$found) { - if ($found) { - $ewiki_links[$id] = ewiki_interwiki($found[0]); - } - } - ewiki_metadb::UNLOAD(); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/interwiki/neighbor.meta b/mods/wiki/plugins/interwiki/neighbor.meta deleted file mode 100644 index af42da685..000000000 --- a/mods/wiki/plugins/interwiki/neighbor.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -hooks: link_final -type: mangle -title: NeighborPages -description: adds additional links behind any page link if it exists on foreign Wikis too -priority: rare diff --git a/mods/wiki/plugins/interwiki/neighbor.php b/mods/wiki/plugins/interwiki/neighbor.php deleted file mode 100644 index 25f899011..000000000 --- a/mods/wiki/plugins/interwiki/neighbor.php +++ /dev/null @@ -1,37 +0,0 @@ -$iw:"; - } - - $str .= " (" . implode(", ", $inj). ")"; - } - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/interwiki/sisterpages.meta b/mods/wiki/plugins/interwiki/sisterpages.meta deleted file mode 100644 index 13cda47ea..000000000 --- a/mods/wiki/plugins/interwiki/sisterpages.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: hypertext -hooks: page_final -type: transform -config: - EWIKI_SISTER_ONLY_NONEXIST=0 // SisterPages only for edit/ screen -title: SisterPages -description: prints links to same-named pages on foreign Wikis on top of every page -priority: bonus diff --git a/mods/wiki/plugins/interwiki/sisterpages.php b/mods/wiki/plugins/interwiki/sisterpages.php deleted file mode 100644 index 4592c660f..000000000 --- a/mods/wiki/plugins/interwiki/sisterpages.php +++ /dev/null @@ -1,49 +0,0 @@ -$iw:$id"; - } - - if ($inj) { - $o = (($action!="edit") ? ewiki_t("SISTER") : "") - . implode(", ", $inj) - . "
        \n" . $o; - } - } - - ewiki_metadb::UNLOAD(); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/interwiki/virtualsister.meta b/mods/wiki/plugins/interwiki/virtualsister.meta deleted file mode 100644 index d0cb2dc77..000000000 --- a/mods/wiki/plugins/interwiki/virtualsister.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -hooks: handler -type: intercept -title: VirtualSister -description: puts virtual links to SisterPages at the bottom of every page -priority: rare diff --git a/mods/wiki/plugins/interwiki/virtualsister.php b/mods/wiki/plugins/interwiki/virtualsister.php deleted file mode 100644 index d55baa08b..000000000 --- a/mods/wiki/plugins/interwiki/virtualsister.php +++ /dev/null @@ -1,44 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/interwiki/walking.meta b/mods/wiki/plugins/interwiki/walking.meta deleted file mode 100644 index 1887c80c7..000000000 --- a/mods/wiki/plugins/interwiki/walking.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -hooks: handler -type: intercept -title: walking -description: provides WikiFeatures:InterMapWalking (already built-in!) -priority: deprecated diff --git a/mods/wiki/plugins/interwiki/walking.php b/mods/wiki/plugins/interwiki/walking.php deleted file mode 100644 index c47c63d8e..000000000 --- a/mods/wiki/plugins/interwiki/walking.php +++ /dev/null @@ -1,22 +0,0 @@ -$href"); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/jump.meta b/mods/wiki/plugins/jump.meta deleted file mode 100644 index 89bd8eb26..000000000 --- a/mods/wiki/plugins/jump.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -hooks: handler -type: intercept -funcs: ewiki_handler_jump -title: PageJumping -description: page redirection feature -priority: standard -category: feature diff --git a/mods/wiki/plugins/jump.php b/mods/wiki/plugins/jump.php deleted file mode 100644 index 574578b21..000000000 --- a/mods/wiki/plugins/jump.php +++ /dev/null @@ -1,106 +0,0 @@ -Redirection loop detected

        \nOperation stopped, because we're traped in an infinite redirection loop with page \$id."; - -#-- plugin glue -$ewiki_plugins["handler"][] = "ewiki_handler_jump"; -$ewiki_config["interwiki"]["jump"] = ""; -$ewiki_config["interwiki"]["goto"] = ""; - - -function ewiki_handler_jump(&$id, &$data, &$action) { - - global $ewiki_config; - - static $redirect_count = 5; - $jump_markup = array("jump", "goto", "redirect", "location"); - - #-- we only care about "view" action - if ($action != "view") { - return; - } - - #-- escape from loop - if (isset($_REQUEST[EWIKI_UP_REDIRECT_COUNT])) { - $redirect_count = $_REQUEST[EWIKI_UP_REDIRECT_COUNT]; - } - if ($redirect_count-- <= 0) { - return(ewiki_t("REDIRECTION_LOOP", array("id"=>$id))); - } - - #-- search for [jump:...] - if ($links = explode("\n", trim($data["refs"]))) - foreach ($links as $link) { - - if (strlen($link) && strpos($link, ":") - && in_array(strtolower(strtok($link, ":")), $jump_markup) - && ($dest = trim(strtok("\n"))) ) - { - #-- URL - $url = ""; - if (strpos($dest, "://")) { - $url = $dest; - } - #-- InterWiki:Link - else { - $url = ewiki_interwiki($dest, $uu, $uu2); - } - - #-- Location: - if (EWIKI_JUMP_HTTP && EWIKI_HTTP_HEADERS && !headers_sent()) { - - #-- simple PageLink - if (empty($url)) { - $url = ewiki_script("", $dest, - array(EWIKI_UP_REDIRECT_COUNT=>$redirect_count), - 0, 0, ewiki_script_url() - ); - $url .= defined("SID") ? EWIKI_ADDPARAMDELIM.SID : ""; - } - header("Location: $url"); - die(); - - } - #-- show page as usual, what will reveal dest URL - elseif ($url) { - return(""); - # the rendering kernel will just show up the [jump:]! - # (without the jump: of course) - } - #-- it's simply about another WikiPage - else { - - #-- we'll just restart ewiki - $data = array(); - $id = $dest; - return(ewiki_page("view/".$id)); - } - } - }#-search -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/COLLEGE.ttf b/mods/wiki/plugins/lib/COLLEGE.ttf deleted file mode 100644 index 400fe5cef357b5f661bd8bc66fda4b4cd068b440..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5896 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 diff --git a/mods/wiki/plugins/lib/cache.meta b/mods/wiki/plugins/lib/cache.meta deleted file mode 100644 index 51c62787a..000000000 --- a/mods/wiki/plugins/lib/cache.meta +++ /dev/null @@ -1,13 +0,0 @@ -api: ewiki -type: intercept -hooks: handler, page_final -title: PageCaching -decription: keeps a cache of already rendered pages -priority: extra -category: optimation -config: - EWIKI_CACHE_FULL=1|0 // include control-links line in cache - EWIKI_CACHE_ALL=0|1 // cache also virtual pages - EWIKI_CACHE_DIR=./var/cache // preferred over db storage - EWIKI_CACHE_DB=system/cache/ // only has effect, if _DIR undefined -description: caching of rendered (html) pages diff --git a/mods/wiki/plugins/lib/cache.php b/mods/wiki/plugins/lib/cache.php deleted file mode 100644 index e050d7acf..000000000 --- a/mods/wiki/plugins/lib/cache.php +++ /dev/null @@ -1,136 +0,0 @@ - $id, - "version" => 1, - "flags" => EWIKI_DB_F_BINARY¦EWIKI_DB_F_TEXT|EWIKI_DB_F_HTML, - "created" => filectime($file), - "lastmodified" => filemtime($file), - "content" => $content, - "meta" => array("class"=>"cache"), - ); - } - } - } - } - elseif (defined("EWIKI_CACHE_DB") && (EWIKI_CACHE_DB)) { - $id = EWIKI_CACHE_DB."$action/$id"; - $row = ewiki_db::GET($id); - } - return($row); -} - - -#-- return rendered page -function ewiki_handler_cache_full($id, &$data, $action) { - global $ewiki_config; - if (in_array($action, $ewiki_config["cache.actions"]) && ($cache = ewiki_get_cache($action,$id))) { - if ($cache["lastmodified"] >= $data["lastmodified"]) { - $data = &$cache; - ewiki_http_headers($data["content"], $id, $cache, $action); - return($data["content"]); - } - } -} - - -#-- if we get here, we should store the rendered page -function ewiki_store_cache_full(&$o, $id, &$data, $action) { - global $ewiki_config; - if (in_array($action, $ewiki_config["cache.actions"]) && ($data["version"] || EWIKI_CACHE_ALL) && ($_SERVER["REQUEST_METHOD"]=="GET")) { - - #-- only store, if we got just a few QueryString parameters - if (count($_GET) <= 2) { - ewiki_put_cache($action, $id, $o); - } - } -} - - -#-- real save function -function ewiki_put_cache($action, $id, &$o) { - #-- save into cache dir - if (defined("EWIKI_CACHE_DIR") && EWIKI_CACHE_DIR) { - $file = EWIKI_CACHE_DIR . "/" . $action . "," . urlencode($id); - $f = gzopen($file, "w9"); - if ($f) { - gzwrite($f, $o); - fclose($f); - } - } - #-- store in ewiki database - elseif (defined("EWIKI_CACHE_DB") && (EWIKI_CACHE_DB)) { - $id = EWIKI_CACHE_DB."$action/$id"; - $save = array( - "id" => $id, - "version" => 1, - "flags" => EWIKI_DB_F_BINARY¦EWIKI_DB_F_TEXT|EWIKI_DB_F_HTML, - "created" => $data["lastmodified"], - "lastmodified" => time(), - "content" => &$o, - "meta" => array("class"=>"cache"), - "author" => ewiki_author("ewiki_cache"), - ); - ewiki_db::WRITE($save, true); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/captcha.meta b/mods/wiki/plugins/lib/captcha.meta deleted file mode 100644 index 7ced08f8c..000000000 --- a/mods/wiki/plugins/lib/captcha.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: PHP -type: functions -priority: auto -title: CAPTCHA -description: provides graphical riddle to get rid of aggressive spambots/spiders -version: 0.8 -homepage: http://freshmeat.net/p/captchaphp -category: library diff --git a/mods/wiki/plugins/lib/captcha.php b/mods/wiki/plugins/lib/captcha.php deleted file mode 100644 index c94832b90..000000000 --- a/mods/wiki/plugins/lib/captcha.php +++ /dev/null @@ -1,280 +0,0 @@ - and alike. User input is veryfied with captcha::check(). - You should leave the sample COLLEGE.ttf next to this script, else you - have to define the _FONT_DIR constant correctly. Use only one type. - - Includes a sluggish workaround for Internet Explorer; but this script - must reside in a www-accessible directory then. - - Public Domain, available via http://freshmeat.net/p/captchaphp -*/ - - -#-- config -define("EWIKI_FONT_DIR", dirname(__FILE__)); // which fonts to use -define("CAPTCHA_INVERSE", 0); // white or black(=1) -define("CAPTCHA_TIMEOUT", 5000); // in seconds (=max 4 hours) - - -/* static - (you could instantiate it, but...) */ -class captcha { - - - /* gets parameter from $_REQUEST[] array (POST vars) and so can - verify input, @returns boolean - */ - function check() { - if (($hash = $_REQUEST["captcha_hash"]) - and ($pw = trim($_REQUEST["captcha_input"]))) { - return((captcha::hash($pw)==$hash) || (captcha::hash($pw,-1)==$hash)); - } - } - - - /* yields fields html string (no complete form), with captcha - image already embedded as data:-URI - */ - function form($title="→ retype that here", $more="Enter the correct letters and numbers from the image into the text box. This small test serves as access restriction against malicious bots. Simply reload the page if this graphic is too hard to read.") { - $pw = captcha::mkpass(); - $hash = captcha::hash($pw); - $maxsize = (strpos("MSIE", $_SERVER["HTTP_USER_AGENT"]) ? 3000 : 6000); - @header("Vary: User-Agent"); - $img = "data:image/jpeg;base64," - . base64_encode(captcha::image($pw, 200, 60, CAPTCHA_INVERSE, $maxsize)); - $alt = htmlentities(captcha::textual_riddle($pw)); - $html = - '' - . '' - . '' - . '
        '.$alt. ''.$title. '
        ' - . '' - . '
        '.$more.'
        '; - #-- js/html fix if ("MSIE") - { - $base = "http://$_SERVER[SERVER_NAME]:$_SERVER[SERVER_PORT]/" - . substr(realpath(__FILE__), strlen($_SERVER["DOCUMENT_ROOT"])); - $html .= << -END; - } - $html = "
        $html
        "; - return($html); - } - - - /* generates alternative (non-graphic), human-understandable - representation of the passphrase - */ - function textual_riddle($phrase) { - $symbols0 = '"\'-/_:'; - $symbols1 = array("\n,", "\n;", ";", "\n&", "\n-", ",", ",", "\nand then", "\nfollowed by", "\nand", "\nand not a\n\"".chr(65+rand(0,26))."\",\nbut"); - $s = "Guess the letters and numbers\n(passphrase riddle)\n--\n"; - for ($p=0; $p= 'A') { - $type = ($c >= 'a' ? "small " : ""); - do { - $n = rand(-3,3); - $c2 = chr((ord($c) & 0x5F) + $n); - } - while (($c2 < 'A') || ($c2 > 'Z')); - if ($n < 0) { - $n = -$n; - $add .= "$type'$c2' +$n letters"; - } - else { - $add .= "$n chars before $type$c2"; - } - } - #-- number - else { - $add = "???"; - $n = (int) $c; - do { - do { $x = rand(1, 10); } while (!$x); - $op = rand(0,11); - if ($op <= 2) { - $add = "($add * $x)"; $n *= $x; - } - elseif ($op == 3) { - $x = 2 * rand(1,2); - $add = "($add / $x)"; $n /= $x; - } - elseif ($sel % 2) { - $add = "($add + $x)"; $n += $x; - } - else { - $add = "($add - $x)"; $n -= $x; - } - } - while (rand(0,1)); - $add .= " = $n"; - } - $s .= "$add"; - $s .= $symbols1[rand(0,count($symbols1)-1)] . "\n"; - } - return($s); - } - - - /* returns jpeg file stream with unscannable letters encoded - in front of colorful disturbing background - */ - function image($phrase, $width=200, $height=60, $inverse=0, $maxsize=0xFFFFF) { - - #-- initialize in-memory image with gd library - srand(microtime()*21017); - $img = imagecreatetruecolor($width, $height); - $R = $inverse ? 0xFF : 0x00; - imagefilledrectangle($img, 0,0, $width,$height, captcha::random_color($img, 222^$R, 255^$R)); - $c1 = rand(150^$R, 185^$R); - $c2 = rand(195^$R, 230^$R); - - #-- configuration - $fonts = array( - // "COLLEGE.ttf", - ); - $fonts += glob(EWIKI_FONT_DIR."/*.ttf"); - - #-- encolour bg - $wd = 20; - $x = 0; - while ($x < $width) { - imagefilledrectangle($img, $x, 0, $x+=$wd, $height, captcha::random_color($img, 222^$R, 255^$R)); - $wd += max(10, rand(0, 20) - 10); - } - - #-- make interesting background I, lines - $wd = 4; - $w1 = 0; - $w2 = 0; - for ($x=0; $x<$width; $x+=(int)$wd) { - if ($x < $width) { // verical - imageline($img, $x+$w1, 0, $x+$w2, $height-1, captcha::random_color($img,$c1,$c2)); - } - if ($x < $height) { // horizontally ("y") - imageline($img, 0, $x-$w2, $width-1, $x-$w1, captcha::random_color($img,$c1,$c2)); - } - $wd += rand(0,8) - 4; - if ($wd < 1) { $wd = 2; } - $w1 += rand(0,8) - 4; - $w2 += rand(0,8) - 4; - if (($x > $height) && ($y > $height)) { - break; - } - } - - #-- more disturbing II, random letters - $limit = rand(30,90); - for ($n=0; $n<$limit; $n++) { - $letter = ""; - do { - $letter .= chr(rand(31,125)); // random symbol - } while (rand(0,1)); - $size = rand(5, $height/2); - $half = (int) ($size / 2); - $x = rand(-$half, $width+$half); - $y = rand(+$half, $height); - $rotation = rand(60, 300); - $c1 = captcha::random_color($img, 130^$R, 240^$R); - $font = $fonts[rand(0, count($fonts)-1)]; - imagettftext($img, $size, $rotation, $x, $y, $c1, $font, $letter); - } - - #-- add the real text to it - $len = strlen($phrase); - $w1 = 10; - $w2 = $width / ($len+1); - for ($p=0; $p<$len; $p++) { - $letter = $phrase[$p]; - $size = rand(18, $height/2.2); - $half = (int) $size / 2; - $rotation = rand(-33, 33); - $y = rand($size+3, $height-3); - $x = $w1 + $w2*$p; - $w1 += rand(-$width/90, $width/40); // @BUG: last char could be +30 pixel outside of image - $font = $fonts[rand(0, count($fonts)-1)]; - $r=rand(30,99); $g=rand(30,99); $b=rand(30,99); // two colors for shadow - $c1 = imagecolorallocate($img, $r*1^$R, $g*1^$R, $b*1^$R); - $c2 = imagecolorallocate($img, $r*2^$R, $g*2^$R, $b*2^$R); - imagettftext($img, $size, $rotation, $x+1, $y, $c2, $font, $letter); - imagettftext($img, $size, $rotation, $x, $y-1, $c1, $font, $letter); - } - - #-- let JFIF stream be generated - $quality = 67; - $s = array(); - do { - ob_start(); ob_implicit_flush(0); - imagejpeg($img, "", (int)$quality); - $jpeg = ob_get_contents(); ob_end_clean(); - $size = strlen($jpeg); - $s_debug[] = ((int)($quality*10)/10) . "%=$size"; - $quality = $quality * ($maxsize/$size) * 0.93 - 1.7; // -($quality/7.222)* - } - while (($size > $maxsize) && ($quality >= 16)); - imagedestroy($img); -#print_r($s_debug); - return($jpeg); - } - - - /* helper code */ - function random_color($img, $a,$b) { - return imagecolorallocate($img, rand($a,$b), rand($a,$b), rand($a,$b)); - } - - - /* unreversable hash from passphrase, with time() slice encoded */ - function hash($text, $dtime=0) { - $text = strtolower($text); - $pfix = (int) (time() / CAPTCHA_TIMEOUT) + $dtime; - return md5("captcha::$pfix:$text::".__FILE__.":$_SERVER[SERVER_NAME]:80"); - } - - - /* makes string of random letters for embedding into image and for - encoding as hash, later verification - */ - function mkpass() { - $s = ""; - for ($n=0; $n<10; $n++) { - $s .= chr(rand(0, 255)); - } - $s = base64_encode($s); // base64-set, but filter out unwanted chars - $s = preg_replace("/[+\/=IG0ODQR]/i", "", $s); // (depends on YOUR font) - $s = substr($s, 0, rand(5,7)); - return($s); - } -} - - -#-- IE workaround -if (isset($_REQUEST["_ddu"])) { - header("Content-Type: image/jpeg"); - die(base64_decode(substr($_REQUEST["_ddu"], 0))); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/fakedba.meta b/mods/wiki/plugins/lib/fakedba.meta deleted file mode 100644 index e2588ac2c..000000000 --- a/mods/wiki/plugins/lib/fakedba.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: library -title: fakedba -description: emualtes dba support if PHP supports at least the dbm interface -type: functions -priority: deprecated diff --git a/mods/wiki/plugins/lib/fakedba.php b/mods/wiki/plugins/lib/fakedba.php deleted file mode 100644 index 2ae8b37ff..000000000 --- a/mods/wiki/plugins/lib/fakedba.php +++ /dev/null @@ -1,61 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/lib/fakezlib.meta b/mods/wiki/plugins/lib/fakezlib.meta deleted file mode 100644 index c848d59d8..000000000 --- a/mods/wiki/plugins/lib/fakezlib.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: library -title: fakezlib -description: required for outdated PHP installations -type: functions -priority: deprecated diff --git a/mods/wiki/plugins/lib/fakezlib.php b/mods/wiki/plugins/lib/fakezlib.php deleted file mode 100644 index bc0feaadd..000000000 --- a/mods/wiki/plugins/lib/fakezlib.php +++ /dev/null @@ -1,35 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/lib/feed.meta b/mods/wiki/plugins/lib/feed.meta deleted file mode 100644 index d17f020b2..000000000 --- a/mods/wiki/plugins/lib/feed.meta +++ /dev/null @@ -1,11 +0,0 @@ -api: ewiki -type: functions -title: feed generation -description: utility code to send out Atom/RSS feeds -category: library -priority: optional -config: - EWIKI_DESC= // site description - EWIKI_COPY= // overall site copyright, e.g. "PrimarilyPublicDomain" - EWIKI_CATEGORY= // site subject - EWIKI_LOGO_URL= // "http://.../logo.png" diff --git a/mods/wiki/plugins/lib/feed.php b/mods/wiki/plugins/lib/feed.php deleted file mode 100644 index 3a6cc5c8a..000000000 --- a/mods/wiki/plugins/lib/feed.php +++ /dev/null @@ -1,440 +0,0 @@ - EWIKI_NAME, - "lang" => EWIKI_DEFAULT_LANG, - "desc" => defined("EWIKI_DESC")?EWIKI_DESC : EWIKI_NAME . " - an open hypertext site", - "copyright" => defined("EWIKI_COPY")?EWIKI_COPY : "copyrighted", - "category" => defined("EWIKI_CATEGORY")?EWIKI_CATEGORY : "None", -// "logo" => defined("EWIKI_LOGO_URL")?EWIKI_LOGO_URL : "http://erfurtwiki.sf.net/squirrel.jpeg", - "url" => ewiki_script_url(), - "rc_url" => ewiki_script_url("", "UpdatedPages"), - "ewiki" => "ewiki/".EWIKI_VERSION, - "charset" => EWIKI_CHARSET, - ); - - #-- fix/prepare feed entries - $lm = UNIX_MILLENNIUM; - foreach ($pages as $i=>$data) { - if (!is_array($data)) { - $data = ewiki_db::GET($data); - $pages[$i] = $data; - } - // ... - if ($data["id"]) { - if (empty($data["title"])) { $pages[$i]["title"] = ewiki_split_title($data["id"], -1, 0); } - if (empty($data["url"])) { $pages[$i]["url"] = ewiki_script_url("", $data["id"]); } - if (empty($data["uri"])) { $pages[$i]["uri"] = "x-wiki:".EWIKI_NAME.":".ewiki_xmlentities(urlencode($data["id"])); } - if (empty($data["guid"])) { $pages[$i]["guid"] = ewiki_script_url("", $data["id"], "version=$data[version]"); } - } - $pages[$i]["content"] = strtr(ewiki_xmlentities(substr($data["content"], 0, 300)), "\r\n\t\f", " "); - $pages[$i]["pdate"] = gmstrftime("%a, %d %b %G %T %Z", $data["lastmodified"]); - $pages[$i]["idate"] = gmstrftime("%G%m%dT%TZ", $data["lastmodified"]); - $pages[$i]["icdate"] = gmstrftime("%G%m%dT%TZ", $data["created"]); - if ($lm < $data["lastmodified"]) { - $lm = $data["lastmodified"]; - } - $data["content"] = ""; - } - $info["modified"] = $lm; - - #-- respect some common parameters - if (($limit = $_REQUEST["limit"]) - or ($limit = $_REQUEST["items"]) - or ($limit = $ewiki_config["list_limit_rss"]) - or ($limit = $ewiki_config["list_limit"])) { - $pages = array_slice($pages, 0, $limit); - } - - #-- encode everything into UTF-8? - // no - - #-- engage compression - if ($_SERVER["HTTP_ACCEPT_ENCODING"]) { - ob_start("ob_gzhandler"); - ob_implicit_flush(0); - } - - #-- what to return - if (!is_string($type) || (strtoupper($type)=="AUTO") || ($type=="*")) { - $type = ewiki_feed_type(); - } - header("Vary: accept,negotiate"); - header("TCN: choice"); - switch ($type) { - case "RSS0": - ewiki_feed_rss0($feed_info, $pages); - case "RSS2": - ewiki_feed_rss2($feed_info, $pages); - case "RSS3": - ewiki_feed_rss3($feed_info, $pages); - case "RSS1": - ewiki_feed_rss1($feed_info, $pages); - case "ATOM": - ewiki_feed_atom($feed_info, $pages); - case "DUMB": - default: - header("Status: 406 Not Acceptable"); - header("Content-Type: text/plain"); - die("You are using a pretty dumb feed reader, it didn't\n". - "send any appropriate Accept: header. Go away."); - } - die(); -} - - - -#--------------------------------------------------------------------------- -# returns Netscape RSS 0.91 (other versions are neglectable) -# -function ewiki_feed_rss0($info, $pages) -{ -# header('Content-Type: text/x-rss'); - header('Content-Type: application/rss+xml; revision="0.91"'); - - $pages = array_slice($pages, 0, 15); - $name = $info["title"]; - -echo<< - - - - $info[title] - $info[lang] - $info[desc] - $info[url] \n -EOT; - - #-- items - foreach ($pages as $data) { -echo<< - $data[title] - $data[url] - $data[content] - $data[pdate] - \n -EOT; - } //\n\n"; - die(); -} - - - -#--------------------------------------------------------------------------- -# writes RSS 2.0 -# -function ewiki_feed_rss2($info, $pages) -{ - header('Content-Type: application/rss+xml; revision="2.0"'); - - $name = $info["title"]; - -echo<< - - - $info[title] - $info[url] - $info[lang] - $info[desc] - $info[ewiki] - $_SERVER[SERVER_ADMIN]\n -EOT; - - #-- items - foreach ($pages as $data) { -echo<< - $data[title] - $data[url] - $data[content] - $data[pdate] - $data[guid] - \n -EOT; - } //\n\n"; - die(); -} - - - -#--------------------------------------------------------------------------- -# outputs RSS 3.0 (text/plain, much like 822) -# -function ewiki_feed_rss3($info, $pages) -{ - header('Content-Type: text/plain; charset="'.$info["charset"].'"'); - - $name = $info["title"]; - -echo<<\n" : ""; - -echo<< - - - $name - $name - $info[rc_url] - UpdatedPages on $name - $name - $_logo - - \n -EOT; - #-- output Seq ids - foreach ($pages as $i=>$data) { - $pages[$i]["rdf_id"] = "$urnpfix:$name:".ewiki_xmlentities(urlencode($data["id"]))."#$data[version]_$data[lastmodified]"; - echo ' ' . "\n"; - } // - - -\n -EOT; - #-- logo - if ($_logo) { -echo<< - $name - $url - $info[logo] - \n -EOT; - } //$data) { - preg_match('/^([^\s]+).+\(.*([\d.]+)\)/', $data["author"], $uu); - $author_host = $uu[2]; - $author_name = $uu[1]; - $url_diff = ewiki_script_url("diff", $data["id"]); - $url_info = ewiki_script_url("info", $data["id"]); - $stat = ($data["version"]==1) ? "created" : "updated"; -echo<< - $data[title] - $data[title] - $data[content] - $data[url] - $url_diff - $url_info - $data[version] - $stat - $data[idate] - - - $author_name - - - \n -EOT; - } //\n"; - die(); -} - - - -#--------------------------------------------------------------------------- -# returns ATOM 0.3 feed -# -function ewiki_feed_atom($info, $pages) -{ - header('Content-Type: application/atom+xml'); - $name = $info["title"]; - $ilm = gmstrftime("%G%m%dT%TZ", $info["modified"]); - -echo<< - - $name - - $ilm - * - $info[ewiki]\n -EOT; - - #-- write items - foreach ($pages as $i=>$data) { - $etag = ewiki_etag($data); - echo<< - $data[title] - - $etag - $data[icdate] - $data[icdate] - $data[idate] - $data[content] - \n -EOT; - } //\n"; - die(); -} - - - -#--------------------------------------------------------------------------- -# checks HTTP Accept: header for guessing what's desired -# (btw, we just ignore dumb and HTTP incompliant clients) -# -function ewiki_feed_type() -{ - $regex_RSS = '#^(text|application)/(x[-.])*rss(\+xml)?$|^\*/\*$#'; - $regex_RDF = '#^(text|application)/(x[-.])*(rss[-.+])?rdf([-.]rss)?(\+xml)?$#'; - $regex_ATOM= '#^(text|application)/(x[-.])*atom(\+xml)*$#'; - $what = "DUMB"; - $types = ewiki_sort_accept($_SERVER["HTTP_ACCEPT"]); - foreach ($types as $type=>$attr) { - #-- RSS - if (preg_match($regex_RSS, $type) || ($type == "text/xml")) { - $ver = isset($attr["version"]) ? (int) $attr["version"] : (int) $attr["revision"]; - if ($ver < 4) { - $WHAT = "RSS$ver"; // one of "RSS0", "RSS1", "RSS2", "RSS3" - if ($ver != 1) { - break; - } - } - } - #-- ATOM - elseif (preg_match($regex_ATOM, $type)) { - $WHAT = "ATOM"; - break; - } - #-- exceptions - elseif (preg_match($regex_RDF, $type)) - { $WHAT = "RSS1"; break; } - elseif ($type == "text/plain") - { $WHAT = "RSS3"; break; } - elseif ($type == "*/*") - { $WHAT = "RSS2"; } - } - return($WHAT); -} - - - -#--------------------------------------------------------------------------- -# evaluates and sorts Accept: header (and alikes) -# -function ewiki_sort_accept($str) { - $r = array(); - $attr = array(); - $def = 0.99; - foreach (explode(",", $str) as $type) { - $type = strtok(trim($type), ";"); - $q = ($def *= 0.99); - if ($params = trim(strtok("\000"))) { - foreach (explode(";", $params) as $p) { - $pname = trim(strtok($p, "=")); - $val = trim(strtok("\000")); - if ($pname == "q") { - ($q = $val * 1.0) or ($q = $def); - } - $attr[$type][$pname] = $val; - } - } - $r[$type] = $q; - } - arsort($r); - foreach ($r as $t=>$uu) { - $r[$t] = $attr[$t]; - } - return($r); -} - - -#-- PHP backwards compatibility -if (!function_exists("xmlentities")) { - function xmlentities($str) { - return strtr($str, array("&"=>"&", "<"=>"<", - ">"=>">", "\""=>""", "'"=>"'")); - } -} - -#-- does not reescape numeric XML entities -function ewiki_xmlentities($str) { - $xe = array("&"=>"&", "<"=>"<", ">"=>">", "\""=>""", "'"=>"'"); - return preg_replace("/(&(?>!#x|#\d)|[<>\"'])/e", '$xe["$1"]', $str); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/feedparse.meta b/mods/wiki/plugins/lib/feedparse.meta deleted file mode 100644 index 35fd2e5ae..000000000 --- a/mods/wiki/plugins/lib/feedparse.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -type: functions -provides: rss-parser, atom-parser -depends: xml, http, http_cached -title: RSS/Atom parser -description: can load and decipher various syndication feed formats -category: library -priority: optional diff --git a/mods/wiki/plugins/lib/feedparse.php b/mods/wiki/plugins/lib/feedparse.php deleted file mode 100644 index e03435ecf..000000000 --- a/mods/wiki/plugins/lib/feedparse.php +++ /dev/null @@ -1,120 +0,0 @@ -parse(); - if (isset($xml->channel)) { - $r = array($xml->channel, $xml->item); - } - } - #-- text/rfc822 rss - else { - $item = ewiki_decode_rfc822($xml); - $channel = $item[0]; - unset($item[0]); - $r = array($channel, $item); - } - #-- unified timestamps - if ($r[1]) foreach($r[1] as $i=>$d) { - $r[1][$i]["time"] = ewiki_decode_datetime($d["pubDate"]); - } - return($r); -} - - -#-- separates multiple blocks of name:value pairs -function ewiki_decode_rfc822($text) { - $blocks = array(); - foreach (preg_split("/\r?\n\r?\n/", $xml) as $part) { - $r = array(); - foreach (preg_split("/\r?\n(?>[^\s])/") as $field) - { - $r[trim(strtolower(strtok($field, ":")))] - = trim(preg_replace("/\s+/", " ", strtok("\000"))); - } - $blocks[] = $r; - } - return($blocks); -} - - -#-- tries to decipher a date+time string into a unixish timestamp -function ewiki_decode_datetime($str, $localize=1, $gmt=0) { - $done = 0; - $months = array_flip(array("Err", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")); - - #-- 8601 - if (($str[4] == "-") - and preg_match("/(\d+)-(\d+)-(\d+)(T(\d+):(\d+)(:(\d+))?)?/", $str, $uu)) { - $t = gmmktime($uu[5], $uu[6], $uu[8], $uu[2], $uu[3], $uu[1]); - } - #-- mbox, ANSI C asctime() - elseif (($str[3] == " ") - and preg_match("/\w+ (\w+) +(\d+) (\d+):(\d+):(\d+) (\d+)/", $str, $uu)) { - $t = gmmktime($uu[3], $uu[4], $uu[5], $months[$uu[1]], $uu[2], $uu[6]); - $gmt = 1; - } - #-- rfc822/1123, (rfc850/1036), mostly for HTTP - elseif (1 - and preg_match("/\w+, (\d+)[- ](\w+)[- ](\d+) (\d+):(\d+):(\d+)/", $str, $uu)) { - $t = gmmktime($uu[4], $uu[5], $uu[6], $months[$uu[2]], $uu[1], $uu[3]); - $gmt = 1; - } - #-- already was a timestamp - elseif (((int)$str) == $str) { - $t = (int)$str; - $gmt = 1; - } - #-- last resort - else { - $t = strtotime($str); - $gmt = 1; - } - - #-- is local time (iso8601 only) - if (!$gmt && $localize && preg_match('/([+-])(\d+):(\d+)$/', $str, $uu)) { - $dt = $uu[1] * 60 + $uu[2]; - if ($uu[1] == "+") { - $t -= $dt; - } - else { - $t += $dt; - } - } - - return($t); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/fix.meta b/mods/wiki/plugins/lib/fix.meta deleted file mode 100644 index a851ef778..000000000 --- a/mods/wiki/plugins/lib/fix.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: PHP -type: intercept -title: PHP fixes -descriptions: removes bogus magic_quotes and left over superglobals -priority: auto -category: library -conflicts: strike_register_globals, strip_wonderful_slashes diff --git a/mods/wiki/plugins/lib/fix.php b/mods/wiki/plugins/lib/fix.php deleted file mode 100644 index 877505a51..000000000 --- a/mods/wiki/plugins/lib/fix.php +++ /dev/null @@ -1,49 +0,0 @@ -$value) { - if (isset($TO[$var]) && ($TO[$var]==$FROM[$var])) { - unset($TO[$var]); - } - } - } - function ewiki_recursive_stripslashes(&$var) { - if (is_array($var)) { - foreach ($var as $key=>$item) { - ewiki_recursive_stripslashes($var[$key]); - } - } - else { - $var = stripslashes($var); - } - } - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/gzdecode.meta b/mods/wiki/plugins/lib/gzdecode.meta deleted file mode 100644 index 75be849f2..000000000 --- a/mods/wiki/plugins/lib/gzdecode.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: PHP -type: emulation -title: gzdecode() -description: adds support for the gzdecode() function, superseded by upgrade.php -priority: deprecated diff --git a/mods/wiki/plugins/lib/http.meta b/mods/wiki/plugins/lib/http.meta deleted file mode 100644 index 105cfcc9e..000000000 --- a/mods/wiki/plugins/lib/http.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: PHP -type: functions -category: library -priority: optional -provides: http-request -title: HTTP requests -description: implements HTTP protocol, various request methods supported -url: http://freshmeat.net/p/upgradephp -version: 11.3 diff --git a/mods/wiki/plugins/lib/http.php b/mods/wiki/plugins/lib/http.php deleted file mode 100644 index 410df9730..000000000 --- a/mods/wiki/plugins/lib/http.php +++ /dev/null @@ -1,623 +0,0 @@ -$params (form variables) on the fly, it's a hash - - if the initial URL contains a query string, the vars will be - extracted first - - set the ->$enc very carefully, because many CGI apps and HTTP - servers can't deal with it (else "gzip" and "deflate" are nice) - - there are abbreviations for the content ->$type values (namely - "form" , "url" and "php") - - user:password@ pairs may be included in the initially given URL - - headers always get normalized to "Studly-Caps" - - won't support keep-alive connections - - for PUT and other methods, the ->$params var may just hold the - request body - - files can be added to the ->params array as hash with specially - named fields: "content"/"data", and "filename"/"name" , "type" - - you can add authentication information using the standard notation - "http://user:passw@www.example.com/..." for ->$url and ->$proxy - - A response object will have a ->$content field, ->$headers[] and - ->len, ->type attributes as well. You could also ->decode() the - body, if it is app/vnd.php.serialized or app/x-www-form-urlencoded. - - Public Domain (use freely, transform into any other license, like - LGPL, BSD, MPL, ...; but if you change this into GPL please be so - kind and leave your users a hint where to find the free version). -*/ - - -#-- request objects -class http_request { - - var $method = "GET"; - var $proto = "HTTP/1.1"; - var $url = ""; - var $params = array(); // URL/form post vars, or single request body str - var $headers = array(); - var $cookies = array(); - var $type = "url"; // content-type, abbrv. for x-www-form-... - var $enc = false; // "gzip" or "deflate" - var $error="", $io_err=0, $io_err_s=""; - var $active_client = 1; // enables redirect-following - var $redirects = 3; - var $proxy = false; // set to "http://host:NN/" - var $timeout = 15; - - - #-- constructor - function http_request($method="GET", $url="", $params=NULL) { - $this->headers["User-Agent"] = "http_query/17.2 {$GLOBALS[ewiki_config][ua]}"; - $this->headers["Accept"] = "text/html, application/xml;q=0.9, text/xml;q=0.7, xml/*;q=0.6, text/plain;q=0.5, text/*;q=0.1, image/png;q=0.8, image/*;q=0.4, */*+xml;q=0.3; application/x-msword;q=0.001, */*;q=0.075"; - $this->headers["Accept-Language"] = "en, eo, es;q=0.2, fr;q=0.1, nl;q=0.1, de;q=0.1"; - $this->headers["Accept-Charset"] = "iso-8859-1, utf-8"; - $this->headers["Accept-Feature"] = "textonly, tables, !tcpa, !javascript, !activex, !graphic"; - $this->headers["Accept-Encoding"] = "deflate, gzip, compress, x-gzip, x-bzip2"; - //$this->headers["Referer"] = '$google'; - $this->headers["TE"] = "identity, chunked, binary, base64"; - $this->headers["Connection"] = "close"; - //$this->headers["Content-Type"] = & $this->type; - if (isset($params)) { - $this->params = $params; - } - if (strpos($method, "://")) { - $url = $method; # glue for incompat PEAR::Http_Request - $method = "GET"; - } - $this->method($method); - $this->setURL($url); - } - - - #-- sets request method - function method($str = "GET") { - $this->method = $str; - } - - #-- special headers - function setcookie($str="name=value", $add="") { - $this->cookies[strtok($str,"=")] = strtok("\000").$add; - } - - - #-- deciphers URL into server+path and query string - function setURL($url) { - if ($this->method == "GET") { - $this->url = strtok($url, "?"); - if ($uu = strtok("\000")) { - $this->setQueryString($uu); - } - } - else { - $this->url = $url; - } - } - - - #-- decodes a query strings vars into the $params hash - function setQueryString($qs) { - $qs = ltrim($qs, "?"); - parse_str($qs, $this->params); - } - - - #-- returns params as querystring for GET requests - function getQueryString() { - $qs = ""; - if (function_exists("http_build_query")) { - $qs = http_build_query($this->params); - } - else { - foreach ($this->params as $n=>$v) { - $qs .= "&" . urlencode($n) . "=" . urlencode($v); - } - $qs = substr($qs, 1); - } - return($qs); - } - - - #-- transforms $params into request body - function pack(&$path) { - $m = strtoupper($this->method); - - #-- GET, HEAD - if (($m == "GET") || ($m == "HEAD")) { - $BODY = ""; - $path .= (strpos($path, "?") ? "&" : "?") . $this->getQueryString(); - } - - #-- POST - elseif (($m == "POST") && is_array($this->params)) { - - #-- known encoding types - $type = $this->type($this->type, 0); - if ($type == "url") { - $BODY = $this->getQueryString($prep=""); - } - elseif ($type == "php") { - $BODY = serialize($this->params); - } - elseif ($type == "form") { - // boundary doesn't need checking, unique enough - $bnd = "snip-".dechex(time())."-".md5(serialize($this->params)) - . "-".dechex(rand())."-snap"; - $BODY = ""; - foreach ($this->params as $i=>$v) { - $ct = "text/plain"; - $inj = ""; - if (is_array($v)) { - ($ct = $v["ct"].$v["type"].$v["content-type"]) || ($ct = "application/octet-stream"); - $inj = ' filename="' . urlencode($v["name"].$v["file"].$v["filename"]) . '"'; - $v = $v["data"].$v["content"].$v["body"]; - } - $BODY .= "--$bnd\015\012" - . "Content-Disposition: form-data; name=\"".urlencode($i)."\"$inj\015\012" - . "Content-Type: $ct\015\012" - . "Content-Length: " . strlen($v) . "\015\012" - . "\015\012$v\015\012"; - } - $BODY .= "--$bnd--\015\012"; - $ct = $this->type("form") . "; boundary=$bnd"; - } - #-- ignore - else { - $this->error = "unsupported POST encoding"; - // return(false); - $BODY = & $this->params; - } - - $this->headers["Content-Type"] = isset($ct) ? $ct : $this->type($type, 1); - } - - #-- PUT, POST, PUSH, P* - elseif ($m[0] == "P") { - $BODY = & $this->$params; - } - - #-- ERROR (but don't complain) - else { - $this->error = "unsupported request method '{$this->method}'"; - // return(false); - $BODY = & $this->params; - } - - return($BODY); - } - - - #-- converts content-type strings from/to shortened nick - function type($str, $long=1) { - $trans = array( - "form" => "multipart/form-data", - "url" => "application/x-www-form-urlencoded", - "php" => "application/vnd.php.serialized", - ); - $trans["multi"] = &$trans["form"]; - if ($long) { - $new = $trans[$str]; - } - else { - $new = array_search($str, $trans); - } - return( $new ? $new : $str ); - } - - - #-- initiate the configured HTTP request ------------------------------ - function go($force=0, $asis=0) { - - #-- prepare parts - $url = $this->prepare_url(); - if (!$url && !$force) { return; } - $BODY = $this->body($url); - if (($BODY===false) && !$force) { return; } - $HEAD = $this->head($url); - - #-- open socket - if (!$this->connect($url)) { - return; - } - - #-- send request data - fwrite($this->socket, $HEAD); - fwrite($this->socket, $BODY); - $HEAD = false; - $BODY = false; - - #-- read response, end connection - while (!feof($this->socket) && (strlen($DATA) <= 1<<22)) { - $DATA .= fread($this->socket, 32<<10); - } - fclose($this->socket); - unset($this->socket); - - #-- for raw http pings - if ($asis) { - return($DATA); - } - - #-- decode response - $r = new http_response(); - $r->from($DATA); // should auto-unset $DATA - - #-- handle redirects - if ($this->active_client) { - $this->auto_actions($r); - } - - #-- fin - return($r); - } - - #-- alias - function start($a=0, $b=0) { - return $this->go($a, $b); - } - - - #-- creates socket connection - function connect(&$url) { - if ((isset($this->socket) and !feof($this->socket)) - or ($this->socket = fsockopen($url["host"], $url["port"], $this->io_err, $this->io_err_s, $this->timeout))) { - socket_set_blocking($this->socket, true); - socket_set_timeout($this->socket, $this->timeout, 555); - return(true); - } - else { - $this->error = "no socket/connection"; - return(false); - } - } - - - #-- separate URL into pieces, prepare special headers - function prepare_url() { - $this->setURL($this->url); - if (!$this->proxy) { - $url = parse_url($this->url); - if (strtolower($url["scheme"]) != "http") { - $this->error = "unsupported protocol/scheme"; - return(false); - } - if (!$url["host"]) { return; } - if (!$url["port"]) { $url["port"] = 80; } - if (!$url["path"]) { $url["path"] = "/"; } - if ($url["query"]) { $url["path"] .= "?" . $url["query"]; } - $proxy = ""; - } - else { - $url = parse_url($this->proxy); - $url["path"] = $this->url; - $proxy = "Proxy-"; - $this->headers["Proxy-Connection"] = $this->headers["Connection"]; - } - - #-- inj auth headers - if ($url["user"] || $url["pass"]) { - $this->headers[$proxy."Authorization"] = "Basic " . base64_encode("$url[user]:$url[pass]"); - } - - return($url); - } - - - #-- generates request body (if any), must be called before ->head() - function body(&$url) { - - #-- encoding of variable $params as request body (according to reqmethod) - $BODY = $this->pack($url["path"]); - if ($BODY === false) { - return false; - } - elseif ($len = strlen($BODY)) { - $this->headers["Content-Length"] = $len; - } - $enc_funcs = array("gzip"=>"gzencode", "deflate"=>"gzinflate", "bzip2"=>"bzcompress", "x-bzip2"=>"bzcompress", "compress"=>"gzcompress"); - if ((strlen($BODY) >= 1024) && ($f = $enc_funcs[$this->enc]) && function_exists($f)) { - $BODY = $f($BODY); - $this->headers["Content-Encoding"] = $this->enc; - $this->headers["Content-Length"] = strlen($BODY); - } - return($BODY); - } - - - #-- generates request head part - function head(&$url) { - - #-- inject cookie header (if any) - if ($this->cookies) { - $c = ""; - foreach ($this->cookies as $i=>$v) { - $c .= "; " . urlencode($i) . "=" . urlencode($v); - } - $this->headers["Cookie"] = substr($c, 2); - $this->headers["Cookie2"] = '$Version="1"'; - } - - #-- request head - $CRLF = "\015\012"; - $HEAD = "{$this->method} {$url[path]} {$this->proto}$CRLF"; - $HEAD .= "Host: {$url[host]}$CRLF"; - foreach ($this->headers as $h=>$v) { - $HEAD .= trim($h) . ": " . strtr(trim($v), "\n", " ") . $CRLF; - } - $HEAD .= $CRLF; - return($HEAD); - } - - #-- perform some things automatically (redirects) - function auto_actions(&$r) { - - #-- behaviour table - static $bhv = array( - "failure" => "204,300,304,305,306", - "clean_::POST" => "300,301,302,303,307", - "clean_::PUT" => "300,301,302,303,307", - "clean_::GET" => "300", // $params:=undef - "GET_::POST" => "303", - "GET_::PUT" => "303", // downgrade $method:=GET - ); - - #-- failure - if (strstr($this->behaviour_table["failure"], $r->status)) { - return; - } - - #-- HTTP redirects - if (($pri_url=$r->headers["Location"]) || ($pri_url=$r->headers["Uri"])) { - - if ((($this->redirects--) >= 0) && ($r->status >= 300) && ($r->status < 400)) { - $m = strtoupper($this->method); - if (strstr($this->behaviour_table["clean_::$m"], $r->status)) { - unset($this->params); - } - if (strstr($this->behaviour_table["GET_::$m"], $r->status)) { - $this->method("GET"); - } - $this->setURL($pri_url); - $this->go(); - } - } - } - - #-- aliases for compatiblity to PEAR::HTTP_Request - function sendRequest() { - return $this->go(); - } - function setBasicAuth($user, $pw) { - $this->url = preg_replace("#//(.+?@)?#", "//$user@$pw", $this->url); - } - function setMethod($m) { - $this->method($m); - } - function setProxy($host, $port=8080, $user="", $pw="") { - $auth = ($pw ? "$user:$pw@" : ($user ? "$user@" : "")); - $this->proxy = "http://$auth$server:$port"; - } - function addHeader($h, $v) { - $this->headers[$h] = $v; - } - function getResponseStatus() { - $this->headers[$h] = $v; - } -} -class http_query extends http_request { - /* this is just an alias */ -} - - - - -#-- every query result will be encoded in such an object -------------------- -class http_response { - - var $status = 520; - var $status_str = ""; - var $headers_str = ""; - var $headers = array(); - var $len = 0; - var $type = "message/x-raw"; - var $content = ""; - - - function http_response() { - } - - - #-- fill object from given HTTP response BLOB - function from(&$SRC) { - $this->breakHeaders($SRC); // split data into body + headers - $SRC = false; - $this->decodeHeaders(); // normalize header names - $this->headerMeta(); - $this->decodeTransferEncodings(); // chunked - $this->decodeContentEncodings(); // gzip, deflate - $this->len = strlen($this->content); - } - - - #-- separates headers block from response body part - function breakHeaders(&$DATA) { - $l = strpos($DATA, "\012\015\012"); $skip = 3; - $r = strpos($DATA, "\012\012"); - if ($r && ($r<$l)) { $l = $r; $skip = 2; } - if (!$l) { $l = strlen($DATA); } - $this->headers_str = rtrim(substr($DATA, 0, $l), "\015"); - $this->content = substr($DATA, $l + $skip); - $this->body = & $this->content; - $this->data = & $this->content; // aliases - $this->ct = & $this->type; - } - - - #-- splits up the $headers_str into an array and normalizes header names - function decodeHeaders() { - - #-- normalize linebreaks - $str = & $this->headers_str; -// $str = str_replace("\n ", " ", $str); - $str = str_replace("\r", "", $str); - - #-- strip headline - $nl = strpos($str, "\n") + 1; - $this->proto = strtok(substr($str, 0, $nl), " "); - $this->status = (int) strtok(" "); - $this->status_str = strtok("\000\r\n"); - if ($this->status == 100) { - $this->full_duplex = 1; - } - - #-- go through lines, split name:value pairs - foreach (explode("\n", substr($str, $nl)) as $line) { - - $i = trim(strtok($line, ":")); - $v = trim(strtok("\000")); - - #-- normalize name look&feel - $i = strtr(ucwords(strtolower(strtr($i, "-", " "))), " ", "-"); - - #-- add to, if key exists - if (!empty($this->headers[$i])) { - $this->headers[$i] .= ", ".$v; - } - else { - $this->headers[$i] = $v; - } - - } - } - - - #-- extract interesting values - function headerMeta() { - $this->len = strlen($this->content); - $this->type = trim(strtok(strtolower($this->headers["Content-Type"]), ";")); - } - - - #-- strip any content transformation - function decodeTransferEncodings() { - $enc = trim(strtok(strtolower($this->headers["Transfer-Encoding"]), ",;")); - if ($enc) { - switch ($enc) { - case "chunked": - $this->decodeChunkedEncoding(); - break; - case "base64": - $this->content = base64_decode($this->content); - $this->len = strlen($this->content); - break; - case "identity": case "binary": - case "7bit": case "8bit": - break; - default: - trigger_error("http_response::decodeTransferEncodings: unkown TE of '$enc'\n", E_WARNING); - } - } - } - - - #-- scripts on HTTP/1.1 servers may send fragmented response - function decodeChunkedEncoding() { - - $data = ""; # decoded data - $p = 0; # current string position - - while ($p < strlen($this->content)) { - - #-- read len token - $n = strtok(substr($this->content, $p, 20), "\n"); - $p += strlen($n)+1; - - #-- make integer - $n = 0 + (int) (trim($n)); - if (!$n) { - break; - } - - #-- read data - $data .= substr($this->content, $p, $n); - $p += $n; - } - - $this->content = $data; - unset($data); - $this->len = strlen($this->content); - } - - - #-- uncompress response body - function decodeContentEncodings() { - $enc = trim(strtok(strtolower($this->headers["Content-Encoding"]), ";,")); - $dat = &$this->content; - if ($enc == "deflate") { - $dat = gzinflate($dat); - } - elseif (($enc == "gzip") || ($enc == "x-gzip")) { - if (function_exists("gzdecode")) { - $dat = gzdecode($dat); - } - else { - $dat = gzinflate(substr($dat, 10, strlen($dat)-18)); - } - } - elseif ($enc == "compress") { - $dat = gzuncompress($dat); - } - elseif (($enc == "x-bzip2") || ($enc == "bzip2")) { - if (function_exists("bzdecompress")) { - $dat = bzdecompress($dat); - } - else trigger_error("http_response::decodeContentEncoding: bzip2 decoding isn't supported with this PHP interpreter version", E_WARNING); - } - $this->len = strlen($this->content); - } - - - #-- can handle special content-types (multipart, serialized, form-data) - function decode() { - $t = http_request::type($this->type, 0); - if ($t == "php") { - return(unserialize($this->content)); - } - elseif ($t == "url") { - parse_str($this->content, $r); - return($r); - } - elseif ($t == "form") { - // oh, not yet exactly - } - } - - #-- aliases for compatiblity to PEAR::HTTP_Request - function getResponseBody() { - return $this->content; - } - function getResponseStatus() { - return $this->status; - } - function getResponseCode() { - return $this->status; - } - function getResponseHeader($i=NULL) { - if (!isset($i)) { - return $this->headers; - } - $i = strtolower($i); - foreach ($this->headers as $h=>$v) { - if (strtolower($h)==$i) { - return $v; - } - } - } -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/http_cache.meta b/mods/wiki/plugins/lib/http_cache.meta deleted file mode 100644 index 3d27e1934..000000000 --- a/mods/wiki/plugins/lib/http_cache.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -type: functions -category: library -priority: extra -depends: http -title: cached HTTP GETs -description: caches HTTP GET requests as temporary database entries diff --git a/mods/wiki/plugins/lib/http_cache.php b/mods/wiki/plugins/lib/http_cache.php deleted file mode 100644 index 43b56d599..000000000 --- a/mods/wiki/plugins/lib/http_cache.php +++ /dev/null @@ -1,51 +0,0 @@ -header["Accept"] = "application/atom+xml, application/rss+xml, text/rss, xml/*, */*rss*"; - if ($data["meta"]["Last-Modified"]) { - $req->headers["If-Modified-Since"] = $data["meta"]["Last-Modified"]; - } - if ($data["meta"]["Etag"]) { - $req->headers["If-None-Match"] = $data["meta"]["Etag"]; - } - $result = $req->go(); - - #-- create/overwrite cache entry - if ($result->status == 200) { - $data = ewiki_db::CREATE($url, 0x0000, "ewiki_cache_url"); - $data["flags"] = 0x0000; - $data["content"] = $result->body; - foreach ($result->headers as $i=>$v) { - $data["meta"][$i] = $v; - } - $data["meta"]["class"] = "temp"; - $data["meta"]["kill-after"] = time() + $cache_min; - if ($t = $data["meta"]["Last-Modified"]) { - // $data["lastmodified"] = ewiki_decode_datetime($t); - } - ewiki_db::WRITE($data,"_OVERWRITE=1"); - } - - $ewiki_cache_ctype = $data["Content-Type"]; - return($data["content"]); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/js.meta b/mods/wiki/plugins/lib/js.meta deleted file mode 100644 index 6e9bf54d6..000000000 --- a/mods/wiki/plugins/lib/js.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: library -title: JavaScript -description: server-side JS interpreter in PHP -priority: deprecated -type: api diff --git a/mods/wiki/plugins/lib/libxprofile.meta b/mods/wiki/plugins/lib/libxprofile.meta deleted file mode 100644 index b4545771e..000000000 --- a/mods/wiki/plugins/lib/libxprofile.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: PHP -type: api -version: 0.1.0 -depends: http, xml -title: XUP/XProfile -description: parser for XML User Profiles -homepage: http://xprofile.berlios.de/ -category: library diff --git a/mods/wiki/plugins/lib/libxprofile.php b/mods/wiki/plugins/lib/libxprofile.php deleted file mode 100644 index 0cb581fdc..000000000 --- a/mods/wiki/plugins/lib/libxprofile.php +++ /dev/null @@ -1,148 +0,0 @@ -login($password)) { - ... - echo $xuser->info["nickname"]; - } - - Should work with the older PEAR and the HTTP request class (PD) from - upgradephp. -*/ - -#-- libs -if (!class_exists("http_request")) { - include_once("http.php"); # from upgradephp/contrib/ - //include_once("http/request.php"); # from PEAR -} - -#-- config -//define("XPROFILE_SITE", "example.com"); // preferred identifier of website -define("XPROFILE_SITE", preg_replace("/^www\./","",$_SERVER["SERVER_NAME"])); - - -#-- retrieves and verifies xml user profile -class xprofile { - - #-- constructor takes URL of profile or "user@domain" shortcut - function xprofile($url, $xml=NULL, $uu0=0, $_redir=1) { - - #-- shortcut id - if (strpos($url, "@") && !strpos($url, "/")) { - $un = strtok($url, "@"); - $url = "http://" . strtok("@") . "/xprofile/" . $un; - } - - #-- keep id - $this->url = $url; - - #-- fetch data - if (empty($xml) && !strncmp($url, "http://", 7)) { - list($xml, $head) = $this->http("GET", $url); - if (!$xml) { return; } - } - - #-- parse it - $p = new xprofile_parser($xml); - $p->parse(); - if (isset($p->control) || isset($p->info)) { - $this->control = (array)$p->control; - $this->info = (array)$p->info; - $this->text = (array)$p->text; // already lcased - } - #-- "real" URL found? - if ($this->url != $this->control["self"]) { - $this->url = $this->control["self"]; - if ($_redir) { - $this->xprofile($this->url, NULL, 0, 0); - } - } - } - - #-- verifies a user as owner of profile instance - function login($password) { - if ($login = $this->control["login"]) { - $params = array( - "url" => $this->url, - "password" => $password, - "site" => XPROFILE_SITE, - ); - list($result, $headers) = $this->http("POST", $login, $params); - // should come without appended \r or \n (as per spec, but hey) - return(rtrim($result) === "1"); - } - } - - #-- HTTP requests - function http($method, $url, $formdata=array()) { - if (class_exists("http_request")) { - $req = new http_request(); - $req->setMethod($method); - $req->setURL($url); - $req->addHeader("Accept", "xml/user-profile, text/boolean, */*; q=0.1"); - if ($formdata) { - $req->params += $formdata; - $req->_postData = $formdata; // PEAR tries to annoy us - } - $r = $req->sendRequest(); - if ($r && ($r->getResponseStatus() == 200)) { - return array($r->getResponseBody(), $r->getResponseHeader()); - } - } - elseif ($method=="GET") { - return array(file_get_contents($url), array()); - } - elseif ($method=="POST") { - // give up - } - return array(NULL, NULL); - } -} - - -#-- xup parsing -class xprofile_parser extends easy_xml { - - function xprofile_parser($xml) { - #-- prepare - $this->easy_xml(); - $this->xmlns["urn:mime:xml/user-profile"] = "xup"; - $this->xmlns2["xup"] = ""; - #-- go - $this->parse($xml); - return($this); - } - - #-- XML tags - function start($xp, &$tag, &$attr) { - parent::start($xp, $tag, $attr); - $p = $this->parent; - unset($this->text_meta); - if ($tag == "link") { - $this->{$p}[strtolower($attr["rel"])] = $attr["href"]; - } - elseif ($tag == "meta") { - $name = strtolower($attr["name"]); - if (isset($attr["content"])) { - $this->{$p}[$name] = $attr["content"]; - } - elseif ($this->parent == "text") { - $this->text_meta = $name; - } - } - } - #-- text:meta content - function cdata($xp, $text) { - if (isset($this->text_meta)) { - $this->text[$this->text_meta] = $text; - unset($this->text_meta); - } - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/mime_magic.meta b/mods/wiki/plugins/lib/mime_magic.meta deleted file mode 100644 index 6c6cc9fa5..000000000 --- a/mods/wiki/plugins/lib/mime_magic.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: library -title: mime magic data -description: adds a built-in auto detection for mime types, helpful to the downloads extension -priority: rare -hooks: mime_magic -type: special diff --git a/mods/wiki/plugins/lib/mime_magic.php b/mods/wiki/plugins/lib/mime_magic.php deleted file mode 100644 index 7e34fe3a0..000000000 --- a/mods/wiki/plugins/lib/mime_magic.php +++ /dev/null @@ -1,560 +0,0 @@ -NOT-PD ############################### - - -/* - -# this was originally implemented for Nanoweb, but can now be used -# within ewiki to enhance the download/upload plugin. -# It was assembled from Debians mime-magic data, and is eventually -# covered by copyright and a BSD (?) license, please see your local -# /usr/share/misc/magic and the file(1) man page. - -*/ - - -$ewiki_plugins["mime_magic"][] = "ewiki_mime_magic"; - - - -function ewiki_mime_magic(&$binary_data) { - - global $mime_magic_data; - - $fd = substr($binary_data, 0, 3072); - - foreach ($mime_magic_data as $def) { - - if ($def[0] >= $f_read) { - continue; - } - - $pos0 = $def[0]; - - if ($pos0[0] == ">") { - - $pos0 = substr($pos0, 1); - - if (strpos($fd, $def[3], $pos0) !== false) { - - return($def[4]); - } - - } - else { - - $part = substr($fd, $pos0, $def[1]); - - if ($mask = $def[2]) { - - $value = 1 * ('0x'.bin2hex($part)); - - if (($value & $mask) == $def[3]) { - - return($def[4]); - } - - } - else { - - if ($part == $def[3]) { - - return($def[4]); - } - - } - } - - } - -} - - - - - - $GLOBALS["mime_magic_data"] = array( - array(0, 2, 0, "\x06\x02", "application/x-alan-adventure-game"), - array(0, 4, 0, "TADS", "application/x-tads-game"), - array(0, 2, 0, "\x01\x10", "application/x-executable-file"), - array(0, 2, 0, "\x01\x11", "application/x-executable-file"), - array(0, 2, 0, "\x01ƒ", "application/x-executable-file"), - array(0, 5, 0, "Core\001", "application/x-executable-file"), - array(0, 22, 0, "AMANDA: TAPESTART DATE", "application/x-amanda-header"), - array(0, 2, 0xfff0, 0xf0ff, "audio/mpeg"), - array(4, 2, 0, "¯\x11", "video/fli"), - array(4, 2, 0, "¯\x12", "video/flc"), - array(0, 4, 0, "MOVI", "video/x-sgi-movie"), - array(4, 4, 0, "moov", "video/quicktime"), - array(4, 4, 0, "mdat", "video/quicktime"), - array(0, 18, 0, "FiLeStArTfIlEsTaRt", "text/x-apple-binscii"), - array(0, 3, 0, "\x0aGL", "application/data"), - array(0, 2, 0, "\x76\xff", "application/data"), - array(0, 6, 0, "NuFile", "application/data"), - array(0, 6, 0, "N\xf5F\xe9l\xe5", "application/data"), - array(0, 4, 0, "\x00\x16\x05\x00", "application/data"), - array(0, 4, 0, "\x07\x16\x05\x00", "application/data"), - array(257, 6, 0, "ustar\0", "application/x-tar"), - array(257, 8, 0, "ustar\040\040\0", "application/x-gtar"), - array(0, 2, 0, "qÇ", "application/x-cpio"), - array(0, 2, 0, "Çq", "application/x-bcpio"), - array(0, 6, 0, "070707", "application/x-cpio"), - array(0, 6, 0, "070701", "application/x-cpio"), - array(0, 6, 0, "070702", "application/x-cpio"), - array(0, 2, 0, "ÿm", "application/data"), - array(0, 2, 0, "ÿe", "application/data"), - array(0, 5, 0, "=", "application/x-ar"), - array(0, 19, 0, "!\n__________E", "application/x-ar"), - array(0, 3, 0, "-h-", "application/data"), - array(0, 7, 0, "!", "application/x-ar"), - array(0, 4, 0, "", "application/x-ar"), - array(0, 4, 0, ">ra<", "application/x-ar"), - array(0, 4, 0, "!\n\n________64E", "application/data"), - array(0, 2, 0, "\x01ˆ", "application/x-executable-file"), - array(0, 2, 0, "\x01", "application/x-object-file"), - array(0, 3, 0, "\377\377\177", "application/data"), - array(0, 3, 0, "\377\377\174", "application/data"), - array(0, 3, 0, "\377\377\176", "application/data"), - array(0, 3, 0, "\033c\033", "application/data"), - array(0, 4, 0, "\x00\x12և", "image/x11"), - array(0, 8, 0, "!!\n", "application/x-prof"), - array(0, 2, 0, "\x05\x01", "application/x-locale"), - array(0, 4, 0, "\177ELF", "application/x-executable-file"), - array(0, 2, 0, "\x01T", "application/data"), - array(0, 2, 0, "\x01U", "application/x-executable-file"), - array(0x438, 2, 0, "ïS", "application/x-linux-ext2fs"), - array(0, 4, 0, "\366\366\366\366", "application/x-pc-floppy"), - array(0774, 2, 0, "¾Ú", "application/data"), - array(0x1FE, 2, 0, "ªU", "application/data"), - array(0x410, 2, 0, "\x13", "application/x-filesystem"), - array(0x410, 2, 0, "\x13", "application/x-filesystem"), - array(0x410, 2, 0, "\x24h", "application/x-filesystem"), - array(0x410, 2, 0, "\x24x", "application/x-filesystem"), - array(0, 9, 0, "-rom1fs-\0", "application/x-filesystem"), - array(0, 4, 0, "\x1b\x03\x136", "application/x-bootable"), - array(0x18b, 4, 0, "OS/2", "application/x-bootable"), - array(0, 4, 0, "FONT", "font/x-vfont"), - array(0, 2, 0, "\x01\x1e", "font/x-vfont"), - array(0, 2, 0, "\x1e\x01", "font/x-vfont"), - array(0, 18, 0, "%!PS-AdobeFont-1.0", "font/type1"), - array(6, 18, 0, "%!PS-AdobeFont-1.0", "font/type1"), - array(0, 10, 0, "STARTFONT\040", "font/x-bdf"), - array(0, 4, 0, "\001fcp", "font/x-pcf"), - array(0, 5, 0, "D1.0\015", "font/x-speedo"), - array(0, 3, 0, "flf", "font/x-figlet"), - array(0, 3, 0, "flc", "application/x-font"), - array(0, 4, 0, "\x19Y\x02\x14", "font/x-libgrx"), - array(0, 4, 0, "NOFÿ", "font/x-dos"), - array(7, 4, 0, "AGE\x00", "font/x-dos"), - array(7, 4, 0, "DIV\x00", "font/x-dos"), - array(0, 10, 0, "2', 2, 0, "º¾", "application/java"), - array(8, 4, 0, "AIFF", "audio/x-aiff"), - array(8, 4, 0, "AIFC", "audio/x-aiff"), - array(8, 4, 0, "8SVX", "audio/x-aiff"), - array('>8', 4, 0, "WAVE", "audio/x-wav"), - array('>8', 3, 0, "AVI", "video/x-msvideo"), - array(0, 3, 0, "ID3", "audio/mpeg"), - array(0, 4, 0, "OggS", "audio/x-ogg"), - array(0, 6, 0, "/* XPM", "image/x-xpm"), - array(16, 2, 0, "==", "image/x-3ds"), - array(0, 11, 0, "#!/bin/tcsh", "application/x-shellscript"), - array(0, 12, 0, "#! /bin/tcsh", "application/x-shellscript"), - array(0, 18, 0, "#! /usr/local/tcsh", "application/x-shellscript"), - array('>8', 6, 0, "debian", "application/x-debian-package"), - array('>2', 2, 0, "Ûî", "application/x-rpm"), - array(2, 5, 0, "-lh -", "application/x-lha"), - array(2, 5, 0, "-lh6-", "application/x-lha"), - array(2, 5, 0, "-lh7-", "application/x-lha"), - array(0, 15, 0, "8', 4, 0, "AVI ", "video/avi"), - array(0, 1, 0, "\x01", "video/unknown"), - array(0, 1, 0, "\x02", "video/unknown"), - array(0, 19, 0, "[KDE Desktop Entry]", "application/x-kdelnk"), - array(0, 18, 0, "\# KDE Config File", "application/x-kdelnk"), - array(0, 7, 0, "\# xmcd", "text/xmcd"), - array(0, 4, 0, "\x8aMNG", "video/x-mng"), - array(0, 4, 0, "ó\x03\x00\x00", "application/x-executable-file"), - array(0, 4, 0, "ç\x03\x00\x00", "application/x-library-file"), - array(0, 4, 0, "³\x01\x00\x00", "video/mpeg"), - array(0, 4, 0, "º\x01\x00\x00", "video/mpeg"), - array(0, 4, 0, "\x00\x00l", "application/x-apl-workspace"), - array(0, 4, 0, "\x00\x00ÿm", "application/x-ar"), - array(0, 4, 0, "\x00\x00ÿe", "application/data"), - array(0, 4, 0, "\x00\x00\x01\x06", "application/x-executable-file"), - array(0, 4, 0, "G\x01\x00\x00", "application/x-object-file"), - array(0, 4, 0, "K\x01\x00\x00", "application/x-executable-file"), - array(0, 4, 0, "M\x01\x00\x00", "application/x-executable-file"), - array(0, 4, 0, "O\x01\x00\x00", "application/x-executable-file"), - array(24, 4, 0, "kê\x00\x00", "application/data"), - array(24, 4, 0, "lê\x00\x00", "application/data"), - array(24, 4, 0, "mê\x00\x00", "application/data"), - array(24, 4, 0, "nê\x00\x00", "application/data"), - array(0, 4, 0, "\x01\x00\x00", "application/x-object-file"), - array(0, 4, 0, "‡\x01\x00\x00", "application/data"), - array(24, 4, 0, "\x00\x00êl", "application/x-dump"), - array(24, 4, 0, "\x00\x00êk", "application/x-dump"), - array(0, 4, 0, "\x00\x00¾1", "text/vnd.ms-word"), - array(0, 2, 0, "\x00\x00", "audio/mpeg"), - array('>16', 2, 0, "\x00\x01", "application/x-object"), - array('>16', 2, 0, "\x00\x02", "application/x-executable"), - array('>16', 2, 0, "\x00\x03", "application/x-sharedlib"), - array('>16', 2, 0, "\x00\x04", "application/x-coredump"), - array(0, 4, 0, "\x00\x00\x00Ì", "application/x-executable-file"), - array(0, 4, 0, "\x04\x00\x00\x00", "font/x-snf"), - array(0, 4, 0, "\x00\x00\x00\x04", "font/x-snf"), - array('>12', 4, 0, "\x01\x00\x00\x00", "audio/basic"), - array('>12', 4, 0, "\x02\x00\x00\x00", "audio/basic"), - array('>12', 4, 0, "\x03\x00\x00\x00", "audio/basic"), - array('>12', 4, 0, "\x04\x00\x00\x00", "audio/basic"), - array('>12', 4, 0, "\x05\x00\x00\x00", "audio/basic"), - array('>12', 4, 0, "\x06\x00\x00\x00", "audio/basic"), - array('>12', 4, 0, "\x07\x00\x00\x00", "audio/basic"), - array('>12', 4, 0, "\x17\x00\x00\x00", "audio/x-adpcm"), - array('>12', 4, 0, "\x00\x00\x00\x01", "audio/x-dec-basic"), - array('>12', 4, 0, "\x00\x00\x00\x02", "audio/x-dec-basic"), - array('>12', 4, 0, "\x00\x00\x00\x03", "audio/x-dec-basic"), - array('>12', 4, 0, "\x00\x00\x00\x04", "audio/x-dec-basic"), - array('>12', 4, 0, "\x00\x00\x00\x05", "audio/x-dec-basic"), - array('>12', 4, 0, "\x00\x00\x00\x06", "audio/x-dec-basic"), - array('>12', 4, 0, "\x00\x00\x00\x07", "audio/x-dec-basic"), - array('>12', 4, 0, "\x00\x00\x00\x17", "audio/x-dec-adpcm") - ); - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/minidav.meta b/mods/wiki/plugins/lib/minidav.meta deleted file mode 100644 index 0d6a356aa..000000000 --- a/mods/wiki/plugins/lib/minidav.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: PHP -type: api -priority: auto -category: library -title: WebDAV API -description: protocol handling -depends: xml, upgrade diff --git a/mods/wiki/plugins/lib/minidav.php b/mods/wiki/plugins/lib/minidav.php deleted file mode 100644 index 17d4d7abe..000000000 --- a/mods/wiki/plugins/lib/minidav.php +++ /dev/null @@ -1,729 +0,0 @@ -xmlns[] keeps a prefix list) - + PROPFIND uses simple property lists, with path and status inside - + LOCK, PROPATCH, MOVE, COPY, DELETE are unimplemented as of yet - + all M$-DAV compatibility workarounds have been disabled - + the GET() interface will NOT work with file handles and big files - - This class automatically adds and removes the base URL from incoming - and sent pathnames. It also translates XML namespace qualifiers, if - they get registered correctly beforehand. Most request parameters are - available as object properties AND as method parameters. - - File lists for PROPFIND and PROPPATCH simply contain a "path" (again - without the base URL) and multiple DAV: properties (without any xmlns - monikers). "status" is of course optional, and custom (from other XML - namespaces) entries may be there. While it is possible to treat some - of them specially, most should be simple name-value pairs. - - Simply derive a class from "MiniDav" and implement at least GET and - PROPFIND as described by the out-commented examples herein. Then make - an object instance "$dav = new YourDavClass();" and call the main - "$dav->ServerRequest();" method. Place an exit; after that into your - interface script. - - This class does not handle authentication (one of the many parts of - the WebDAV spec everybody ignores). Implement an ->auth() method, - which is already called for all RW-methods (PUT, DELELTE, MKCOL). -*/ - -define("MINIDAV_IGNORE_MIME", 0); // there are a few bogus clients - - -#-- WebDAV base class -class MiniDav { - - #-- request - var $path = ""; - var $depth = 9; - var $dest = ""; - var $version = NULL; // no SVN proto support - var $props = NULL; - - #-- both must be lowercase here - var $int_charset = "iso-8859-1"; - var $ext_charset = "iso-8859-1"; - - #-- namespace mapping (we don't want to deal with ugly URIs throughout the code) - var $xmlns = array(); // gets fed directly into xml parsers - - #-- pre-defined values (constants) - var $base_url = ""; // will get prefixed to PROPFIND response URLs - // and stripped from incoming path names - - #-- special handling - var $prop_as_tag = array( - "resourcetype" => 1, - ); - var $prop_as_date = array( - "creationdate" => "%G-%m-%dT%TZ", - "getlastmodified" => "%a, %d %b %G %T %Z", - ); - - - #-- constructor - function MiniDav() { - - #-- you have to set all desired namespace prefixes beforehand - //@FIX: list not yet feeded into XML parser - $this->xmlns[""] = "DAV:"; // - $this->xmlns["wiki1"] = "http://purl.org/rss/1.0/modules/wiki/"; - ## $this->xmlns["ms-time-compat"] = "urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"; - } - - - #-- main function - function ServeRequest($path="") { - - #-- pathname - if (!$path) { - $path = $_SERVER["PATH_INFO"]; - } - $this->path = $path; - - #-- base url - if (!$this->base_url) { - $port = $_SERVER["SERVER_PORT"]; - $s = ($_SERVER["HTTPS"] && $_SERVER["SSL_PROTOCOL"] || ($port == 443) ? "s" : ""); - $port = ($port != ($s?443:80) ? ":$port" : ""); - $this->base_url = "http" . $s . "://" . $_SERVER["SERVER_NAME"] . $port . $_SERVER["SCRIPT_NAME"]; - } - - #-- depth - if (isset($_SERVER["HTTP_DEPTH"])) { - $d = trim(strtolower($_SERVER["HTTP_DEPTH"])); - if ($d == "infinity") { - $d = 16; - } - $this->depth = (int)$d; - } - - #-- destination path - if ($this->dest = trim($_SERVER["HTTP_DESTINATION"])) { - if (!strncmp($this->dest, $this->base_url, strlen($this->base_url))) { - $this->dest = substr($this->dest, strlen($this->base_url)); - } - else { - $this->dest = ""; - } - } - - #-- overwrite? - $this->overwrite = (($_SERVER["HTTP_OVERWRITE"] != "F") ? 1 : 0); - - #-- ??? more params - // ... - - -# $this->request_debug(); - #-- call subroutine - $method = strtoupper($_SERVER["REQUEST_METHOD"]); - $handler = $method."_request"; - if (method_exists($this, $handler) and method_exists($this, $method)) { - call_user_method("$handler", $this); - } - else { - $this->http_error("405 Unimplemented Request Method"); // or 501 ? - $this->OPTIONS_request(); - } - - #-- stop here - // exit; - # (this is handled by the caller typically) - } - - - - #------------------------------------------------------- request methods --- - - - - /////// GET /////// - - #-- retrieve a single document - function GET_request() { - $ok = $this->GET( $this->path ); - $this->http_error($ok); - } - - /* - function GET($path) { - - just call the ->GET_response() handler with some file $data - } - */ - - #-- finish - function GET_response($data, $mtime=0, $ctype="") { - - #-- fix params - if (!$mtime) { - $mtime = time(); - } - if (!$ctype) { - $ctype = "application/octet-stream"; - } - if (is_resource($data)) { - $data = fread($data, 1<<22); - } - - #-- send - header("Content-Type: $ctype"); - header("Last-Modified: ".gmstrftime($this->prop_as_date["getlastmodified"], $mtime)); - $this->cut_content($data); - $this->content_encode($data); - print($data); - - #-- done - return("200 OK"); - } - - - - ////// HEAD /////// - - #-- we handle this by calling ->GET() - function HEAD_request() { - $this->HEAD( $this->path ); - } - - #-- HEAD() gets automatically emulated - function HEAD($path) { - ob_start(); - $this->GET(); - ob_end_clean(); - } - - - - /////// PUT /////// - - #-- store resources under given filename - function PUT_request() { - $this->auth(); - - #-- prepare params - list($content_type, $charset) = $this->get_ctype(); - if (!$content_type) { - $this->http_error("415 Use a MIME compliant client!"); - } - else { - $ok = $this->PUT( $this->path, $content_type, $charset ); - $this->http_error($ok); - } - } - - /* - function PUT($path, $ctype, $charset) { - - simply calls $this->get_body() to get the decompressed - input stream - - checks $overwrite and $ctype, $charset - - complains at will - } - */ - - - - ///// PROPFIND ///// - - #-- sort of directory listing - function PROPFIND_request() { - - #-- request type - if (($ctype = $this->get_ctype()) and ($this->is_xml($ctype[0])) - and ($body = $this->get_body())) - { - $p = & new MiniDav_PropFind($body, $ctype[1], $this->int_charset, $this->xmlns); - $p->parse(); -#print_r($p); - if (isset($p->prop)) { - $this->props = array_keys($p->prop); - } - elseif (isset($p->allprop)) { - $this->props = 1; - } - elseif (isset($p->propname)) { - $this->props = 0; - } - else { - $this->http_error("400 Couldn't determine request type"); - exit; - } - } - else { - $this->props = 1; // ALL -#print_r($_SERVER); -#echo "NON($ctype[0],$body)"; - } -#print_r($this); - - #-- get - $files = $this->PROPFIND($this->path, $this->props); - - #-- send transformed list - $this->PROPFIND_response($files); - } - - /* - function PROPFIND($path, $wanted_props) { - - searches resources for given $path up to ->depth subdirs - - generates a result list in a $files[] array with $wanted_props: - $files[] = array( - "path"=>"/fn/...", // ALWAYS!, without URL prefix - "status"=>"200 OK", // optional - "getcontenttype"=>"...", // in DAV: default namespace - "myXmlNs:p1"=>"...", // other XML namespace - ); - - $wanted_props is either 1 or 0 or an array (1 = ALL fields, 0 = only NAMES - of fields, or ARRAY = the respective list of requested property field names) - - send the collected file info list to ->PROPFIND_response() finally - } - */ - - #-- send back - function PROPFIND_response($files) { - - #-- start - header("Content-Type: application/xml"); - echo "int_charset}\" ?>\n"; - echo "xmlns_out() . ">\n"; - - #-- required fields - $add_req = array(); - if (is_array($this->props)) { - foreach ($this->props as $id) { - $add_req[$id] = false; // become nodes - } - } -#print_r($add_req); -#print_r($this); - - #-- files - foreach ($files as $row) { - - #-- transform/add fields - $href = $this->xmlentities($this->base_url . $row["path"]); - if (!$href) { continue; } - unset($row["path"]); - $status = $row["status"] ? $row["status"] : "HTTP/1.0 200 OK"; - unset($row["status"]); - - #-- add _required_ fields (but empty then) - if ($add_req) { - $row = $row + $add_req; - } - - #-- throw entry + properties - echo " \n"; - echo " $href\n"; - echo " \n"; - echo " \n"; - - #-- output fields - foreach ($row as $id=>$value) { - - #-- names only? - if (!$this->props || ($value===false)) { - echo "\t<$id/>\n"; - } - else { - #-- skip filtered - if (is_array($this->props) && !in_array($id, $this->props)) { - continue; - } - #-- xml encode - if ($this->prop_as_tag[$id]) { - if (!strlen($value)) { - $value = ""; - } - else { - $value = "<$value/>"; - } - } - elseif ($sft = $this->prop_as_date[$id]) { - $value = gmstrftime($sft, $value); - } - else { - $value = $this->xmlentities($value); - } - echo "\t<$id>$value\n"; - } - } - echo " \n"; - echo " $status\n"; - echo " \n"; - echo " \n"; - } - - #-- fin - echo "\n"; - } - - - - //// PROPPATCH //// - - function PROPPATCH_request() { - } - - /* - function PROPPATCH($path, $set, $remove) { - - $set and $remove are associate arrays, with property names - and values ($set only) inside - - $remove only contains false as values, and tells to unset - the according property from all matched files - - $path is either a file or a directory again (should honor - $this->depth then) - - returns a $files[] list, similar to the PROPFIND() method, - which contains property names associated to status values: - array( "getcontenttype" => "500 bad request", ) - (1 is allowed as status value) - } - */ - - - - ////// MKCOL ////// - - #-- create a collection (sub directory) - function MKCOL_request() { - $this->auth(); - $r = $this->MKCOL($this->path); - $this->http_error($r); - } - - /* - function MKCOL($dir) { - } - */ - - - - ////// COPY /////// - - #-- removes an entry - function COPY_request() { - $this->auth(); - $this->check_src_dest(); - $r = $this->COPY($this->path, $this->dest, $this->overwrite, $this->depth); - $this->http_error($r); - } - - /* - function COPY($src, $dest, $overwrite, $depth) { - - duplicates a $src file or a directory tree ($depth) to the - give $dest-ination - - if $overwrite is 1, then existing files should be ->DELETEd - automatically (simply overwrite) - - return success - } - */ - - #-- simple pre-conditions for COPY and MOVE - function check_src_dest() { - if (!$this->dest) { - $this->http_error("400 No valid Destination: given"); - exit; - } - elseif (trim($this->dest, "/") == trim($this->path, "/")) { - $this->http_error("409 Source and Destination are the same"); - exit; - } - } - - - - ////// MOVE /////// - - #-- removes an entry - function MOVE_request() { - $this->auth(); - $this->check_src_dest(); - $r = $this->MOVE($this->path, $this->dest, $this->overwrite, $this->depth); - $this->http_error($r); - } - - /* - function MOVE($src, $dest, $overwrite, $depth) { - - works like COPY, but that all source files must be deleted - after a successful move - } - */ - - - - ///// DELETE ////// - - #-- removes an entry - function DELETE_request() { - $this->auth(); - $this->DELETE($this->path); - } - - /* - function DELETE($path) { - - purge the given file if it wants to - - watch out for directories and $this->depth - } - */ - - - - ///// OPTIONS ///// - - #-- yields some informational headers - function OPTIONS_request() { - header("Allow: " . implode(", ", $this->get_options())); - header("DAV: 1"); // version 1 means without locking support - } - - function OPTIONS() { - // nothing to do - } - - #-- list of defined request method handler pairs - function get_options() { - $class = get_class($this); - $r = array(); - foreach (get_class_methods($class) as $fn) { - #-- for every "METHOD()", there must be a "METHOD_request()" - if (!strpos($fn, "_") && method_exists($this, "{$fn}_request")) { - $r[] = strtoupper($fn); - } - } - - $r[] = "TRACE"; // Apache must handle this - return($r); - } - - - - /////////////////// - - - ////// LOCK /////// - - - ///// UNLOCK ////// - - - - /////////////////// - - - - - #------------------------------------------------------ utility code --- - - - #-- is called for all writing methods - function auth() { - // Makes it easy to bring up authentication. - // If you want to "protect" the read-only WebDAV method as - // well, then just wrap this into your interface script. - - # include("ewiki/plugins/../fragments/funcs/auth.php"); - } - - - #-- encode string values - function xmlentities($s) { - return xmlentities($s); - } - - - #-- serialize all valid $this->xmlns[] - function xmlns_out() { - $s = ""; - foreach ($this->xmlns as $prefix=>$uri) { - if (strpos($uri, ":")) { - $s .= " xmlns" . ($prefix ? ":$prefix" : "") ."=\"" . $uri . "\""; - } - } - return($s); - } - - - - - #------------------------------------------------------- http in/out --- - - - #-- compress page content (prior sending) - function content_encode(&$body) { - $ae = strtolower($_SERVER["ACCEPT_ENCODING"]); - $alg = array("gzip"=>"gzencode", "deflate"=>"gzdeflate", "compress"=>"gzcompress", "x-bzip2"=>"bzcompress"); - if ($ae) { - foreach (explode(",", $ae) as $ae) { - $ae = trim(strtok($ae, ";")); - if ($pf = $alg[$ae]) { - $body = $pf($body); - header("Content-Encoding: $ae"); - break; - } - } - } -// unset($_SERVER["ACCEPT_ENCODING"]); //@HACK: prevent accidential double encoding - ewiki plugins could do this automatically - } - - - #-- or decompress received body - function content_decode(&$body) { - $de = strtolower(trim($_SERVER["HTTP_CONTENT_ENCODING"])); - if (!strlen($de)) { /* nop */ } - elseif ($de == "gzip") { $body = function_exists("gzdecode") ? gzdecode($body) : gzinflate(substr($body, 10, strlen($body) - 18)); } - elseif ($de == "deflate") { $body = gzinflate($body); } - elseif ($de == "compress") { $body = gzuncompress($body); } - elseif ($de == "x-bzip2") { $body = bzuncompress($body); } -// unset($_SERVER["HTTP_CONTENT_ENCODING"]); //@HACK: prevent accidential double decoding, wrong here - } - - - #-- convinience function for sending HTTP status responses - function http_error($w=false, $def_success="200 OkiDoki") { - if ($w == false) { - $w = "500 Internal Error"; - } - elseif (($w === true) || ($w === 1)) { - $w = $def_success; - } - if (!headers_sent() && !isset($this->no_status)) { - if (ini_get("cgi.rfc2616_headers")) { - header("HTTP/1.1 $w"); - } - header("Status: $w"); // always ok - } - } - - - #-- check content type and charset - function get_ctype() { - $ct = trim(strtolower(strtok($_SERVER["CONTENT_TYPE"], ";,("))); - $rest = strtok(",("); - if (preg_match("#charset=[\"\']?([-\d\w]+)#", $rest, $uu)) { - $charset = $uu[1]; - } - elseif ($ct == "text/xml") { - $charset = "iso-8859-1"; - } - return(array($ct, $charset)); - } - - - #-- check content-type for being */*xml* - function is_xml($ct) { - if (preg_match("#(^x\.?ml/...|...[/+]xml$)#", $ct) || MINIDAV_IGNORE_MIME) { - return(true); - } - } - - - #-- get request body, decoded - function get_body() { - - #-- fetch - $f = fopen("php://input", "rb"); - $body = fread($f, 1<<22); - fclose($f); - - #-- uncompress - $this->content_decode($body); - - return($body); - } - - - #-- partial responses (only contiguous ranges) - function cut_content(&$data) { - - if (($h = $_SERVER["HTTP_RANGE"]) - and preg_match("/^bytes=(\d*)-(\d+)$/", trim($h), $uu)) - { - list($uu, $start, $end) = $uu; - - #-- correct positions - $len = strlen($data); - if (!strlen($start)) { - if ($end > $len) { - $start = 0; - } - else { - $start = $len - $end; - } - $end = $len - 1; - } - if ($start > $end) { - $this->http_error("416 Unsatisfiable Range:"); - return; - } - - #-- cut - $data = substr($data, $start, $end - $start + 1); - - #-- send headers - header("Content-Range: bytes $start-$end/$len"); - $this->http_error("206 Partial Content"); - $this->no_status = 1; - } - } - - - #---------------------------------------------------------- old code --- - - /* - #-- output raw page data - function out_content(&$data) { - $c = & $data["content"]; - $this->content_encode($c); - header("Content-Length: ".strlen($c)); - print $c; - } - */ - - - #-- debugging - function request_debug() { - ob_start(); - print_r($_SERVER); - echo $this->get_body(); - print_r($this); - $d = ob_get_contents(); - ob_end_clean(); - file_put_contents("/tmp/minidav.".time().".".rand(0, 99), $d); - } - - - -}// end of class - - - - -#------------------------------------------------------------------ xml --- - - -#-- request bodies -class MiniDav_PropFind extends easy_xml { - - function MiniDav_PropFind($xml, $ctype="", $uu=NULL, $addns=array()) { - parent::easy_xml($xml, $ctype); - $this->xmlns2["dav"] = ""; - $this->xmlns += array_flip($addns); - } - - function start($xp, $tag, $attr) { - parent::start($xp, $tag, $attr); - if ($this->parent) { - $this->{$this->parent}[$tag] = true; - } - } -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/navbar.meta b/mods/wiki/plugins/lib/navbar.meta deleted file mode 100644 index afa236443..000000000 --- a/mods/wiki/plugins/lib/navbar.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: fragments -config: - EWIKI_NAVBAR_SELECTALL_DEPTH=99 - EWIKI_NAVBAR_ACTIVATEPARENTS=1 - EWIKI_NAVBAR_ACTIVATECHILDREN=1 -title: NavigationBar -description: ewiki nav bar plugin - by AndyFundinger -priority: bonus -type: functions diff --git a/mods/wiki/plugins/lib/navbar.php b/mods/wiki/plugins/lib/navbar.php deleted file mode 100644 index f5a524ac9..000000000 --- a/mods/wiki/plugins/lib/navbar.php +++ /dev/null @@ -1,305 +0,0 @@ - - -The NavBar array is composed of one line per button as follows: -$NavBar[]=array( line text, depth, activation,target page); - -Call mkLiveWebNavBar() from within your page to create a NavBar. -*/ - -define("EWIKI_NAVBAR_SELECTALL_DEPTH",99); -define("EWIKI_NAVBAR_ACTIVATEPARENTS",1); -define("EWIKI_NAVBAR_ACTIVATECHILDREN",1); -define('EWIKI_NAVBAR_ACTION','view'); - -//Select only Parents, Siblings, Uncles, and Children -$ewiki_plugins['select_navbar_buttons'][]="ewiki_navbar_select_psuc"; -//Select entire menu, highlight current page, selects to depth of -// EWIKI_NAVBAR_SELECTALL_DEPTH -$ewiki_plugins['select_navbar_buttons'][]="ewiki_navbar_selectall_buttons"; -//Renders NavBar as a set of nested lists -$ewiki_plugins['render_navbar_section'][]='ewiki_render_navbar_list'; -//Alternate render routine that puts sub bars below the major categories. -$ewiki_plugins['render_navbar_section'][]='ewiki_render_navbar_fixedtop_list'; - -//Create a navBar, call with a page to be turned into the bar and a page to be -// selected, uses $ewiki_plugins['select_navbar_buttons'][0] and -// $ewiki_plugins['render_navbar_section'][0]. Returns nothing if no bar is -// created. -function mkLiveWebNavBar($navBarPage, $activePage){ - #-- fetch from db - $data = ewiki_db::GET($navBarPage); - - #-- Authenticate, return nothing if authentication fails - if (ewiki_auth($navBarPage, $data, EWIKI_NAVBAR_ACTION, $ring=3, $force=0)) { - return(""); - } - - #-- escape if navBarPage does not exist or was not retrieved. - if(empty($data["content"])){ - return(""); - } - //echo(":".$data["content"].":"); - - $o .= ewiki_navbar_format ( $data["content"], 1,urlencode($activePage) ); - - //Apply class only if we have a bar at all - if($o) - return("
        \n".$o."\n
        \n"); - return(""); -} - -//An adaptation of ewiki_format to format navigation bars -function ewiki_navbar_format ($wiki_source, $scan_links=1, - $currpage=EWIKI_PAGE_INDEX) -{ - global $ewiki_links, $ewiki_plugins; - - //echo("navbar function run"); - // pre-scan WikiLinks - if ($scan_links) { - ewiki_scan_wikiwords($wiki_source, $ewiki_links); - } - - // formatted output - $o = "\n"; - - // plugins only format finals are respected - $pf_final = @$ewiki_plugins["format_final"]; - - $table_defaults = 'cellpadding="2" border="1" cellspacing="0"'; - $syn_htmlentities = array( - "&" => "&", - ">" => ">", - "<" => "<", - "%%%" => "
        " - ); - $wm_list = array( - "-" => array('ul type="square"', "", "li"), - "*" => array('ul type="circle"', "", "li"), - "#" => array("ol", "", "li"), - ":" => array("dl", "dt", "dd"), - ";" => array("dl", "dt", "dd"), - ); - - // eleminate html - foreach ($syn_htmlentities as $find=>$replace) { - $wiki_source = str_replace($find, $replace, $wiki_source); - } - array_pop($syn_htmlentities); // strips "&" - - // add a last empty line to get opened tables/lists closed correctly - $wiki_source = trim($wiki_source) . "\n"; - - - #-- finally the link-detection-regex - # (impossible to do with the simple string functions) - ewiki_render_wiki_links($wiki_source); - - $NavBar = array(); - - //return($wiki_source); - foreach (explode("\n", $wiki_source) as $line) { - - $line = rtrim($line); - $lineout=""; - - #-- wiki list markup - if ( strlen($line) && isset($wm_list[@$line[0]]) ) { - $n = 0; - $li = ""; - #-- count depth of list - # line has length first character in the line is in wm_list - while (strlen($line) && ('*'==$line[0]) ) { - $li .= '*'; //add new list delim to list count - $n++; //count depth - $line = substr($line, 1); //remove first character - } - $line = ltrim($line); - - $regex='#$row){ - //echo("($id,$currpage)"); - if($row[1]>$maxlevel){ - next; - }elseif($row[3]==$currpage){ - $NavBar[$id][2]=2; - }else{ - $NavBar[$id][2]=1; - } - //echo("($id,$row[0],".$NavBar[$id][2].")"); - } - return($NavBar); -} - -//Selects parents, siblings, uncles and children -function ewiki_navbar_select_psuc( $NavBar,$currpage){ - foreach($NavBar as $id=>$row){ - //echo("($row[3],$currpage)"); - if($row[3]==$currpage){ - $NavBar[$id][2]=2; - $selLev=$row[1]; - - for($index=$id-1;$index>=0;$index--){ - if($NavBar[$index][1]<=$selLev){ - //set to displayed or active depending on ACTIVATEPARENTS - $NavBar[$index][2]= - ((($NavBar[$index][1]==$selLev)|| - (!EWIKI_NAVBAR_ACTIVATEPARENTS))? 1 : 2); - $selLev=$NavBar[$index][1]; //reduce selected level - } - } - - $selLev=$row[1]+1; - for($index=$id+1;$index"; - $myPost="

      "; - do{ - if(($element[1]>$currLevel)){ - $myPost.=ewiki_render_navbar_fixedtop_list($myPre,$myPost,$NavBar); - $element=current($NavBar); - continue; - }elseif($element[2]>=2){ - $mySection.="
    • ".$element[0]."
    • "; - }elseif($element[2]>=1){ - $mySection.="
    • ".$element[0]."
    • "; - }else{ - //$mySection.=$element[0] ."($element[1],$element[2])"; - } - $element=next($NavBar); - }while(($element[1]>=$currLevel)); - - //Return list if there are elements - if($mySection) - return($myPre.$mySection.$myPost); - return(""); -} - -//Render nav bar as a simple list -function ewiki_render_navbar_list($pre,$post,&$NavBar){ - - $element=current($NavBar); - $currLevel=$element[1]; - //echo("processing".$currLevel.$uu[0]); - $myPre="
        "; - $myPost="
      \n"; - do{ - if(($element[1]>$currLevel)){ - $mySection.=ewiki_render_navbar_list($myPre,$myPost,$NavBar); - $element=current($NavBar); - continue; - }elseif($element[2]>=2){ - $mySection.="
    • ".$element[0]."
    • "; - }elseif($element[2]>=1){ - $mySection.="
    • ".$element[0]."
    • "; - }else{ - //$mySection.=$element[0] ."($element[1],$element[2])"; - - } - $element=next($NavBar); - }while(($element[1]>=$currLevel)); - - //Return list if there are elements - if($mySection) - return($myPre.$mySection.$myPost); - return(""); -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/opensearch.meta b/mods/wiki/plugins/lib/opensearch.meta deleted file mode 100644 index 486347351..000000000 --- a/mods/wiki/plugins/lib/opensearch.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -type: api -category: library -version: 0.4.0 -title: OpenSearch API -description: implements the OpenSearch live searching API (over XML-RPC) -url: http://opensearch.berlios.de/ -priority: bonus diff --git a/mods/wiki/plugins/lib/opensearch.php b/mods/wiki/plugins/lib/opensearch.php deleted file mode 100644 index 16d3b83fb..000000000 --- a/mods/wiki/plugins/lib/opensearch.php +++ /dev/null @@ -1,194 +0,0 @@ - 1000, - "m_title" => 3.0, - "q_pos" => 2.0, - "q_not" => 0.0, - "limit" => 5000, - ); - $n_hit = $params["n_hit"]; - $q_pos = $params["q_pos"]; - $q_not = $params["q_not"]; - $calc = array(); - - #-- search target field mapped to internal SQL row names - $fieldnames = array( - "title" => "title", - "text" => "text", - "" => "content", - "author" => "author", - "links" => "links", - "meta" => "meta", - "filename" => "title", - ); - - - #-- sort request terms into MUST and NOT ------------------------ SQL --- - $sql = array( - "MUST" => array(), - "NOT" => array(), - ); - foreach ($query as $i=>$qterm) { - list($pattern, $dep, $field, $flags) = $qterm; - $f_regex = strpos($flags, "REGEX") !== false; - $f_nocase = strpos($flags, "NOCASE") !== false; - $m_field = isset($params["m_$field"]) ? $params["m_$field"] : 0; - - if ($field = $fieldnames[$field]) { - - $pattern = mysql_escape_string($pattern); - - if ($f_regex) { - $s = "$field REGEXP '$pattern'"; - } - elseif ($f_nocase) { - $pattern = strtolower($pattern); - $s = "LOCATE('$pattern', LCASE($field)) > 0"; - } - else { - $s = "LOCATE('$pattern', $field) > 0"; - } - - #-- add - $sql[$dep][] = "($s)"; - } - - $calc[] = array($pattern, $dep, $field, $f_regex, $f_nocase, $m_field); - - } - if ($q_not) { - $sql_MUST = implode(" OR ", $sql["MUST"]); - $sql_NOT = ""; - } - else { - $sql_MUST = implode(" AND ", $sql["MUST"]); - $sql_NOT = implode(" OR ", $sql["NOT"]); - if ($sql_NOT) { $sql_NOT = " AND NOT ($sql_NOT)"; } - } - - #-- last validity checks - if (!$sql_MUST) { - // no way to send an error with ED xmlrpclib ? - return("551: at least one MUST search term must be given"); - } - - - #-- get hit list - $sql_DB_F_TEXT = "((flags & 1) > 0) AND"; - $sql_query_result = mysql_query($sql=" - SELECT - pagename AS id, version AS version, - pagename AS title, - content AS text, - CONCAT(pagename, content) AS content, - meta, - author, - refs AS links, - lastmodified, - created, - flags - FROM - ewiki - WHERE - $sql_DB_F_TEXT - $sql_MUST - $sql_NOT - GROUP BY id ORDER BY version - "); - - #-- start hit score calculation ---------------------------------- CALC --- - $result_list = array(); - $ordered_list = array(); - if ($sql_query_result) while ($row = mysql_fetch_array($sql_query_result)) { - - $score = 0.0; // final score - $m_fin = 1.0; // to eventually decrease it later - - #-- score each search term for hit - foreach ($calc as $qterm) { - list($pattern, $dep, $field, $f_regex, $f_nocase, $m_field) = $qterm; - - #-- minscore - $add = $n_hit; - if ($m_field) { - $add *= $m_field; - } - - #-- regex hit - if ($f_regex) { - $ok = preg_match($pattern, $row["field"]); - if ($dep=="MUST") { - $score += $add * ($ok ? 1.0 : $q_not); - } - elseif ($dep=="NOT") { - if ($ok) { - $m_fin *= $q_not; - } - } - } - #-- strsearch hit - else { - $text = $f_nocase ? strtolower($row[$field]) : $row[$field]; - $len = strlen($text) + 1; - - #-- add points for each hit, weighted by match position - if ($dep=="MUST") { - $p = -1; - while (false !== ($p = strpos($text, $pattern, $p+1))) { - $score += $add * ($q_pos - ($q_pos - 1) * ($p / $len)); - } - } - #-- NOT search term - elseif (strpos($text, $pattern) !== false) { - $m_fin *= $q_not; - } - } - - } - - #-- add to list - if ($score *= $m_fin) { - $result_list[] = array( - "title" => $row["title"], - "url" => ewiki_script_url("", $row["title"]), - "excerpt" => substr(strtr($row["text"], "\r\n\t\f", " "), 0, 300), - "score" => $score, - "lastmodified" => $row["lastmodified"], - ); - $ordered_list[] = $score; - } - } - - #-- sort result? - arsort($ordered_list); - foreach ($ordered_list as $i=>$uu) { - $ordered_list[$i] = $result_list[$i]; - unset($result_list[$i]); - } - $result_list = & $ordered_list; - - - #-- done - return($ordered_list); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/page_delegator.meta b/mods/wiki/plugins/lib/page_delegator.meta deleted file mode 100644 index 7170556d8..000000000 --- a/mods/wiki/plugins/lib/page_delegator.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: library -hooks: page -type: api -title: page_delegator -description: calls a series of ewiki handlers until one returns a page -priority: bonus diff --git a/mods/wiki/plugins/lib/page_delegator.php b/mods/wiki/plugins/lib/page_delegator.php deleted file mode 100644 index af13dcba8..000000000 --- a/mods/wiki/plugins/lib/page_delegator.php +++ /dev/null @@ -1,40 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/lib/phprequest.meta b/mods/wiki/plugins/lib/phprequest.meta deleted file mode 100644 index 1b40cff87..000000000 --- a/mods/wiki/plugins/lib/phprequest.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: library -title: phprequest -description: allows http "POST" and "PUSH" requests with a Content-Type of application/vnd.php.serialized -priority: deprecated -type: intercept diff --git a/mods/wiki/plugins/lib/phprequest.php b/mods/wiki/plugins/lib/phprequest.php deleted file mode 100644 index 723b2c2e9..000000000 --- a/mods/wiki/plugins/lib/phprequest.php +++ /dev/null @@ -1,52 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/lib/phprpc.meta b/mods/wiki/plugins/lib/phprpc.meta deleted file mode 100644 index 914139865..000000000 --- a/mods/wiki/plugins/lib/phprpc.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: PHP -type: functions -provides: rpc, php-rpc -category: library -priority: bonus -title: PHP-RPC interface -description: simple PHP-encoded remote procedure calls diff --git a/mods/wiki/plugins/lib/phprpc.php b/mods/wiki/plugins/lib/phprpc.php deleted file mode 100644 index a42c14ed2..000000000 --- a/mods/wiki/plugins/lib/phprpc.php +++ /dev/null @@ -1,165 +0,0 @@ - $func, - "params" => $args, - ); - $args = serialize($args); - $args = gzdeflate($args); - $len_args = strlen($args); - - #-- prepare HTTP request - $c = parse_url($url); - extract($c); - ($port) || ($port=80); - ($query) && ($path .= "?$query"); - $n = "\015\012"; - $req = "POST $path HTTP/1.0$n" - . "Host: $host$n" - . ($user ? "Authorization: Basic ".base64_encode("$user:$pass").$n : "") - . "User-Agent: $ewiki_config[ua]$n" - . "Accept-Encoding: deflate$n" - . "Connection: close$n" - . "Accept: ".PHPRPC_TYPE."$n" - . "Content-Type: ".PHPRPC_TYPE."; version=".PHP_VERSION."$n" - . "$n"; - - #-- open connection - if ($f = fsockopen($host, $port, $io_err, $io_err_s, 20)) { - socket_set_blocking($f, true); - socket_set_timeout($f, 17, 555); - - #-- send - fwrite($f, $req); - fwrite($f, "Content-Length: $len_args$n"); - fwrite($f, "$n"); - fwrite($f, $args); $args = ""; //freemem() - fwrite($f, "$n"); - - #-- read - $result = ""; - while (!feof($f)) { - $result .= fread($f, 1<<21); // max 2MB (incl. headers) - } - - #-- strip headers - while ($p = strpos($result, "\n")) { - $line = trim(substr($result, 0, $p)); - $result = substr($result, $p + 1); - if (!strlen($line)) { - break; - } - $h[strtolower(strtok($line, ":"))] = trim(strtok("\000")); - } - fclose($f); -#print_r($h); -#print_r($result); - - #-- decode - if (strtolower(trim(strtok($h["content-type"], ";"))) == PHPRPC_TYPE) { - if ($h["content-encoding"] == "gzip") { - $result = gzinflate(substr($result, 10, strlen($result)-18)); - } - if ($h["content-encoding"] == "deflate") { - $result = gzinflate($result); - } - $result = unserialize($result); - - #-- ok - if ($result) { - return($result); - } - }//decode - - } else { $phprpc_error = "no socket/connection"; } //socket -} - - - -#-- handle calls -function phprpc_server($allowed="*") { - - global $phprpc_methods, $ewiki_config, $HTTP_RAW_POST_DATA; - if ($phprpc_methods) { - $allowed = $phprpc_methods; - } - - if (($_SERVER["REQUEST_METHOD"] == "POST") - and (strtolower(trim(strtok($_SERVER["CONTENT_TYPE"], ";"))) == PHPRPC_TYPE)) - { - #-- get raw data - if ($f = fopen("php://input", "rb")) { - $HTTP_RAW_POST_DATA = fread($f, 1<<21); // 2MB max (packed) - fclose($f); - } - $call = unserialize(gzinflate($HTTP_RAW_POST_DATA)); - - #-- make function call - if (is_array($call)) { - - #-- params - ($method = $call["method"]) || ($method = $call["func"]) || ($method = $call["function"]) || ($method = $call["methodName"]); - ($args = $call["args"]) || ($args = $call["params"]); - - #-- plain function or static method call - if (strpos($method, ":") || strpos($method, ".")) { - $class = strtok($method, ":."); - $method = trim(strtok(" "), ":"); - } - if ($class) { - $method = array($class, $method); - } - - #-- exec, if - if (($allowed=="*") || in_array(strtolower($method), $allowed) - || in_array(strtolower($class), $allowed) - || ($method = $allowed[strtolower($method)])) - { - $r = call_user_func_array($method, $args); - } - else { - header("Status: 400 Forbidden Method"); exit; - } - } - else { - header("Status: 500 Could Not Unserialize"); exit; - } - - #-- return result - if ($r) { - header("X-Server: $ewiki_config[ua]"); - header("Content-Type: ".PHPRPC_TYPE."; version=".PHP_VERSION); - header("Cache-Control: no-cache, private"); - $r = serialize($r); - $r = gzdeflate($r); - header("Content-Encoding: deflate"); - header("Content-Length: ".strlen($r)); - print($r); - exit; - } - - #-- error - header("Status: 500 Didn't Work"); - exit; - } - else { - header("X-PHP-RPC-Error: Wrong request method $_SERVER[REQUEST_METHOD] and/or type $_SERVER[CONTENT_TYPE]"); - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/pluginmetadata.meta b/mods/wiki/plugins/lib/pluginmetadata.meta deleted file mode 100644 index bc1feff79..000000000 --- a/mods/wiki/plugins/lib/pluginmetadata.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -type: functions -title: plugin manager -description: parses plugin .meta data files and resolves dependencies -priority: never -category: library diff --git a/mods/wiki/plugins/lib/pluginmetadata.php b/mods/wiki/plugins/lib/pluginmetadata.php deleted file mode 100644 index 08b196c9a..000000000 --- a/mods/wiki/plugins/lib/pluginmetadata.php +++ /dev/null @@ -1,201 +0,0 @@ -$tmp) { - $info[$uu[1][$i]] = $uu[2][$i]; - } - } - return($info); -} - - -#-- scan all .meta files or read from cache file -function ewiki_pmd($read_cached=0, $else_write=1, $warn=0, $gauge_callback="") { - global $ewiki_pmd; - $basedir = dirname(dirname(__FILE__)); - $metaf = "$basedir/meta.bin"; - - #-- cached data - if ($read_cached && filesize($metaf)) { - $ewiki_pmd = unserialize((file_get_contents($metaf))); - } - #-- load from .meta files - else { - $ewiki_pmd = array(); - $files = glob("$basedir/*.meta") + glob("$basedir/*/*.meta"); - foreach ($files as $num=>$fn) { - if ($gauge_callback) { - $gauge_callback($num, count($files)); - } - $id = basename($fn, ".meta"); - - #-- read - $add = ewiki_pmd_read($fn); - if ($add) { - - #-- .php script - $php = substr($fn, 0, -5) . ".php"; - if (file_exists($php) && ($l = strpos($php, "/plugins/"))) { - $php = substr($php, 1 + $l); - $add["fn"] = $php; - } - - #-- plugin id: - if ($add["id"]) { - $id = "$add[id]"; - } - - #-- provides: - foreach(explode(",", "$id,$add[provides],$add[delivers]") as $p) { - if ($p = trim($p)) { - $ewiki_pmd[".provides"][$p][] = $id; // only the first gets used - } - } - - #-- append to list - if ($warn && isset($ewiki_pmd[$id])) { - echo "WARNING: a plugin with the name '$id' is already registered\n"; - } - $ewiki_pmd[$id] = $add; - } - } - - #-- save - if ($else_write && is_writeable($metaf)) { - file_put_contents($metaf, (serialize($ewiki_pmd))); - } - } - return($ewiki_pmd); //redundant -} - - -#-- apply dependencies on plugin list -function ewiki_pmd_resolve_dependencies(&$list, $add_suggested=1) { - global $ewiki_pmd; - $error = array(); - - #-- how to handle fields - $fields = array( - "depends" => +1, - "conflicts" => -1, - "replaces" => -1, - "recommends" => $add_suggested, - ); - - #-- check all entries in name list - foreach ($list as $list_i_id=>$id) { - #-- fields - foreach ($fields as $name=>$action) { - if ($action && !empty($ewiki_pmd[$id][$name])) - foreach (explode(",",$ewiki_pmd[$id][$name]) as $dep) - { // multiple dependencies may be given - $dep = trim($dep); - - #-- add - if ($action >= +1) { - if (!in_array($dep, $list)) { - if (!isset($ewiki_pmd[".provides"][$dep])) { - // ooops - unset($list[$list_i_id]); - $error[$id] = "unmet dependency: $dep"; - } - else { - // always adds only the very first entry - $list[] = $ewiki_pmd[".provides"][$dep][0]; - } - } - } - #-- remove - elseif ($action <= -1) { - foreach ($ewiki_pmd[".provides"][$dep] as $dep) { - if (in_array($dep, $list)) { - unset($list[array_search($dep, $list)]); - } - } - } - } - } - - #-- does such a plugin exist at all? - if (!$ewiki_pmd[$id]) { - $error[$id] = "plugin '$id' does not exist"; - } - } - - return($error); //ouch, if you forget that this isn't a result -} - - -#-- -function ewiki_pmd_get_config_settings($list) { -} - - -#-- get include_once() filenames -function ewiki_pmd_get_plugin_files($list) { - global $ewiki_pmd; - $r = array(); - $n = 2001; - foreach($list as $id) { - $fn = $ewiki_pmd[$id]["fn"]; - $type = $ewiki_pmd[$id]["type"]; - ($sort = $ewiki_pmd[$id]["sort"]) or ($sort = 0); - $n--; - if ($fn && ($type != "R") && !in_array($fn, $r)) { - $r["$sort.$n"] = $fn; - } - } - ksort($r); -# $r = array_values($r); - return($r); -} - - -#-- plugin sorting -function ewiki_pmd_by_category() { - global $ewiki_pmd; - $r = array(); - foreach ($ewiki_pmd as $id=>$row) { - if ($id[0] != ".") { - ($cat = $row["category"]) or ($cat = "else"); - $r[$cat][$id] = $row; - } - } - return($r); -} - - -#-- flip array by entry -function ewiki_pmd_by($field) { - global $ewiki_pmd; - $r = array(); - foreach ($ewiki_pmd as $id=>$row) { - if (isset($row[$field])) { - $r[$row[$field]] = $id; - } - } - return($r); -} - - -#-- unwanted plugins -function ewiki_pmd_hidden($row) { - return - !strlen($row["type"]) || ($row["type"] == "R") - || !strlen($row["title"]) - || ($row["priority"] == "never") - || ($row["priority"] == "deprecated"); -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/protmode.meta b/mods/wiki/plugins/lib/protmode.meta deleted file mode 100644 index 820e3eddf..000000000 --- a/mods/wiki/plugins/lib/protmode.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: library -hooks: handler_binary -type: intercept -title: protmode -description: holds utility functions (not core, but required by multiple plugin) for the ProtectedMode -priority: rare diff --git a/mods/wiki/plugins/lib/protmode.php b/mods/wiki/plugins/lib/protmode.php deleted file mode 100644 index bc06bfe52..000000000 --- a/mods/wiki/plugins/lib/protmode.php +++ /dev/null @@ -1,49 +0,0 @@ - once we reached here???) - if (!ewiki_auth($id, $data, $action, $ring=false, $force=EWIKI_AUTO_LOGIN)) { - //echo("not authenticated id".$id." action ".$action); - return($ewiki_errmsg); - } - //echo("authenticated id:".$id." action ".$action); - #-- chain to one of the action_BINARY plugins - if ($pf = $ewiki_plugins["action_binary"][$action]) { - //echo("running ".$pf."()"); - return($pf($id, $data, $action)); - } - - #-- else let ?binary= return the requested 'page' entry - //Consider binary view here - //ewiki_binary($id); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/save_storevars.meta b/mods/wiki/plugins/lib/save_storevars.meta deleted file mode 100644 index 3db54ae51..000000000 --- a/mods/wiki/plugins/lib/save_storevars.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: library -hooks: edit_save -type: intercept -title: save_storevars -description: automatically stores global variables into a ... -priority: bonus diff --git a/mods/wiki/plugins/lib/save_storevars.php b/mods/wiki/plugins/lib/save_storevars.php deleted file mode 100644 index 2ac4df084..000000000 --- a/mods/wiki/plugins/lib/save_storevars.php +++ /dev/null @@ -1,35 +0,0 @@ - "meta_field_name", -# "icon" => "icon", -# "counter" => "X-Hit-Counter", -); - - -#-- glue -$ewiki_plugins["edit_save"][] = "ewiki_edit_save_storevars"; - - -#-- implementation -function ewiki_edit_save_storevars(&$save, &$old_data) { - - global $ewiki_config; - - foreach ($ewiki_config["save_storevars"] as $globalname => $metaname) { - if ($value = &$GLOBALS[$globalname]) { - $save["meta"][$metaname] = $value; - } - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/shutdown.meta b/mods/wiki/plugins/lib/shutdown.meta deleted file mode 100644 index 3c6ea0c59..000000000 --- a/mods/wiki/plugins/lib/shutdown.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -type: intercept -hook: shutdown -title: shutdown hook -description: adds another hook which activates plugins at shutdown -category: library -priority: optional diff --git a/mods/wiki/plugins/lib/shutdown.php b/mods/wiki/plugins/lib/shutdown.php deleted file mode 100644 index 2eec2c092..000000000 --- a/mods/wiki/plugins/lib/shutdown.php +++ /dev/null @@ -1,29 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/lib/spamblock_whois.meta b/mods/wiki/plugins/lib/spamblock_whois.meta deleted file mode 100644 index 3a5691630..000000000 --- a/mods/wiki/plugins/lib/spamblock_whois.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: library -hooks: ban_loopup -type: special -title: spamblock_whois -description: initiates a whois query on the domain names of newly blocked URLs (to block further domains from the same spammer) -priority: rare diff --git a/mods/wiki/plugins/lib/spamblock_whois.php b/mods/wiki/plugins/lib/spamblock_whois.php deleted file mode 100644 index ae2c91d68..000000000 --- a/mods/wiki/plugins/lib/spamblock_whois.php +++ /dev/null @@ -1,35 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/lib/speed.meta b/mods/wiki/plugins/lib/speed.meta deleted file mode 100644 index 6534b8f3f..000000000 --- a/mods/wiki/plugins/lib/speed.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -type: intercept -title: HTTP speed-up -description: implements PHP-side support for conditional HTTP requests -category: optimation -priority: bonus diff --git a/mods/wiki/plugins/lib/speed.php b/mods/wiki/plugins/lib/speed.php deleted file mode 100644 index c3ebf82b7..000000000 --- a/mods/wiki/plugins/lib/speed.php +++ /dev/null @@ -1,89 +0,0 @@ - $if) { - $yes = 1; - } - } - - #-- invert result - if ($inverse) { - $yes = $yes ? 0 : 1; - } - - #-- abort ewiki rendering, if matched or senseful to do so - if ($yes || ($_SERVER["REQUEST_METHOD"] == "HEAD")) { - /* - #ewiki_http_headers($o, $id, $data, $action); - (It was probably bad to send the ETag and Content-Version fields - for this http answer?) - */ - header("Status: 304 Not Modified"); - die(304); - } - elseif ($precond) { - if (!$inverse || ($_SERVER["REQUEST_METHOD"]!="GET")) { - header("Status: 412 Precondition Failed"); - die(412); - } - } - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/subpagelist.meta b/mods/wiki/plugins/lib/subpagelist.meta deleted file mode 100644 index 9e493aef1..000000000 --- a/mods/wiki/plugins/lib/subpagelist.meta +++ /dev/null @@ -1,4 +0,0 @@ -priority: auto -type: functions -title: SubpageFunctions -category: library diff --git a/mods/wiki/plugins/lib/subpagelist.php b/mods/wiki/plugins/lib/subpagelist.php deleted file mode 100644 index a24d90bcd..000000000 --- a/mods/wiki/plugins/lib/subpagelist.php +++ /dev/null @@ -1,30 +0,0 @@ -get()) { - - #-- retrieve and check rights if running in protected mode - - if ($_hiding){ - if(!ewiki_auth($row["id"], $uu,'view', $ring=false, $force=0)) { - continue; - } - } - $pages[$row["id"]] = ""; - } - return($pages); -} - - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/sync.meta b/mods/wiki/plugins/lib/sync.meta deleted file mode 100644 index da91c3865..000000000 --- a/mods/wiki/plugins/lib/sync.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -type: functions -priority: rare -category: library -title: WikiSync -description: allows syncing content with/from remote Wiki installation diff --git a/mods/wiki/plugins/lib/sync.php b/mods/wiki/plugins/lib/sync.php deleted file mode 100644 index bc8665197..000000000 --- a/mods/wiki/plugins/lib/sync.php +++ /dev/null @@ -1,117 +0,0 @@ -$FROM_ver) { - set_time_limit(+2999); - - $DEST_ver = $DEST_list[$id]; - if ($DEST_ver < $FROM_ver) { - - echo "{$title}ing " . htmlentities($id) . "[{$FROM_ver}]... "; - $L = $FROM_api("::GET", array($id)); - - #-- did never exist, - # or this version is identical on both systems - if (!$DEST_ver || ewiki_sync_no_conflict($id, $FROM_api, $DEST_api)) { - echo ($DEST_api("::WRITE", $L) ? "ok" : "error"); - } - #-- conflict - else { - echo "cannot synchronize with [{$DEST_ver}] - conflict!"; - } - - echo "
      \n"; - flush(); - - #-- no further processing with these entries - unset($FROM_list[$id]); - unset($DEST_list[$id]); - } - else { -# echo "nothing to do for '$id' because $FROM_ver==$DEST_ver
      \n"; - } - } -} - - -#-- compare remote against local version for conflicts -function ewiki_sync_no_conflict($id, $OLD_api, $NEWER_api) { - - #-- fetch - $OLD = $OLD_api("::GET", array($id)); // last - $NEW = $NEWER_api("::GET", array($id, $R["version"])); - - #-- 700% identical! - if (md5(serialize($OLD)) == serialize(md5($NEW))) { - return true; - } - else { - return ewiki_sync_half_identical($OLD, $NEW); - } -} - - -#-- less exact comparison -# - it only skips the {hits} entry when matching fields, -# because that's where differences are (huh, big secret!) -function ewiki_sync_half_identical($A, $B) { - - return - true - && (strtolower($A["id"]) == strtolower($B["id"])) - && ($A["flags"] == $B["flags"]) - && ($A["version"] == $B["version"]) - && ($A["lastmodified"] == $B["lastmodified"]) - && (serialize($A["meta"]) == serialize($B["meta"])) - - #-- you may wish to remove the following (two/???) : - && ($A["lastmodified"] == $B["lastmodified"]) - && ($A["author"] == $B["author"]) - ; -} - - - -#-- access to remotely located wikisync interface -function ewiki_sync_remote($func, $args=NULL) { - global $proto, $url; - if ($proto == "sync") { - switch (strtoupper(trim($func, ":"))) { - case "GET": - return phprpc($url, "ewiki.sync", array("::GET", $args)); - case "WRITE": - return phprpc($url, "ewiki.sync", array("::WRITE", $args)); - case "LIST": - return phprpc($url, "ewiki.sync", array("::LIST", false)); - default: - } - } -} - - -#-- the public/main API, access local database -function ewiki_sync_local($func, $args=NULL) { - switch (strtoupper(trim($func, ":"))) { - case "GET": - return ewiki_db::GET($args[0], $args[1]); - case "WRITE": - return ewiki_db::WRITE($args); - case "LIST": - $all = ewiki_db::GETALL(array("id", "version")); - $r = array(); - while ($row = $all->get()) { - $r[$row["id"]] = $row["version"]; - } - return $r; - default: - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/upgrade.meta b/mods/wiki/plugins/lib/upgrade.meta deleted file mode 100644 index 25d7f8be3..000000000 --- a/mods/wiki/plugins/lib/upgrade.meta +++ /dev/null @@ -1,11 +0,0 @@ -api: PHP -type: emulation -priority: auto -category: library -sort: -200 -provides: upgrade-php -title: PHP-Upgrade -description: backwards-compatility layer for older PHP versions -license: Public Domain -url: http://freshmeat.net/p/upgradephp -version: 12.0 diff --git a/mods/wiki/plugins/lib/upgrade.php b/mods/wiki/plugins/lib/upgrade.php deleted file mode 100644 index a66201fc5..000000000 --- a/mods/wiki/plugins/lib/upgrade.php +++ /dev/null @@ -1,1594 +0,0 @@ - -*/ - - - -#------------------------------------------------------------------ CVS --- -// most of this appeared in 5.0 -// ... - - - - -#------------------------------------------------------------------ 6.0 --- -// following functions were never implemented in PHP - - -#-- inflates a string enriched with gzip headers -# (this is the logical counterpart to gzencode(), but don't tell anyone!) -if (!function_exists("gzdecode")) { - function gzdecode($data, $maxlen=NULL) { - - #-- decode header - $len = strlen($data); - if ($len < 20) { - return; - } - $head = substr($data, 0, 10); - $head = unpack("n1id/C1cm/C1flg/V1mtime/C1xfl/C1os", $head); - list($ID, $CM, $FLG, $MTIME, $XFL, $OS) = array_values($head); - $FTEXT = 1<<0; - $FHCRC = 1<<1; - $FEXTRA = 1<<2; - $FNAME = 1<<3; - $FCOMMENT = 1<<4; - $head = unpack("V1crc/V1isize", substr($data, $len-8, 8)); - list($CRC32, $ISIZE) = array_values($head); - - #-- check gzip stream identifier - if ($ID != 0x1f8b) { - trigger_error("gzdecode: not in gzip format", E_USER_WARNING); - return; - } - #-- check for deflate algorithm - if ($CM != 8) { - trigger_error("gzdecode: cannot decode anything but deflated streams", E_USER_WARNING); - return; - } - - #-- start of data, skip bonus fields - $s = 10; - if ($FLG & $FEXTRA) { - $s += $XFL; - } - if ($FLG & $FNAME) { - $s = strpos($data, "\000", $s) + 1; - } - if ($FLG & $FCOMMENT) { - $s = strpos($data, "\000", $s) + 1; - } - if ($FLG & $FHCRC) { - $s += 2; // cannot check - } - - #-- get data, uncompress - $data = substr($data, $s, $len-$s); - if ($maxlen) { - $data = gzinflate($data, $maxlen); - return($data); // no checks(?!) - } - else { - $data = gzinflate($data); - } - - #-- check+fin - $chk = crc32($data); - if ($CRC32 != $chk) { - trigger_error("gzdecode: checksum failed (real$chk != comp$CRC32)", E_USER_WARNING); - } - elseif ($ISIZE != strlen($data)) { - trigger_error("gzdecode: stream size mismatch", E_USER_WARNING); - } - else { - return($data); - } - } -} - - -#-- get all already made headers(), -# CANNOT be emulated, because output buffering functions -# already swallow up any sent http header -if (!function_exists("ob_get_headers")) { - function ob_get_headers() { - return (array)NULL; - } -} - - -#-- encodes required named XML entities, like htmlentities(), -# but does not re-encode numeric &#xxxx; character references -# - could screw up scripts which then implement this themselves -# - doesn't fix bogus or invalid numeric entities -if (!function_exists("xmlentities")) { - function xmlentities($str) { - return strtr($str, array( - "&#"=>"&#", "&"=>"&", "'"=>"'", - "<"=>"<", ">"=>">", "\""=>""", - )); - } -} - - - -#------------------------------------------------------------------ 5.0 --- -# set_exception_handler - unimpl. -# restore_exception_handler - unimpl. -# debug_print_backtrace - unimpl. -# class_implements - unimplementable -# proc_terminate - unimpl? -# proc_get_status - unimpl. -# -- -# proc_nice -# dns_get_record -# date_sunrise - undoc. -# date_sunset - undoc. - - - -#-- constant: end of line -if (!defined("PHP_EOL")) { - define("PHP_EOL", ( (DIRECTORY_SEPARATOR == "\\") ?"\015\012" :(strncmp(PHP_OS,"D",1)?"\012":"\015") ) ); #" -} - - -#-- case-insensitive string search function, -# - finds position of first occourence of a string c-i -# - parameters identical to strpos() -if (!function_exists("stripos")) { - function stripos($haystack, $needle, $offset=NULL) { - - #-- simply lowercase args - $haystack = strtolower($haystack); - $needle = strtolower($needle); - - #-- search - $pos = strpos($haystack, $needle, $offset); - return($pos); - } -} - - -#-- case-insensitive string search function -# - but this one starts from the end of string (right to left) -# - offset can be negative or positive -if (!function_exists("strripos")) { - function strripos($haystack, $needle, $offset=NULL) { - - #-- lowercase incoming strings - $haystack = strtolower($haystack); - $needle = strtolower($needle); - - #-- [-]$offset tells to ignore a few string bytes, - # we simply cut a bit from the right - if (isset($offset) && ($offset < 0)) { - $haystack = substr($haystack, 0, strlen($haystack) - 1); - } - - #-- let PHP do it - $pos = strrpos($haystack, $needle); - - #-- [+]$offset => ignore left haystack bytes - if (isset($offset) && ($offset > 0) && ($pos > $offset)) { - $pos = false; - } - - #-- result - return($pos); - } -} - - -#-- case-insensitive version of str_replace -if (!function_exists("str_ireplace")) { - function str_ireplace($search, $replace, $subject, $count=NULL) { - - #-- call ourselves recursively, if parameters are arrays/lists - if (is_array($search)) { - $replace = array_values($replace); - foreach (array_values($search) as $i=>$srch) { - $subject = str_ireplace($srch, $replace[$i], $subject); - } - } - - #-- sluice replacement strings through the Perl-regex module - # (faster than doing it by hand) - else { - $replace = addcslashes($replace, "$\\"); - $search = "{" . preg_quote($search) . "}i"; - $subject = preg_replace($search, $replace, $subject); - } - - #-- result - return($subject); - } -} - - -#-- performs a http HEAD request -if (!function_exists("get_headers")) { - function get_headers($url, $parse=0) { - - #-- extract URL parts ($host, $port, $path, ...) - $c = parse_url($url); - extract($c); - if (!isset($port)) { - $port = 80; - } - - #-- try to open TCP connection - $f = fsockopen($host, $port, $errno, $errstr, $timeout=15); - if (!$f) { - return; - } - - #-- send request header - socket_set_blocking($f, true); - fwrite($f, "HEAD $path HTTP/1.0\015\012" - . "Host: $host\015\012" - . "Connection: close\015\012" - . "Accept: */*, xml/*\015\012" - . "User-Agent: ".trim(ini_get("user_agent"))."\015\012" - . "\015\012"); - - #-- read incoming lines - $ls = array(); - while ( !feof($f) && ($line = trim(fgets($f, 1<<16))) ) { - - #-- read header names to make result an hash (names in array index) - if ($parse) { - if ($l = strpos($line, ":")) { - $name = substr($line, 0, $l); - $value = trim(substr($line, $l + 1)); - #-- merge headers - if (isset($ls[$name])) { - $ls[$name] .= ", $value"; - } - else { - $ls[$name] = $value; - } - } - #-- HTTP response status header as result[0] - else { - $ls[] = $line; - } - } - - #-- unparsed header list (numeric indices) - else { - $ls[] = $line; - } - } - - #-- close TCP connection and give result - fclose($f); - return($ls); - } -} - - -#-- list of already/potentially sent HTTP responsee headers(), -# CANNOT be implemented (except for Apache module maybe) -if (!function_exists("headers_list")) { - function headers_list() { - trigger_error("headers_list(): not supported by this PHP version", E_USER_WARNING); - return (array)NULL; - } -} - - -#-- write formatted string to stream/file, -# arbitrary numer of arguments -if (!function_exists("fprintf")) { - function fprintf(/*...*/) { - $args = func_get_args(); - $stream = array_shift($args); - return fwrite($stream, call_user_func_array("sprintf", $args)); - } -} - - -#-- write formatted string to stream, args array -if (!function_exists("vfprintf")) { - function vfprintf($stream, $format, $args=NULL) { - return fwrite($stream, vsprintf($format, $args)); - } -} - - -#-- splits a string in evenly sized chunks -# and returns this as array -if (!function_exists("str_split")) { - function str_split($str, $chunk=1) { - $r = array(); - - #-- return back as one chunk completely, if size chosen too low - if ($chunk < 1) { - $r[] = $str; - } - - #-- add substrings to result array until subject strings end reached - else { - $len = strlen($str); - for ($n=0; $n<$len; $n+=$chunk) { - $r[] = substr($str, $n, $chunk); - } - } - return($r); - } -} - - -#-- constructs a QUERY_STRING (application/x-www-form-urlencoded format, non-raw) -# from a nested array/hash with name=>value pairs -# - only first two args are part of the original API - rest used for recursion -if (!function_exists("http_build_query")) { - function http_build_query($data, $int_prefix="", $subarray_pfix="", $level=0) { - - #-- empty starting string - $s = ""; - ($SEP = ini_get("arg_separator.output")) or ($SEP = "&"); - - #-- traverse hash/array/list entries - foreach ($data as $index=>$value) { - - #-- add sub_prefix for subarrays (happens for recursed innovocation) - if ($subarray_pfix) { - if ($level) { - $index = "[" . $index . "]"; - } - $index = $subarray_pfix . $index; - } - #-- add user-specified prefix for integer-indices - elseif (is_int($index) && strlen($int_prefix)) { - $index = $int_prefix . $index; - } - - #-- recurse for sub-arrays - if (is_array($value)) { - $s .= http_build_query($value, "", $index, $level + 1); - } - else { // or just literal URL parameter - $s .= $SEP . $index . "=" . urlencode($value); - } - } - - #-- remove redundant "&" from first round (-not checked above to simplifiy loop) - if (!$subarray_pfix) { - $s = substr($s, strlen($SEP)); - } - - #-- return result / to previous array level and iteration - return($s); - } -} - - -#-- transform into 3to4 uuencode -# - this is the bare encoding, not the uu file format -if (!function_exists("convert_uuencode")) { - function convert_uuencode($data) { - - #-- init vars - $out = ""; - $line = ""; - $len = strlen($data); -# $data .= "\252\252\252"; // PHP and uuencode(1) use some special garbage??, looks like "\000"* and "`\n`" simply appended - - #-- canvass source string - for ($n=0; $n<$len; ) { - - #-- make 24-bit integer from first three bytes - $x = (ord($data[$n++]) << 16) - + (ord($data[$n++]) << 8) - + (ord($data[$n++]) << 0); - - #-- disperse that into 4 ascii characters - $line .= chr( 32 + (($x >> 18) & 0x3f) ) - . chr( 32 + (($x >> 12) & 0x3f) ) - . chr( 32 + (($x >> 6) & 0x3f) ) - . chr( 32 + (($x >> 0) & 0x3f) ); - - #-- cut lines, inject count prefix before each - if (($n % 45) == 0) { - $out .= chr(32 + 45) . "$line\n"; - $line = ""; - } - } - - #-- throw last line, +length prefix - if ($trail = ($len % 45)) { - $out .= chr(32 + $trail) . "$line\n"; - } - - // uuencode(5) doesn't tell so, but spaces are replaced with the ` char in most implementations - $out = strtr("$out \n", " ", "`"); - return($out); - } -} - - -#-- decodes uuencoded() data again -if (!function_exists("convert_uudecode")) { - function convert_uudecode($data) { - - #-- prepare - $out = ""; - $data = strtr($data, "`", " "); - - #-- go through lines - foreach(explode("\n", ltrim($data)) as $line) { - if (!strlen($line)) { - break; // end reached - } - - #-- current line length prefix - unset($num); - $num = ord($line{0}) - 32; - if (($num <= 0) || ($num > 62)) { // 62 is the maximum line length - break; // according to uuencode(5), so we stop here too - } - $line = substr($line, 1); - - #-- prepare to decode 4-char chunks - $add = ""; - for ($n=0; strlen($add)<$num; ) { - - #-- merge 24 bit integer from the 4 ascii characters (6 bit each) - $x = ((ord($line[$n++]) - 32) << 18) - + ((ord($line[$n++]) - 32) << 12) // were saner with "& 0x3f" - + ((ord($line[$n++]) - 32) << 6) - + ((ord($line[$n++]) - 32) << 0); - - #-- reconstruct the 3 original data chars - $add .= chr( ($x >> 16) & 0xff ) - . chr( ($x >> 8) & 0xff ) - . chr( ($x >> 0) & 0xff ); - } - - #-- cut any trailing garbage (last two decoded chars may be wrong) - $out .= substr($add, 0, $num); - $line = ""; - } - - return($out); - } -} - - -#-- return array of filenames in a given directory -# (only works for local files) -if (!function_exists("scandir")) { - function scandir($dirname, $desc=0) { - - #-- check for file:// protocol, others aren't handled - if (strpos($dirname, "file://") === 0) { - $dirname = substr($dirname, 7); - if (strpos($dirname, "localh") === 0) { - $dirname = substr($dirname, strpos($dirname, "/")); - } - } - - #-- directory reading handle - if ($dh = opendir($dirname)) { - $ls = array(); - while ($fn = readdir($dh)) { - $ls[] = $fn; // add to array - } - closedir($dh); - - #-- sort filenames - if ($desc) { - rsort($ls); - } - else { - sort($ls); - } - return $ls; - } - - #-- failure - return false; - } -} - - -#-- like date(), but returns an integer for given one-letter format parameter -if (!function_exists("idate")) { - function idate($formatchar, $timestamp=NULL) { - - #-- reject non-simple type parameters - if (strlen($formatchar) != 1) { - return false; - } - - #-- get current time, if not given - if (!isset($timestamp)) { - $timestamp = time(); - } - - #-- get and turn into integer - $str = date($formatchar, $timestamp); - return (int)$str; - } -} - - - -#-- combined sleep() and usleep() -if (!function_exists("time_nanosleep")) { - function time_nanosleep($sec, $nano) { - sleep($sec); - usleep($nano); - } -} - - - -#-- search first occourence of any of the given chars, returns rest of haystack -# (char_list must be a string for compatibility with the real PHP func) -if (!function_exists("strpbrk")) { - function strpbrk($haystack, $char_list) { - - #-- prepare - $len = strlen($char_list); - $min = strlen($haystack); - - #-- check with every symbol from $char_list - for ($n = 0; $n < $len; $n++) { - $l = strpos($haystack, $char_list{$n}); - - #-- get left-most occourence - if (($l !== false) && ($l < $min)) { - $min = $l; - } - } - - #-- result - if ($min) { - return(substr($haystack, $min)); - } - else { - return(false); - } - } -} - - - -#-- logo image activation URL query strings (gaga feature) -if (!function_exists("php_real_logo_guid")) { - function php_real_logo_guid() { return php_logo_guid(); } - function php_egg_logo_guid() { return zend_logo_guid(); } -} - - -#-- no need to implement this -# (there aren't interfaces in PHP4 anyhow) -if (!function_exists("get_declared_interfaces")) { - function get_declared_interfaces() { - trigger_error("get_declared_interfaces(): Current script won't run reliably with PHP4.", E_USER_WARNING); - return( (array)NULL ); - } -} - - -#-- creates an array from lists of $keys and $values -# (both should have same number of entries) -if (!function_exists("array_combine")) { - function array_combine($keys, $values) { - - #-- convert input arrays into lists - $keys = array_values($keys); - $values = array_values($values); - $r = array(); - - #-- one from each - foreach ($values as $i=>$val) { - if ($key = $keys[$i]) { - $r[$key] = $val; - } - else { - $r[] = $val; // useless, PHP would have long aborted here - } - } - return($r); - } -} - - -#-- apply userfunction to each array element (descending recursively) -# use it like: array_walk_recursive($_POST, "stripslashes"); -# - $callback can be static function name or object/method, class/method -if (!function_exists("array_walk_recursive")) { - function array_walk_recursive(&$input, $callback, $userdata=NULL) { - #-- each entry - foreach ($input as $key=>$value) { - - #-- recurse for sub-arrays - if (is_array($value)) { - array_walk_recursive($input[$key], $callback, $userdata); - } - - #-- $callback handles scalars - else { - call_user_func_array($callback, array(&$input[$key], $key, $userdata) ); - } - } - - // no return value - } -} - - -#-- complicated wrapper around substr() and and strncmp() -if (!function_exists("substr_compare")) { - function substr_compare($haystack, $needle, $offset=0, $len=0, $ci=0) { - - #-- check params - if ($len <= 0) { // not well documented - $len = strlen($needle); - if (!$len) { return(0); } - } - #-- length exception - if ($len + $offset >= strlen($haystack)) { - trigger_error("substr_compare: given length exceeds main_str", E_USER_WARNING); - return(false); - } - - #-- cut - if ($offset) { - $haystack = substr($haystack, $offset, $len); - } - #-- case-insensitivity - if ($ci) { - $haystack = strtolower($haystack); - $needle = strtolower($needle); - } - - #-- do - return(strncmp($haystack, $needle, $len)); - } -} - - -#-- stub, returns empty list as usual; -# you must load "ext/spl.php" beforehand to get this -if (!function_exists("spl_classes")) { - function spl_classes() { - trigger_error("spl_classes(): not built into this PHP version"); - return (array)NULL; - } -} - - - -#-- gets you list of class names the given objects class was derived from, slow -if (!function_exists("class_parents")) { - function class_parents($obj) { - - #-- first get full list - $all = get_declared_classes(); - $r = array(); - - #-- filter out - foreach ($all as $potential_parent) { - if (is_subclass_of($obj, $potential_parent)) { - $r[$potential_parent] = $potential_parent; - } - } - return($r); - } -} - - -#-- an alias -if (!function_exists("session_commit") && function_exists("session_write_close")) { - function session_commit() { - // simple - session_write_close(); - } -} - - -#-- aliases -if (!function_exists("dns_check_record")) { - function dns_check_record($host, $type=NULL) { - // synonym to - return checkdnsrr($host, $type); - } -} -if (!function_exists("dns_get_mx")) { - function dns_get_mx($host, $mx) { - $args = func_get_args(); - // simple alias - except the optional, but referenced third parameter - if ($args[2]) { - $w = & $args[2]; - } - else { - $w = false; - } - return getmxrr($host, $mx, $w); - } -} - - -#-- setrawcookie(), -# can this be emulated 100% exactly? -if (!function_exists("setrawcookie")) { - // we output everything directly as HTTP header(), PHP doesn't seem - // to manage an internal cookie list anyhow - function setrawcookie($name, $value=NULL, $expire=NULL, $path=NULL, $domain=NULL, $secure=0) { - if (isset($value) && strpbrk($value, ",; \r\t\n\f\014\013")) { - trigger_error("setrawcookie: value may not contain any of ',; \r\n' and some other control chars; thrown away", E_USER_WARNING); - } - else { - $h = "Set-Cookie: $name=$value" - . ($expire ? "; expires=" . gmstrftime("%a, %d-%b-%y %H:%M:%S %Z", $expire) : "") - . ($path ? "; path=$path": "") - . ($domain ? "; domain=$domain" : "") - . ($secure ? "; secure" : ""); - header($h); - } - } -} - - -#-- write-at-once file access (counterpart to file_get_contents) -if (!function_exists("file_put_contents")) { - function file_put_contents($filename, $data, $flags=0, $resource=NULL) { - - #-- prepare - $mode = ($flags & FILE_APPEND ? "a" : "w" ) ."b"; - $incl = $flags & FILE_USE_INCLUDE_PATH; - $length = strlen($data); - - #-- open for writing - $f = fopen($filename, $mode, $incl); - if ($f) { - $written = fwrite($f, $data); - fclose($f); - - #-- only report success, if completely saved - return($length == $written); - } - } -} - - -#-- file-related constants -if (!defined("FILE_APPEND")) { - define("FILE_USE_INCLUDE_PATH", 1); - define("FILE_IGNORE_NEW_LINES", 2); - define("FILE_SKIP_EMPTY_LINES", 4); - define("FILE_APPEND", 8); - define("FILE_NO_DEFAULT_CONTEXT", 16); -} - - -#-- more new constants for 5.0 -if (!defined("E_STRICT")) { - define("E_STRICT", 2048); // _STRICT is a special case of _NOTICE (_DEBUG) - # PHP_CONFIG_FILE_SCAN_DIR -} - - -#-- array count_recursive() -if (!defined("COUNT_RECURSIVE")) { - define("COUNT_NORMAL", 0); // count($array, 0); - define("COUNT_RECURSIVE", 1); // not supported -} - - -#-- we introduce a new function, because we cannot emulate the -# newly introduced second parameter to count() -if (!function_exists("count_recursive")) { - function count_recursive($array, $mode=1) { - if (!$mode) { - return(count($array)); - } - else { - $c = count($array); - foreach ($array as $sub) { - if (is_array($sub)) { - $c += count_recursive($sub); - } - } - return($c); - } - } -} - - - - - - - -#------------------------------------------------------------------ 4.3 --- -# money_format - unimpl? -# sha1, sha1_file - too much code to pack it into here; and this -# has already been implemented elsewhere, btw - - -#-- simplified file read-at-once function -if (!function_exists("file_get_contents")) { - function file_get_contents($filename, $use_include_path=1) { - - #-- open file, let fopen() report error - $f = fopen($filename, "rb", $use_include_path); - if (!$f) { return; } - - #-- read max 2MB - $content = fread($f, 1<<21); - fclose($f); - return($content); - } -} - - - -#-- shell-like filename matching (* and ? globbing characters) -if (!function_exists("fnmatch")) { - - #-- associated constants - define("FNM_PATHNAME", 1<<0); // no wildcard ever matches a "/" - define("FNM_NOESCAPE", 1<<1); // backslash can't escape meta chars - define("FNM_PERIOD", 1<<2); // leading dot must be given explicit - define("FNM_LEADING_DIR", 1<<3); // not in PHP - define("FNM_CASEFOLD", 0x50); // match case-insensitive - define("FNM_EXTMATCH", 1<<5); // not in PHP - - #-- implementation - function fnmatch($pattern, $str, $flags=0x0000) { - - #-- 'hidden' files - if ($flags & FNM_PERIOD) { - if (($str[0] == ".") && ($pattern[0] != ".")) { - return(false); // abort early - } - } - - #-- case-insensitivity - $rxci = ""; - if ($flags & FNM_CASEFOLD) { - $rxci = "i"; - } - #-- handline of pathname separators (/) - $wild = "."; - if ($flags & FNM_PATHNAME) { - $wild = "[^/".DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR."]"; - } - - #-- check for cached regular expressions - static $cmp = array(); - if (isset($cmp["$pattern+$flags"])) { - $rx = $cmp["$pattern+$flags"]; - } - - #-- convert filename globs into regex - else { - $rx = preg_quote($pattern); - $rx = strtr($rx, array( - "\\*"=>"$wild*?", "\\?"=>"$wild", "\\["=>"[", "\\]"=>"]", - )); - $rx = "{^" . $rx . "$}" . $rxci; - - #-- cache - if (count($cmp) >= 50) { - $cmp = array(); // free - } - $cmp["$pattern+$flags"] = $rx; - } - - #-- compare - return(preg_match($rx, $str)); - } -} - - -#-- file search and name matching (with shell patterns) -if (!function_exists("glob")) { - - #-- introduced constants - define("GLOB_MARK", 1<<0); - define("GLOB_NOSORT", 1<<1); - define("GLOB_NOCHECK", 1<<2); - define("GLOB_NOESCAPE", 1<<3); - define("GLOB_BRACE", 1<<4); - define("GLOB_ONLYDIR", 1<<5); - define("GLOB_NOCASE", 1<<6); - define("GLOB_DOTS", 1<<7); - // unlikely to work under Win(?), without replacing the explode() with - // a preg_split() incorporating the native DIRECTORY_SEPARATOR as well - - #-- implementation - function glob($pattern, $flags=0x0000) { - $ls = array(); - $rxci = ($flags & GLOB_NOCASE) ? "i" : ""; -#echo "\n=> glob($pattern)...\n"; - - #-- transform glob pattern into regular expression - # (similar to fnmatch() but still different enough to require a second func) - if ($pattern) { - - #-- look at each directory/fn spec part separately - $parts2 = explode("/", $pattern); - $pat = preg_quote($pattern); - $pat = strtr($pat, array("\\*"=>".*?", "\\?"=>".?")); - if ($flags ^ GLOB_NOESCAPE) { - // uh, oh, ouuch - the above is unclean enough... - } - if ($flags ^ GLOB_BRACE) { - $pat = preg_replace("/\{(.+?)\}/e", 'strtr("[$1]", ",", "")', $pat); - } - $parts = explode("/", $pat); -#echo "parts == ".implode(" // ", $parts) . "\n"; - $lasti = count($parts) - 1; - $dn = ""; - foreach ($parts as $i=>$p) { - - #-- basedir included (yet no pattern matching necessary) - if (!strpos($p, "*?") && (strpos($p, ".?")===false)) { - $dn .= $parts2[$i] . ($i!=$lasti ? "/" : ""); -#echo "skip:$i, cause no pattern matching char found -> only a basedir spec\n"; - continue; - } - - #-- start reading dir + match filenames against current pattern - if ($dh = opendir($dn ?$dn:'.')) { - $with_dot = ($p[1]==".") || ($flags & GLOB_DOTS); -#echo "part:$i:$p\n"; -#echo "reading dir \"$dn\"\n"; - while ($fn = readdir($dh)) { - if (preg_match("\007^$p$\007$rxci", $fn)) { - - #-- skip over 'hidden' files - if (($fn[0] == ".") && !$with_dot) { - continue; - } - - #-- add filename only if last glob/pattern part - if ($i==$lasti) { - if (is_dir("$dn$fn")) { - if ($flags & GLOB_ONLYDIR) { - continue; - } - if ($flags & GLOB_MARK) { - $fn .= "/"; - } - } -#echo "adding '$fn' for dn=$dn to list\n"; - $ls[] = "$dn$fn"; - } - - #-- initiate a subsearch, merge result list in - elseif (is_dir("$dn$fn")) { - // add reamaining search patterns to current basedir - $remaind = implode("/", array_slice($parts2, $i+1)); - $ls = array_merge($ls, glob("$dn$fn/$remaind", $flags)); - } - } - } - closedir($dh); - - #-- prevent scanning a 2nd part/dir in same glob() instance: - break; - } - - #-- given dirname doesn't exist - else { - return($ls); - } - - }// foreach $parts - } - - #-- return result list - if (!$ls && ($flags & GLOB_NOCHECK)) { - $ls[] = $pattern; - } - if ($flags ^ GLOB_NOSORT) { - sort($ls); - } -#print_r($ls); -#echo "<=\n"; - return($ls); - } -} //@FIX: fully comment, remove debugging code (- as soon as it works ;) - - -#-- redundant alias for isset() -if (!function_exists("array_key_exists")) { - function array_key_exists($key, $search) { - return isset($search[$key]); - } -} - - -#-- who could need that? -if (!function_exists("array_intersect_assoc")) { - function array_intersect_assoc( /*array, array, array...*/ ) { - - #-- parameters, prepare - $in = func_get_args(); - $cmax = count($in); - $whatsleftover = array(); - - #-- walk through each array pair - # (take first as checklist) - foreach ($in[0] as $i => $v) { - for ($c = 1; $c < $cmax; $c++) { - #-- remove entry, as soon as it isn't present - # in one of the other arrays - if (!isset($in[$c][$i]) || (@$in[$c][$i] !== $v)) { - continue 2; - } - } - #-- it was found in all other arrays - $whatsleftover[$i] = $v; - } - return $whatsleftover; - } -} - - -#-- the opposite of the above -if (!function_exists("array_diff_assoc")) { - function array_diff_assoc( /*array, array, array...*/ ) { - - #-- params - $in = func_get_args(); - $diff = array(); - - #-- compare each array with primary/first - foreach ($in[0] as $i=>$v) { - for ($c=1; $c$word entries - elseif ($result >= 2) { - $r = array(); - $l = 0; - foreach ($uu[1] as $word) { - $l = strpos($string, $word, $l); - $r[$l] = $word; - $l += strlen($word); // speed up next search - } - return($r); - } - - #-- only count - else { - return(count($uu[1])); - } - } -} - - -#-- creates a permutation of the given strings characters -# (let's hope the random number generator was alread initialized) -if (!function_exists("str_shuffle")) { - function str_shuffle($str) { - $r = ""; - - #-- cut string down with every iteration - while (strlen($str)) { - $n = strlen($str) - 1; - if ($n) { - $n = rand(0, $n); // glibcs` rand is ok since 2.1 at least - } - - #-- cut out elected char, add to result string - $r .= $str{$n}; - $str = substr($str, 0, $n) . substr($str, $n + 1); - } - return($r); - } -} - - -#-- simple shorthands -if (!function_exists("get_include_path")) { - function get_include_path() { - return(get_cfg_var("include_path")); - } - function set_include_path($new) { - return ini_set("include_path", $new); - } - function restore_include_path() { - ini_restore("include_path"); - } -} - - -#-- constants for 4.3 -if (!defined("PATH_SEPARATOR")) { - define("PATH_SEPARATOR", ((DIRECTORY_SEPARATOR=='\\') ? ';' :':')); - define("PHP_SHLIB_SUFFIX", ((DIRECTORY_SEPARATOR=='\\') ? 'dll' :'so')); -} -if (!defined("PHP_SAPI")) { - define("PHP_SAPI", php_sapi_name()); -} - - -#-- not identical to what PHP reports (it seems to `which` for itself) -if (!defined("PHP_PREFIX") && isset($_ENV["_"])) { - define("PHP_PREFIX", substr($_ENV["_"], 0, strpos($_ENV["_"], "bin/"))); -} - - - - - - -#------------------------------------------------------------------ 4.2 --- -# almost complete!? - - -#-- shy away from this one - it was broken in all real PHP4.2 versions, and -# this function emulation script won't change that -if (!function_exists("str_rot13")) { - function str_rot13($str) { - static $from = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - static $to = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"; - return strtr($str, $from, $to); - } -} - - -#-- well, if you need it -if (!function_exists("array_change_key_case")) { - - #-- introduced constants - define("CASE_LOWER", 0); - define("CASE_UPPER", 1); - - #-- implementation - function array_change_key_case($array, $case=CASE_LOWER) { - - #-- loop through - foreach ($array as $i=>$v) { - #-- do anything for strings only - if (is_string($i)) { - unset($array[$i]); - $i = ($case==CASE_LOWER) ? strtolower($i) : strtoupper($i); - $array[$i] = $v; - } - // non-recursive - } - return($array); - } -} - - -#-- create fixed-length array made up of $value data -if (!function_exists("array_fill")) { - function array_fill($start_index, $num, $value) { - - #-- params - $r = array(); - $i = $start_index; - $end = $num + $start_index; - - #-- append - for (; $i < $end; $i++) - { - $r[$i] = $value; - } - return($r); - } -} - - -#-- split an array into evenly sized parts -if (!function_exists("array_chunk")) { - function array_chunk($input, $size, $preserve_keys=false) { - - #-- array for chunked output - $r = array(); - $n = -1; // chunk index - - #-- enum input array blocks - foreach ($input as $i=>$v) { - - #-- new chunk - if (($n < 0) || (count($r[$n]) == $size)) { - $n++; - $r[$n] = array(); - } - - #-- add input value into current [$n] chunk - if ($preserve_keys) { - $r[$n][$i] = $v; - } - else { - $r[$n][] = $v; - } - } - return($r); - } -} - - -#-- convenience wrapper -if (!function_exists("md5_file")) { - function md5_file($filename, $raw_output=false) { - - #-- read file, apply hash function - $data = file_get_contents($filename, "rb"); - $r = md5($data); - $data = NULL; - - #-- transform? and return - if ($raw_output) { - $r = pack("H*", $r); - } - return $r; - } -} - - -#-- object type checking -if (!function_exists("is_a")) { - function is_a($obj, $classname) { - - #-- lowercase everything for comparison - $classnaqme = strtolower($classname); - $obj_class = strtolower(get_class($obj)); - - #-- two possible checks - return ($obj_class == $classname) or is_subclass_of($obj, $classname); - } -} - - -#-- floating point modulo -if (!function_exists("fmod")) { - function fmod($x, $y) { - $r = $x / $y; - $r -= (int)$r; - $r *= $y; - return($r); - } -} - - -#-- makes float variable from string -if (!function_exists("floatval")) { - function floatval($str) { - $str = ltrim($str); - return (float)$str; - } -} - - -#-- floats -if (!function_exists("is_infinite")) { - - #-- constants as-is - define("NAN", "NAN"); - define("INF", "INF"); // there is also "-INF" - - #-- simple checks - function is_infinite($f) { - $s = (string)$f; - return( ($s=="INF") || ($s=="-INF") ); - } - function is_nan($f) { - $s = (string)$f; - return( $s=="NAN" ); - } - function is_finite($f) { - $s = (string)$f; - return( !strpos($s, "N") ); - } -} - - -#-- throws value-instantiation PHP-code for given variable -# (a bit different from the standard, was intentional for its orig use) -if (!function_exists("var_export")) { - function var_export($var, $return=false, $indent="", $output="") { - - #-- output as in-class variable definitions - if (is_object($var)) { - $output = "class " . get_class($var) . " {\n"; - foreach (((array)$var) as $id=>$var) { - $output .= " var \$$id = " . var_export($var, true) . ";\n"; - } - $output .= "}"; - } - - #-- array constructor - elseif (is_array($var)) { - foreach ($var as $id=>$next) { - if ($output) $output .= ",\n"; - else $output = "array(\n"; - $output .= $indent . ' ' - . (is_numeric($id) ? $id : '"'.addslashes($id).'"') - . ' => ' . var_export($next, true, "$indent "); - } - if (empty($output)) $output = "array("; - $output .= "\n{$indent})"; - #if ($indent == "") $output .= ";"; - } - - #-- literals - elseif (is_numeric($var)) { - $output = "$var"; - } - elseif (is_bool($var)) { - $output = $var ? "true" : "false"; - } - else { - $output = "'" . preg_replace("/([\\\\\'])/", '\\\\$1', $var) . "'"; - } - - #-- done - if ($return) { - return($output); - } - else { - print($output); - } - } -} - - -#-- strcmp() variant that respects locale setting, -# existed since PHP 4.0.5, but under Win32 first since 4.3.2 -if (!function_exists("strcoll")) { - function strcoll($str1, $str2) { - return strcmp($str1, $str2); - } -} - - - - - -#------------------------------------------------------------------ 4.1 --- -# nl_langinfo - unimpl? -# getmygid -# version_compare -# -# See also "ext/math41.php" for some more (rarely used mathematical funcs). - - - - -#-- aliases (an earlier fallen attempt to unify PHP function names) -if (!function_exists("diskfreespace")) { - function diskfreespace() { - return disk_free_sapce(); - } - function disktotalspace() { - return disk_total_sapce(); - } -} - - -#-- variable count of arguments (in array list) printf variant -if (!function_exists("vprintf")) { - function vprintf($format, $args=NULL) { - call_user_func_array("fprintf", get_func_args()); - } -} - - -#-- same as above, but doesn't output directly and returns formatted string -if (!function_exists("vsprintf")) { - function vsprintf($format, $args=NULL) { - $args = array_merge(array($format), array_values((array)$args)); - return call_user_func_array("sprintf", $args); - } -} - - -#-- can be used to simulate a register_globals=on environment -if (!function_exists("import_request_variables")) { - function import_request_variables($types="GPC", $pfix="") { - - #-- associate abbreviations to global var names - $alias = array( - "G" => "_GET", - "P" => "_POST", - "C" => "_COOKIE", - "S" => "_SERVER", // non-standard - "E" => "_ENV", // non-standard - ); - #-- alias long names (PHP < 4.0.6) - if (!isset($_REQUEST)) { - $_GET = & $HTTP_GET_VARS; - $_POST = & $HTTP_POST_VARS; - $_COOKIE = & $HTTP_COOKIE_VARS; - } - - #-- copy - for ($i=0; $i$val) { - if (!isset($GLOBALS[$pfix.$key])) { - $GLOBALS[$pfix . $key] = $val; - } - } - } - } - // done - } -} - - -// a few mathematical functions follow -// (wether we should really emulate them is a different question) - -#-- me has no idea what this function means -if (!function_exists("hypot")) { - function hypot($num1, $num2) { - return sqrt($num1*$num1 + $num2*$num2); // as per PHP manual ;) - } -} - -#-- more accurate logarithm func, but we cannot simulate it -# (too much work, too slow in PHP) -if (!function_exists("log1p")) { - function log1p($x) { - return( log(1+$x) ); - } - #-- same story for: - function expm1($x) { - return( exp($x)-1 ); - } -} - -#-- as per PHP manual -if (!function_exists("sinh")) { - function sinh($f) { - return( (exp($f) - exp(-$f)) / 2 ); - } - function cosh($f) { - return( (exp($f) + exp(-$f)) / 2 ); - } - function tanh($f) { - return( sinh($f) / cosh($f) ); // ok, that one makes sense again :) - } -} - -#-- these look a bit more complicated -if (!function_exists("asinh")) { - function asinh($x) { - return( log($x + sqrt($x*$x+1)) ); - } - function acosh($x) { - return( log($x + sqrt($x*$x-1)) ); - } - function atanh($x) { - return( log1p( 2*$x / (1-$x) ) / 2 ); - } -} - - -#-- HMAC from RFC2104, but see also PHP_Compat and Crypt_HMAC -if (!function_exists("mhash")) { - - #-- constants - define("MHASH_CRC32", 0); - define("MHASH_MD5", 1); // RFC1321 - define("MHASH_SHA1", 2); // RFC3174 - define("MHASH_TIGER", 7); - define("MHASH_MD4", 16); // RFC1320 - define("MHASH_SHA256", 17); - define("MHASH_ADLER32", 18); - - #-- implementation - function mhash($hashtype, $text, $key) { - - #-- hash function - static $hash_funcs = array( - MHASH_CRC32 => "crc32", // needs dechex()ing here - MHASH_MD5 => "md5", - MHASH_SHA1 => "sha1", - ); - if (!($func = $hash_funcs[$hashtype]) || !function_exists($func)) { - return trigger_error("mhash: cannot use hash algorithm #$hashtype/$func", E_USER_ERROR); - } - if (!$key) { - trigger_error("mhash: called without key", E_USER_WARNING); - } - - #-- params - $bsize = 64; // fixed size - - #-- pad key - if (strlen($key) > $bsize) { // hash key, when it's too long - $key = $func($key); - $key = pack("H*", $key); // binarify - } - $key = str_pad($key, $bsize, "\0"); // fill up with NULs (1) - - #-- prepare inner and outer padding stream - $ipad = str_pad("", $bsize, "6"); // %36 - $opad = str_pad("", $bsize, "\\"); // %5C - - #-- call hash func // php can XOR strings for us - $dgst = pack("H*", $func( ($key ^ $ipad) . $text )); // (2,3,4) - $dgst = pack("H*", $func( ($key ^ $opad) . $dgst )); // (5,6,7) - return($dgst); - } -} - - - -#-- other stuff -/* - removed funcs?? - [18] => leak -*/ - - - -#-- pre-4.1 -- end -// no need to implement anything below that, because such old versions -// will be incompatbile anyhow (- none of the newer superglobals known), -// but see also "ext/old" - - -?> diff --git a/mods/wiki/plugins/lib/uservars_pages.meta b/mods/wiki/plugins/lib/uservars_pages.meta deleted file mode 100644 index 8ee247328..000000000 --- a/mods/wiki/plugins/lib/uservars_pages.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: library -hooks: login_handler -type: special -title: uservars_pages -description: override to use old standard -priority: bonus diff --git a/mods/wiki/plugins/lib/uservars_pages.php b/mods/wiki/plugins/lib/uservars_pages.php deleted file mode 100644 index 75f3a041e..000000000 --- a/mods/wiki/plugins/lib/uservars_pages.php +++ /dev/null @@ -1,301 +0,0 @@ -".ewiki_uservars_getvar('Real Name').'

      '); - echo("

      ".ewiki_uservars_getvar('Fake Name','No alias').'

      '); - ewiki_uservars_setvar('Real Name',"Andy"); - ewiki_uservars_setvar('Fake Name',"Andriod"); - echo("

      ".ewiki_get_uservar('Real Name').'

      '); - - $o = ob_get_contents(); - ob_end_clean(); - return $o; -} -// */ - -function ewiki_getall_uservar($username=NULL){ - global $ewiki_plugins; - - #-- plugins to call - $pf = @$ewiki_plugins['uservars_getall'][0]; - - if ($pf && function_exists($pf)) { - $r=$pf($username); - if($r){ - ewiki_log('UserVars getall_uservar: uservariables successfully retrieved for "'.$username.'"', 3); - return($r); - } else { - ewiki_log('UserVars: there was an error retrieving uservariables for "'.$username.'"', 3); - } - } - return(array()); -} - -function ewiki_clear_uservar($varname, $username=NULL){ - global $ewiki_plugins; - - #-- plugins to call - $pf = @$ewiki_plugins['uservars_clear'][0]; - - $varname=trim(strtr($varname, "_", " ")); - - if ($pf && function_exists($pf)) { - $r=$pf($varname, $username); - if($r){ - ewiki_log('UserVars clear_uservar: "'.$varname.'" successfully cleared for user "'.$username.'"', 3); - return($r); - } else { - ewiki_log('UserVars clear_uservar: error clearing"'.$varname.'" for user "'.$username.'"', 3); - } - } - return(FALSE); -} - -function ewiki_search_uservar($varname, $value=NULL){ - global $ewiki_plugins; - - #-- plugins to call - $pf = @$ewiki_plugins['uservars_search'][0]; - - - if ($pf && function_exists($pf)) { - //echo("ewiki_search_uservar calling $pf($varname,$value)"); - $r=$pf($varname,$value); - if($r){ - ewiki_log('UserVars search_uservar: search for "'.$value.'" in field "'.$varname.'" was successful', 3); - return($r); - } else { - ewiki_log('UserVars search_uservar: search for "'.$value.'" in field "'.$varname.'" failed', 3); - } - } - return(array()); -} - -function ewiki_get_uservar($varname, $defaultValue=NULL, $username=NULL){ - global $ewiki_plugins; - - #-- plugins to call - $pf = @$ewiki_plugins['uservars_get'][0]; - - - if ($pf && function_exists($pf)) { - $r=$pf($varname, $defaultValue, $username); - if($r){ - ewiki_log('UserVars get_uservar: get "'.$varname.'" for user "'.$username.'" was successful', 3); - return($r); - } else { - ewiki_log('UserVars get_uservar: get "'.$varname.'" for user "'.$username.'" failed', 3); - } - } - return($defaultValue); -} -function ewiki_set_uservar($varname, $value, $username=NULL){ - global $ewiki_plugins; - - $varname=trim(strtr($varname, "_", " ")); - #-- plugins to call - $pf = @$ewiki_plugins['uservars_set'][0]; - - - if ($pf && function_exists($pf)) { - $r=$pf($varname, $value, $username); - if($r){ - ewiki_log('UserVars set_uservar: seting "'.$varname.'" to "'.$value.'" for user "'.$username.'" was successful', 3); - return($r); - } else { - ewiki_log('UserVars set_uservar: seting "'.$varname.'" to "'.$value.'" for user "'.$username.'" failed', 3); - } - - } - return(FALSE); -} - -/* -Gets all variables for $username or the current user if $username -is not set. -*/ -function ewiki_uservars_pages_getallvar($username=NULL){ - return(ewiki_uservars_pages_retrieve($username)); -} - -/* -Gets the variable $varname for $username or the current user if $username -is not set. If $varname is not set $defaultValue is returned. -*/ -function ewiki_uservars_pages_getvar($varname, $defaultValue=NULL, $username=NULL){ - $data=ewiki_uservars_pages_retrieve($username); - if(isset($data[$varname])){ - return($data[$varname]); - }else{ - return($defaultValue); - } -} - -function ewiki_uservars_pages_clear($varname, $username=NULL){ - $data=ewiki_uservars_pages_retrieve($username); - unset($data[$varname]); - return(ewiki_uservars_pages_store($data,$username)); -} - -function ewiki_uservars_pages_search($varname, $value=NULL){ - - $result = ewiki_db::SEARCH("content", $varname); - - //Get a list of all pages containing our varname - while ($row = $result->get()) { - if(!preg_match("/".EWIKI_USERVARS_PAGENAME_PREFIX."(.*)/",$row["id"],$matches)){ - continue; - }//Page name is properly formed as a UserVars page name - $username=$matches[1]; - - //echo("Checking $username for $varname"); - if(!($data=ewiki_uservars_pages_retrieve($username))){ - //echo(" rejected, no data retrieved"); - continue; - }//data was retrieved from the page. - - if(!isset($data[$varname])){ - //echo(" rejected, variable not set $varname"); - continue; - }//The varname we are searching for was there - - if(isset($value)&&($value!=$data[$varname])){ - //echo("rejected $value != ".$data[$varname]); - continue; - }//if we were looking for a value, it matches - - //echo("passed, setting $data[$varname] to $values[$varname]"); - $values[$username]=$data[$varname]; - } - - return($values); -} - -/* -Sets the variable $varname to $value for $username or the current user if $username -is not set. -*/ -function ewiki_uservars_pages_setvar($varname, $value, $username=NULL){ - $data=ewiki_uservars_pages_retrieve($username); - $data[$varname]=$value; - return(ewiki_uservars_pages_store($data,$username)); -} - -/* -Stores $data as the user variables for $username returning sucess and storing it in -global $ewiki_uservars if you are storing the user data for the current user. - -$username is optional, $GLOBALS['ewiki_auth_user']) is assumed. -$data is optional, global $ewiki_uservars is stored if none is passed. -*/ -function ewiki_uservars_pages_store($data=NULL, $username=NULL){ - global $ewiki_uservars,$ewiki_errmsg; - - if(!isset($username)){ - $username = $GLOBALS['ewiki_auth_user']; - } - if($username == $GLOBALS['ewiki_auth_user']){ - if(!isset($data)){ - $data=$ewiki_uservars; - }else{ - $ewiki_uservars=$data; - } - } - - //echo("

      Storing user variables for $username

      "); - $oldpage=ewiki_db::GET(EWIKI_USERVARS_PAGENAME_PREFIX.$username); - - //if there was already an existing, non-system page, fail out. - if(($oldpage['version']>0)&&(!($oldpage["flags"] & EWIKI_DB_F_SYSTEM))){ - $ewiki_errmsg=ewiki_t('ERRORSAVING'); - return(0); - } - - $save = array( - "id" => EWIKI_USERVARS_PAGENAME_PREFIX.$username, - "version" => @$oldpage["version"] + 1, - "flags" => EWIKI_DB_F_SYSTEM, - "content" => serialize($data), - "author" => ewiki_author(), - "lastmodified" => time(), - "created" => ($uu=@$oldpage["created"]) ? $uu : time(), - "meta" => ($uu=@$oldpage["meta"]) ? $uu : "", - "hits" => ($uu=@$oldpage["hits"]) ? $uu : "0", - ); - - return(ewiki_db::WRITE($save)); -} - -/* -Retrieves the userdata for $username returning it and storing it in -global $ewiki_uservars if you are retrieving the user data for the current user. - -$username is optional, $GLOBALS['ewiki_auth_user']) is assumed. -*/ -function ewiki_uservars_pages_retrieve($username=NULL){ - global $ewiki_uservars; - if(!isset($username)){ - $username = $GLOBALS['ewiki_auth_user']; - } - - if(!empty($ewiki_uservars)&&($username == $GLOBALS['ewiki_auth_user'])){ - return($ewiki_uservars); - } - - $data=ewiki_db::GET(EWIKI_USERVARS_PAGENAME_PREFIX.$username); - - //User data must be on system pages - if($data["flags"] & EWIKI_DB_F_SYSTEM){ - //echo("System flag set "); - $userdata=unserialize($data['content']); - } - //log and fail if no userdata found i.e. no page, no system flag, or not an array - if(!is_array($userdata)){ - //echo(" retrieved no user data"); - ewiki_log("No userdata for $username in ewiki_uservars_pages_retrieve()",2); - return(array()); - } - - if($username == $GLOBALS['ewiki_auth_user']){ - $ewiki_uservars=$userdata; - } - - return($userdata); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/webdav.meta b/mods/wiki/plugins/lib/webdav.meta deleted file mode 100644 index 29e1bf3ae..000000000 --- a/mods/wiki/plugins/lib/webdav.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: library -config: - EWIKI_SCRIPT_WEBDAV=EWIKI_BASE_URL . "z.php/" // may be we should use a separate z_dav.php script or so? - EWIKI_PAGE_CTYPE="text/wiki; variant=ewiki; charset=iso-8859-1" -title: WebDAV -description: remote filesystem access over HTTP (for online authoring) -priority: deprecated -type: api -depends: minidav diff --git a/mods/wiki/plugins/lib/webdav.php b/mods/wiki/plugins/lib/webdav.php deleted file mode 100644 index 27399a9ba..000000000 --- a/mods/wiki/plugins/lib/webdav.php +++ /dev/null @@ -1,263 +0,0 @@ -int_charset = strtolower(EWIKI_CHARSET); // L1 only! - if (!function_exists("ewiki_http_header_errors") && !function_exists("ewiki_xml_comment_errors")) { - error_reporting(0); - } - $this->xmlns["page"] = "urn:x-ewiki:db:page-data"; - $this->xmlns["meta"] = "urn:x-ewiki:db:meta-meta"; - } - - - - #-- retrieve a page - function GET($path) { - - #-- page name, look it up in database - $id = $this->id($path); - $version = NULL; - $data = ewiki_db::GET($id, $version); - - #-- found? - if ($id && $data && $data["version"]) { - - #-- headers - ewiki_http_headers($data["content"], $id, $data, "view", $_saveasfn=0); - - #-- send - return $this->GET_response($data["content"], $data["lastmodified"], EWIKI_PAGE_CTYPE); - - } - else { - return "404 Not Found"; - } - } - - - - #-- get meta data of page - function PROPFIND($path, $props) { - - #-- page name, prep - $id = $this->id($path); - $files = array(); - - #-- list pages - if (!strlen($id) || ($id=="/")) { - - $oldest_time = 2*UNIX_MILLENNIUM; - $result = ewiki_db::GETALL(array()); - while ($data = $result->get(1, 0x137f)) { - if ($this->depth >= WEBDAV_DIR_DEPTH) { - $files[] = $this->fileinfo($data); - } - $oldest_time = min($oldest_time, $data["created"]); - } - - #-- add entry for virtual root directory - $data = array( - "id"=>"/", - "created"=>$oldest_time, - ); - $files[] = $this->dirinfo($data); - } - - #-- just the specified one - else { - $version = NULL; - $data = ewiki_db::GET($id, $version); - if ($data) { - $files[] = $this->fileinfo($data); - } - } - - #-- fin - return($files); - } - - - - #-- rearrange page meta data fields as array for WebDAV class - function fileinfo(&$data) { - - #-- create meta/properties array - ($ct = $data["meta"]["Content-Type"]) or ($ct = EWIKI_PAGE_CTYPE); - $m = array( - "path" => "/" . $data["id"], // yes just a slash, no _SCRIPT_WEBDAV prefix - "resourcetype" => "", // "" ordinary page, was "collection" for dirs - "creationdate" => $data["created"], - "getcontentlength" => strlen($data["content"]), - "getlastmodified" => $data["lastmodified"], - "getcontenttype" => $ct, - "displayname" => ewiki_split_title($data["id"]), - "getetag" => ewiki_etag($data), - "getcontentlanguage" => EWIKI_DEFAULT_LANG, - "page:author" => $data["author"], - "page:version" => $data["version"], - "page:hits" => $data["hits"], - "page:log" => $data["meta"]["log"], - "page:user-agent" => $data["meta"]["user-agent"], - ); - - #-- add {meta}² entries - if ($meta = $data["meta"]["meta"]) foreach ($meta as $i=>$v) { - $m["meta:$i"] = implode(", ", $v); - } - - return($m); - } - - - #-- needed only for (virtual) root element/dir - function dirinfo(&$data) { - - #-- create meta/properties array - $ct = "httpd/unix-directory"; - $m = array( - "path" => "/" . trim($data["id"], "/"), - "resourcetype" => "collection", // it's a dir - "creationdate" => $data["created"], - "getcontentlength" => 0, -// "getlastmodified" => $data["lastmodified"], - "getcontenttype" => $ct, -// "displayname" => EWIKI_NAME.":", - ); - - return($m); - } - - - - #-- save page into database (no overwriting) - function PUT($path, $ct, $charset) { - - #-- let's call the auth routine once more?? - $this->auth(); - - #-- get old page version - $id = $this->id($path); - ($data = ewiki_db::GET($id)) - or ($data = ewiki_db::CREATE($id)); - - #-- read from whereever - $data["content"] = $this->get_body(); - - #-- check content-type - if (($ct != "text/wiki") && ($ct != "text/plain")) { - return("422 Only WikiPages Accepted"); - } - - #-- save back to db - ewiki_db::UPDATE($data); - $data["version"] += 1; - $ok = ewiki_db::WRITE($data); - - #-- handle response here - if ($ok) { - return("200 Written Successfully"); - } - return("500 Couldn't Save"); - } - - -// #-- returns only the HTTP headers for a given page -// function HEAD() { -// } // will anyhow get emulated via GET() - - - function PROPPATCH() { - } - - - #-- no real page deletion without authenticated admin/pw, and we - # simply clear the page, if it exists (content:="DeletedPage") - function DELETE() { - } - - - function COPY() { - } - function MOVE() { - } - - -// #-- we could emulate this via 'plugins/edit/lock|warn' -// function LOCK() { -// } -// function UNLOCK() { -// } - - - - #-- just to be sure we call it again (already done in z.php) - function auth() { - parent::auth(); - include("plugins/../fragments/funcs/auth.php"); - } - - - - - - #-- decode page id from the $path arg - function id($path) { - $id = $path; -// if (strpos($id, EWIKI_SCRIPT_WEBDAV) === 0) { -// $id = substr($id, strlen(EWIKI_SCRIPT_WEBDAV)); -// } - #-- MiniDav base class always leaves the slash in (originally came from PATH_INFO) - if ($id[0] == "/") { - $id = substr($id, 1); - } - return $id; - } - - -} // end of class - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/wikiapi.meta b/mods/wiki/plugins/lib/wikiapi.meta deleted file mode 100644 index 5840dd21e..000000000 --- a/mods/wiki/plugins/lib/wikiapi.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -type: api -category: library -title: API to Wiki -description: restricted remote-access functionality -priority: rare diff --git a/mods/wiki/plugins/lib/wikiapi.php b/mods/wiki/plugins/lib/wikiapi.php deleted file mode 100644 index 27694de07..000000000 --- a/mods/wiki/plugins/lib/wikiapi.php +++ /dev/null @@ -1,185 +0,0 @@ - "wikiapi_supportedVersion", - "wiki.getPage" => "wikiapi_getPage", - "wiki.getPageVersion" => "wikiapi_getPage", - "wiki.getPageHtml" => "wikiapi_getPageHtml", - "wiki.getPageHtmlVersion" => "wikiapi_getPageHtml", - "wiki.getPageInfo" => "wikiapi_getPageInfo", - "wiki.getPageInfoVersion" => "wikiapi_getPageInfo", - "wiki.getAllPages" => "wikiapi_getAllPages", - "wiki.getRecentChanges" => "wikiapi_getRecentChanges", - "wiki.listLinks" => "wikiapi_listLinks", - "wiki.putPage" => "wikiapi_putPage", - "ewiki.getBackLinks" => "ewiki_get_backlinks", - "ewiki.getLinks" => "ewiki_get_links", -// "ewiki.linkDatabase" => "wikiapi_linkdatabase", -// "ewiki.searchPages" => "wikiapi_search", -// "ewiki.titleSearch" => "wikiapi_search_titles", - "ewiki.url" => "ewiki_script", - "ewiki.ahref" => "ewiki_link", - "ewiki.getInterWikiUrl" => "ewiki_interwiki", - "ewiki.log" => "ewiki_log", -); -$wikiapi_encode = 0; - - -# API switch helper functions (XML+RPC needs encoded fields) -# -function wikiapi_b64encode($str) { - global $wikiapi_encode; - if ($wikiapi_encode) { - return(new xmlrpc_base64(base64_encode($str))); - // NOTE: possible Wiki XML-RPC bugs everywhere: - // this text snippet will be in L1 charset, as - // is for binary transportation (as opposed to text - // s) - } - else return($str); -} - -function wikiapi_time($t) { - global $wikiapi_encode; - if ($wikiapi_encode) { - return(new xmlrpc_datetime($t)); - } - else return($str); -} - - -#--------------------------------------------------------------------------- -# API implementation - - - -// we're now version TWO - no more base64+urlencoding!! -function wikiapi_supportedVersion() { - return(2); -} - - -function wikiapi_getAllPages() { - return(wikiapi_getRecentChanges(NULL)); -} - - -# helper function -# -function wikiapi_pageinfo(&$data) { - $author = strtok($data["author"], "(,| "); - $res = array( - "name" => $data["id"], - "lastModified" => wikiapi_time($data["modified"]), - "author" => $author, - "version" => $data["version"], - ); - return($res); -} - -function wikiapi_getRecentChanges($since=UNIX_MILLENNIUM) { - $r = array(); - $result = ewiki_db::GETALL(array("flags", "lastmodified")); - while ($row = $result->get(0, 0x0020)) { - if (EWIKI_DB_F_TEXT == ($row["flags"] & EWIKI_DB_F_TYPE)) { - if (!isset($since)) { - $r[] = $row["id"]; - } - elseif ($row["lastmodified"] >= $since) { - $r[] = wikiapi_pageinfo($data); - } - } - } - return($r); -} - - -function wikiapi_getPageInfo($id, $ver=NULL) { - $data = ewiki_db::GET($id, $ver); - if ($data) { - $res = wikiapi_pageinfo($data); - return($res); - } -} - - -function wikiapi_getPage($id, $ver=NULL) { - $data = ewiki_db::GET($id, $ver); - if ($data) { - return($data["content"]); #wikiapi_b64encode() - } -} - - -function wikiapi_getPageHtml($id, $ver=NULL) { - $data = ewiki_db::GET($id, $ver); - if ($data) { - $render_args = array( - "scan_links" => 1, - "html" => (EWIKI_ALLOW_HTML||(@$data["flags"]&EWIKI_DB_F_HTML)), - ); - $res = ewiki_format($data["content"], $render_args); - return($res); #wikiapi_b64encode() - } -} - - -function wikiapi_listLinks($id, $ver=NULL) { - global $ewiki_config; - $iw = &$ewiki_config["interwiki"]; - - $data = ewiki_db::GET($id, $ver); - if ($data) { - $r = array(); - $refs = explode("\n", trim($data["refs"])); - foreach ($refs as $link) { - #-- interwiki - if (($m = strtok($link, ":")) && ($p = strtok("\000"))) { - if ($url = ewiki_array($iw, $m)) { - while (($uu = ewiki_array($iw, $url)) !== NULL) { - $url = $uu; - } - $link = $url . $p; - } - } - #-- absolute URLs - if (strpos($link, "://")) { - if (strpos($link, EWIKI_IDF_INTERNAL) === 0) { - $link = ewiki_script_binary("", $link); - # BAD NEWS: we can't get absolute URLs for - # internal:// image links - } - $r[] = array( - "page" => $link, - "type" => "external", - "href" => $href, - ); - } - #-- internal WikiLinks - else { - $r[] = array( - "page" => $link, - "type" => "local", - "href" => ewiki_script("", $link), - ); - } - } - return($r); - } -} - - -function wikiapi_putPage($id, $raw) { - if (EWIKI_PROTECTED_MODE) { - return(false); - } - return(false); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/wikinews.php b/mods/wiki/plugins/lib/wikinews.php deleted file mode 100644 index 16fbd29be..000000000 --- a/mods/wiki/plugins/lib/wikinews.php +++ /dev/null @@ -1,12 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/lib/xml.meta b/mods/wiki/plugins/lib/xml.meta deleted file mode 100644 index 150f1e99a..000000000 --- a/mods/wiki/plugins/lib/xml.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: PHP -type: functions -category: library -title: XML parsing -description: namespace-aware and simplified parsing of data-oriented XML -version: 0.8.2 -priority: auto diff --git a/mods/wiki/plugins/lib/xml.php b/mods/wiki/plugins/lib/xml.php deleted file mode 100644 index b74bf50af..000000000 --- a/mods/wiki/plugins/lib/xml.php +++ /dev/null @@ -1,309 +0,0 @@ - we don't want to deal with URIs - # but get shortened abbreviations instead (and not unpredictable ones) - var $xmlns = array( - "http://www.w3.org/1999/02/22-rdf-syntax-ns#" => "rdf", - "http://purl.org/dc/elements/1.1/" => "dc", - "http://purl.org/rss/1.0/modules/wiki/" => "rss-wiki", - "http://purl.org/rss/1.0/" => "rss", // (at least its similar enough) - "http://purl.org/atom/ns#" => "atom", - "DAV:" => "dav", -## "urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" => "ms-dav-time", - "http://xmlns.com/foaf/0.1/" => "foaf", - ); - #-- final xmlns= qualifier down-mapping, - # think of this as "local xmlns:tag renaming" - var $xmlns2; - - #-- tagname mappings - var $map = array( - //"xmlns-prefix:weird-tag-name" => "desired", - ); - - #-- tag name stack - var $current, $parent, $stack=array(); - - - #-- prepare parser - function easy_xml($xml="", $charset=NULL, $targetcoding="ISO-8859-1") { - - #-- init (no "_ns" parser, because we can handle that better) - $this->xp = xml_parser_create($charset); - xml_parser_set_option($this->xp, XML_OPTION_CASE_FOLDING, false); - xml_parser_set_option($this->xp, XML_OPTION_SKIP_WHITE, true); - xml_parser_set_option($this->xp, XML_OPTION_TARGET_ENCODING, $targetcoding); - $this->xml = &$xml; - - #-- handlers - xml_set_character_data_handler($this->xp, array(&$this,"cdata")); - xml_set_element_handler($this->xp, array(&$this,"start"), array(&$this,"end")); - - #-- we take care of namespaces ourselves - $this->xmlns2 = array(); - } - - - #-- action - function parse($more_xml="") { - $r = xml_parse($this->xp, trim($this->xml . $more_xml), $_is_final=TRUE); - if ($e = xml_get_error_code($this->xp)) { - trigger_error("XML error #$e: " . xml_error_string($e), E_WARNING); - } - unset($this->xml); - unset($this->stack); - unset($this->current); - unset($this->parent); - unset($this->l); - unset($this->map); - unset($this->as_content); - unset($this->as_list); - $r = xml_parser_free($this->xp) && ($r); - unset($this->xp); - return($r); - } - - - #-- map ugly XMLNS urls to known identifiers/internal representation - function tag($tag) { - while (($l = strrpos($tag, ":")) - and ($prefix = substr($tag, 0, $l)) - and (isset($this->xmlns2[$prefix])) ) - { - $ns = $this->xmlns2[$prefix]; - if ($ns == $prefix) { - break; - } - - #-- strip known xmlns qualifier/moniker - $tag = substr($tag, $l+1); - if ($ns) { - $tag = $ns . ":" . $tag; - } - else break; - } - - #-- and also rewrite to preferred tag names - if (isset($this->map[$tag])) { - $tag = $this->map[$tag]; - } - - return($tag); - } - - - #-- log tags - function start($xp, &$tag, &$attr) { - #-- normalize attributes and discover namespaces - if ($attr) { - $a = array(); - foreach ($attr as $i=>$v) { - if (strncmp($i, "xmlns:", 6) == 0) { - $this->xmlns($xp, substr($i, 6), $v); - } - else { - $i = $this->tag($i); - $a[$i] = $v; - } - } - $attr = $a; - } - - #-- normalize tag names - $tag = $this->tag($tag); - - #-- track where we are - if ($this->current) { - $this->stack[] = $this->current; - } - $this->parent = $this->current; - $this->current = $tag; - } - - - #-- track tags - function end($xp, &$tag) { - $tag = $this->tag($tag); - $this->current = $this->parent; - $this->parent = array_pop($this->stack); - } - - - #-- data extr - function cdata($xp, $data) { - } - - - #-- we handle namespaces ourselves to decipher silly URIs and - # get rid of uncommon prefixes - function xmlns($xp, $short, $uri) { - #-- setup back-mapping to OUR preferred xmlnamespace abbr - if ($desired = $this->xmlns[$uri]) { - if (($short != $desired) - and (isset($this->xmlns2["rw:"][$short]) - or !isset($this->xmlns2[$short])) ) - { - $this->xmlns2[$short] = $desired; - $this->xmlns2["rw:"][$short] = 1; // mark as overwritable entry - } - // prevents 1:1-conversions - } - #-- keep it - else { - $this->xmlns[$uri] = $short; // log - // $this->xmlns2[$short] = $short; - } - } - - -}//class - - - -#-- simple data/array XML file -------------------------------------------- -# can decode only two-level data containers -class easy_xml_data extends easy_xml { - - #-- which elements always to expect multiple times (= becomes list) - var $as_list = array(); - - #-- which attributes to transmove into cdata - var $as_content = array(); - - - #-- append string data to collection - function cdata($xp, $data) { - if (trim($data)) { - $this->l[$this->parent][$this->current] = $data; - } - } - - - #-- extract single blocks from array collection list - function end($xp, $tag) { - - parent::end($xp, $tag); - - if (isset($this->l[$tag])) { - #-- make list - if (isset($this->{$tag}) || in_array($tag, $this->as_list)) { - #-- convert into list - if (isset($this->{$tag}) && !isset($this->{$tag}[0])) { - $this->{$tag} = array( - 0 => $this->{$tag} - ); - } - $this->{$tag}[] = $this->l[$tag]; - } - #-- no list (asis) - else { - $this->{$tag} = $this->l[$tag]; - } - unset($this->l[$tag]); - } - } - - - #-- converts certain expected tag attributes into cdata - function start($xp, &$tag, &$attr) { - parent::start($xp, $tag, $attr); - foreach ($attr as $i=>$content) { - if ($this->as_content[$tag]==$i) { - $this->cdata($xp, $content); - } - } - } - -}//class - - - -#-- special simplifications for RSS- and Atom- XML files -------------------- -class easy_xml_rss extends easy_xml_data { - - #-- add a few mappings to make RSS and Atom look similar - function easy_xml_rss($xml, $cs=NULL, $tc="ISO-8859-1") { - parent::easy_xml($xml, $cs, $tc); - // kill some of _our_ namespace prefixes - $this->xmlns2 += array( -// "rss-wiki" => "", - "rss" => "", - "atom" => "", - "dc" => "", - ); - // rename tags (mainly for Atom) - $this->map += array( - // atom: - "feed" => "channel", - "entry" => "item", - "content" => "description", - "id" => "guid", - // dc: - "date" => "pubDate", - ); - // tag attributes to auto-convert into content - $this->as_content += array( - "link"=>"href", - ); - // always make list-array of items - $this->as_list = array( - "item", - ); - } -}//class - - - - -#-- decode into structs (fast, but annoying to work with) ------------------ -class ewiki_xml_fast { - - var $data; - var $tags; - - #-- do - function parse() { - xml_parse_into_struct($this->xp, $this->xml, $this->data, $this->tags); - - #-- fix xmlns, tag names - $data = &$this->data; - $tags = &$this->tags; - foreach ($data as $i=>$d) { - if ($new = $this->tag($data[$i]["tag"])) { - $data[$i]["tag"] = $new; - } - if (isset($data[$i]["attributes"])) { - foreach ($data[$i]["attributes"] as $key=>$val) { - if ($new = ewiki_short_xmlns($key, $xmlns)) { - unset($data[$i]["attributes"][$key]); - $data[$i]["attributes"][$new] = $val; - } - } - } - } - foreach ($tags as $key=>$val) { - if ($new = $this->tag($key)) { - unset($tags[$key]); - $tags[$new] = $val; - } - } - - unset($this->xml); - } -}//class - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/lib/xmlrpc.meta b/mods/wiki/plugins/lib/xmlrpc.meta deleted file mode 100644 index 667fecc6e..000000000 --- a/mods/wiki/plugins/lib/xmlrpc.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: PHP -type: api -provides: rpc, xml-rpc -version: 0.3.9 -category: library -priority: optional -title: XML-RPC client and server -description: serves remote procedure calls -version: 11.3 -homepage: http://freshmeat.net/p/upgradephp diff --git a/mods/wiki/plugins/lib/xmlrpc.php b/mods/wiki/plugins/lib/xmlrpc.php deleted file mode 100644 index c02292fe9..000000000 --- a/mods/wiki/plugins/lib/xmlrpc.php +++ /dev/null @@ -1,1148 +0,0 @@ - values converted into Unix -# timestamps and unpacked into strings. -# -function xmlrpc($server, $method=NULL /*, ... */) { - if ($method) { - $params = func_get_args(); - shift($params); shift($params); - return - xmlrpc_request($server, $method, $params); - } - else { - return - new xmlrpc_connection($server); - } -} - - - -#-- Generate and send request, decode response. -function xmlrpc_request($url, $method, $params=array(), $plus=XMLRPC_PLUS, $gzip=0) { - global $xmlrpc_response_headers, $xmlrpc_error; - - #-- init whole lib for request (we are not-OO here) - $xmlrpc_error = false; - $xmlrpc_response_headers = array(); - - #-- encapsulate req, transmit it - $socket = xmlrpc_request_send($url, $method, $params, $plus, $gzip); - if (!$socket) { - return xmlrpc_error(-32768, "no connection", 0, "GLOBALVARS"); - } - - #-- wait for, read response - $response = ""; - while (!feof($socket) && (strlen($DATA) <= 768<<10)) { - $response .= fread($socket, 4<<10); - } - fclose($socket); - if (XMLRPC_DEBUG >= 3) { - echo "$response"; - } - - #-- decode answer and give results - return xmlrpc_response_decode($response); -} - - -#-- an alias -function xmlrpc_call($url, $method, $params=array(), $plus=XMLRPC_PLUS, $gzip=0) { - return xmlrpc_request($url, $method, $params, $plus, $gzip); -} - - - -#-- marshall request parameters into array, hash, xml string -function xmlrpc_request_send($url, $method, &$params, $plus, $gzip, $blocking=true) { - - #-- get connection data - $c = parse_url($url); - ($host = $c["host"]); - ($port = @$c["port"]) or ($port = 80); - ($path = $c["path"]) or ($path = "/"); - if (strpos($c["scheme"], "+")) { - $plus++; - } - if (strpos($c["scheme"], "gzip")) { - $gzip++; - } - if (!$host) { return(NULL); } - $inj = ""; - if ($str = $c["user"]) { - if ($c["pass"]) { $str .= ":" . $c["pass"]; } - $inj = "Authorization: Basic " . base64_encode($str) . "\n"; - } - - #-- mk request HTTP+XML block from params - $request = xmlrpc_request_marshall($method, $params); - $request = xmlrpc_request_http($request, $path, $host, $plus, $gzip, $inj); - - #-- connect, send request - if ($socket = fsockopen($host, $port, $io_err, $io_err_s, 30)) { - socket_set_blocking($socket, $blocking); - socket_set_timeout($socket, 17, 555); - } - else { - echo "Could not connect to '$host:$port$path' - error $io_err: $io_err_s.
      \n"; - return(NULL); - } - fputs($socket, $request); - - #-- done here - return($socket); -} - - -#-- marshall function call into XML+HTTP string -function xmlrpc_request_marshall($method, &$params) { - - #-- use xmlrpc-epi - if (XMLRPC_FAST && XMLRPC_EPI) { - $query = xmlrpc_encode_request($method, $params); - return($query); - } - - #-- build query - $query = array( - "methodCall" => array( - "methodName" => array( ",0"=>$method ), - "params" => array() - ) - ); - foreach ($params as $i=>$p) { - $query["methodCall"]["params"]["param,$i"] = xmlrpc_compact_value($p); - } - $query = array2xml($query, 1, 'encoding="'.XMLRPC_CHARSET.'" '); - - #-- encode? - if (XMLRPC_AUTO_UTF8) { - $query = utf8_encode($query); - } - - return($query); -} - - -#-- enclose body into HTTP request string -function xmlrpc_request_http(&$query, $path, $host, $plus, $gzip, $inj_header="") { - - #-- build request - $n = "\015\012"; - $request = "POST $path HTTP/1.0$n" - . "Host: $host$n" - . ($inj_header ? str_replace("\n", $n, $inj_header) : "") - . "User-Agent: " . XMLRPC_UA . "$n" - . "Accept: ".XMLRPC_ACCEPT."$n" - . (!XMLRPC_DEBUG ? "Accept-Encoding: deflate$n" : "") - . "Content-Type: ".($plus ? XMLRPC_MIME_NEW : XMLRPC_MIME_OLD) - ."; charset=".XMLRPC_CHARSET."$n"; - - #-- compress? - if ($gzip) { - $query = gzdeflate($query); - $request .= "Content-Encoding: deflate$n"; - } - $request .= "Content-Length: " . strlen($query) . "$n" . "$n"; - $request .= $query . "$n"; - - return($request); -} - - -#-- unpack response from HTTP and XML representation -function xmlrpc_response_decode(&$response) { - global $xmlrpc_response_headers; - - #-- split into headers and content - $l1 = strpos($response, "\n\n"); - $l2 = strpos($response, "\n\r\n"); - if ($l2 && (!$l1 || ($l2<$l1))) { - $head = substr($response, 0, $l2); - $response = substr($response, $l2+3); - } - else { - $head = substr($response, 0, $l1); - $response = substr($response, $l2+2); - } - - #-- decode headers, decompress body - foreach (explode("\n", $head) as $line) { - $xmlrpc_response_headers[strtolower(trim(strtok($line, ":")))] = trim(strtok("\000")); - } - if ($enc = trim(@$xmlrpc_response_headers["content-encoding"])) { - if (($enc == "gzip") || ($enc == "x-gzip")) { - $response = gzinflate(substr($response, 10, strlen($response)-18)); - } - elseif (($enc == "compress") || ($enc == "x-compress")) { - $response = gzuncompress($response); - } - elseif (($enc == "deflate") || ($enc == "x-deflate")) { - $response = gzinflate($response); - } - } - - $r = xmlrpc_response_unmarshall($response); - if (XMLRPC_DEBUG) {var_dump($r);} - return($r); -} - - -#-- decode XML-RPC from string into array and extract its actual meaning -function xmlrpc_response_unmarshall(&$response) { - global $xmlrpc_response_headers; - - #-- strip encoding - if (XMLRPC_AUTO_UTF8) { - xmlrpc_decode_utf8xml($response, @$xmlrpc_response_headers["content-type"].@$xmlrpc_response_headers["content-charset"]); - } - - if (XMLRPC_DEBUG >= 4) { fwrite(fopen("/tmp/xmlrpc:resp_in_xml","w"), $response); } - - #-- use xmlrpc-epi - if (XMLRPC_FAST && XMLRPC_EPI) { - $r = xmlrpc_decode_request($response, $uu); - xmlrpc_epi_decode_xtypes($r); - if (is_array($r) && (count($r)==2) && isset($r["faultCode"]) && isset($r["faultString"])) { - return xmlrpc_error($r["faultCode"], $r["faultString"], 1, "GLOBALVARS"); - } - else { - return($r); - } - } - - - #-- unmarshall XML - $response = xml2array($response); - - #-- fetch content (one returned element) - if ($r = @$response["methodResponse,0"]["params,0"]["param,0"]["value,0"]) { - $r = xmlrpc_decode_value($r); - return($r); - } - - #-- error cases - # (we should rather return an error object here) - if (($r = @$response["methodResponse,0"]["fault,0"]["value,0"]) && ($r = xmlrpc_decode_value($r))) { - return xmlrpc_error($r["faultCode"], $r["faultString"], 1, "GLOBALVARS"); - } - else { - return xmlrpc_error(-32600, "xml+rpc: invalid response", 0, "GLBLVRS"); - } - return(NULL); -} - - - -#-- Establish a virtual XML+RPC or XML-RPC server connection (a pseudo -# handshake is used to determine supported protocol / extensions). -class xmlrpc_connection { - - #-- init - function xmlrpc_connection($url, $autodiscovery=0) { - global $xmlrpc_response_headers; - $this->server = $url; - $this->plus = 0; - $this->gzip = 0; - - #-- handshake to check supported protocol - $funcs = $this->call("system.getVersion"); - $this->plus = (strpos($xmlrpc_response_headers["accept"], XMLRPC_MIME_NEW) !== false); - $this->gzip = (strpos($xmlrpc_response_headers["accept_encoding"], "deflate") !== false); - - #-- auto-discovery, create 'method' names - if ($funcs && (XMLRPC_AUTODISCOVERY || $autodiscovery)) { - foreach ($funcs as $fn) { - $short = $fn; - if ($l = strpos($fn, ".")) { - $short = substr($fn, $l + 1); - if (substr($fn, 0, $l) == "system") { continue; } - } - $this->short = create_function("", "return xmlrpc_request('{$this->server}','$fn',func_get_args(),{$this->plus},{$this->gzip});"); - } - } - } - - #-- generical call (needs func name) - function call($method /*, ... */) { - $params = func_get_args(); - shift($params); - $r = xmlrpc_request($this->serverm, $method, $params, $this->plus, $this->gzip); - return($r); - } -} - -#-- an alias -class xmlrpc extends xmlrpc_connection { -} - - - - -############################################################################ -# # -# server implementation # -# # -############################################################################ - - -#-- Check request and execute function if registered in $xmlrpc_methods[] -# array. -function xmlrpc_server() { - - global $xmlrpc_methods; - - #-- server is active - define("XMLRPC_SERVER", getmypid()); - if (XMLRPC_DEBUG) { error_reporting(E_ALL^E_NOTICE); } - ob_start(); - - #-- standard reply headers - header("Accept: ".XMLRPC_MIME_NEW.", ".XMLRPC_MIME_OLD."; q=0.5"); - header("Accept-Encoding: deflate"); - header("X-Server: " . XMLRPC_UA); - header("Connection: close"); - header("Cache-Control: private"); - - #-- fixes for PHP/Apache - if (function_exists("getallheaders")) { - foreach (getallheaders() as $i=>$v) { - $_SERVER[strtoupper(strtr("HTTP_$i", "-", "_"))] = $v; - } - } - - #-- check and get call - $allowed = array( - "REQUEST_METHOD" => array("POST", "PUT", "CALL"), - "CONTENT_TYPE" => array(XMLRPC_MIME_NEW, XMLRPC_MIME_OLD), - ); - foreach ($allowed as $WHAT=>$WHICH) { - if (!in_array(trim(strtok($WRONG=$_SERVER[$WHAT], ";,(")), $WHICH)) { - header("Status: 400 Go Away, Stupid!"); - if (!$WRONG) { - $WRONG = "undefined"; - } - die("

      Error

      Your request was bogus, $WHAT must be " - . implode(" or ", $WHICH) . ", but yours was '$WRONG'.\n"); - } - } - if (!($xml_request = xmlrpc_fetch_post_chunk())) { - header("Status: 500 How Sad"); - die("

      Error

      Could not fetch POST data.\n"); - } - - #-- decipher incoming XML request string - $method = ""; - if (XMLRPC_FAST && XMLRPC_EPI) { - $params = xmlrpc_decode_request($xml_request, $method); - xmlrpc_epi_decode_xtypes($params); - } - else { - $params = xmlrpc_request_unmarshall($xml_request, $method); - } - - - #-- add the few system.methods() - //if (empty($xmlrpc_methods)) { - // $xmlrpc_methods = get_defined_functions(); - //} - $xmlrpc_methods["system"] = "xmlrpc_system_methods"; # a class - - #-- call - $result = xmlrpc_exec_method($method, $params); - - #-- send back result - if (isset($result)) { - if (isset($result)) { - $resp["methodResponse"]["params"]["param"] = xmlrpc_compact_value($result); - } - else { - $resp["methodResponse"]["params"] = array(); - } - - xmlrpc_send_response($resp); - } - else { - $result = xmlrpc_error(0, "No Result"); - xmlrpc_send_response($result); - } -} - - - -#-- decode XML string into understandable chunks, -# gives $params as return value and $method name via pass-by-ref -function xmlrpc_request_unmarshall(&$xml_request, &$method) { - - #-- mangle charset - if (XMLRPC_AUTO_UTF8) { - xmlrpc_decode_utf8xml($xml_request, $_SERVER["CONTENT_TYPE"].$_SERVER["HTTP_CONTENT_CHARSET"]); - } - - #-- decode XML string into PHP arrays - $call = xml2array($xml_request, 1); - $xml_request = NULL; - - $call = $call["methodCall,0"]; - if (!$call) { - xmlrpc_send_response(xmlrpc_error(-32600, "Bad Request, missing")); - } - $method = $call["methodName,0"][",0"]; - if (!$method) { - xmlrpc_send_response(xmlrpc_error(-32600, "Bad Request, missing")); - } - - $params = array(); - foreach ($call["params,1"] as $uu => $param) { - $params[] = xmlrpc_decode_value($param["value,0"]); - } - - return($params); -} - - - -#-- Call the requested method (using the XML-method to PHP-function mapping -# table and hints). -function xmlrpc_exec_method($method, $params) { - - global $xmlrpc_methods; - if (XMLRPC_DEBUG >= 2) { error_reporting(E_ALL^E_NOTICE); } - - #-- check if allowed call - $rf = strtr($method, ".", "_"); - $cl = strtok($method, "."); - if (!$xmlrpc_methods[$method] && !$xmlrpc_methods[$cl] - && !in_array($method, $xmlrpc_methods) - && !in_array($rf, $xmlrpc_methods) && !in_array($cl, $xmlrpc_methods) ) - { - xmlrpc_send_response(xmlrpc_error(-32601)); - } - - #-- real function call - if ($php_func_name = $xmlrpc_methods[$method]) { - $rf = $method = $php_func_name; - } - if (function_exists($rf)) { - $result = call_user_func_array($rf, $params); - if (XMLRPC_DEBUG >= 4) { fwrite(fopen("/tmp/xmlrpc:func_call_res","w"),serialize(array($rf,$result,$params))); } - return($result); - } - #-- PHP object method calls - else { - $class = strtok($method, "."); - $method = strtok("\000"); - if ($uu = $xmlrpc_methods[$class]) { - $class = $uu; - } - if ($class && class_exists($class) && $method) { - $obj = new $class; - if (method_exists($obj, $method)) { - $result = call_user_method_array($method, $obj, $params); // - return($result); - } - } - } - - #-- else error - xmlrpc_send_response(xmlrpc_error(-32601)); -} - - - -#-- Get POST data from PHP (if it gives it to us). -function xmlrpc_fetch_post_chunk() { - global $HTTP_RAW_POST_DATA; - - $data = false; - if ($f = fopen("php://input", "rb")) { - $data = fread($f, 0x0100000); - fclose($f); - } - if (empty($data)) { - ini_set("always_populate_raw_post_data", "true"); // well, maybe(!?) - $data = $HTTP_RAW_POST_DATA; - $HTTP_RAW_POST_DATA = ""; - } - $enc = trim(strtolower($_SERVER["HTTP_CONTENT_ENCODING"])); - $funcs = array("deflate"=>"gzinflate", "gzip"=>"gzdecode", "compress"=>"gzuncompress", "x-gzip"=>"gzdecode", "x-bzip2"=>"bzuncompress"); - if ($enc && ($pf = $funcs[$enc]) && function_exists($pf)) { - $data = $pf($data); - } - return($data); -} - - -#-- converts UTF-8 documents into Latin-1 ones -function xmlrpc_decode_utf8xml(&$xml, $ct) { - if (strpos(strtolower($ct), "utf-8") or preg_match('/<\?xml[^>]+encoding=["\']utf-8/i', $xml)) { - $xml = utf8_decode($xml); - $xml = preg_replace('/(<\?xml[^>]+encoding=["\'])utf-8(["\'])/i', '$1iso-8859-1$2', $xml, 1); - } -} - - - -#-- Creates an error object. -function xmlrpc_error($no=-32500, $str="", $type=1, $into_vars=0) { - global $xmlrpc_error, $xmlrpc_errorcode; - $errors = array( - 0 => "No Result", - -32300 => "Transport error", - -32400 => "Internal Server Error", - -32500 => "Application error", - -32600 => "Invalid message format / Bad request", - -32601 => "Method does not exist", - -32602 => "Parameter type mismatch", - -32603 => "Internal XML-RPC error", - -32604 => "Too many parameters", - -32700 => "Not well-formed XML", - -32701 => "Unsupported encoding - only ISO-8859-1 and UTF-8 capable", - -32702 => "Invalid characters, encoding mismatch", - ); - #-- build response xml/array - if (!($str) && !($str = $errors[$no])) { - $str = "Unknown Error"; - } - if ($into_vars && !XMLRPC_OO) { - $xmlrpc_error = $str; - $xmlrpc_errorcode = $no; - return(NULL); - } - else { - return new xmlrpc_error($no, $str, $type); - } -} - - -#-- error object -class xmlrpc_error { - - var $type = 1; // else an HTTP error - var $no; - var $str; - - function xmlrpc_error($no, $str, $type=1) { - $this->type = $type; - $this->no = $no; - $this->str = $str; - } - - function send() { - $error = xmlrpc_compact_value(array( - "faultCode" => $no, - "faultString" => $str, - )); - $resp = array( - "methodResponse" => array( - "fault" => $error - ) - ); - xmlrpc_send_response($resp); - } -} - - -#-- Sends a response. -function xmlrpc_send_response($r) { - - #-- error objects send itself (by calling _send_response() again ;-) - if (is_object($r)) { - $r->send(); - } - - #-- answer XML-RPC and XML+RPC requests - $ct = trim(strtok(strtolower($_SERVER["CONTENT_TYPE"]), ";,(")); // from original request - $cs = XMLRPC_CHARSET; - header("Content-Type: $ct; charset=\"$cs\""); - - #-- make XML document from it - if (is_array($r)) { - $r = array2xml($r, 1, 'encoding="'.$cs.'" '); - } - - #-- compress answer? - if (!headers_sent()) { - $enc = trim(strtolower($_SERVER["HTTP_ACCEPT_ENCODING"])); - $funcs = array("deflate"=>"gzdeflate", "gzip"=>"gzencode", "compress"=>"gzcompress", "x-gzip"=>"gzencode", "x-bzip2"=>"bzcompress"); - if ($enc && ($pf = $funcs[$enc]) && function_exists($pf)) { - header("Content-Encoding: $enc"); - $r = $pf($r); - } - } - - #-- send - if (ob_get_level()) { - #-- this prevents that PHP errors appear as garbage in our response - $add .= ""; - ob_end_clean(); - } - header("Content-Length: " . strlen($r)); - print $r . $add; - die; -} - - - -#-- Provides "system.*" method namespace. -class xmlrpc_system_methods { - - function listMethods() { - global $xmlrpc_methods; - $r = array(); - foreach ($xmlrpc_methods as $i=>$i2) { - $real = is_int($i) ? $i2 : $i; - if (class_exists($real) && ($i2=$real) || class_exists($i2)) { - foreach (get_class_methods($i2) as $add) { - $r[] = $real.".".$add; - } - } - else { - $r[] = $real; - } - } - return($r); - } - - function time() { - return new xmlrpc_datetime(time()); - } -} - - -############################################################################ -# # -# misc functions # -# # -############################################################################ - - -function xmlrpc_log($message) { -} - -function xmlrpc_die($error="", $str="") { -} - - - -############################################################################ -# # -# data representation mangling # -# # -############################################################################ - - -#-- Makes compact-array2xml datavar from a PHP variable. -function xmlrpc_compact_value($var, $n=0) { - - #-- create compact-array2xml tree - $root = array( - "value,$n" => array(), - ); - $r = &$root["value,$n"]; - - #-- detect PHP values to be complex types in XML-RPC - if (XMLRPC_AUTO_TYPES && is_string($var)) { - if ((strlen($var) >= 64) && preg_match('/^[\w]+=*$/', $var)) { - $var = new xmlrpc_base64($var); - } - elseif ((strlen($var)==17) && ($var[8]=="T") && preg_match('/^\d{8}T\d\d:\d\d:\d\d$/', $var)) { - $var = new xmlrpc_datetime($var); - } - } - - #-- complex types - if (is_object($var)) { - $r = $var->out(); - } - #-- arrays and hashes(structs) - elseif (is_array($var)) { - if (isset($var[0]) || empty($var)) { - $r = array("array,$n" => array("data,0" => array())); - $r = &$r["array,$n"]["data,0"]; - foreach ($var as $n=>$val) { - $r = array_merge($r, xmlrpc_compact_value($val, $n)); - } - } - else { - $r = array("struct,$n"=>array()); - $r = &$r["struct,$n"]; - $n = 0; - foreach ($var as $i=>$val) { - $r["member,$n"] = array_merge(array( - "name,0" => array(",0" => "$i"), - ), xmlrpc_compact_value($val, 1)); - $n++; - } - } - } - #-- simple types - elseif (is_bool($var)) { - $r = array( - "boolean,$n" => array(",0" => ($var?1:0)), - ); - } - elseif (is_int($var)) { - $r = array( - "int,$n" => array(",0" => $var), - ); - } - elseif (is_float($var)) { - $r = array( - "double,$n" => array(",0" => $var), - ); - } - elseif (is_string($var)) { - $r = array( - "string,$n" => array(",0" => $var), - ); - } - return($root); -} - - -#-- Makes a PHP array from a compact-xml2array representation. $value must -# always be the xml2array elements _below_ the ["value,0"] or ["data,0"] -# or ["member,N"] entry. -function xmlrpc_decode_value($value) { - $val = NULL; - foreach ($value as $i=>$d) { - - #-- use single (text) content xml2array entry as actual $d var - if (is_array($d) && isset($d[",0"])) { - $d = $d[",0"]; - } - - #-- convert into PHP var based on type - $type = strtok($i, ","); - switch ($type) { - - case "array": - $val = array(); - foreach ($d["data,0"] as $i=>$value) { - $val[] = xmlrpc_decode_value($value); - } - break; - - case "struct": - $val = array(); - foreach ($d as $uu=>$d2) { - if (($in=$d2["name,0"][",0"]) && ($pos2=1) || ($in=$d2["name,1"][",0"]) && ($pos2=0)) { - $val[$in] = xmlrpc_decode_value($d2["value,$pos2"]); - } - } - break; - - case "": # handles also 's' instead - case "0": # of 's' - case "string": - $val = is_array($d) ? "" : (string)$d; - break; - - case "base64": - $val = (XMLRPC_AUTO_TYPES>=2) ? base64_decode($d) : (string)$d; - if ((XMLRPC_AUTO_UTF8 >= 2) && ($uu = utf8_decode($val))) { - $val = $uu; - } - break; - - // case "real": case "float": // neither is allowed - case "double": - $val = (double)$d; - break; - case "i4": - case "int": - $val = (int)$d; - break; - - case "boolean": - $val = (boolean)$d; - break; - - case "dateTime.iso8601": - $val = xmlrpc_strtotime($d); - break; - - default: - if (defined("XMLRPC_SERVER")) { - xmlrpc_send_response(xmlrpc_error(-32600, "Unknown data type '$type'")); - } - else { - echo $xmlrpc_error = "UNKNOWN XML-RPC DATA TYPE '$type'
      \n"; - $xmlrpc_errorcode = -32207; - } -# echo "\n"; -# xmlrpc_log("bad data type '$type' enountered"); - } - } - return($val); -} - - -#-- More complex XML-RPC data types need object representation to -# distinguish them from ordinary string and integer vars. -class xmlrpc_xtype { - var $scalar = ""; - var $xmlrpc_type = "string"; - var $tag = "string"; - function xmlrpc_type($str) { - $this->data = $str; - } - function out() { - return array($this->tag.",0" => array(",0"=>$this->scalar)); - } -} -class xmlrpc_base64 extends xmlrpc_xtype { - function xmlrpc_base64($str) { - $this->tag = "base64"; - $this->xmlrpc_type = "base64"; - if (XMLRPC_AUTO_UTF8 >= 2) { - $str = utf8_encode($str); - } - if (!preg_match("/^[=\w\s]+$/", $str)) { - $this->encode=1; - } - $this->scalar = $str; - } - function out() { - if (isset($this->encode)) { - $this->scalar = chunk_split(base64_encode($this->scalar), 74, "\n"); - } - return xmlrpc_xtype::out(); - } -} -class xmlrpc_datetime extends xmlrpc_xtype { - function xmlrpc_datetime($t) { - $this->tag = "dateTime.iso8601"; - $this->xmlrpc_type = "datetime"; - if (($t > 0) && ($t[8] != "T")) { - $this->timestamp = $t; - $t = xmlrpc_timetostr($t); - } - $this->scalar = $t; - } -} - -#-- Further simplify use of the above ones. -function xmlrpc_base64($string) { - return(new xmlrpc_base64($string)); -} -function xmlrpc_datetime($timestr) { - return(new xmlrpc_datetime($timestr)); -} - - -#-- Deciphers ISO datetime string into UNIX timestamp. -function xmlrpc_strtotime($str) { - $tm = explode(":", substr($str, 9)); - $t = mktime($tm[0], $tm[1], $tm[2], substr($str, 4, 2), substr($str, 6, 2), substr($str, 0, 4)); - return($t); -} -function xmlrpc_timetostr($time) { - return(gmstrftime("%Y%m%dT%T", $time)); -} - - -#-- helping hand for the xmlrpc-epi extension of php -function xmlrpc_epi_decode_xtypes(&$r) { - if (is_object($r) && isset($r->xmlrpc_type)) { - if (isset($r->timestamp)) { - $r = $r->timestamp; - } - else { - $r = $r->scalar; - } - } - elseif (is_array($r)) { - foreach ($r as $i=>$v) { - xmlrpc_epi_decode_xtypes($r[$i]); - } - } -} - - - - -############################################################################ -# # -# simplified XML parser # -# # -############################################################################ - - -#-- Encode the two chars & and < into htmlentities (there is nothing said -# about the possible other entities in the XML-RPC spec). -function xml_entities($str) { - $e = array( - "&" => "&", - "<" => "<", -// ">" => ">", - ); - return(strtr($str, $e)); -} -function xml_decode_entities($str) { - $e = array( - "<" => "<", - ">" => ">", - "'" => "'", - """ => '"', - "&" => "&", - ); - if (strpos($e, "&#") !== false) { - $e = preg_replace('/&#(\d+);/e', 'chr($1)', $e); - $e = preg_replace('/&#x([\da-fA-F]+);/e', 'chr(hexdec("$1"))', $e); - } - return(strtr($str, $e)); -} - - -#-- Can split simplified XML into a PHP array structure. The now used -# 'compact' format will yield tag sub arrays with an "*,0" index and -# just [",0"] for text nodes. -function xml2array($xml, $compact="ALWAYS") { - $r = array(); - if (function_exists("xml_parser_create") && (strlen($xml) >= 512)) { - $r = xml2array_php($xml); - } - else { - xml2array_parse($xml, $r, $compact); - } - return($r); -} - - -#-- Recursively builds an array of the chunks fetched via strtok() from -# the original XML input string. -function xml2array_parse(&$string, &$r, $compact=1) { - $n = 0; - do { - #-- split chunks - $l = strpos($string, "<"); - $p = strpos($string, ">", $l); - $text = $attr=$close = $tag = false; - if ($l === false) { - $text = $string; - $string = false; - } - else { - $tag = strtok(substr($string, $l+1, $p-$l-1), " "); - if ((strncmp($tag, "![CDATA[", 8)==0) && ($p = strpos($string, "]]>", $l))) { - $text = substr($string, $l+9, $p-$l-9); - } - else { - if ($l) { - $text = xml_decode_entities(substr($string, 0, $l)); - } - $attr = strtok("\000"); - $close = $attr && ($attr[strlen($attr)-1]=="/"); - $string = substr($string, $p+1); - } - } - #-- insert text/body content into array - if (trim($text)) { -# if ($compact) { - $r[",$n"] = $text; -# } -# else { -# $r[] = $text; -# } - $n++; - } - #-- recurse for tags - if ($tag && ($tag[0] >= 'A')) { #-- don't read array()); -# $new = &$r[count($r)-1][$tag]; -# } - if (!$close) { - xml2array_parse($string, $new, $compact); - } - $n++; - } - #-- stop if no more tags or content - if (empty($tag) && empty($text) || empty($string)) { - $tag = "/"; - } - } while ($tag[0] != "/"); -} - - -#-- Uses the XML extension of PHP to convert an XML stream into the -# compact array representation. -function xml2array_php(&$xml, $compact=1) { - - $p = xml_parser_create(xml_which_charset($xml)); - xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, false); - xml_parser_set_option($p, XML_OPTION_TARGET_ENCODING, "ISO-8859-1"); - - xml_parse_into_struct($p, $xml, $struct); - - $a = array(); // will hold all tag nodes - $tree = array(&$a); // stack of pointers to last node of any tree level - $in = &$a; // pointer to last created node - - foreach ($struct as $t) { - unset($value); - extract($t); - - $depth = count($tree) - 1; - $in = &$tree[$depth]; - $tag .= "," . count($in); -//echo "#$depth, TAG=\"$tag\", TYP=$type, LEV=$level, VAL=$value\n"; - - switch ($type[1]) { - - #-- OpEN - case "p": - $in[$tag] = array(); - if ($type=="open") { - $tree[] = &$in[$tag]; - } - if (isset($value) && trim($value)) { - $in[$tag][",0"] = $value; - } - break; - - #-- CoMPLETE - case "o": - $in[$tag] = array(); - if (isset($value) && trim($value)) { - $in[$tag][",0"] = $value; - } - break; - - #-- ClOSE - case "l": - array_pop($tree); - break; - - #-- CdATA - usually just whitespace - case "d": - if (isset($value) && trim($value)) { - $in[",".count($in)] = $value; - } - break; - - default: - // case "attribute": - // and anything else we do not want - } - - } - - return($a); -} - - - -function xml_which_charset(&$xml) { - return( strpos(strtok($xml, "\n"), '-8859-1"') ? "iso-8859-1" : "utf-8" ); -} - - - -############################################################################ -# # -# simplified XML creator # -# # -############################################################################ - - -#-- This is the opposite of the above xml2array, and can also work with the -# so called $compact format. -function array2xml($r, $compact=1, $ins="") { - $string = ""; - array2xml_push($string, $r, $compact); - return($string); -} - - -#-- Recursively throws out the XMLified tree generated by the xml2array() -# 'parser' function. -function array2xml_push(&$string, &$r, $compact, $ind=-1) { - $old_ind = ++$ind - 1; - if ($old_ind < 0) { $old_ind = 0; } - foreach ($r as $i=>$d) { - $d = &$r[$i]; - if (is_scalar($d)) { - $string .= xml_entities($d); - } - elseif (is_array($d)) { - if ($compact) { - $i = strtok($i, ","); - } - $ls = str_repeat(" ", $ind); - $string .= "\n$ls<$i>"; - $string .= array2xml_push($string, $d, $compact, $ind); - $ls = str_repeat(" ", $old_ind); - $string .= "\n$ls"; - } - } -} - - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/a_nofollow.meta b/mods/wiki/plugins/linking/a_nofollow.meta deleted file mode 100644 index fd8a0d7f0..000000000 --- a/mods/wiki/plugins/linking/a_nofollow.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -hooks: link_final -type: link -title: all rel=nofollow -priority: deprecated -description: Google's lazy response to link spammers diff --git a/mods/wiki/plugins/linking/a_nofollow.php b/mods/wiki/plugins/linking/a_nofollow.php deleted file mode 100644 index 984f45d26..000000000 --- a/mods/wiki/plugins/linking/a_nofollow.php +++ /dev/null @@ -1,19 +0,0 @@ - prevents additional page rank bonus - for linked pages. This is a countermeasure against link spam. (See - doc/LinkSpammers) - - This is a dumb plugin, because it adds this to ALL links. Use the - "new_nofollow" version which appends this flag only to FRESH links. -*/ - -$ewiki_plugins["link_final"][] = "ewiki_linking_all_urls_nofollow"; - -function ewiki_linking_all_urls_nofollow(&$str, $type, $href, $title, &$states) { - if (strpos($href, "://")) { - $states["xhtml"]["rel"] = "NOFOLLOW"; - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/autolinkext.meta b/mods/wiki/plugins/linking/autolinkext.meta deleted file mode 100644 index 8e4411b67..000000000 --- a/mods/wiki/plugins/linking/autolinkext.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: hypertext -title: AutoLink -description: MeatBall:AutoLink, WikiFeatures:AutoLink -type: R -priority: rare diff --git a/mods/wiki/plugins/linking/autolinking.meta b/mods/wiki/plugins/linking/autolinking.meta deleted file mode 100644 index e1f38edb0..000000000 --- a/mods/wiki/plugins/linking/autolinking.meta +++ /dev/null @@ -1,9 +0,0 @@ -api: ewiki -category: hypertext -title: AutoLinking / GagaParser -description: links single words, if the according pages exist; but needs preparation by admin tool (for speed reasons) -priority: rare -hooks: format_source -type: transform -config: - EWIKI_AUTOLINKING_CACHE="system/tmp/autolinking" diff --git a/mods/wiki/plugins/linking/autolinking.php b/mods/wiki/plugins/linking/autolinking.php deleted file mode 100644 index 61992f14f..000000000 --- a/mods/wiki/plugins/linking/autolinking.php +++ /dev/null @@ -1,115 +0,0 @@ -get()) { - if ((EWIKI_DB_F_TEXT == ($row["flags"] && EWIKI_DB_F_TYPE)) - && !strpos($row["id"], " ") && preg_match('/^.['.EWIKI_CHARS_L.']+$/', $row["id"]) ) - { - $words[] = $row["id"]; - } - } - } -*/ - - -/* - #-- or add your list of words which should automatically get linked as pages - $words = array_merge((array)$words, array( - "start", - "office", - "...", - )); -*/ - - -/* - #-- actually replace these words with square brackets around them - if ($words) { - - if (count($words) >= 50) { - $find_regex = "/\b(\w{3,})\b/e"; - $regex_replace = "(in_array('\\1', \$words) ? '[\\1]' : '\\1')"; - } - else { - $find_regex = "/\b(" . (implode("|", $words)) . ")\b/"; - $regex_replace = "[\\1]"; - } - - $wiki = preg_replace($find_regex, $regex_replace, $wiki); - } -*/ - - - #-- faster(???) simple string functions based replacing; - # (this is not exactly matching, but still better than the above - # regex approach) - if ($words) { - foreach ($words as $word) { - - $max = strlen($wiki); - $l = 0; - while ((($l = strpos($wiki, $word, $l)) !== false) && ($l < $max) ) { - - #-- check if the word stands alone (no letters before or after) - $r = $l + strlen($word); - if ( ($l >= 1) && ($c = ord($wiki[$l-1])) && ($c >= 64) && ($c <= 122) - || ($max>=$r) && ($c = ord($wiki[$r])) && ($c >= 64) && ($c <= 122) ) - { - $l = $r + 3; - continue; - } - - #-- guess if the word is enclosed in square brackets - if ( (($close_sq = strpos($wiki, "]", $l)) === false) - || (($open_sq = strpos($wiki, "[", $l)) !== false) && ($open_sq <= $close_sq) - || (($line_end = strpos($wiki, "\n", $l)) !== false) && ($line_end <= $close_sq)) - { - $wiki = substr($wiki, 0, $l) - . "[$word]" - . substr($wiki, $l + strlen($word)); - } - - $l = $r + 3; // skip, so we won't end up in a loop - } - } - } - - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/deadly_hidden.meta b/mods/wiki/plugins/linking/deadly_hidden.meta deleted file mode 100644 index 5052db369..000000000 --- a/mods/wiki/plugins/linking/deadly_hidden.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -hooks: format_prepare_linking -type: link -title: deadly_hidden -description: links to _HIDDEN pages will appear as QuestionMarkLinks (fake not-existant) -priority: rare diff --git a/mods/wiki/plugins/linking/deadly_hidden.php b/mods/wiki/plugins/linking/deadly_hidden.php deleted file mode 100644 index 422fe085e..000000000 --- a/mods/wiki/plugins/linking/deadly_hidden.php +++ /dev/null @@ -1,18 +0,0 @@ -$v) { - if (is_array($v) && ($v["flags"]&EWIKI_DB_F_HIDDEN) || ($v&EWIKI_DB_F_HIDDEN)) { - $ewiki_links[$id] = 0; - } } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/instanturl_find.meta b/mods/wiki/plugins/linking/instanturl_find.meta deleted file mode 100644 index 083b8d898..000000000 --- a/mods/wiki/plugins/linking/instanturl_find.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -title: InstantFind -description: introduces the [find:..] moniker, which searches for URL abbreviations/names in the interwiki and instanturls pages, falls back to fuzzy page search or Google -priority: rare -hooks: intermap -type: link diff --git a/mods/wiki/plugins/linking/instanturl_find.php b/mods/wiki/plugins/linking/instanturl_find.php deleted file mode 100644 index dfbf3215e..000000000 --- a/mods/wiki/plugins/linking/instanturl_find.php +++ /dev/null @@ -1,41 +0,0 @@ -$url) { - if (strtolower($pn) == $page_i) { - return($url); - } - } - - #-- find a page - $result = ewiki_db::SEARCH("id",$page_i); - while ($row = $result->get()) { - if (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) { - return(ewiki_script("", $row["id"])); - } - } - - #-- Google saves the day! - return("http://www.google.com/search?q=".urlencode($page)); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/instanturls.meta b/mods/wiki/plugins/linking/instanturls.meta deleted file mode 100644 index f994e7e16..000000000 --- a/mods/wiki/plugins/linking/instanturls.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -title: InstantUrls -description: allows naming URLs in a table or definition list on the page
      InstantURLs or -priority: bonus -hooks: format_prepare_linking -type: transform diff --git a/mods/wiki/plugins/linking/instanturls.php b/mods/wiki/plugins/linking/instanturls.php deleted file mode 100644 index eda04259e..000000000 --- a/mods/wiki/plugins/linking/instanturls.php +++ /dev/null @@ -1,72 +0,0 @@ -$is) { - if (!$is) { - - ($url = $ewiki_config["instant"][$id]) - or - ($url = $ewiki_config["interwiki"][$id]) - ; - - #-- use URL if defined - if ($url) { - $ewiki_links[$id] = $url; - } - } } -} - - -function ewiki_get_instanturls() { - global $ewiki_config; - - $ewiki_config["instant"] = array(); - $DL = '[:|]([^:|]+)[:|]([^|]+)'; - - #-- walk through URL definition pages - foreach ($ewiki_config["instant_url_pages"] as $id) { - - #-- fetch content - $data = ewiki_db::GET($id); - if ($data) { - preg_match_all("/^$DL/m", $data["content"], $uu); - if ($uu) { - foreach ($uu[1] as $i=>$name) { - $ewiki_config["instant"][trim($name)] = strtok(trim($uu[2][$i]), " "); - } - } } - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/link_css.meta b/mods/wiki/plugins/linking/link_css.meta deleted file mode 100644 index 600756623..000000000 --- a/mods/wiki/plugins/linking/link_css.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -title: LinkCss -description: adds CSS information for link types -priority: extra -hooks: link_final -type: link diff --git a/mods/wiki/plugins/linking/link_css.php b/mods/wiki/plugins/linking/link_css.php deleted file mode 100644 index 0f20d45ac..000000000 --- a/mods/wiki/plugins/linking/link_css.php +++ /dev/null @@ -1,43 +0,0 @@ - links generated by ewiki_format() - - known classes (always lowercase): - - - ... - - and all others - - and all others -*/ - - - -$ewiki_plugins["link_final"][] = "ewiki_link_css"; - - - -function ewiki_link_css(&$html, $type, $href, $title) { - - if (count($type)) { - - ksort($type); - - $classes = strtolower(implode(" ", $type)); - - if (strpos(">?", $html)) { - $html = str_replace(" \ No newline at end of file diff --git a/mods/wiki/plugins/linking/link_icons.meta b/mods/wiki/plugins/linking/link_icons.meta deleted file mode 100644 index 578da35d9..000000000 --- a/mods/wiki/plugins/linking/link_icons.meta +++ /dev/null @@ -1,12 +0,0 @@ -api: ewiki -category: hypertext -hooks: link_final -type: link -config: - EWIKI_LINK_ICONS_DIR="/icons/" // absolute to www root - EWIKI_LINK_ICONS_LOOKUP_DIR="./icons" // to access the files - EWIKI_LINK_ICONS_LOOKUP_SIZE=1 // use getimagesize() - EWIKI_LINK_ICONS_DEFAULT_SIZE='width="14" height="14"' // fallback -title: LinkIcons -description: this _link_regex_callback() plugin scans for icons in a -priority: bonus diff --git a/mods/wiki/plugins/linking/link_icons.php b/mods/wiki/plugins/linking/link_icons.php deleted file mode 100644 index 222a97750..000000000 --- a/mods/wiki/plugins/linking/link_icons.php +++ /dev/null @@ -1,75 +0,0 @@ - "", - "notfound" => "bomb.png", - "email" => "letter.gif", - "binary" => "disk.jpeg", - "http" => "www", - "mailto" => "letter.gif", - "ftp" => "disk.jpeg", -); - - - -function ewiki_link_icons(&$html, $type, $href, $title) { - - global $ewiki_link_icons; - - ksort($type); - foreach (array_reverse($type) as $probe) { - - if ($probe == "image") { - return; - } - $probe = strtolower($probe); - - $test = array( - $ewiki_link_icons[$probe], - $probe, - $probe.".png", - $probe.".gif", - $probe.".jpeg", - ); - - foreach ($test as $f) { - - if (strlen($f) && file_exists($fn2 = EWIKI_LINK_ICONS_LOOKUP_DIR . "/" . $f)) { - - if (EWIKI_LINK_ICONS_LOOKUP_SIZE && ($uu = @getimagesize($fn2))) { - $img_sizes = $uu[4]; - } - else { - $img_sizes = EWIKI_LINK_ICONS_DEFAULT_SIZE; - } - - $img = '\''; - - $html = strtok($html, ">") . ">" . $img . strtok("\000"); - - return; - } - - } - - } - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/link_target_blank.meta b/mods/wiki/plugins/linking/link_target_blank.meta deleted file mode 100644 index b77cbe339..000000000 --- a/mods/wiki/plugins/linking/link_target_blank.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -title: target=_blank -description: for all external links (user annoyment!!) -hooks: link_final -type: link -priority: deprecated diff --git a/mods/wiki/plugins/linking/link_target_blank.php b/mods/wiki/plugins/linking/link_target_blank.php deleted file mode 100644 index b0f52f841..000000000 --- a/mods/wiki/plugins/linking/link_target_blank.php +++ /dev/null @@ -1,20 +0,0 @@ - for external http:// urls, which will -# make (most) browsers open the links in a new window - - - -$ewiki_plugins["link_final"][] = "ewiki_link_final_target_blank"; - - -function ewiki_link_final_target_blank(&$str, $type, $href, $title) { - - if (is_array($type) && in_array("url", $type)) { - $str = str_replace(' \ No newline at end of file diff --git a/mods/wiki/plugins/linking/linkdatabase.meta b/mods/wiki/plugins/linking/linkdatabase.meta deleted file mode 100644 index 00c2ce9a6..000000000 --- a/mods/wiki/plugins/linking/linkdatabase.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -title: UseMod compatible LinkDataBase -description: is loved by all web spiders -priority: extra -hooks: page, handler -type: page diff --git a/mods/wiki/plugins/linking/linkdatabase.php b/mods/wiki/plugins/linking/linkdatabase.php deleted file mode 100644 index 9f9325811..000000000 --- a/mods/wiki/plugins/linking/linkdatabase.php +++ /dev/null @@ -1,132 +0,0 @@ -). -*/ - - -$ewiki_plugins["page"]["LinkDatabase"] = "ewiki_linkdatabase"; -$ewiki_plugins["handler"][] = "ewiki_linkdatabase"; - - -function ewiki_linkdatabase($id, &$data, $action) { - - if (($_REQUEST["action"]=="links") && ($id=="action=links") && empty($_REQUEST["id"])) { - - $o = array( - "editlink" => 0, - "empty" => 0, - "names" => 1, - "unique" => 1, #012 unimplemented - "sort" => 1, - "exists" => 2, - "url" => 0, #012 - "inter" => 0, #012 - "search" => "", - ); - $o = array_merge($o, $_REQUEST); - - #-- first read in all pages - $res = ewiki_db::GETALL(array("flags", "version", "refs")); - $all = array(); - while ($row = $res->get()) { - if (($row["version"]&EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) { - $refs = trim($row["refs"]); - if (!$o["empty"] && empty($refs)) { - continue; - } - $all[$row["id"]] = $refs; - } - } - - #-- sort - ksort($all); - - #-- output - $out = ""; - foreach ($all as $i=>$refs) { - $refs = explode("\n", $refs); - if ($refs) { - $refs = ewiki_db::FIND($refs); - } - foreach ($refs as $ri=>$rv) { - if ($o["exists"]!= 2) { - if ($rv != $o["exists"]) { - unset($refs[$ri]); - } - } - if ($o["url"] != 1) { - if ($o["url"] XOR strpos($ri, "://")) { - unset($refs[$ri]); - } - } - if ($o["inter"] != 1) { - if ($o["inter"] XOR strpos($ri, ":") && !strpos($ri, "://")) { - unset($refs[$ri]); - } - } - if ($o["search"] && (strpos($ri, $o["search"])===false)) { - unset($refs[$ri]); - } - } - if (!$o["empty"] && empty($refs)) { - continue; - } - if ($o["sort"]) { - asort($refs); - } - $out .= "$i "; - foreach ($refs as $i=>$rv) { - $title = $o[names] ? $i : " "; - if ($rv) { - $out .= " $title"; - } - else { - $out .= " $title"; - if ($o["editlink"]) { - $out .= "?"; - } - } - } - $out .= "\n"; - } - return("\n
      \n\n\n\n$out
      \n"); - } - elseif ($id == "LinkDatabase") { - $url = "url:?"; -# $url = "ErfurtWiki:"; - return ewiki_format(<< -* [{$url}action=links&sort=0] order pages and their links -* [{$url}action=links&exists=0] only links to not existing pages -* [{$url}action=links&exists=1] only existing page links -* [{$url}action=links&url=1] add URLs -* [{$url}action=links&url=2] __only__ URLs -* [{$url}action=links&inter=1] add ~InterWiki:Links -* [{$url}action=links&inter=2] __only__ ~InterWiki:Links -* [{$url}action=links&search=google] apply search pattern to page links - -handy combinations -* [{$url}action=links&inter=1&editlink=1&empty=1&url=1&sort=0&names=1] show all links -* [{$url}action=links&search=sourceforge&url=2] only URL links to sourceforge -* [{$url}action=links&sort=0&exists=0] unsorted missing pages - -Only [{$url}action=links&unique=0] has not been implemented. - -EOT - ); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/linkexcerpts.meta b/mods/wiki/plugins/linking/linkexcerpts.meta deleted file mode 100644 index e4a8510b6..000000000 --- a/mods/wiki/plugins/linking/linkexcerpts.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -title: excerpt tooltips -description: for linked pages -priority: bonus -hooks: handler, link_final -type: intercept diff --git a/mods/wiki/plugins/linking/linkexcerpts.php b/mods/wiki/plugins/linking/linkexcerpts.php deleted file mode 100644 index 6da91ff83..000000000 --- a/mods/wiki/plugins/linking/linkexcerpts.php +++ /dev/null @@ -1,43 +0,0 @@ - page - excerpt. This however slows down rendering a lot (pre-fetching all - associated pages is required) - eventually one could write another - SQL-only version. -*/ - - -$ewiki_plugins["handler"][] = "ewiki_handler_fancy_linkexcerpts"; -$ewiki_plugins["link_final"][] = "ewiki_ahref_fancy_linkexcerpts"; - - -function ewiki_handler_fancy_linkexcerpts($id, &$data, $action) { - global $ewiki_fancy_linkexcerpts; - if ($action == "view") { - $ewiki_fancy_linkexcerpts = array(); - foreach (explode("\n", trim($data["refs"])) as $link) { - $row = ewiki_db::GET($link); - if (($row["flags"] & EWIKI_DB_F_TYPE) == EWIKI_DB_F_TEXT) { - $text = trim(substr($row["content"], 0, 160)); - $text = substr($text, 0, strrpos($text, " ")); - $text = strtr($text, "\t\r\n", " "); - $text = htmlentities($text); - $text = wordwrap($text, 40, " ", 0); - $ewiki_fancy_linkexcerpts[strtolower($link)] = $text; - } - } - - } -} - - -function ewiki_ahref_fancy_linkexcerpts(&$str, &$type, &$href, &$title) { - global $ewiki_fancy_linkexcerpts; - if ($text = $ewiki_fancy_linkexcerpts[strtolower($href)]) { - $str = str_replace(' \ No newline at end of file diff --git a/mods/wiki/plugins/linking/new_nofollow.meta b/mods/wiki/plugins/linking/new_nofollow.meta deleted file mode 100644 index fb47087fd..000000000 --- a/mods/wiki/plugins/linking/new_nofollow.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -hooks: fromat_prepare_linking, link_final -type: link -title: new rel=nofollow -description: sets the rel="NOFOLLOW" attribute only on fresh hyperlinks -priority: rare diff --git a/mods/wiki/plugins/linking/new_nofollow.php b/mods/wiki/plugins/linking/new_nofollow.php deleted file mode 100644 index fa9000e46..000000000 --- a/mods/wiki/plugins/linking/new_nofollow.php +++ /dev/null @@ -1,50 +0,0 @@ - tag, you'll prevent - additional page rank bonus and thus any interest for link spammers to - target your Wiki (see [doc/LinkSpammers]). This plugin is a bit more - clueful in only adding this flag to fresh/new links. - - It looks up the (at least) two weeks older version of a page to make - a decision. That isn't all too slow actually, but you could use the - dumber variant "plugins/linking/a_nofollow" alternatively. -*/ - -$ewiki_plugins["fromat_prepare_linking"][] = "ewiki_prepare_linking_find_old_links"; -$ewiki_plugins["link_final"][] = "ewiki_linking_nofollow_flag_fresh_urls"; - - -#-- searches links from older page version -function ewiki_prepare_linking_find_old_links(&$src) { - global $ewiki_config, $ewiki_id, $ewiki_data; - - #-- prepare - $ewiki_config["old_version_links"] = array(); - $max_time = time() - 2*7 * 24*60*60; - if ($ewiki_data["lastmodified"] <= $max_time) { - return; - } - - #-- search version which is at least two weeks older - $version = $ewiki_data["version"] - 1; - while ($version > 1) { - $data = ewiki_db::GET($ewiki_id, $version-1); - if ($data && ($data["lastmodified"] <= $max_time)) { - break; - } - } - if ($data) { - $ewiki_config["old_version_links"] = explode("\n", trim($data["refs"])); - } -} - - -#-- adds NOFOLLOW attribute to "fresh" urls -function ewiki_linking_nofollow_flag_fresh_urls(&$str, $type, $href, $title, &$states) { - global $ewiki_config; - if (strpos($href, "://") && !in_array($href, $ewiki_config["old_version_links"])) { - $states["xhtml"]["rel"] = "NOFOLLOW , NOPAGERANK , NOCOUNT"; - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/plural.meta b/mods/wiki/plugins/linking/plural.meta deleted file mode 100644 index a401aa452..000000000 --- a/mods/wiki/plugins/linking/plural.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -title: plural -description: initiates a fuzzy page name matching (slow) -priority: bonus -hooks: format_prepare_linking, handler, page -type: intercept diff --git a/mods/wiki/plugins/linking/plural.php b/mods/wiki/plugins/linking/plural.php deleted file mode 100644 index 0dab871a6..000000000 --- a/mods/wiki/plugins/linking/plural.php +++ /dev/null @@ -1,106 +0,0 @@ -$exists) { - - if ($new_id && $exists) { - return($new_id); - } - } - - #-- none found - return(false); -} - - -/* searches for and loads another page, if requested $id not found -*/ -function ewiki_handler_plural(&$id, &$data, &$action) { - - #-- current page not found, but an alternative exists in DB - if (!$data["version"] && ($new_id = ewiki_plural_alternative($id))) { - - #-- restart ewiki - return(ewiki_page($id = $new_id)); - } -} - - -/* fakes existing pages by creating ["page"] plugin entries -*/ -function ewiki_plural_linking_patch(&$src) { - - global $ewiki_links, $ewiki_plugins; - - - #-- search for not-found entries - foreach ($ewiki_links as $missing_id=>$exists) { - - if (!$exists && ewiki_plural_alternative($missing_id)) { - $ewiki_plugins["page"][$missing_id] = "ewiki_page"; - } - - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/selfbacklinks.meta b/mods/wiki/plugins/linking/selfbacklinks.meta deleted file mode 100644 index 9320fcd5c..000000000 --- a/mods/wiki/plugins/linking/selfbacklinks.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -title: SelfBackLink -hooks: format_prepare_linking -type: transform -description: any occourence of the current page name will point to the links/ list instead -priority: bonus diff --git a/mods/wiki/plugins/linking/selfbacklinks.php b/mods/wiki/plugins/linking/selfbacklinks.php deleted file mode 100644 index 4ba8b0613..000000000 --- a/mods/wiki/plugins/linking/selfbacklinks.php +++ /dev/null @@ -1,15 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/linking/selfmetawiki.meta b/mods/wiki/plugins/linking/selfmetawiki.meta deleted file mode 100644 index bccffa8e3..000000000 --- a/mods/wiki/plugins/linking/selfmetawiki.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -title: SelfLink to MetaWiki -hooks: format_prepare_linking -type: transform -description: any SelfLink on the current page will be redirected to MetaWiki: -priority: bonus diff --git a/mods/wiki/plugins/linking/selfmetawiki.php b/mods/wiki/plugins/linking/selfmetawiki.php deleted file mode 100644 index 5080a7fe5..000000000 --- a/mods/wiki/plugins/linking/selfmetawiki.php +++ /dev/null @@ -1,14 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/linking/selfsearch.meta b/mods/wiki/plugins/linking/selfsearch.meta deleted file mode 100644 index a680e94fd..000000000 --- a/mods/wiki/plugins/linking/selfsearch.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -title: SelfSearch -priority: bonus -hooks: format_prepare_linking -type: transform -description: any SelfLink of a page will trigger a PowerSearch diff --git a/mods/wiki/plugins/linking/selfsearch.php b/mods/wiki/plugins/linking/selfsearch.php deleted file mode 100644 index a0e929301..000000000 --- a/mods/wiki/plugins/linking/selfsearch.php +++ /dev/null @@ -1,14 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/linking/shortwiki.meta b/mods/wiki/plugins/linking/shortwiki.meta deleted file mode 100644 index d44fb25e7..000000000 --- a/mods/wiki/plugins/linking/shortwiki.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -hooks: format_source -type: transform -title: ShortWiki -description: adds a markup extension to render "User|Name" -priority: deprecated diff --git a/mods/wiki/plugins/linking/shortwiki.php b/mods/wiki/plugins/linking/shortwiki.php deleted file mode 100644 index 01fe2974b..000000000 --- a/mods/wiki/plugins/linking/shortwiki.php +++ /dev/null @@ -1,24 +0,0 @@ - [Short|ShortLink] -*/ - -$ewiki_plugins["format_source"][] = "ewiki_markup_short_wiki_links"; - -function ewiki_markup_short_wiki_links(&$src) { - - $u = EWIKI_CHARS_U; - $l = EWIKI_CHARS_L; - - $src = "[" . $src; - $src = preg_replace( - "/([\]\n][^\[]*?)([$u]+[$l]+[$u$l]*)\|([$u]+[$l]+[$u$l]*)/ms", - '\1[\2|\2\3]', - $src - ); - $src = substr($src, 1); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/targets.meta b/mods/wiki/plugins/linking/targets.meta deleted file mode 100644 index d757dacc3..000000000 --- a/mods/wiki/plugins/linking/targets.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -hooks: interxhtml -type: link -title: LinkTargets -description: allows to use target: settings in links -priority: bonus diff --git a/mods/wiki/plugins/linking/targets.php b/mods/wiki/plugins/linking/targets.php deleted file mode 100644 index 5017960ca..000000000 --- a/mods/wiki/plugins/linking/targets.php +++ /dev/null @@ -1,38 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/linking/tcn.meta b/mods/wiki/plugins/linking/tcn.meta deleted file mode 100644 index 531320b17..000000000 --- a/mods/wiki/plugins/linking/tcn.meta +++ /dev/null @@ -1,11 +0,0 @@ -api: ewiki -category: hypertext -title: LanguageNegotiation -description: selects the correct page if multiple variants exist (PageName.en, PageName.fr) -priority: bonus -hooks: handler, view_final -type: intercept -config: - EWIKI_DEFAULT_LANG="en" - EWIKI_AUTO_CHOOSE=1 - EWIKI_UP_FORCE_LANG="lang" diff --git a/mods/wiki/plugins/linking/tcn.php b/mods/wiki/plugins/linking/tcn.php deleted file mode 100644 index 07872467b..000000000 --- a/mods/wiki/plugins/linking/tcn.php +++ /dev/null @@ -1,117 +0,0 @@ - "en", - "Spanish" => "es", - "German" => "de", - "Dutch" => "nl", -); - - -$ewiki_plugins["handler"][] = "ewiki_tcn_handler_select_best"; -$ewiki_plugins["view_final"][] = "ewiki_tcn_view_final_add_variants"; - - -function ewiki_tcn_which_variant($id) { - - $langnames = &$GLOBALS["ewiki_config"]["langnames"]; - - $n = strlen($id); - $r = array($id, EWIKI_DEFAULT_LANG); - - if (($id[$n-3] == ".") || ($id[$n-3] == "*")) { - $r = array(substr($id, 0, $n-3), substr($id, $n-2, 2)); - } - else { - foreach ($langnames as $str=>$cd) { - if (substr($id, $n-strlen($str)) == $str) { - $r = array(substr($id, 0, $n-strlen($str)), $cd); - } - } - } - return($r); -} - - -function ewiki_tcn_find_variants($id) { - - list($base_id, $id_lang) = ewiki_tcn_which_variant($id); - $variants = array( - "$id" => "$id_lang", - ); - - $result = ewiki_db::SEARCH("id",$base_id); - while ($result && ($row = $result->get())) { - if (substr($row["id"], 0, strlen($base_id)) == $base_id) { - list($i, $l) = ewiki_tcn_which_variant($row["id"]); - if ($i == $base_id) { - $variants[$row["id"]] = $l; - } - } - } - - return($variants); -} - - -function ewiki_tcn_handler_select_best(&$id, &$data, &$action) { - - global $ewiki_variants, $ewiki_t; - - $ewiki_variants = ewiki_tcn_find_variants($id); - - if ($action == "view") { - if (count($ewiki_variants) >= 2) { - - $wanted_langs = $ewiki_t["languages"]; - if ($force_lang = $_REQUEST[EWIKI_UP_FORCE_LANG]) { - array_unshift($wanted_langs, $force_lang); - } - - foreach ($wanted_langs as $l) { - foreach ($ewiki_variants as $v_id=>$v_l) { - if ($l==$v_l) { - $id = $v_id; - $data = ewiki_db::GET($id); - break 2; - } - } - }#--langs - - } - } - -} - - -function ewiki_tcn_view_final_add_variants(&$o, $id, &$data, &$action) { - - global $ewiki_variants; - - if (count($ewiki_variants) >= 2) { - - $add = ''."\n"; - - $o = $add . $o; - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/titlefix.meta b/mods/wiki/plugins/linking/titlefix.meta deleted file mode 100644 index cac4d8047..000000000 --- a/mods/wiki/plugins/linking/titlefix.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -title: TitleSwapping -description: allows to use wrong [page|title] syntax -priority: deprecated -hooks: link_notfound -type: link diff --git a/mods/wiki/plugins/linking/titlefix.php b/mods/wiki/plugins/linking/titlefix.php deleted file mode 100644 index cb0f509fb..000000000 --- a/mods/wiki/plugins/linking/titlefix.php +++ /dev/null @@ -1,39 +0,0 @@ -' . $title . ''; - $type = array("wikipage", "title-swapped"); - return($str); - } - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/xfn.meta b/mods/wiki/plugins/linking/xfn.meta deleted file mode 100644 index c929d195a..000000000 --- a/mods/wiki/plugins/linking/xfn.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: hypertext -hooks: interxhtml -type: link -title: XFN -description: the [http://gmpg.org/xfn/] XHTML Friends Network spec leverages HTML4 -priority: bonus diff --git a/mods/wiki/plugins/linking/xfn.php b/mods/wiki/plugins/linking/xfn.php deleted file mode 100644 index b7687688e..000000000 --- a/mods/wiki/plugins/linking/xfn.php +++ /dev/null @@ -1,43 +0,0 @@ - - - This plugin allows a few more technical (non-person-related) page meta - link flags, like "unlink" to defend against untruthful backlinks. -*/ - - -$ewiki_config["xhtml_rel"] = array( - "friend", "acquaintance", - "met", - "child", "parent", "sibling", "spouse", - "co-resident", "neighbor", - "co-worker", "colleague", - "muse", "crush", "date", "sweatheart", - #-- not XFN -- - "unlink", // anti-link (against XFN spam) - "near", "contains", "partof", // for things -); - - -$ewiki_plugins["interxhtml"][] = "ewiki_interxhtml_xfn"; - -function ewiki_interxhtml_xfn($prefix, &$page, &$s) { - global $ewiki_config; - - if (in_array($ewiki_config["xhtml_rel"], $prefix)) { - $s["xhtml"]["rel"] = trim($s["xhtml"]["rel"] . " $prefix"); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/linking/zero_pagerank.meta b/mods/wiki/plugins/linking/zero_pagerank.meta deleted file mode 100644 index 2be8126b7..000000000 --- a/mods/wiki/plugins/linking/zero_pagerank.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: hypertext -hooks: link_url -type: link -config: - ZERO_PAGERANK="http://www.google.com/url?sa=D&q=" - EWIKI_PAGE_BANNED="BannedLinks" -title: ZeroPagerank -description: filter all BannedLinks through a page rank killer -priority: rare diff --git a/mods/wiki/plugins/linking/zero_pagerank.php b/mods/wiki/plugins/linking/zero_pagerank.php deleted file mode 100644 index c99506024..000000000 --- a/mods/wiki/plugins/linking/zero_pagerank.php +++ /dev/null @@ -1,61 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/markup/1emphasis.meta b/mods/wiki/plugins/markup/1emphasis.meta deleted file mode 100644 index f98364455..000000000 --- a/mods/wiki/plugins/markup/1emphasis.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: markup -title: OneCharEmphasis -description: allows to use *bold* and /italic/ -priority: rare -hooks: format_source -type: transform diff --git a/mods/wiki/plugins/markup/1emphasis.php b/mods/wiki/plugins/markup/1emphasis.php deleted file mode 100644 index c09cabcae..000000000 --- a/mods/wiki/plugins/markup/1emphasis.php +++ /dev/null @@ -1,15 +0,0 @@ -$1
      ", $src); - $src = preg_replace("/\B\/(\w+)\/\B/", "$1", $src); - $src = preg_replace("/\b\_([a-zA-Z\d\300-\377]+)\_\b/", "$1", $src); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/markup/abbr.meta b/mods/wiki/plugins/markup/abbr.meta deleted file mode 100644 index 08985cf0d..000000000 --- a/mods/wiki/plugins/markup/abbr.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: markup -title: abbreviations -description: are hosted in table or definition lists on dedicated pages, and then become tooltips everywhere else -priority: extra -hooks: format_final, page_final -type: mangle diff --git a/mods/wiki/plugins/markup/abbr.php b/mods/wiki/plugins/markup/abbr.php deleted file mode 100644 index c19ed8ea3..000000000 --- a/mods/wiki/plugins/markup/abbr.php +++ /dev/null @@ -1,49 +0,0 @@ - and tags - on other pages (case-sensitive). -*/ - -$ewiki_config["acronym"][] = "Acronyms"; -$ewiki_config["abbr"][] = "Abbreviations"; - - -$ewiki_plugins["format_final"][] = "ewiki_acronyms"; -//(or even) $ewiki_plugins["page_final"][] = "ewiki_acronyms"; - - -function ewiki_acronyms(&$html) { - - global $ewiki_config; - - foreach (array("acronym", "abbr") as $tag) { - - #-- read in data pages - $list = array(); - foreach ($ewiki_config[$tag] as $id) { - $data = ewiki_db::GET($id); - preg_match_all('/^[|:]\s*(\w+)\s*[|:]\s*(.+?)[|:\s]*$/m', $data["content"], $uu); - foreach ($uu[1] as $i=>$str) { - $list[$str] = htmlentities($uu[2][$i]); - } - } - - #-- add html tags to current page - if ($list && ($search = implode("|", array_keys($list)))) { - $html .= "<"; - $html = preg_replace( - "/($search)([^>]*<)/mse", - "'<$tag title=\"'.\$list['$1'].'\">$1' . stripslashes('$2')", - $html - ); - $html = rtrim($html, "<"); - } - } - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/markup/asciitbl.meta b/mods/wiki/plugins/markup/asciitbl.meta deleted file mode 100644 index 38c2d6a9f..000000000 --- a/mods/wiki/plugins/markup/asciitbl.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: markup -title: AsciiArtTables -description: are rarely used -priority: rare -hooks: format_source -type: transform diff --git a/mods/wiki/plugins/markup/asciitbl.php b/mods/wiki/plugins/markup/asciitbl.php deleted file mode 100644 index ca93ba4e8..000000000 --- a/mods/wiki/plugins/markup/asciitbl.php +++ /dev/null @@ -1,76 +0,0 @@ -$line) { - $add = explode("|", trim($line, "|")); - if (empty($cells)) { - $cells = $add; - } - else { - foreach ($add as $i=>$text) { - if (!trim($text) && ($l+1\s*)+\|/', "|", $str); - return($str); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/markup/bbcode.meta b/mods/wiki/plugins/markup/bbcode.meta deleted file mode 100644 index 77b4e234e..000000000 --- a/mods/wiki/plugins/markup/bbcode.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: markup -title: BBcode -hooks: format_source -type: transform -description: converts the "bulletin board code" to the easier Wiki syntax -priority: deprecated diff --git a/mods/wiki/plugins/markup/bbcode.php b/mods/wiki/plugins/markup/bbcode.php deleted file mode 100644 index 8488e540b..000000000 --- a/mods/wiki/plugins/markup/bbcode.php +++ /dev/null @@ -1,45 +0,0 @@ - '[', - '[/link]' => ']', - '[url]' => '[', - '[/url]' => ']', - '[img]' => '[', - '[/img]' => ']', - '[email]' => '[', - '[/email]' => ']', - '[b]' => '__', - '[/b]' => '__', - '[i]' => "''", - '[/i]' => "''", - '[u]' => "_", - '[/u]' => "_", - '[list' => 'href' - # - WikiLink - # - %Wiki links% - # - {http://include} - - # it is rather slow due to the use of regexs - nevertheless faster - # than sfWiki I think ;-> - - - $ewiki_plugins["format_source"][] = "ewiki_format_source_emulate_sfwiki"; - - -function ewiki_format_source_emulate_sfwiki (&$source) { - - $source = preg_replace('/\{([a-z0-9]+:\/\/[^}\s]+)\}/', - '', $source); - - $source = preg_replace('/<nolink<([^&]+)</nolink>/', - '!$1', $source); - - $source = preg_replace('/%([^%]+)%/', '[$1]', $source); - - $source = preg_replace('/([^\s]+)-->([^\s]+)/', - '[$1|$2]', $source); - -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/markup/smilies.meta b/mods/wiki/plugins/markup/smilies.meta deleted file mode 100644 index 528d49322..000000000 --- a/mods/wiki/plugins/markup/smilies.meta +++ /dev/null @@ -1,10 +0,0 @@ -api: ewiki -category: markup -title: Smilies -description: are automatically replaced with images; you must install the graphic package separately -hooks: format_final -type: transform -config: - SMILIES_DIR="./img/smilies/" - SMILIES_BASE_HREF="/img/smilies/" -priority: rare diff --git a/mods/wiki/plugins/markup/smilies.php b/mods/wiki/plugins/markup/smilies.php deleted file mode 100644 index 8f7d43890..000000000 --- a/mods/wiki/plugins/markup/smilies.php +++ /dev/null @@ -1,106 +0,0 @@ - "cap.gif", -); - - -$ewiki_plugins["format_final"][] = "smilies_format_final"; - -function smilies_format_final(&$html) { - - global $ewiki_config; - - #-- read in directories - static $imgs, $regex; - if (!isset($imgs)) { - $imgs = array(); - $regex = array(); - foreach (smilies_dir(SMILIES_DIR) as $fn) { - #-- check for file name extensions - if (($r = strrpos($fn, ".")) >= 2) { - $id = substr($fn, 0, $r); - if ($r = strrpos($fn, "/")) { - $id = substr($fn, $r+1); - } - $id0 = $id[0]; - - #-- word images - if (($id0>="a") && ($id0<="z") || ($id0>="0") && ($id0<="9")) { - $id = ":$id:"; - } - else { - $id = htmlentities($id); - } - - #-- decoding, encoding - if ((strpos($id, "%")!==false) && ($uu = urldecode($id))) { - $id = $uu; - } - $imgs[$id] = $fn; - $regex[] = preg_quote($id); - } - } - - #-- append default images and aliases - foreach ($ewiki_config["smilies"] as $id=>$fn) { - $imgs[$id] = $fn; - $regex[] = preg_quote($id); - } - - $regex = implode("|", $regex); - } -#print_r($imgs); -#print_r($regex); - - #-- use regex to insert tags - if ($imgs) { - $html = preg_replace( - '/(?!<[^>]*)('.$regex.')/e', - ' - "\""" - ', - $html - ); - } -} - - -function smilies_dir($dir, $prep="") { - $r = array(); - if ($dh = opendir($dir)) { - while ($fn = readdir($dh)) { - if (is_dir("$dir/$fn")) { - if ($fn[0] != ".") { - $r = array_merge($r, smilies_dir("$dir/$fn", "$fn/")); - } - } - else { - $r[] = "$prep$fn"; - } - } - closedir($dh); - } - return($r); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/markup/table_colspan.meta b/mods/wiki/plugins/markup/table_colspan.meta deleted file mode 100644 index ea9b3e3c2..000000000 --- a/mods/wiki/plugins/markup/table_colspan.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: markup -hooks: format_final -type: transform -title: table_colspan -description: table row merging syntax -priority: rare diff --git a/mods/wiki/plugins/markup/table_colspan.php b/mods/wiki/plugins/markup/table_colspan.php deleted file mode 100644 index 4d73cee03..000000000 --- a/mods/wiki/plugins/markup/table_colspan.php +++ /dev/null @@ -1,23 +0,0 @@ -\s*)+ \ No newline at end of file diff --git a/mods/wiki/plugins/markup/table_rowspan.meta b/mods/wiki/plugins/markup/table_rowspan.meta deleted file mode 100644 index 42e8669a5..000000000 --- a/mods/wiki/plugins/markup/table_rowspan.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: markup -title: table rowspan -description: to join table cells -priority: rare -hooks: format_final -type: transform diff --git a/mods/wiki/plugins/markup/table_rowspan.php b/mods/wiki/plugins/markup/table_rowspan.php deleted file mode 100644 index f52dcc306..000000000 --- a/mods/wiki/plugins/markup/table_rowspan.php +++ /dev/null @@ -1,23 +0,0 @@ -\s*)+"', - $html - ); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/markup/tex.meta b/mods/wiki/plugins/markup/tex.meta deleted file mode 100644 index 8a35de60f..000000000 --- a/mods/wiki/plugins/markup/tex.meta +++ /dev/null @@ -1,12 +0,0 @@ -api: ewiki -category: markup -hooks: format_block -type: transform -config: - MIMETEX_BIN="mimetex" - MIMETEX_DIR="/home/www/user28494/htdocs/ewiki/var/mimetex/" - MIMETEX_PATH="/ewiki/var/mimetex/" - MIMETEX_INLINE=0 -title: tex -description: provides ... tags for embedding formulars -priority: bonus diff --git a/mods/wiki/plugins/markup/tex.php b/mods/wiki/plugins/markup/tex.php deleted file mode 100644 index 384c9adfe..000000000 --- a/mods/wiki/plugins/markup/tex.php +++ /dev/null @@ -1,72 +0,0 @@ -... tags which allow you to - integrate formulas into wiki pages, if you have the MimeTeX - package (from John Forkosh) installed. You can get it from - [http://www.forkosh.com/mimetex.html] (source or as binary) - - The original idea and implementation of this plugin was done by - Francois Vanderseypen as you can see at - [http://netron.sourceforge.net/ewiki/netron.php?id=MimeTeX] - - \aleph = \bigsum_{\alpha,\beta}\Bigint_{0}^{\infty}\:\Gamma_{\alpha\beta}(x)\,dx -*/ - -define("MIMETEX_BIN", "mimetex"); - # the actual mimetex utility (on poorly configured UNIX boxes you would - # have to give the full path name here) - -define("MIMETEX_DIR", "/home/www/user28494/htdocs/ewiki/var/mimetex/"); - # where generated images are thrown in (world-writeable!), you could - # use "/tmp" if _INLINE was ok for your users - -define("MIMETEX_PATH", "/ewiki/var/mimetex/"); - # where to access the generated images then (prefix for the URLs) - -define("MIMETEX_INLINE", 0); - # if you'd instead like data: URIs for images (does not work with IE <7) - - -$ewiki_plugins["format_block"]["tex"]= array("mimetex_format_block"); -$ewiki_config["format_block"]["tex"] = array("<tex>", "</tex>", false, 0x0410); - - -function mimetex_format_block(&$str, &$in, &$iii, &$s, $btype) { - $str = mimetex_generate($str); -} - - -/* - calls mimetex to create image or returns link to cached file -*/ -function mimetex_generate($formula) { - - $formula = preg_replace("/[\s]+/", "", $formula); - $filename = md5($formula).".gif"; - $fullname = MIMETEX_DIR."/$filename"; - - $url = false; - if (is_file($fullname)) { - $url = MIMETEX_PATH."/$filename"; - } - else { - $cmd = MIMETEX_BIN . " -e $fullname '" . escapeshellarg($formula) . "'"; - system($cmd, $status); - if (!$status_code) { - $url = MIMETEX_PATH."/$filename"; - } - } - - if ($url) { - if (MIMETEX_INLINE) { - $url = "data:image/gif;base64," . base64_encode(implode("", file($fullname))); - } - return(''.htmlentities($formula).''); - } - else { - return("[MimeTex could not convert formula \"$formula\".]"); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/markup/timestamp.meta b/mods/wiki/plugins/markup/timestamp.meta deleted file mode 100644 index 4b1c65dd6..000000000 --- a/mods/wiki/plugins/markup/timestamp.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: markup -hooks: edit_save -type: intercept -title: timestamp -description: diff --git a/mods/wiki/plugins/markup/timestamp.php b/mods/wiki/plugins/markup/timestamp.php deleted file mode 100644 index 186fcc1e6..000000000 --- a/mods/wiki/plugins/markup/timestamp.php +++ /dev/null @@ -1,31 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/markup/update_format.meta b/mods/wiki/plugins/markup/update_format.meta deleted file mode 100644 index d4e34856c..000000000 --- a/mods/wiki/plugins/markup/update_format.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: markup -hooks: action, edit_form_append -type: action -title: update_format -description: Converts/Fixes misused markup to correct format (meaning of ! for -priority: rare diff --git a/mods/wiki/plugins/markup/update_format.php b/mods/wiki/plugins/markup/update_format.php deleted file mode 100644 index 98f0e13d7..000000000 --- a/mods/wiki/plugins/markup/update_format.php +++ /dev/null @@ -1,44 +0,0 @@ -' . ewiki_t("UPDHEADERFORMAT") . ''); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/markup/usemod.meta b/mods/wiki/plugins/markup/usemod.meta deleted file mode 100644 index 42c6bb737..000000000 --- a/mods/wiki/plugins/markup/usemod.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: markup -title: UseMod -hooks: format_source -type: transform -description: Emulates UseMode like headlines (but others use this too). -priority: rare diff --git a/mods/wiki/plugins/markup/usemod.php b/mods/wiki/plugins/markup/usemod.php deleted file mode 100644 index 9c066f81a..000000000 --- a/mods/wiki/plugins/markup/usemod.php +++ /dev/null @@ -1,46 +0,0 @@ - -*/ - - -$ewiki_plugins["format_source"][] = "ewiki_format_src_usemod_headings"; - - -function ewiki_format_src_usemod_headings(&$src) { - - global $usemod_toc; - - #-- ===Headlines=== - $src = preg_replace('/^(={2,4})([^=].*?)==+\s*$/me', - ' - str_repeat("!", $we = (5 - strlen("\\1")) ) . " " - . (($uu=stripslashes(trim("\\2"))) && ($uu[0]=="#") - ? ($GLOBALS["usemod_toc"][][$we]=$uu=trim(substr($uu, 1))) - . (" #[" . preg_replace("/[^\w]/", "_", $uu) . "]") - : ($uu) - ) - . "\n\n" - ', $src); - - #-- - if (strpos($src, "<toc>")) { - foreach ($usemod_toc as $i=>$d) { - foreach ($d as $num=>$str) { - $toc_str .= str_repeat("*", 4 - $num) . " [.#$str \"$str\"] \n"; - } - } - $src = preg_replace("'<toc>'", $toc_str, $src); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/meta.bin b/mods/wiki/plugins/meta.bin deleted file mode 100644 index 333b0a22e..000000000 --- a/mods/wiki/plugins/meta.bin +++ /dev/null @@ -1,157 +0,0 @@ -a:296:{s:9:".provides";a:302:{s:4:"core";a:1:{i:0;s:4:"core";}s:13:"email_protect";a:1:{i:0;s:13:"email_protect";}s:14:"input_trimming";a:1:{i:0;s:14:"input_trimming";}s:4:"jump";a:1:{i:0;s:4:"jump";}s:6:"notify";a:1:{i:0;s:6:"notify";}s:11:"patchsaving";a:1:{i:0;s:11:"patchsaving";}s:12:"pluginloader";a:1:{i:0;s:12:"pluginloader";}s:6:"spages";a:1:{i:0;s:6:"spages";}s:10:"like_pages";a:1:{i:0;s:10:"like_pages";}s:7:"manpage";a:1:{i:0;s:7:"manpage";}s:3:"raw";a:1:{i:0;s:3:"raw";}s:14:"relatedchanges";a:1:{i:0;s:14:"relatedchanges";}s:3:"rss";a:1:{i:0;s:3:"rss";}s:11:"translation";a:1:{i:0;s:11:"translation";}s:7:"verdiff";a:1:{i:0;s:7:"verdiff";}s:7:"control";a:1:{i:0;s:7:"control";}s:21:"page_searchandreplace";a:1:{i:0;s:21:"page_searchandreplace";}s:16:"page_searchcache";a:1:{i:0;s:16:"page_searchcache";}s:15:"fancy_list_dict";a:1:{i:0;s:15:"fancy_list_dict";}s:12:"listpages_br";a:1:{i:0;s:12:"listpages_br";}s:13:"listpages_tbl";a:1:{i:0;s:13:"listpages_tbl";}s:12:"listpages_ul";a:1:{i:0;s:12:"listpages_ul";}s:14:"title_calendar";a:1:{i:0;s:14:"title_calendar";}s:13:"auth_liveuser";a:1:{i:0;s:13:"auth_liveuser";}s:21:"liveuser_addusers_gui";a:1:{i:0;s:21:"liveuser_addusers_gui";}s:12:"liveuser_aux";a:1:{i:0;s:12:"liveuser_aux";}s:13:"liveuser_conf";a:1:{i:0;s:13:"liveuser_conf";}s:18:"liveuser_perms_gui";a:1:{i:0;s:18:"liveuser_perms_gui";}s:18:"liveuser_prefs_gui";a:1:{i:0;s:18:"liveuser_prefs_gui";}s:19:"liveuser_rights_gui";a:1:{i:0;s:19:"liveuser_rights_gui";}s:14:"liveuser_setup";a:1:{i:0;s:14:"liveuser_setup";}s:20:"liveuser_setup_prefs";a:1:{i:0;s:20:"liveuser_setup_prefs";}s:18:"liveuser_users_gui";a:1:{i:0;s:18:"liveuser_users_gui";}s:13:"perm_liveuser";a:1:{i:0;s:13:"perm_liveuser";}s:13:"pref_liveuser";a:1:{i:0;s:13:"pref_liveuser";}s:19:"session_ip_verifier";a:1:{i:0;s:19:"session_ip_verifier";}s:16:"auth_method_form";a:1:{i:0;s:16:"auth_method_form";}s:11:"auth-method";a:3:{i:0;s:16:"auth_method_form";i:1;s:16:"auth_method_http";i:2;s:14:"password_locks";}s:16:"auth_method_http";a:1:{i:0;s:16:"auth_method_http";}s:13:"auth_perm_old";a:1:{i:0;s:13:"auth_perm_old";}s:14:"auth_perm_ring";a:1:{i:0;s:14:"auth_perm_ring";}s:14:"auth_perm_unix";a:1:{i:0;s:14:"auth_perm_unix";}s:11:"auth_phplib";a:1:{i:0;s:11:"auth_phplib";}s:14:"password_locks";a:1:{i:0;s:14:"password_locks";}s:16:"userdb_anonymous";a:1:{i:0;s:16:"userdb_anonymous";}s:12:"userdb_array";a:1:{i:0;s:12:"userdb_array";}s:10:"userdb_sql";a:1:{i:0;s:10:"userdb_sql";}s:19:"userdb_systempasswd";a:1:{i:0;s:19:"userdb_systempasswd";}s:19:"userdb_userregistry";a:1:{i:0;s:19:"userdb_userregistry";}s:15:"userdb_xprofile";a:1:{i:0;s:15:"userdb_xprofile";}s:10:"users_ldap";a:1:{i:0;s:10:"users_ldap";}s:3:"you";a:1:{i:0;s:3:"you";}s:16:"aedit_authorname";a:1:{i:0;s:16:"aedit_authorname";}s:21:"aedit_deletebutton.js";a:1:{i:0;s:21:"aedit_deletebutton.js";}s:9:"aedit_log";a:1:{i:0;s:9:"aedit_log";}s:15:"aedit_pageimage";a:1:{i:0;s:15:"aedit_pageimage";}s:15:"aedit_templates";a:1:{i:0;s:15:"aedit_templates";}s:9:"backlinks";a:1:{i:0;s:9:"backlinks";}s:4:"blog";a:1:{i:0;s:4:"blog";}s:8:"control2";a:1:{i:0;s:8:"control2";}s:12:"downloadlist";a:1:{i:0;s:12:"downloadlist";}s:15:"fpage_copyright";a:1:{i:0;s:15:"fpage_copyright";}s:10:"fpage_logo";a:1:{i:0;s:10:"fpage_logo";}s:9:"imgappend";a:1:{i:0;s:9:"imgappend";}s:8:"linktree";a:1:{i:0;s:8:"linktree";}s:9:"pagetrail";a:1:{i:0;s:9:"pagetrail";}s:12:"piclogocntrl";a:1:{i:0;s:12:"piclogocntrl";}s:5:"posts";a:1:{i:0;s:5:"posts";}s:8:"subpages";a:1:{i:0;s:8:"subpages";}s:7:"threads";a:1:{i:0;s:7:"threads";}s:3:"toc";a:1:{i:0;s:3:"toc";}s:3:"any";a:1:{i:0;s:3:"any";}s:12:"binary_store";a:1:{i:0;s:12:"binary_store";}s:3:"dba";a:1:{i:0;s:3:"dba";}s:4:"dzf2";a:1:{i:0;s:4:"dzf2";}s:9:"ext_multi";a:1:{i:0;s:9:"ext_multi";}s:11:"ext_subwiki";a:1:{i:0;s:11:"ext_subwiki";}s:10:"fast_files";a:1:{i:0;s:10:"fast_files";}s:10:"flat_files";a:1:{i:0;s:10:"flat_files";}s:5:"mysql";a:1:{i:0;s:5:"mysql";}s:6:"oldapi";a:1:{i:0;s:6:"oldapi";}s:9:"phpwiki13";a:1:{i:0;s:9:"phpwiki13";}s:12:"read_pmwiki1";a:1:{i:0;s:12:"read_pmwiki1";}s:3:"rpc";a:3:{i:0;s:3:"rpc";i:1;s:6:"phprpc";i:2;s:6:"xmlrpc";}s:3:"zip";a:1:{i:0;s:3:"zip";}s:7:"verbose";a:1:{i:0;s:7:"verbose";}s:9:"warn_utf8";a:1:{i:0;s:9:"warn_utf8";}s:6:"xerror";a:1:{i:0;s:6:"xerror";}s:10:"authorname";a:1:{i:0;s:10:"authorname";}s:15:"deletebutton.js";a:1:{i:0;s:15:"deletebutton.js";}s:5:"flags";a:1:{i:0;s:5:"flags";}s:8:"helptext";a:1:{i:0;s:8:"helptext";}s:10:"limitlinks";a:1:{i:0;s:10:"limitlinks";}s:4:"lock";a:1:{i:0;s:4:"lock";}s:3:"log";a:1:{i:0;s:3:"log";}s:5:"minor";a:1:{i:0;s:5:"minor";}s:3:"msg";a:1:{i:0;s:3:"msg";}s:9:"pageimage";a:1:{i:0;s:9:"pageimage";}s:4:"plog";a:1:{i:0;s:4:"plog";}s:16:"requirespassword";a:1:{i:0;s:16:"requirespassword";}s:10:"spam_block";a:1:{i:0;s:10:"spam_block";}s:11:"spam_deface";a:1:{i:0;s:11:"spam_deface";}s:9:"templates";a:1:{i:0;s:9:"templates";}s:6:"upload";a:1:{i:0;s:6:"upload";}s:4:"warn";a:1:{i:0;s:4:"warn";}s:7:"anacron";a:1:{i:0;s:7:"anacron";}s:13:"announcements";a:1:{i:0;s:13:"announcements";}s:14:"appendcomments";a:1:{i:0;s:14:"appendcomments";}s:10:"appendonly";a:1:{i:0;s:10:"appendonly";}s:11:"appendwrite";a:1:{i:0;s:11:"appendwrite";}s:15:"fset_actionurls";a:1:{i:0;s:15:"fset_actionurls";}s:14:"imgfile_naming";a:1:{i:0;s:14:"imgfile_naming";}s:12:"imgresize_gd";a:1:{i:0;s:12:"imgresize_gd";}s:13:"imgresize_gd2";a:1:{i:0;s:13:"imgresize_gd2";}s:16:"imgresize_magick";a:1:{i:0;s:16:"imgresize_magick";}s:8:"pingback";a:1:{i:0;s:8:"pingback";}s:10:"refererlog";a:1:{i:0;s:10:"refererlog";}s:10:"spellcheck";a:1:{i:0;s:10:"spellcheck";}s:11:"spellcheck2";a:1:{i:0;s:11:"spellcheck2";}s:3:"xpi";a:1:{i:0;s:3:"xpi";}s:4:"xpi0";a:1:{i:0;s:4:"xpi0";}s:9:"f_fixhtml";a:1:{i:0;s:9:"f_fixhtml";}s:9:"f_msiepng";a:1:{i:0;s:9:"f_msiepng";}s:6:"f_tidy";a:1:{i:0;s:6:"f_tidy";}s:8:"fun_chef";a:1:{i:0;s:8:"fun_chef";}s:16:"fun_screamomatic";a:1:{i:0;s:16:"fun_screamomatic";}s:14:"fun_upsidedown";a:1:{i:0;s:14:"fun_upsidedown";}s:9:"fun_wella";a:1:{i:0;s:9:"fun_wella";}s:16:"search_highlight";a:1:{i:0;s:16:"search_highlight";}s:8:"editable";a:1:{i:0;s:8:"editable";}s:8:"intermap";a:1:{i:0;s:8:"intermap";}s:11:"intermaptxt";a:1:{i:0;s:11:"intermaptxt";}s:6:"metadb";a:1:{i:0;s:6:"metadb";}s:4:"near";a:1:{i:0;s:4:"near";}s:8:"neighbor";a:1:{i:0;s:8:"neighbor";}s:11:"sisterpages";a:1:{i:0;s:11:"sisterpages";}s:13:"virtualsister";a:1:{i:0;s:13:"virtualsister";}s:7:"walking";a:1:{i:0;s:7:"walking";}s:5:"cache";a:1:{i:0;s:5:"cache";}s:7:"captcha";a:1:{i:0;s:7:"captcha";}s:7:"fakedba";a:1:{i:0;s:7:"fakedba";}s:8:"fakezlib";a:1:{i:0;s:8:"fakezlib";}s:4:"feed";a:1:{i:0;s:4:"feed";}s:9:"feedparse";a:1:{i:0;s:9:"feedparse";}s:10:"rss-parser";a:1:{i:0;s:9:"feedparse";}s:11:"atom-parser";a:1:{i:0;s:9:"feedparse";}s:3:"fix";a:1:{i:0;s:3:"fix";}s:8:"gzdecode";a:1:{i:0;s:8:"gzdecode";}s:4:"http";a:1:{i:0;s:4:"http";}s:12:"http-request";a:1:{i:0;s:4:"http";}s:10:"http_cache";a:1:{i:0;s:10:"http_cache";}s:2:"js";a:1:{i:0;s:2:"js";}s:11:"libxprofile";a:1:{i:0;s:11:"libxprofile";}s:10:"mime_magic";a:1:{i:0;s:10:"mime_magic";}s:7:"minidav";a:1:{i:0;s:7:"minidav";}s:6:"navbar";a:1:{i:0;s:6:"navbar";}s:10:"opensearch";a:1:{i:0;s:10:"opensearch";}s:14:"page_delegator";a:1:{i:0;s:14:"page_delegator";}s:10:"phprequest";a:1:{i:0;s:10:"phprequest";}s:6:"phprpc";a:1:{i:0;s:6:"phprpc";}s:7:"php-rpc";a:1:{i:0;s:6:"phprpc";}s:14:"pluginmetadata";a:1:{i:0;s:14:"pluginmetadata";}s:8:"protmode";a:1:{i:0;s:8:"protmode";}s:14:"save_storevars";a:1:{i:0;s:14:"save_storevars";}s:8:"shutdown";a:1:{i:0;s:8:"shutdown";}s:15:"spamblock_whois";a:1:{i:0;s:15:"spamblock_whois";}s:5:"speed";a:1:{i:0;s:5:"speed";}s:11:"subpagelist";a:1:{i:0;s:11:"subpagelist";}s:4:"sync";a:1:{i:0;s:4:"sync";}s:7:"upgrade";a:1:{i:0;s:7:"upgrade";}s:11:"upgrade-php";a:1:{i:0;s:7:"upgrade";}s:14:"uservars_pages";a:1:{i:0;s:14:"uservars_pages";}s:6:"webdav";a:1:{i:0;s:6:"webdav";}s:7:"wikiapi";a:1:{i:0;s:7:"wikiapi";}s:3:"xml";a:1:{i:0;s:3:"xml";}s:6:"xmlrpc";a:1:{i:0;s:6:"xmlrpc";}s:7:"xml-rpc";a:1:{i:0;s:6:"xmlrpc";}s:10:"a_nofollow";a:1:{i:0;s:10:"a_nofollow";}s:11:"autolinkext";a:1:{i:0;s:11:"autolinkext";}s:11:"autolinking";a:1:{i:0;s:11:"autolinking";}s:13:"deadly_hidden";a:1:{i:0;s:13:"deadly_hidden";}s:15:"instanturl_find";a:1:{i:0;s:15:"instanturl_find";}s:11:"instanturls";a:1:{i:0;s:11:"instanturls";}s:8:"link_css";a:1:{i:0;s:8:"link_css";}s:10:"link_icons";a:1:{i:0;s:10:"link_icons";}s:17:"link_target_blank";a:1:{i:0;s:17:"link_target_blank";}s:12:"linkdatabase";a:1:{i:0;s:12:"linkdatabase";}s:12:"linkexcerpts";a:1:{i:0;s:12:"linkexcerpts";}s:12:"new_nofollow";a:1:{i:0;s:12:"new_nofollow";}s:6:"plural";a:1:{i:0;s:6:"plural";}s:13:"selfbacklinks";a:1:{i:0;s:13:"selfbacklinks";}s:12:"selfmetawiki";a:1:{i:0;s:12:"selfmetawiki";}s:10:"selfsearch";a:1:{i:0;s:10:"selfsearch";}s:9:"shortwiki";a:1:{i:0;s:9:"shortwiki";}s:7:"targets";a:1:{i:0;s:7:"targets";}s:3:"tcn";a:1:{i:0;s:3:"tcn";}s:8:"titlefix";a:1:{i:0;s:8:"titlefix";}s:3:"xfn";a:1:{i:0;s:3:"xfn";}s:13:"zero_pagerank";a:1:{i:0;s:13:"zero_pagerank";}s:9:"1emphasis";a:1:{i:0;s:9:"1emphasis";}s:4:"abbr";a:1:{i:0;s:4:"abbr";}s:8:"asciitbl";a:1:{i:0;s:8:"asciitbl";}s:6:"bbcode";a:1:{i:0;s:6:"bbcode";}s:9:"braceabbr";a:1:{i:0;s:9:"braceabbr";}s:10:"complextbl";a:1:{i:0;s:10:"complextbl";}s:3:"css";a:1:{i:0;s:3:"css";}s:12:"css_singleat";a:1:{i:0;s:12:"css_singleat";}s:15:"definitionlinks";a:1:{i:0;s:15:"definitionlinks";}s:19:"fix_source_mangling";a:1:{i:0;s:19:"fix_source_mangling";}s:9:"footnotes";a:1:{i:0;s:9:"footnotes";}s:9:"htmltable";a:1:{i:0;s:9:"htmltable";}s:4:"miki";a:1:{i:0;s:4:"miki";}s:12:"naturallists";a:1:{i:0;s:12:"naturallists";}s:7:"phpwiki";a:1:{i:0;s:7:"phpwiki";}s:14:"rendering_null";a:1:{i:0;s:14:"rendering_null";}s:10:"rescuehtml";a:1:{i:0;s:10:"rescuehtml";}s:6:"sfwiki";a:1:{i:0;s:6:"sfwiki";}s:7:"smilies";a:1:{i:0;s:7:"smilies";}s:13:"table_colspan";a:1:{i:0;s:13:"table_colspan";}s:13:"table_rowspan";a:1:{i:0;s:13:"table_rowspan";}s:3:"tex";a:1:{i:0;s:3:"tex";}s:9:"timestamp";a:1:{i:0;s:9:"timestamp";}s:13:"update_format";a:1:{i:0;s:13:"update_format";}s:6:"usemod";a:1:{i:0;s:6:"usemod";}s:13:"block_chinese";a:1:{i:0;s:13:"block_chinese";}s:17:"builtincategories";a:1:{i:0;s:17:"builtincategories";}s:7:"f_title";a:1:{i:0;s:7:"f_title";}s:4:"meta";a:1:{i:0;s:4:"meta";}s:8:"calendar";a:1:{i:0;s:8:"calendar";}s:15:"collectuserdata";a:1:{i:0;s:15:"collectuserdata";}s:9:"downloads";a:1:{i:0;s:9:"downloads";}s:9:"fset_blog";a:1:{i:0;s:9:"fset_blog";}s:4:"tour";a:1:{i:0;s:4:"tour";}s:12:"uservars_gui";a:1:{i:0;s:12:"uservars_gui";}s:8:"mpi+cdml";a:1:{i:0;s:8:"mpi+cdml";}s:8:"mpi+moin";a:1:{i:0;s:8:"mpi+moin";}s:3:"mpi";a:1:{i:0;s:3:"mpi";}s:14:"mpi_addcomment";a:1:{i:0;s:14:"mpi_addcomment";}s:11:"mpi_addlink";a:1:{i:0;s:11:"mpi_addlink";}s:13:"mpi_backlinks";a:1:{i:0;s:13:"mpi_backlinks";}s:12:"mpi_backtree";a:1:{i:0;s:12:"mpi_backtree";}s:8:"mpi_blog";a:1:{i:0;s:8:"mpi_blog";}s:13:"mpi_bugreport";a:1:{i:0;s:13:"mpi_bugreport";}s:18:"mpi_bugreportstate";a:1:{i:0;s:18:"mpi_bugreportstate";}s:9:"mpi_embed";a:1:{i:0;s:9:"mpi_embed";}s:12:"mpi_fallback";a:1:{i:0;s:12:"mpi_fallback";}s:14:"mpi_farinclude";a:1:{i:0;s:14:"mpi_farinclude";}s:12:"mpi_honeypot";a:1:{i:0;s:12:"mpi_honeypot";}s:15:"mpi_inlineframe";a:1:{i:0;s:15:"mpi_inlineframe";}s:10:"mpi_insert";a:1:{i:0;s:10:"mpi_insert";}s:16:"mpi_localsitemap";a:1:{i:0;s:16:"mpi_localsitemap";}s:14:"mpi_multimedia";a:1:{i:0;s:14:"mpi_multimedia";}s:11:"mpi_phpwiki";a:1:{i:0;s:11:"mpi_phpwiki";}s:17:"mpi_redirectlinks";a:1:{i:0;s:17:"mpi_redirectlinks";}s:16:"mpi_registerspam";a:1:{i:0;s:16:"mpi_registerspam";}s:16:"mpi_removedlinks";a:1:{i:0;s:16:"mpi_removedlinks";}s:12:"mpi_settitle";a:1:{i:0;s:12:"mpi_settitle";}s:15:"mpi_sparsetable";a:1:{i:0;s:15:"mpi_sparsetable";}s:10:"mpi_survey";a:1:{i:0;s:10:"mpi_survey";}s:13:"mpi_syndicate";a:1:{i:0;s:13:"mpi_syndicate";}s:15:"mpi_tableeditor";a:1:{i:0;s:15:"mpi_tableeditor";}s:14:"mpi_wikiscript";a:1:{i:0;s:14:"mpi_wikiscript";}s:5:"alias";a:1:{i:0;s:5:"alias";}s:11:"markup_code";a:1:{i:0;s:11:"markup_code";}s:11:"markup_html";a:1:{i:0;s:11:"markup_html";}s:17:"markup_paragraphs";a:1:{i:0;s:17:"markup_paragraphs";}s:6:"README";a:1:{i:0;s:6:"README";}s:12:"aboutplugins";a:1:{i:0;s:12:"aboutplugins";}s:10:"addnewpage";a:1:{i:0;s:10:"addnewpage";}s:13:"createnewpage";a:1:{i:0;s:13:"createnewpage";}s:8:"ewikilog";a:1:{i:0;s:8:"ewikilog";}s:10:"extractall";a:1:{i:0;s:10:"extractall";}s:7:"fortune";a:1:{i:0;s:7:"fortune";}s:10:"hitcounter";a:1:{i:0;s:10:"hitcounter";}s:12:"imagegallery";a:1:{i:0;s:12:"imagegallery";}s:12:"interwikimap";a:1:{i:0;s:12:"interwikimap";}s:8:"minidump";a:1:{i:0;s:8:"minidump";}s:13:"orphanedpages";a:1:{i:0;s:13:"orphanedpages";}s:9:"pageindex";a:1:{i:0;s:9:"pageindex";}s:7:"phpinfo";a:1:{i:0;s:7:"phpinfo";}s:11:"powersearch";a:1:{i:0;s:11:"powersearch";}s:10:"randompage";a:1:{i:0;s:10:"randompage";}s:13:"recentchanges";a:1:{i:0;s:13:"recentchanges";}s:8:"scandisk";a:1:{i:0;s:8:"scandisk";}s:13:"since_updates";a:1:{i:0;s:13:"since_updates";}s:7:"sitemap";a:1:{i:0;s:7:"sitemap";}s:10:"textupload";a:1:{i:0;s:10:"textupload";}s:11:"wantedpages";a:1:{i:0;s:11:"wantedpages";}s:8:"weekdiff";a:1:{i:0;s:8:"weekdiff";}s:8:"wikidump";a:1:{i:0;s:8:"wikidump";}s:9:"wikidump2";a:1:{i:0;s:9:"wikidump2";}s:8:"wikinews";a:1:{i:0;s:8:"wikinews";}s:13:"wikiuserlogin";a:1:{i:0;s:13:"wikiuserlogin";}s:9:"wordindex";a:1:{i:0;s:9:"wordindex";}s:15:"antibot_captcha";a:1:{i:0;s:15:"antibot_captcha";}s:16:"antibot_checkbox";a:1:{i:0;s:16:"antibot_checkbox";}s:13:"antibot_delay";a:1:{i:0;s:13:"antibot_delay";}s:11:"cookieusers";a:1:{i:0;s:11:"cookieusers";}s:9:"watchonly";a:1:{i:0;s:9:"watchonly";}s:10:"arrowadmin";a:1:{i:0;s:10:"arrowadmin";}s:6:"dbpref";a:1:{i:0;s:6:"dbpref";}s:11:"sessionpref";a:1:{i:0;s:11:"sessionpref";}}s:4:"core";a:12:{s:3:"api";s:3:"PHP";s:4:"type";s:3:"api";s:8:"priority";s:4:"core";s:4:"sort";s:3:"100";s:8:"category";s:7:"library";s:5:"title";s:17:"ewiki core script";s:11:"description";s:37:"basic functionality provided by ewiki";s:2:"fn";s:9:"ewiki.php";s:6:"config";s:1032:" - EWIKI_SCRIPT=?id= // all links are constructed with this path prefix - EWIKI_NAME=UnnamedWiki // name of your wiki - EWIKI_PAGE_INDEX=FrontPage // how is the start/default page called - EWIKI_DEFAULT_LANG=en // purely informational - EWIKI_SPLIT_TITLE=0 // inject spaces between parts of WikiWords - EWIKI_PRINT_TITLE=2 // when to display linked headlines - EWIKI_LIST_LIMIT=20 // page lists and searches - EWIKI_CONTROL_LINE=1 // always have action links at bottom of page - EWIKI_ALLOW_HTML=0 // often leads to quirky pages - EWIKI_HTTP_HEADERS=0 // send search engine and user-friendly HTTP headers - EWIKI_NO_CACHE=1 // prevent any caching of pages - EWIKI_AUTO_EDIT=1 // immediately display edit screen if page doesn't exist - EWIKI_EDIT_REDIRECT=1 // quick redirection after edit+save prevents back button problems - EWIKI_CASE_INSENSITIVE=1 // c-i WikiLinks are often more user-friendly - EWIKI_HIT_COUNTING=1 // count visitors for each page - EWIKI_RESOLVE_DNS=1 // disable for faster saving";s:4:"note";s:61:" - This file serves as link to the core script. - Don't care.";s:5:"hooks";s:285:"database, edit_preview, render, init, init, handler, handler, view_append, view_final, page_final, page_final, edit_form_final, format_block, format_block, format_block, format_block, format_block, page, page, page, page, page, page, action, action_always, action, action, page, action";s:5:"funcs";s:1299:"ewiki_enlarge, ewiki_page, gettext, ewiki_http_headers, ewiki_etag, ewiki_page_css_container, ewiki_split_title, ewiki_add_title, ewiki_make_title, ewiki_page_view, ewiki_id, ewiki_script, ewiki_script_binary, ewiki_script_url, ewiki_page_links, ewiki_get_backlinks, ewiki_get_links, ewiki_list_pages, ewiki_page_index, ewiki_page_ordered_list, ewiki_page_newest, ewiki_page_updates, ewiki_page_hits, ewiki_page_versions, ewiki_page_search, ewiki_page_info, ewiki_chunked_page, ewiki_page_edit, ewiki_data_update, ewiki_new_data, ewiki_page_edit_form, ewiki_page_edit_form_final_imgupload, ewiki_page_edit_preview, ewiki_control_links, ewiki_control_links_list, ewiki_format, ewiki_format_close_para, ewiki_format_close_tags, ewiki_format_pre, ewiki_format_html, ewiki_format_comment, ewiki_scan_wikiwords, ewiki_render_wiki_links, ewiki_merge_links, ewiki_link_regex_callback, ewiki_link_img, ewiki_stripentities, ewiki_interwiki, ewiki_intermap_walking, ewiki_link, ewiki_binary, ewiki_binary_save_image, ewiki_localization, ewiki_t, ewiki_lowercase, ewiki_log, ewiki_die, ewiki_array_hash, ewiki_in_array, ewiki_array, ewiki_author, ewiki_author_html, ewiki_auth, ewiki_auth_user, ewiki_form, ewiki_eventually_initialize, dbquery_result, ewiki_dbquery_result, ewiki_database, ewiki_database_mysql";}s:13:"email_protect";a:11:{s:3:"api";s:5:"ewiki";s:4:"type";s:4:"page";s:5:"hooks";s:37:"page, link_url, edit_hook, page_final";s:5:"funcs";s:189:"ewiki_email_protect_enctext, ewiki_email_protect_link, ewiki_email_protect_edit_hook, ewiki_email_protect_form, ewiki_email_protect_encode, str_rot17, ewiki_email_protect_feedbots, nat_rand";s:4:"page";s:14:"ProtectedEmail";s:8:"category";s:7:"feature";s:5:"title";s:22:"ProtectedEmailAdresses";s:11:"description";s:54:"hides email addresses with intermediate formular pages";s:6:"config";s:120:" - EWIKI_PAGE_EMAIL=ProtectedEmail // page name - EWIKI_EMAILPROT_UNLOCK=1|0 // unlock protection, once human verified";s:8:"priority";s:9:"important";s:2:"fn";s:25:"plugins/email_protect.php";}s:14:"input_trimming";a:10:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"intercept";s:5:"hooks";s:4:"init";s:5:"funcs";s:75:"ewiki_input_truncate, ewiki_check_input, ewiki_reset_key, ewiki_set_globals";s:5:"title";s:13:"InputTrimming";s:11:"description";s:67:"secures HTTP input by truncation and unsetting of unknown variables";s:6:"author";s:16:"Jeffrey Engleman";s:8:"category";s:7:"feature";s:8:"priority";s:11:"recommended";s:2:"fn";s:26:"plugins/input_trimming.php";}s:4:"jump";a:9:{s:3:"api";s:5:"ewiki";s:5:"hooks";s:7:"handler";s:4:"type";s:9:"intercept";s:5:"funcs";s:18:"ewiki_handler_jump";s:5:"title";s:11:"PageJumping";s:11:"description";s:24:"page redirection feature";s:8:"priority";s:8:"standard";s:8:"category";s:7:"feature";s:2:"fn";s:16:"plugins/jump.php";}s:6:"notify";a:9:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"transform";s:5:"hooks";s:24:"edit_hook, format_source";s:5:"funcs";s:70:"ewiki_notify_edit_hook, ewiki_notify_links, ewiki_format_remove_notify";s:5:"title";s:13:"Notifications";s:11:"description";s:73:"the invisible markup [notify:you@there.net] will trigger mails on editing";s:8:"priority";s:8:"standard";s:8:"category";s:7:"feature";s:2:"fn";s:18:"plugins/notify.php";}s:11:"patchsaving";a:9:{s:5:"hooks";s:10:"edit_patch";s:4:"type";s:10:"edit_patch";s:5:"funcs";s:16:"ewiki_edit_patch";s:3:"api";s:5:"ewiki";s:5:"title";s:11:"PatchSaving";s:11:"description";s:63:"tries to merge concurrent edits with the 'patch' system utility";s:8:"priority";s:11:"recommended";s:8:"category";s:7:"feature";s:2:"fn";s:23:"plugins/patchsaving.php";}s:12:"pluginloader";a:9:{s:3:"api";s:5:"ewiki";s:4:"type";s:4:"page";s:5:"hooks";s:27:"dl, dl, view_init, page, dl";s:5:"funcs";s:27:"ewiki_dynamic_plugin_loader";s:5:"title";s:14:"PluginLoader-1";s:11:"description";s:65:"loads action and page plugins dynamically using pre-compiled list";s:8:"priority";s:4:"rare";s:8:"category";s:7:"feature";s:2:"fn";s:24:"plugins/pluginloader.php";}s:6:"spages";a:10:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"intercept";s:5:"hooks";s:4:"page";s:5:"funcs";s:30:"ewiki_spage, ewiki_init_spages";s:8:"category";s:7:"feature";s:8:"priority";s:8:"standard";s:5:"title";s:11:"StaticPages";s:11:"description";s:59:"provides virtual pages from static files or dynamic scripts";s:6:"config";s:139:" - EWIKI_SPAGES_DIR="./spages/" // directory with files or plugins - EWIKI_SPAGES_BIN=0|1 // allow serving static files as binary entries";s:2:"fn";s:18:"plugins/spages.php";}s:10:"like_pages";a:8:{s:3:"api";s:5:"ewiki";s:4:"type";s:6:"action";s:8:"category";s:6:"action";s:5:"title";s:9:"LikePages";s:11:"description";s:38:"shows up a list of similar named pages";s:8:"priority";s:8:"standard";s:5:"hooks";s:6:"action";s:2:"fn";s:29:"plugins/action/like_pages.php";}s:7:"manpage";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"action";s:5:"hooks";s:6:"action";s:4:"type";s:6:"action";s:5:"title";s:7:"ManPage";s:11:"description";s:48:"converts page into man(1) document (nroff/troff)";s:8:"priority";s:4:"rare";s:2:"fn";s:26:"plugins/action/manpage.php";}s:3:"raw";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"action";s:5:"title";s:9:"RawSource";s:11:"description";s:58:"allows to download the 'source code' of a page (text/wiki)";s:8:"priority";s:5:"bonus";s:5:"hooks";s:6:"action";s:4:"type";s:6:"action";s:2:"fn";s:22:"plugins/action/raw.php";}s:14:"relatedchanges";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"action";s:5:"hooks";s:13:"action_always";s:4:"type";s:6:"action";s:5:"title";s:14:"RelatedChanges";s:11:"description";s:60:"relchanges/WikiPage will look for changed pages in backlinks";s:8:"priority";s:5:"extra";s:2:"fn";s:33:"plugins/action/relatedchanges.php";}s:3:"rss";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"action";s:5:"hooks";s:12:"action, page";s:4:"type";s:4:"page";s:5:"title";s:8:"RSS/Atom";s:11:"description";s:70:"provides a RSS/Atom feed for individual pages (w/ content-negotiation)";s:8:"priority";s:8:"optional";s:2:"fn";s:22:"plugins/action/rss.php";}s:11:"translation";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"action";s:5:"title";s:20:"AutomaticTranslation";s:11:"description";s:65:"checks text language and provides a BabelFish or GoogleTrans link";s:8:"priority";s:5:"extra";s:5:"hooks";s:7:"handler";s:4:"type";s:9:"intercept";s:2:"fn";s:30:"plugins/action/translation.php";}s:7:"verdiff";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"action";s:8:"priority";s:5:"bonus";s:5:"hooks";s:6:"action";s:4:"type";s:6:"action";s:5:"title";s:12:"DiffVersions";s:11:"description";s:36:"allows to diff any two page versions";s:2:"fn";s:26:"plugins/action/verdiff.php";}s:7:"control";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"admin";s:5:"hooks";s:6:"action";s:4:"type";s:6:"action";s:5:"title";s:7:"control";s:11:"description";s:57:"provides easy to access administration functions per page";s:8:"priority";s:10:"deprecated";s:2:"fn";s:25:"plugins/admin/control.php";}s:21:"page_searchandreplace";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"admin";s:5:"hooks";s:4:"page";s:4:"type";s:4:"page";s:4:"page";s:16:"SearchAndReplace";s:5:"title";s:16:"SearchAndReplace";s:11:"description";s:49:"allows text search and replacing across all pages";s:8:"priority";s:5:"bonus";s:2:"fn";s:39:"plugins/admin/page_searchandreplace.php";}s:16:"page_searchcache";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"admin";s:5:"hooks";s:4:"page";s:4:"type";s:4:"page";s:5:"title";s:20:"generate SearchCache";s:11:"description";s:62:"generates fake text database entries for static/internal pages";s:8:"priority";s:10:"deprecated";s:2:"fn";s:34:"plugins/admin/page_searchcache.php";}s:15:"fancy_list_dict";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:10:"appearance";s:5:"title";s:29:"fancy dictionary-like listing";s:11:"description";s:27:"for PageIndex and WordIndex";s:8:"priority";s:8:"optional";s:5:"hooks";s:9:"list_dict";s:4:"type";s:7:"listing";s:2:"fn";s:38:"plugins/appearance/fancy_list_dict.php";}s:12:"listpages_br";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:10:"appearance";s:5:"title";s:15:"page
      -lists";s:5:"hooks";s:10:"list_pages";s:4:"type";s:7:"listing";s:11:"description";s:32:"prints out
      -separated lists";s:8:"priority";s:5:"extra";s:2:"fn";s:35:"plugins/appearance/listpages_br.php";}s:13:"listpages_tbl";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:10:"appearance";s:5:"title";s:21:"page lists in ";s:5:"hooks";s:10:"list_pages";s:4:"type";s:7:"listing";s:11:"description";s:56:"prints out page lists in a table (instead of
        -lists)";s:8:"priority";s:4:"rare";s:2:"fn";s:36:"plugins/appearance/listpages_tbl.php";}s:12:"listpages_ul";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:10:"appearance";s:5:"title";s:15:"
          page lists";s:5:"hooks";s:10:"list_pages";s:4:"type";s:7:"listing";s:11:"description";s:61:"traditional page listings use
            for simple unordered lists";s:8:"priority";s:8:"optional";s:2:"fn";s:35:"plugins/appearance/listpages_ul.php";}s:14:"title_calendar";a:8:{s:3:"api";s:5:"ewiki";s:4:"type";s:6:"mangle";s:8:"category";s:10:"appearance";s:5:"title";s:18:"CalendarPageTitles";s:11:"description";s:53:"are made non-numeric, more readable and user-friendly";s:8:"priority";s:5:"extra";s:5:"hooks";s:31:"title_transform, list_transform";s:2:"fn";s:37:"plugins/appearance/title_calendar.php";}s:13:"auth_liveuser";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"title";s:19:"LiveUser (API/Core)";s:9:"copyright";s:42:"Copyright (c) 2003, The Burgiss Group, LLC";s:8:"priority";s:4:"rare";s:4:"type";s:4:"auth";s:11:"description";s:61:"chains the PEAR::LiveUser authentication framework with ewiki";s:2:"fn";s:39:"plugins/auth-liveuser/auth_liveuser.php";}s:21:"liveuser_addusers_gui";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"title";s:21:"liveuser_addusers_gui";s:9:"copyright";s:42:"Copyright (c) 2003, The Burgiss Group, LLC";s:8:"priority";s:4:"auto";s:2:"fn";s:47:"plugins/auth-liveuser/liveuser_addusers_gui.php";}s:12:"liveuser_aux";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"title";s:12:"liveuser_aux";s:9:"copyright";s:42:"Copyright (c) 2003, The Burgiss Group, LLC";s:8:"priority";s:4:"auto";s:2:"fn";s:38:"plugins/auth-liveuser/liveuser_aux.php";}s:13:"liveuser_conf";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"title";s:13:"liveuser_conf";s:9:"copyright";s:42:"Copyright (c) 2003, The Burgiss Group, LLC";s:8:"priority";s:4:"auto";s:2:"fn";s:39:"plugins/auth-liveuser/liveuser_conf.php";}s:18:"liveuser_perms_gui";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"title";s:18:"liveuser_perms_gui";s:9:"copyright";s:42:"Copyright (c) 2003, The Burgiss Group, LLC";s:8:"priority";s:4:"auto";s:2:"fn";s:44:"plugins/auth-liveuser/liveuser_perms_gui.php";}s:18:"liveuser_prefs_gui";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"title";s:18:"liveuser_prefs_gui";s:9:"copyright";s:42:"Copyright (c) 2003, The Burgiss Group, LLC";s:8:"priority";s:4:"auto";s:2:"fn";s:44:"plugins/auth-liveuser/liveuser_prefs_gui.php";}s:19:"liveuser_rights_gui";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"title";s:19:"liveuser_rights_gui";s:9:"copyright";s:42:"Copyright (c) 2003, The Burgiss Group, LLC";s:8:"priority";s:4:"auto";s:2:"fn";s:45:"plugins/auth-liveuser/liveuser_rights_gui.php";}s:14:"liveuser_setup";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"title";s:14:"liveuser_setup";s:9:"copyright";s:42:"Copyright (c) 2003, The Burgiss Group, LLC";s:8:"priority";s:4:"auto";s:2:"fn";s:40:"plugins/auth-liveuser/liveuser_setup.php";}s:20:"liveuser_setup_prefs";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"title";s:20:"liveuser_setup_prefs";s:9:"copyright";s:42:"Copyright (c) 2003, The Burgiss Group, LLC";s:8:"priority";s:4:"auto";s:2:"fn";s:46:"plugins/auth-liveuser/liveuser_setup_prefs.php";}s:18:"liveuser_users_gui";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"title";s:18:"liveuser_users_gui";s:9:"copyright";s:42:"Copyright (c) 2003, The Burgiss Group, LLC";s:8:"priority";s:4:"auto";s:2:"fn";s:44:"plugins/auth-liveuser/liveuser_users_gui.php";}s:13:"perm_liveuser";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"title";s:13:"perm_liveuser";s:9:"copyright";s:42:"Copyright (c) 2003, The Burgiss Group, LLC";s:8:"priority";s:4:"auto";s:2:"fn";s:39:"plugins/auth-liveuser/perm_liveuser.php";}s:13:"pref_liveuser";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"title";s:13:"pref_liveuser";s:9:"copyright";s:42:"Copyright (c) 2003, The Burgiss Group, LLC";s:8:"priority";s:4:"auto";s:2:"fn";s:39:"plugins/auth-liveuser/pref_liveuser.php";}s:19:"session_ip_verifier";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:4:"init";s:4:"type";s:9:"intercept";s:5:"title";s:19:"session_ip_verifier";s:11:"description";s:68:"checks to see if the user's ssl_session_id or ip_address has changed";s:8:"priority";s:4:"auto";s:2:"fn";s:45:"plugins/auth-liveuser/session_ip_verifier.php";}s:16:"auth_method_form";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:10:"auth_query";s:4:"type";s:4:"auth";s:5:"title";s:16:"auth_method_form";s:11:"description";s:97:"provides a login
            and uses cookies - this method works not always binary safe and stateless";s:8:"priority";s:10:"deprecated";s:8:"delivers";s:11:"auth-method";s:2:"fn";s:33:"plugins/auth/auth_method_form.php";}s:16:"auth_method_http";a:10:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:10:"auth_query";s:4:"type";s:4:"auth";s:5:"title";s:16:"auth_method_http";s:11:"description";s:80:"provides authentication/login data via HTTP Basic AUTH (recommended login sheme)";s:9:"conflicts";s:16:"auth_method_form";s:8:"delivers";s:11:"auth-method";s:8:"priority";s:5:"extra";s:2:"fn";s:33:"plugins/auth/auth_method_http.php";}s:13:"auth_perm_old";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:9:"auth_perm";s:4:"type";s:4:"auth";s:6:"config";s:58:" - EWIKI_ALLOW_OVERWRITE=0|1 - EWIKI_EDIT_AUTHENTICATE=0|1";s:5:"title";s:13:"auth_perm_old";s:11:"description";s:66:"this permission system wraps the two older configuration constants";s:8:"priority";s:5:"never";s:2:"fn";s:30:"plugins/auth/auth_perm_old.php";}s:14:"auth_perm_ring";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:9:"auth_perm";s:4:"type";s:4:"auth";s:5:"title";s:14:"auth_perm_ring";s:11:"description";s:70:"maps wiki actions and page names onto the ring level permission scheme";s:8:"priority";s:4:"rare";s:2:"fn";s:31:"plugins/auth/auth_perm_ring.php";}s:14:"auth_perm_unix";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:53:"action_always, auth_perm, edit_form_append, edit_save";s:4:"type";s:4:"auth";s:6:"config";s:248:" - EWIKI_USERDB_SYSTEMGROUPS="system/groups" - EWIKI_PERM_UNIX_UMASK=0000 //access rights to strip for new pages - EWIKI_PERM_UNIX_SHAREHOLDERS=1 //group members may revoke rights - EWIKI_PERM_USERSET_FREE=0 //anybody could set the initial owner";s:5:"title";s:21:"UNIX-like permissions";s:11:"description";s:38:"UNIX filesystem like permission system";s:8:"priority";s:4:"rare";s:2:"fn";s:31:"plugins/auth/auth_perm_unix.php";}s:11:"auth_phplib";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:16:"auth_query, page";s:4:"type";s:4:"auth";s:6:"config";s:56:" - EWIKI_PHPLIB_ALLUSERS_PERM="user" - EWIKI_AUTO_EDIT=0";s:5:"title";s:6:"phplib";s:11:"description";s:27:"phplib authentication logic";s:8:"priority";s:4:"rare";s:2:"fn";s:28:"plugins/auth/auth_phplib.php";}s:14:"password_locks";a:10:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:38:"auth_perm, edit_form_append, edit_save";s:4:"type";s:4:"auth";s:6:"config";s:25:" - EWIKI_PROTECTED_MODE=1";s:5:"title";s:15:"PasswordLocking";s:11:"description";s:39:"individual pages can be password locked";s:8:"delivers";s:11:"auth-method";s:8:"priority";s:4:"rare";s:2:"fn";s:31:"plugins/auth/password_locks.php";}s:16:"userdb_anonymous";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:11:"auth_userdb";s:4:"type";s:4:"auth";s:6:"config";s:119:" - EWIKI_AUTH_ANONYMOUS_RING=2 // permission ring level - EWIKI_AUTH_ANONYMOUS_VERIFY=0 // verify given email address";s:5:"title";s:16:"userdb_anonymous";s:11:"description";s:65:"allows login using name "anonymous" and email address as password";s:8:"priority";s:4:"rare";s:2:"fn";s:33:"plugins/auth/userdb_anonymous.php";}s:12:"userdb_array";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:11:"auth_userdb";s:4:"type";s:4:"auth";s:5:"title";s:12:"userdb_array";s:11:"description";s:58:"user database as array, hand edit it in the plugins source";s:8:"priority";s:4:"rare";s:2:"fn";s:29:"plugins/auth/userdb_array.php";}s:10:"userdb_sql";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:11:"auth_userdb";s:4:"type";s:4:"auth";s:5:"title";s:18:"foreign SQL userdb";s:11:"description";s:59:"reuses an existing SQL database user table from foreign CMS";s:8:"priority";s:4:"rare";s:2:"fn";s:27:"plugins/auth/userdb_sql.php";}s:19:"userdb_systempasswd";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:11:"auth_userdb";s:4:"type";s:4:"auth";s:6:"config";s:44:" - EWIKI_USERDB_SYSTEMPASSWD="system/passwd"";s:5:"title";s:13:"system/passwd";s:11:"description";s:57:"user list is kept on system page (only editable by admin)";s:8:"priority";s:5:"bonus";s:2:"fn";s:36:"plugins/auth/userdb_systempasswd.php";}s:19:"userdb_userregistry";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:17:"auth_userdb, page";s:4:"type";s:4:"page";s:6:"config";s:137:" - EWIKI_PAGE_USERREGISTRY="UserRegistry" - EWIKI_USERDB_USERREGISTRY="system/UserRegistry" - EWIKI_REGISTERED_LEVEL=2 // ordinary users";s:5:"title";s:12:"UserRegistry";s:11:"description";s:39:"people can register themselves as users";s:8:"priority";s:5:"bonus";s:2:"fn";s:36:"plugins/auth/userdb_userregistry.php";}s:15:"userdb_xprofile";a:10:{s:3:"api";s:5:"ewiki";s:4:"type";s:4:"auth";s:8:"category";s:14:"authentication";s:5:"title";s:12:"XUP/XProfile";s:11:"description";s:39:"logins against remote XML User Profiles";s:8:"homepage";s:27:"http://xprofile.berlios.de/";s:7:"depends";s:11:"libxprofile";s:5:"hooks";s:11:"auth_userdb";s:5:"funcs";s:26:"ewiki_auth_userdb_xprofile";s:2:"fn";s:32:"plugins/auth/userdb_xprofile.php";}s:10:"users_ldap";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:11:"auth_userdb";s:4:"type";s:4:"auth";s:6:"config";s:150:" - EWIKI_LDAP_SERVER="ldap.example.com" - EWIKI_LDAP_RDN='cn=$USER,ou=users,dc=example,dc=com' - EWIKI_LDAP_FILTER="" // sn=* ??? - EWIKI_LDAP_RING=2";s:5:"title";s:10:"LDAP users";s:11:"description";s:53:"checks login credentials by connecting to LDAP server";s:8:"priority";s:4:"rare";s:2:"fn";s:27:"plugins/auth/users_ldap.php";}s:3:"you";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:14:"authentication";s:5:"hooks";s:11:"auth_userdb";s:4:"type";s:4:"auth";s:6:"config";s:138:" - YOUR_PASSWORD="*" - YOUR_LEVEL=0 // 0 = superuser - EWIKI_PROTECTED_MODE=1 - EWIKI_AUTH_DEFAULT_RING=3 // 3 = read/view/browse-only";s:5:"title";s:3:"you";s:11:"description";s:66:"makes your whole Wiki readonly and editable only with one password";s:8:"priority";s:4:"rare";s:2:"fn";s:20:"plugins/auth/you.php";}s:16:"aedit_authorname";a:2:{s:4:"type";s:1:"R";s:2:"fn";s:34:"plugins/aview/aedit_authorname.php";}s:21:"aedit_deletebutton.js";a:2:{s:4:"type";s:1:"R";s:2:"fn";s:39:"plugins/aview/aedit_deletebutton.js.php";}s:9:"aedit_log";a:2:{s:4:"type";s:1:"R";s:2:"fn";s:27:"plugins/aview/aedit_log.php";}s:15:"aedit_pageimage";a:2:{s:4:"type";s:1:"R";s:2:"fn";s:33:"plugins/aview/aedit_pageimage.php";}s:15:"aedit_templates";a:2:{s:4:"type";s:1:"R";s:2:"fn";s:33:"plugins/aview/aedit_templates.php";}s:9:"backlinks";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:5:"title";s:9:"BackLinks";s:11:"description";s:38:"appends the list of pages linking back";s:8:"priority";s:4:"rare";s:5:"hooks";s:11:"view_append";s:4:"type";s:6:"mangle";s:2:"fn";s:27:"plugins/aview/backlinks.php";}s:4:"blog";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:5:"hooks";s:11:"view_append";s:4:"type";s:6:"mangle";s:5:"title";s:4:"blog";s:11:"description";s:57:"generates wiki-news style summary of the calendar entries";s:8:"priority";s:5:"bonus";s:2:"fn";s:22:"plugins/aview/blog.php";}s:8:"control2";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:5:"hooks";s:10:"view_final";s:4:"type";s:6:"mangle";s:6:"config";s:45:" - EWIKI_CONTROL_LINE=0 - EWIKI_PRINT_TITLE=1";s:5:"title";s:8:"control2";s:11:"description";s:57:"fancifies (CSS) and moves the control link box to the top";s:8:"priority";s:4:"rare";s:2:"fn";s:26:"plugins/aview/control2.php";}s:12:"downloadlist";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:5:"title";s:9:"downloads";s:11:"description";s:39:"lists downloads for/on individual pages";s:8:"priority";s:5:"bonus";s:5:"hooks";s:11:"view_append";s:4:"type";s:6:"mangle";s:2:"fn";s:30:"plugins/aview/downloadlist.php";}s:15:"fpage_copyright";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:5:"hooks";s:10:"page_final";s:4:"type";s:6:"mangle";s:5:"title";s:15:"fpage_copyright";s:11:"description";s:28:"generates a copyright notice";s:8:"priority";s:5:"bonus";s:2:"fn";s:33:"plugins/aview/fpage_copyright.php";}s:10:"fpage_logo";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:5:"hooks";s:10:"page_final";s:4:"type";s:6:"mangle";s:5:"title";s:10:"fpage_logo";s:11:"description";s:35:"appends an image (logo) to the page";s:6:"author";s:16:"Jeffrey Engleman";s:8:"priority";s:5:"bonus";s:2:"fn";s:28:"plugins/aview/fpage_logo.php";}s:9:"imgappend";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:5:"title";s:15:"image appending";s:11:"description";s:36:"more quickly appends image to a page";s:8:"priority";s:4:"rare";s:5:"hooks";s:19:"view_append, action";s:4:"type";s:6:"action";s:2:"fn";s:27:"plugins/aview/imgappend.php";}s:8:"linktree";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:5:"title";s:8:"LinkTree";s:11:"description";s:39:"shows the paths to the root page (slow)";s:8:"priority";s:4:"rare";s:5:"hooks";s:11:"view_append";s:4:"type";s:6:"mangle";s:6:"config";s:60:" - EWIKI_LINKTREE_UL=0 // else a link::list will be printed";s:2:"fn";s:26:"plugins/aview/linktree.php";}s:9:"pagetrail";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:5:"title";s:11:"page trails";s:11:"description";s:30:"<< Prev | ParentPage | Next >>";s:8:"priority";s:4:"rare";s:5:"hooks";s:11:"view_append";s:4:"type";s:6:"mangle";s:2:"fn";s:27:"plugins/aview/pagetrail.php";}s:12:"piclogocntrl";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:5:"hooks";s:7:"handler";s:4:"type";s:9:"intercept";s:5:"title";s:12:"piclogocntrl";s:11:"description";s:53:"for selection of a page logo graphic (see fpage_logo)";s:6:"author";s:29:"Jeremy Mikola, Andy Fundinger";s:8:"priority";s:4:"rare";s:2:"fn";s:30:"plugins/aview/piclogocntrl.php";}s:5:"posts";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:8:"priority";s:4:"rare";s:5:"hooks";s:40:"view_append, action, handler, view_final";s:4:"type";s:9:"intercept";s:5:"title";s:5:"posts";s:11:"description";s:95:"appends a class of wiki pages to the bottom (sub or sibling pages) - often used for discussions";s:2:"fn";s:23:"plugins/aview/posts.php";}s:8:"subpages";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:5:"title";s:8:"SubPages";s:11:"description";s:42:"subpages have names similar to the current";s:8:"priority";s:4:"rare";s:5:"hooks";s:11:"view_append";s:4:"type";s:6:"mangle";s:2:"fn";s:26:"plugins/aview/subpages.php";}s:7:"threads";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:8:"priority";s:4:"rare";s:5:"hooks";s:19:"view_append, action";s:4:"type";s:6:"action";s:5:"title";s:7:"threads";s:11:"description";s:35:"lists thread pages (see also posts)";s:7:"depends";s:5:"posts";s:2:"fn";s:25:"plugins/aview/threads.php";}s:3:"toc";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:5:"aview";s:5:"title";s:15:"TableOfContents";s:11:"description";s:47:"is generated automatically from pages headlines";s:8:"priority";s:5:"bonus";s:5:"hooks";s:27:"format_source, format_final";s:4:"type";s:9:"transform";s:6:"config";s:22:" - EWIKI_TOC_CAPTION=0";s:2:"fn";s:21:"plugins/aview/toc.php";}s:3:"any";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:8:"database";s:5:"hooks";s:8:"database";s:4:"type";s:8:"database";s:6:"config";s:120:" - EWIKI_DB_UTF8=0 // convert from/to UTF-8 for your database (PG) - EWIKI_DB_BIN64=0 // cipher any _BINARY entry (PG)";s:5:"title";s:5:"anydb";s:11:"description";s:67:"provides a SQL database abstraction layer for PostgreSQL and others";s:8:"priority";s:4:"auto";s:2:"fn";s:18:"plugins/db/any.php";}s:12:"binary_store";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:8:"database";s:5:"hooks";s:24:"binary_store, binary_get";s:4:"type";s:8:"database";s:6:"config";s:243:" - EWIKI_DB_STORE_DIRECTORY="/tmp" // where to save binary files - EWIKI_DB_STORE_MINSIZE=0 // send smaller files into db - EWIKI_DB_STORE_MAXSIZE=32 <<20 // 32MB max per file (but - EWIKI_DB_STORE_URL="http://example.com/wiki/files/store/"";s:5:"title";s:12:"binary_store";s:11:"description";s:72:"intercepts binary handling and stores too large blocks into static files";s:8:"priority";s:4:"auto";s:2:"fn";s:27:"plugins/db/binary_store.php";}s:3:"dba";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:8:"database";s:5:"hooks";s:8:"database";s:4:"type";s:8:"database";s:6:"config";s:179:" - EWIKI_DBA="/tmp/mywiki.flatfile" // or use extension .db2 - EWIKI_DBFILES_GZLEVEL=0 // if you want .inifile format (this is not binary safe - also disable image upload then!)";s:5:"title";s:3:"dba";s:11:"description";s:49:"utilizes PHPs "dba" extension as database backend";s:8:"priority";s:4:"auto";s:2:"fn";s:18:"plugins/db/dba.php";}s:4:"dzf2";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:8:"database";s:5:"hooks";s:8:"database";s:4:"type";s:8:"database";s:6:"config";s:286:" - EWIKI_DBFILES_DIRECTORY="pages/" // like with plugins/db/flat_files - EWIKI_DBFF_ACCURATE=1 // makes FIND call return image sizes - DZF2_HIT_COUNTING=1 // enables hit-counting - EWIKI_CASE_INSENSITIVE=true // this is hard-coded in here, so don't disable or everything would break";s:5:"title";s:4:"dzf2";s:11:"description";s:121:"faster file database with deep directory structure, compression, caching, and it's case-insensitive like the SQL backends";s:8:"priority";s:4:"auto";s:2:"fn";s:19:"plugins/db/dzf2.php";}s:9:"ext_multi";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:8:"database";s:5:"hooks";s:8:"database";s:4:"type";s:8:"database";s:6:"config";s:126:" - EWIKI_MULTIDB_GUESS=0 // which database to use for WRITE calls, if disabled this will always fallback to the first backend";s:5:"title";s:9:"ext_multi";s:11:"description";s:41:"allows to join multiple database backends";s:8:"priority";s:5:"never";s:2:"fn";s:24:"plugins/db/ext_multi.php";}s:11:"ext_subwiki";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:8:"database";s:5:"hooks";s:4:"init";s:4:"type";s:9:"intercept";s:6:"config";s:24:" - SUBWIKI_SEPARATOR=":"";s:5:"title";s:11:"ext_subwiki";s:11:"description";s:90:"fragments your database into multiple wikis without touching the backend (not recommended)";s:8:"priority";s:5:"never";s:2:"fn";s:26:"plugins/db/ext_subwiki.php";}s:10:"fast_files";a:6:{s:7:"depends";s:10:"flat_files";s:8:"priority";s:10:"deprecated";s:4:"type";s:1:"R";s:5:"title";s:9:"FastFiles";s:11:"description";s:38:"(wrapper around real FlatFiles script)";s:2:"fn";s:25:"plugins/db/fast_files.php";}s:10:"flat_files";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:8:"database";s:5:"hooks";s:8:"database";s:4:"type";s:8:"database";s:6:"config";s:48:" - EWIKI_DB_FAST_FILES=0 - EWIKI_DBFF_ACCURATE=0";s:5:"title";s:9:"FlatFiles";s:11:"description";s:123:"this backend uses RFC822-style text files for storing pages, binary-safe, but page names are never case-insensitive on Unix";s:8:"priority";s:4:"auto";s:2:"fn";s:25:"plugins/db/flat_files.php";}s:5:"mysql";a:7:{s:3:"api";s:5:"ewiki";s:4:"type";s:7:"virtual";s:8:"category";s:8:"database";s:8:"priority";s:8:"required";s:5:"title";s:5:"MySQL";s:11:"description";s:25:"built-in database backend";s:6:"config";s:51:" - EWIKI_DB_TABLE_NAME=ewiki // SQL database table";}s:6:"oldapi";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:8:"database";s:5:"title";s:7:"old API";s:11:"description";s:36:"wrapper for old database backend API";s:8:"priority";s:5:"never";s:4:"type";s:9:"functions";s:2:"fn";s:21:"plugins/db/oldapi.php";}s:9:"phpwiki13";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:8:"database";s:5:"hooks";s:8:"database";s:4:"type";s:8:"database";s:6:"config";s:26:" - PHPWIKI13_WRITEACCESS=0";s:5:"title";s:9:"phpwiki13";s:11:"description";s:40:"can access PhpWiki 1.3.x MySQL databases";s:8:"priority";s:5:"never";s:2:"fn";s:24:"plugins/db/phpwiki13.php";}s:12:"read_pmwiki1";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:8:"database";s:5:"hooks";s:8:"database";s:4:"type";s:8:"database";s:6:"config";s:103:" - SUBWIKI_SEPARATOR="." - PMWIKI_DB_DIRS="../pmwiki/wiki.d/:../pmiki/wikilib.d/" - PMWIKI_GROUP="Main"";s:5:"title";s:12:"read_pmwiki1";s:11:"description";s:42:"used for importing PmWikis page data files";s:8:"priority";s:5:"never";s:2:"fn";s:27:"plugins/db/read_pmwiki1.php";}s:3:"rpc";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:8:"database";s:6:"config";s:81:" - EWIKI_DB_LOCK=0 - EWIKI_DB_RPC="http://name:pw@rpc.example.com/ewiki/z-db.php"";s:5:"title";s:7:"PHP-RPC";s:11:"description";s:22:"remote ewiki databases";s:8:"priority";s:5:"never";s:4:"type";s:8:"database";s:2:"fn";s:18:"plugins/db/rpc.php";}s:3:"zip";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:8:"database";s:5:"hooks";s:8:"database";s:4:"type";s:8:"database";s:6:"config";s:35:" - EWIKI_DB_ZIP="/tmp/database.zip"";s:5:"title";s:3:"zip";s:11:"description";s:64:"(fun plugin!) can read and write text pages from/into .zip files";s:8:"priority";s:5:"never";s:2:"fn";s:18:"plugins/db/zip.php";}s:7:"verbose";a:7:{s:3:"api";s:3:"PHP";s:4:"tyep";s:9:"intercept";s:8:"category";s:9:"fragments";s:5:"title";s:7:"verbose";s:11:"description";s:44:"PHP error handler for verbose debug messages";s:8:"priority";s:10:"deprecated";s:4:"type";s:9:"intercept";}s:9:"warn_utf8";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"fragments";s:5:"hooks";s:9:"edit_hook";s:4:"type";s:9:"intercept";s:5:"title";s:9:"warn_utf8";s:11:"description";s:50:"check for UTF-8 in incoming URLs (broken browsers)";s:8:"priority";s:10:"deprecated";s:2:"fn";s:27:"plugins/debug/warn_utf8.php";}s:6:"xerror";a:7:{s:3:"api";s:3:"PHP";s:4:"type";s:9:"intercept";s:8:"category";s:9:"fragments";s:5:"title";s:6:"xerror";s:11:"description";s:79:"sends all detected errors as HTTP headers (and not intermingled with page text)";s:8:"priority";s:10:"deprecated";s:2:"fn";s:24:"plugins/debug/xerror.php";}s:10:"authorname";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:8:"priority";s:5:"extra";s:5:"hooks";s:16:"edit_form_append";s:4:"type";s:5:"input";s:5:"title";s:21:"set AuthorName freely";s:11:"description";s:66:"adds an input box for a free-form author name below the edit/ page";s:2:"fn";s:27:"plugins/edit/authorname.php";}s:15:"deletebutton.js";a:8:{s:3:"api";s:5:"ewiki";s:4:"type";s:5:"input";s:8:"category";s:4:"edit";s:5:"hooks";s:16:"edit_form_append";s:5:"title";s:15:"DeleteBotton.js";s:11:"description";s:66:"appends a "Delete Page" button to the edit/ page (JavaScript only)";s:8:"priority";s:4:"rare";s:2:"fn";s:32:"plugins/edit/deletebutton.js.php";}s:5:"flags";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:5:"hooks";s:27:"edit_form_append, edit_save";s:4:"type";s:5:"input";s:5:"title";s:5:"flags";s:11:"description";s:63:"provides users the ability to set certain page flags on editing";s:8:"priority";s:4:"rare";s:2:"fn";s:22:"plugins/edit/flags.php";}s:8:"helptext";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:5:"hooks";s:9:"edit_hook";s:4:"type";s:6:"mangle";s:5:"title";s:8:"helptext";s:11:"description";s:38:"appends an info text to the edit/ page";s:8:"priority";s:5:"bonus";s:2:"fn";s:25:"plugins/edit/helptext.php";}s:10:"limitlinks";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"spam";s:5:"hooks";s:9:"edit_save";s:4:"type";s:9:"intercept";s:6:"config";s:22:" - EWIKI_LIMIT_LINKS=5";s:5:"title";s:10:"limitlinks";s:11:"description";s:85:"disallows adding more than a certain number of external links to a page (very useful)";s:8:"priority";s:8:"optional";s:2:"fn";s:27:"plugins/edit/limitlinks.php";}s:4:"lock";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:5:"hooks";s:9:"edit_hook";s:4:"type";s:9:"intercept";s:5:"title";s:21:"concurrent edit locks";s:11:"description";s:57:"creates lock files (time out) to prevent concurrent edits";s:8:"priority";s:4:"rare";s:2:"fn";s:21:"plugins/edit/lock.php";}s:3:"log";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:8:"priority";s:5:"extra";s:5:"hooks";s:27:"edit_form_append, edit_save";s:4:"type";s:5:"input";s:5:"title";s:9:"ChangeLog";s:11:"description";s:83:"input to the changelog input box on the edit/ screen will be shown on RecentChanges";s:2:"fn";s:20:"plugins/edit/log.php";}s:5:"minor";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:5:"hooks";s:27:"edit_form_append, edit_save";s:4:"type";s:5:"input";s:5:"title";s:11:"minor edits";s:11:"description";s:34:"provides a [x]-minor-edit checkbox";s:8:"priority";s:10:"deprecated";s:2:"fn";s:22:"plugins/edit/minor.php";}s:3:"msg";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:5:"hooks";s:15:"edit_form_final";s:4:"type";s:6:"mangle";s:5:"title";s:19:"custom edit message";s:11:"description";s:57:"allows customized messages to show up when editing a page";s:8:"priority";s:5:"bonus";s:2:"fn";s:20:"plugins/edit/msg.php";}s:9:"pageimage";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:5:"title";s:9:"pageimage";s:11:"description";s:37:"allows selecting a page image graphic";s:8:"priority";s:4:"rare";s:4:"type";s:5:"input";s:2:"fn";s:26:"plugins/edit/pageimage.php";}s:4:"plog";a:6:{s:3:"api";s:5:"ewiki";s:4:"type";s:1:"R";s:8:"category";s:4:"edit";s:5:"title";s:25:"IntComm:PersonalLogServer";s:11:"description";s:40:"sends notifications to users plog server";s:8:"priority";s:10:"deprecated";}s:16:"requirespassword";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:5:"hooks";s:20:"edit_hook, edit_save";s:4:"type";s:9:"intercept";s:6:"config";s:28:" - EWIKI_ADMIN_PW="password"";s:5:"title";s:16:"requirespassword";s:11:"description";s:58:"lightweight alternative to powering up the _PROTECTED_MODE";s:8:"priority";s:4:"rare";s:2:"fn";s:33:"plugins/edit/requirespassword.php";}s:10:"spam_block";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"spam";s:5:"hooks";s:9:"edit_save";s:4:"type";s:9:"intercept";s:6:"config";s:36:" - EWIKI_PAGE_BLOCKED="BlockedLinks"";s:5:"title";s:12:"BlockedLinks";s:11:"description";s:70:"rejects editing attempts with blocked URL patterns (page BlockedLinks)";s:8:"priority";s:4:"rare";s:2:"fn";s:27:"plugins/edit/spam_block.php";}s:11:"spam_deface";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:5:"hooks";s:9:"edit_save";s:4:"type";s:9:"intercept";s:6:"config";s:86:" - ZERO_PAGERANK="http://www.google.com/url?sa=D&q=" - EWIKI_PAGE_BANNED="BannedLinks"";s:5:"title";s:22:"BannedLinks defacement";s:11:"description";s:61:"defaces all URLs which match patterns from "BannedLinks" page";s:8:"priority";s:4:"rare";s:2:"fn";s:28:"plugins/edit/spam_deface.php";}s:9:"templates";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:8:"priority";s:5:"extra";s:5:"hooks";s:26:"edit_form_final, edit_hook";s:4:"type";s:9:"intercept";s:5:"title";s:9:"templates";s:11:"description";s:82:"on creating a new page, users will be left the choice to load a "...Template" page";s:2:"fn";s:26:"plugins/edit/templates.php";}s:6:"upload";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:5:"title";s:6:"upload";s:11:"description";s:68:"shows an upload-from-file field on empty (non-existant) pages";s:4:"type";s:1:"R";s:8:"priority";s:4:"rare";}s:4:"warn";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"edit";s:5:"hooks";s:15:"edit_form_final";s:4:"type";s:6:"mangle";s:5:"title";s:22:"warn conncurrent edits";s:11:"description";s:45:"shows a warning messages for concurrent edits";s:8:"priority";s:8:"optional";s:2:"fn";s:21:"plugins/edit/warn.php";}s:7:"anacron";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"hooks";s:4:"init";s:4:"type";s:9:"intercept";s:6:"config";s:111:" - EWIKI_ANACRON_INTERLEAVE=2*3600 // in seconds - EWIKI_ANACRON_ID="etc/anacron/last-run" // a _SYSTEM entry";s:5:"title";s:7:"anacron";s:11:"description";s:44:"support code for the tools/cron.d/ utilities";s:8:"priority";s:4:"rare";s:2:"fn";s:27:"plugins/feature/anacron.php";}s:13:"announcements";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"hooks";s:9:"delegator";s:4:"type";s:7:"special";s:5:"title";s:13:"announcements";s:11:"description";s:57:"displays pages from a list rather than the requested page";s:6:"author";s:14:"Andy Fundinger";s:8:"priority";s:4:"rare";s:2:"fn";s:33:"plugins/feature/announcements.php";}s:14:"appendcomments";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"hooks";s:29:"edit_hook, edit_save, handler";s:4:"type";s:9:"intercept";s:6:"config";s:44:" - EWIKI_APPENDONLY_COMMENTSPART="/Comments"";s:5:"title";s:14:"appendcomments";s:11:"description";s:63:"_APPENDONLY flagged pages can only be appended text as comments";s:8:"priority";s:4:"rare";s:2:"fn";s:34:"plugins/feature/appendcomments.php";}s:10:"appendonly";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:8:"priority";s:5:"bonus";s:5:"hooks";s:20:"edit_hook, edit_save";s:4:"type";s:9:"intercept";s:5:"title";s:10:"appendonly";s:11:"description";s:77:"if the _APPENDONLY page flag is set, users can further only append text to it";s:2:"fn";s:30:"plugins/feature/appendonly.php";}s:11:"appendwrite";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"hooks";s:29:"handler, edit_hook, edit_save";s:4:"type";s:9:"intercept";s:6:"config";s:31:" - EWIKI_APPENDWRITE_AUTOLOCK=1";s:5:"title";s:11:"appendwrite";s:11:"description";s:96:"allows full-write access to only a second part/section of an _APPENDONLY+_WRITEABLE flagged page";s:8:"priority";s:4:"rare";s:2:"fn";s:31:"plugins/feature/appendwrite.php";}s:15:"fset_actionurls";a:8:{s:3:"api";s:5:"ewiki";s:4:"type";s:7:"virtual";s:8:"category";s:7:"feature";s:6:"config";s:54:" - EWIKI_ACTION_USE_PARAM=2 - EWIKI_ACTION_TAKE_ASIS=0";s:5:"title";s:15:"fset_actionurls";s:11:"description";s:59:"will default ewiki to use "?WikiPage&action=view" like URLs";s:8:"priority";s:5:"never";s:2:"fn";s:35:"plugins/feature/fset_actionurls.php";}s:14:"imgfile_naming";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"title";s:16:"imagefile naming";s:11:"description";s:38:"beautyfies generated internal:// links";s:8:"priority";s:5:"bonus";s:5:"hooks";s:12:"binary_store";s:4:"type";s:8:"database";s:2:"fn";s:34:"plugins/feature/imgfile_naming.php";}s:12:"imgresize_gd";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"title";s:24:"image resizing PHP libgd";s:11:"description";s:50:"scales images down, when uploaded on the edit page";s:8:"priority";s:7:"default";s:5:"hooks";s:12:"image_resize";s:4:"type";s:9:"intercept";s:6:"config";s:24:" - EWIKI_IMGRESIZE_WIN=0";s:2:"fn";s:32:"plugins/feature/imgresize_gd.php";}s:13:"imgresize_gd2";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"hooks";s:12:"image_resize";s:4:"type";s:9:"intercept";s:6:"config";s:378:" - EWIKI_IMGRESIZE_WIN=0 - EWIKI_IMAGE_MAX_PIXELS=11000000 //11 megapixels - EWIKI_IMAGE_MAXSIZE=65536 - EWIKI_IMAGE_TOLERANCE=60000 //don't settle for smaller than this during resize - EWIKI_WORK_AREA=640 //width of whitespace or work area within ewiki - EWIKI_IMAGE_MAX_Y=1000 //max y value if picture is "candy cane" - EWIKI_IMAGE_RATIO=10 //maximum acceptable y:x ratio";s:5:"title";s:13:"imgresize_gd2";s:11:"description";s:49:"refined algorithm for downscaling uploaded images";s:8:"priority";s:5:"bonus";s:2:"fn";s:33:"plugins/feature/imgresize_gd2.php";}s:16:"imgresize_magick";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"title";s:26:"image resizing ImageMagick";s:11:"description";s:54:"requires an installed ImageMagick binary on the server";s:5:"hooks";s:12:"image_resize";s:4:"type";s:9:"intercept";s:8:"priority";s:4:"rare";s:2:"fn";s:36:"plugins/feature/imgresize_magick.php";}s:8:"pingback";a:11:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"hooks";s:15:"edit_save, init";s:4:"type";s:3:"api";s:5:"title";s:8:"PingBack";s:11:"description";s:61:"accept and send PingBacks automatically (with auto-discovery)";s:8:"priority";s:5:"bonus";s:8:"homepage";s:43:"http://www.hixie.ch/specs/pingback/pingback";s:7:"depends";s:6:"xmlrpc";s:7:"version";s:3:"0.2";s:2:"fn";s:28:"plugins/feature/pingback.php";}s:10:"refererlog";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"hooks";s:20:"view_final, shutdown";s:4:"type";s:6:"mangle";s:6:"config";s:24:" - EWIKI_REFERER_NOISE=2";s:5:"title";s:10:"RefererLog";s:11:"description";s:53:"inserts validated REFERER urls at the bottom of pages";s:8:"priority";s:5:"bonus";s:2:"fn";s:30:"plugins/feature/refererlog.php";}s:10:"spellcheck";a:2:{s:4:"type";s:1:"R";s:2:"fn";s:30:"plugins/feature/spellcheck.php";}s:11:"spellcheck2";a:2:{s:4:"type";s:1:"R";s:2:"fn";s:31:"plugins/feature/spellcheck2.php";}s:3:"xpi";a:10:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"intercept";s:4:"hook";s:4:"init";s:4:"page";s:11:"PlugInstall";s:9:"conflicts";s:4:"xpi0";s:5:"title";s:10:"XPI (full)";s:11:"description";s:58:"easy installation and managment of .xpi (and .jpi) plugins";s:8:"priority";s:5:"bonus";s:8:"category";s:9:"extension";s:2:"fn";s:23:"plugins/feature/xpi.php";}s:4:"xpi0";a:9:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"intercept";s:4:"hook";s:4:"init";s:9:"conflicts";s:3:"xpi";s:5:"title";s:11:"XPI support";s:11:"description";s:28:"without the PlugInstall page";s:8:"priority";s:4:"rare";s:8:"category";s:9:"extension";s:2:"fn";s:24:"plugins/feature/xpi0.php";}s:9:"f_fixhtml";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"filter";s:5:"title";s:14:"fiXhtml filter";s:11:"description";s:106:"tries to work around various formatting errors, and can even try to convince ewiki to generate valid XHTML";s:8:"priority";s:4:"rare";s:5:"hooks";s:10:"page_final";s:4:"type";s:6:"mangle";s:6:"config";s:16:" - EWIKI_XHTML=0";s:2:"fn";s:28:"plugins/filter/f_fixhtml.php";}s:9:"f_msiepng";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"filter";s:5:"title";s:17:"MSIE .png support";s:11:"description";s:58:"instructs IE to use an ActiveX imageloader for .png images";s:5:"hooks";s:10:"view_final";s:4:"type";s:6:"mangle";s:6:"config";s:36:" - FIX_MSIE_NULL_GIF="/img/null.gif"";s:8:"priority";s:10:"deprecated";s:2:"fn";s:28:"plugins/filter/f_msiepng.php";}s:6:"f_tidy";a:3:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"filter";s:5:"title";s:6:"f_tidy";}s:8:"fun_chef";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"filter";s:5:"hooks";s:10:"view_final";s:4:"type";s:6:"mangle";s:5:"title";s:8:"fun_chef";s:11:"description";s:68:"Code modelled after Joes Hess` description of the 'chef' filter from";s:8:"priority";s:5:"never";s:2:"fn";s:27:"plugins/filter/fun_chef.php";}s:16:"fun_screamomatic";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"filter";s:5:"title";s:14:"scream-o-matic";s:11:"description";s:76:"uppercases all pages contents, if a user enters too much uppercase on a page";s:8:"priority";s:5:"never";s:5:"hooks";s:21:"edit_save, page_final";s:4:"type";s:6:"mangle";s:2:"fn";s:35:"plugins/filter/fun_screamomatic.php";}s:14:"fun_upsidedown";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"filter";s:5:"hooks";s:19:"view_final, handler";s:4:"type";s:6:"mangle";s:5:"title";s:14:"fun_upsidedown";s:11:"description";s:43:"ripped from the debian text filters package";s:8:"priority";s:5:"never";s:2:"fn";s:33:"plugins/filter/fun_upsidedown.php";}s:9:"fun_wella";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"filter";s:5:"hooks";s:10:"view_final";s:4:"type";s:6:"mangle";s:5:"title";s:9:"fun_wella";s:11:"description";s:48:"adds some CSS to "beautify" the wiki page output";s:8:"priority";s:5:"never";s:2:"fn";s:28:"plugins/filter/fun_wella.php";}s:16:"search_highlight";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"filter";s:5:"title";s:24:"search term highlighting";s:11:"description";s:106:"encolours the words from a previous search that led to the current page (links from PowerSearch or Google)";s:8:"priority";s:5:"extra";s:5:"hooks";s:10:"page_final";s:4:"type";s:6:"mangle";s:2:"fn";s:35:"plugins/filter/search_highlight.php";}s:8:"editable";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:26:"PublicallyEditableIntermap";s:11:"description";s:52:"eases extension of the InterWiki prefix/moniker list";s:8:"priority";s:5:"bonus";s:5:"hooks";s:10:"init, page";s:4:"type";s:4:"page";s:2:"fn";s:30:"plugins/interwiki/editable.php";}s:8:"intermap";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:8:"InterMap";s:11:"description";s:46:"enlarges the list of knwon InterWiki: monikers";s:8:"priority";s:5:"extra";s:4:"type";s:9:"variables";s:2:"fn";s:30:"plugins/interwiki/intermap.php";}s:11:"intermaptxt";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:11:"intermaptxt";s:11:"description";s:78:"loads InterWiki URLs and monikers from a standard 'intermap.txt' file (slower)";s:8:"priority";s:5:"bonus";s:4:"type";s:4:"data";s:2:"fn";s:33:"plugins/interwiki/intermaptxt.php";}s:6:"metadb";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:6:"config";s:27:" - EWIKI_METADB_FN="metadb"";s:5:"title";s:6:"metadb";s:11:"description";s:55:"utility and access code for NearLinks, SisterPages, ...";s:4:"type";s:9:"functions";s:8:"priority";s:4:"auto";s:2:"fn";s:28:"plugins/interwiki/metadb.php";}s:4:"near";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:22:"format_prepare_linking";s:4:"type";s:4:"link";s:5:"title";s:9:"NearPages";s:11:"description";s:57:"tries to link locally non-existant page in any other Wiki";s:8:"priority";s:5:"bonus";s:2:"fn";s:26:"plugins/interwiki/near.php";}s:8:"neighbor";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:10:"link_final";s:4:"type";s:6:"mangle";s:5:"title";s:13:"NeighborPages";s:11:"description";s:76:"adds additional links behind any page link if it exists on foreign Wikis too";s:8:"priority";s:4:"rare";s:2:"fn";s:30:"plugins/interwiki/neighbor.php";}s:11:"sisterpages";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:10:"page_final";s:4:"type";s:9:"transform";s:6:"config";s:69:" - EWIKI_SISTER_ONLY_NONEXIST=0 // SisterPages only for edit/ screen";s:5:"title";s:11:"SisterPages";s:11:"description";s:70:"prints links to same-named pages on foreign Wikis on top of every page";s:8:"priority";s:5:"bonus";s:2:"fn";s:33:"plugins/interwiki/sisterpages.php";}s:13:"virtualsister";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:7:"handler";s:4:"type";s:9:"intercept";s:5:"title";s:13:"VirtualSister";s:11:"description";s:61:"puts virtual links to SisterPages at the bottom of every page";s:8:"priority";s:4:"rare";s:2:"fn";s:35:"plugins/interwiki/virtualsister.php";}s:7:"walking";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:7:"handler";s:4:"type";s:9:"intercept";s:5:"title";s:7:"walking";s:11:"description";s:57:"provides WikiFeatures:InterMapWalking (already built-in!)";s:8:"priority";s:10:"deprecated";s:2:"fn";s:29:"plugins/interwiki/walking.php";}s:5:"cache";a:10:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"intercept";s:5:"hooks";s:19:"handler, page_final";s:5:"title";s:11:"PageCaching";s:10:"decription";s:39:"keeps a cache of already rendered pages";s:8:"priority";s:5:"extra";s:8:"category";s:10:"optimation";s:6:"config";s:252:" - EWIKI_CACHE_FULL=1|0 // include control-links line in cache - EWIKI_CACHE_ALL=0|1 // cache also virtual pages - EWIKI_CACHE_DIR=./var/cache // preferred over db storage - EWIKI_CACHE_DB=system/cache/ // only has effect, if _DIR undefined";s:11:"description";s:32:"caching of rendered (html) pages";s:2:"fn";s:21:"plugins/lib/cache.php";}s:7:"captcha";a:9:{s:3:"api";s:3:"PHP";s:4:"type";s:9:"functions";s:8:"priority";s:4:"auto";s:5:"title";s:7:"CAPTCHA";s:11:"description";s:67:"provides graphical riddle to get rid of aggressive spambots/spiders";s:7:"version";s:3:"0.8";s:8:"homepage";s:33:"http://freshmeat.net/p/captchaphp";s:8:"category";s:7:"library";s:2:"fn";s:23:"plugins/lib/captcha.php";}s:7:"fakedba";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:7:"library";s:5:"title";s:7:"fakedba";s:11:"description";s:63:"emualtes dba support if PHP supports at least the dbm interface";s:4:"type";s:9:"functions";s:8:"priority";s:10:"deprecated";s:2:"fn";s:23:"plugins/lib/fakedba.php";}s:8:"fakezlib";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:7:"library";s:5:"title";s:8:"fakezlib";s:11:"description";s:39:"required for outdated PHP installations";s:4:"type";s:9:"functions";s:8:"priority";s:10:"deprecated";s:2:"fn";s:24:"plugins/lib/fakezlib.php";}s:4:"feed";a:8:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"functions";s:5:"title";s:15:"feed generation";s:11:"description";s:39:"utility code to send out Atom/RSS feeds";s:8:"category";s:7:"library";s:8:"priority";s:8:"optional";s:6:"config";s:193:" - EWIKI_DESC= // site description - EWIKI_COPY= // overall site copyright, e.g. "PrimarilyPublicDomain" - EWIKI_CATEGORY= // site subject - EWIKI_LOGO_URL= // "http://.../logo.png"";s:2:"fn";s:20:"plugins/lib/feed.php";}s:9:"feedparse";a:9:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"functions";s:8:"provides";s:23:"rss-parser, atom-parser";s:7:"depends";s:22:"xml, http, http_cached";s:5:"title";s:15:"RSS/Atom parser";s:11:"description";s:54:"can load and decipher various syndication feed formats";s:8:"category";s:7:"library";s:8:"priority";s:8:"optional";s:2:"fn";s:25:"plugins/lib/feedparse.php";}s:3:"fix";a:8:{s:3:"api";s:3:"PHP";s:4:"type";s:9:"intercept";s:5:"title";s:9:"PHP fixes";s:12:"descriptions";s:53:"removes bogus magic_quotes and left over superglobals";s:8:"priority";s:4:"auto";s:8:"category";s:7:"library";s:9:"conflicts";s:48:"strike_register_globals, strip_wonderful_slashes";s:2:"fn";s:19:"plugins/lib/fix.php";}s:8:"gzdecode";a:5:{s:3:"api";s:3:"PHP";s:4:"type";s:9:"emulation";s:5:"title";s:10:"gzdecode()";s:11:"description";s:67:"adds support for the gzdecode() function, superseded by upgrade.php";s:8:"priority";s:10:"deprecated";}s:4:"http";a:10:{s:3:"api";s:3:"PHP";s:4:"type";s:9:"functions";s:8:"category";s:7:"library";s:8:"priority";s:8:"optional";s:8:"provides";s:12:"http-request";s:5:"title";s:13:"HTTP requests";s:11:"description";s:59:"implements HTTP protocol, various request methods supported";s:3:"url";s:33:"http://freshmeat.net/p/upgradephp";s:7:"version";s:4:"11.3";s:2:"fn";s:20:"plugins/lib/http.php";}s:10:"http_cache";a:8:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"functions";s:8:"category";s:7:"library";s:8:"priority";s:5:"extra";s:7:"depends";s:4:"http";s:5:"title";s:16:"cached HTTP GETs";s:11:"description";s:54:"caches HTTP GET requests as temporary database entries";s:2:"fn";s:26:"plugins/lib/http_cache.php";}s:2:"js";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:7:"library";s:5:"title";s:10:"JavaScript";s:11:"description";s:33:"server-side JS interpreter in PHP";s:8:"priority";s:10:"deprecated";s:4:"type";s:3:"api";}s:11:"libxprofile";a:9:{s:3:"api";s:3:"PHP";s:4:"type";s:3:"api";s:7:"version";s:5:"0.1.0";s:7:"depends";s:9:"http, xml";s:5:"title";s:12:"XUP/XProfile";s:11:"description";s:28:"parser for XML User Profiles";s:8:"homepage";s:27:"http://xprofile.berlios.de/";s:8:"category";s:7:"library";s:2:"fn";s:27:"plugins/lib/libxprofile.php";}s:10:"mime_magic";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:7:"library";s:5:"title";s:15:"mime magic data";s:11:"description";s:81:"adds a built-in auto detection for mime types, helpful to the downloads extension";s:8:"priority";s:4:"rare";s:5:"hooks";s:10:"mime_magic";s:4:"type";s:7:"special";s:2:"fn";s:26:"plugins/lib/mime_magic.php";}s:7:"minidav";a:8:{s:3:"api";s:3:"PHP";s:4:"type";s:3:"api";s:8:"priority";s:4:"auto";s:8:"category";s:7:"library";s:5:"title";s:10:"WebDAV API";s:11:"description";s:17:"protocol handling";s:7:"depends";s:12:"xml, upgrade";s:2:"fn";s:23:"plugins/lib/minidav.php";}s:6:"navbar";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"fragments";s:6:"config";s:101:" - EWIKI_NAVBAR_SELECTALL_DEPTH=99 - EWIKI_NAVBAR_ACTIVATEPARENTS=1 - EWIKI_NAVBAR_ACTIVATECHILDREN=1";s:5:"title";s:13:"NavigationBar";s:11:"description";s:39:"ewiki nav bar plugin - by AndyFundinger";s:8:"priority";s:5:"bonus";s:4:"type";s:9:"functions";s:2:"fn";s:22:"plugins/lib/navbar.php";}s:10:"opensearch";a:9:{s:3:"api";s:5:"ewiki";s:4:"type";s:3:"api";s:8:"category";s:7:"library";s:7:"version";s:5:"0.4.0";s:5:"title";s:14:"OpenSearch API";s:11:"description";s:59:"implements the OpenSearch live searching API (over XML-RPC)";s:3:"url";s:29:"http://opensearch.berlios.de/";s:8:"priority";s:5:"bonus";s:2:"fn";s:26:"plugins/lib/opensearch.php";}s:14:"page_delegator";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:7:"library";s:5:"hooks";s:4:"page";s:4:"type";s:3:"api";s:5:"title";s:14:"page_delegator";s:11:"description";s:57:"calls a series of ewiki handlers until one returns a page";s:8:"priority";s:5:"bonus";s:2:"fn";s:30:"plugins/lib/page_delegator.php";}s:10:"phprequest";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:7:"library";s:5:"title";s:10:"phprequest";s:11:"description";s:92:"allows http "POST" and "PUSH" requests with a Content-Type of application/vnd.php.serialized";s:8:"priority";s:10:"deprecated";s:4:"type";s:9:"intercept";s:2:"fn";s:26:"plugins/lib/phprequest.php";}s:6:"phprpc";a:8:{s:3:"api";s:3:"PHP";s:4:"type";s:9:"functions";s:8:"provides";s:12:"rpc, php-rpc";s:8:"category";s:7:"library";s:8:"priority";s:5:"bonus";s:5:"title";s:17:"PHP-RPC interface";s:11:"description";s:41:"simple PHP-encoded remote procedure calls";s:2:"fn";s:22:"plugins/lib/phprpc.php";}s:14:"pluginmetadata";a:7:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"functions";s:5:"title";s:14:"plugin manager";s:11:"description";s:56:"parses plugin .meta data files and resolves dependencies";s:8:"priority";s:5:"never";s:8:"category";s:7:"library";s:2:"fn";s:30:"plugins/lib/pluginmetadata.php";}s:8:"protmode";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:7:"library";s:5:"hooks";s:14:"handler_binary";s:4:"type";s:9:"intercept";s:5:"title";s:8:"protmode";s:11:"description";s:89:"holds utility functions (not core, but required by multiple plugin) for the ProtectedMode";s:8:"priority";s:4:"rare";s:2:"fn";s:24:"plugins/lib/protmode.php";}s:14:"save_storevars";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:7:"library";s:5:"hooks";s:9:"edit_save";s:4:"type";s:9:"intercept";s:5:"title";s:14:"save_storevars";s:11:"description";s:48:"automatically stores global variables into a ...";s:8:"priority";s:5:"bonus";s:2:"fn";s:30:"plugins/lib/save_storevars.php";}s:8:"shutdown";a:8:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"intercept";s:4:"hook";s:8:"shutdown";s:5:"title";s:13:"shutdown hook";s:11:"description";s:53:"adds another hook which activates plugins at shutdown";s:8:"category";s:7:"library";s:8:"priority";s:8:"optional";s:2:"fn";s:24:"plugins/lib/shutdown.php";}s:15:"spamblock_whois";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:7:"library";s:5:"hooks";s:10:"ban_loopup";s:4:"type";s:7:"special";s:5:"title";s:15:"spamblock_whois";s:11:"description";s:114:"initiates a whois query on the domain names of newly blocked URLs (to block further domains from the same spammer)";s:8:"priority";s:4:"rare";s:2:"fn";s:31:"plugins/lib/spamblock_whois.php";}s:5:"speed";a:7:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"intercept";s:5:"title";s:13:"HTTP speed-up";s:11:"description";s:57:"implements PHP-side support for conditional HTTP requests";s:8:"category";s:10:"optimation";s:8:"priority";s:5:"bonus";s:2:"fn";s:21:"plugins/lib/speed.php";}s:11:"subpagelist";a:5:{s:8:"priority";s:4:"auto";s:4:"type";s:9:"functions";s:5:"title";s:16:"SubpageFunctions";s:8:"category";s:7:"library";s:2:"fn";s:27:"plugins/lib/subpagelist.php";}s:4:"sync";a:7:{s:3:"api";s:5:"ewiki";s:4:"type";s:9:"functions";s:8:"priority";s:4:"rare";s:8:"category";s:7:"library";s:5:"title";s:8:"WikiSync";s:11:"description";s:57:"allows syncing content with/from remote Wiki installation";s:2:"fn";s:20:"plugins/lib/sync.php";}s:7:"upgrade";a:12:{s:3:"api";s:3:"PHP";s:4:"type";s:9:"emulation";s:8:"priority";s:4:"auto";s:8:"category";s:7:"library";s:4:"sort";s:4:"-200";s:8:"provides";s:11:"upgrade-php";s:5:"title";s:11:"PHP-Upgrade";s:11:"description";s:50:"backwards-compatility layer for older PHP versions";s:7:"license";s:13:"Public Domain";s:3:"url";s:33:"http://freshmeat.net/p/upgradephp";s:7:"version";s:4:"12.0";s:2:"fn";s:23:"plugins/lib/upgrade.php";}s:14:"uservars_pages";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:7:"library";s:5:"hooks";s:13:"login_handler";s:4:"type";s:7:"special";s:5:"title";s:14:"uservars_pages";s:11:"description";s:28:"override to use old standard";s:8:"priority";s:5:"bonus";s:2:"fn";s:30:"plugins/lib/uservars_pages.php";}s:6:"webdav";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:7:"library";s:6:"config";s:174:" - EWIKI_SCRIPT_WEBDAV=EWIKI_BASE_URL . "z.php/" // may be we should use a separate z_dav.php script or so? - EWIKI_PAGE_CTYPE="text/wiki; variant=ewiki; charset=iso-8859-1"";s:5:"title";s:6:"WebDAV";s:11:"description";s:57:"remote filesystem access over HTTP (for online authoring)";s:8:"priority";s:10:"deprecated";s:4:"type";s:3:"api";s:7:"depends";s:7:"minidav";s:2:"fn";s:22:"plugins/lib/webdav.php";}s:7:"wikiapi";a:7:{s:3:"api";s:5:"ewiki";s:4:"type";s:3:"api";s:8:"category";s:7:"library";s:5:"title";s:11:"API to Wiki";s:11:"description";s:38:"restricted remote-access functionality";s:8:"priority";s:4:"rare";s:2:"fn";s:23:"plugins/lib/wikiapi.php";}s:3:"xml";a:8:{s:3:"api";s:3:"PHP";s:4:"type";s:9:"functions";s:8:"category";s:7:"library";s:5:"title";s:11:"XML parsing";s:11:"description";s:59:"namespace-aware and simplified parsing of data-oriented XML";s:7:"version";s:5:"0.8.2";s:8:"priority";s:4:"auto";s:2:"fn";s:19:"plugins/lib/xml.php";}s:6:"xmlrpc";a:10:{s:3:"api";s:3:"PHP";s:4:"type";s:3:"api";s:8:"provides";s:12:"rpc, xml-rpc";s:7:"version";s:4:"11.3";s:8:"category";s:7:"library";s:8:"priority";s:8:"optional";s:5:"title";s:25:"XML-RPC client and server";s:11:"description";s:29:"serves remote procedure calls";s:8:"homepage";s:33:"http://freshmeat.net/p/upgradephp";s:2:"fn";s:22:"plugins/lib/xmlrpc.php";}s:10:"a_nofollow";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:10:"link_final";s:4:"type";s:4:"link";s:5:"title";s:16:"all rel=nofollow";s:8:"priority";s:10:"deprecated";s:11:"description";s:39:"Google's lazy response to link spammers";s:2:"fn";s:30:"plugins/linking/a_nofollow.php";}s:11:"autolinkext";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:8:"AutoLink";s:11:"description";s:40:"MeatBall:AutoLink, WikiFeatures:AutoLink";s:4:"type";s:1:"R";s:8:"priority";s:4:"rare";}s:11:"autolinking";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:24:"AutoLinking / GagaParser";s:11:"description";s:105:"links single words, if the according pages exist; but needs preparation by admin tool (for speed reasons)";s:8:"priority";s:4:"rare";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:6:"config";s:51:" - EWIKI_AUTOLINKING_CACHE="system/tmp/autolinking"";s:2:"fn";s:31:"plugins/linking/autolinking.php";}s:13:"deadly_hidden";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:22:"format_prepare_linking";s:4:"type";s:4:"link";s:5:"title";s:13:"deadly_hidden";s:11:"description";s:75:"links to _HIDDEN pages will appear as QuestionMarkLinks (fake not-existant)";s:8:"priority";s:4:"rare";s:2:"fn";s:33:"plugins/linking/deadly_hidden.php";}s:15:"instanturl_find";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:11:"InstantFind";s:11:"description";s:158:"introduces the [find:..] moniker, which searches for URL abbreviations/names in the interwiki and instanturls pages, falls back to fuzzy page search or Google";s:8:"priority";s:4:"rare";s:5:"hooks";s:8:"intermap";s:4:"type";s:4:"link";s:2:"fn";s:35:"plugins/linking/instanturl_find.php";}s:11:"instanturls";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:11:"InstantUrls";s:11:"description";s:104:"allows naming URLs in a table or definition list on the page InstantURLs or";s:8:"priority";s:5:"bonus";s:5:"hooks";s:22:"format_prepare_linking";s:4:"type";s:9:"transform";s:2:"fn";s:31:"plugins/linking/instanturls.php";}s:8:"link_css";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:7:"LinkCss";s:11:"description";s:35:"adds CSS information for link types";s:8:"priority";s:5:"extra";s:5:"hooks";s:10:"link_final";s:4:"type";s:4:"link";s:2:"fn";s:28:"plugins/linking/link_css.php";}s:10:"link_icons";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:10:"link_final";s:4:"type";s:4:"link";s:6:"config";s:248:" - EWIKI_LINK_ICONS_DIR="/icons/" // absolute to www root - EWIKI_LINK_ICONS_LOOKUP_DIR="./icons" // to access the files - EWIKI_LINK_ICONS_LOOKUP_SIZE=1 // use getimagesize() - EWIKI_LINK_ICONS_DEFAULT_SIZE='width="14" height="14"' // fallback";s:5:"title";s:9:"LinkIcons";s:11:"description";s:55:"this _link_regex_callback() plugin scans for icons in a";s:8:"priority";s:5:"bonus";s:2:"fn";s:30:"plugins/linking/link_icons.php";}s:17:"link_target_blank";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:13:"target=_blank";s:11:"description";s:41:"for all external links (user annoyment!!)";s:5:"hooks";s:10:"link_final";s:4:"type";s:4:"link";s:8:"priority";s:10:"deprecated";s:2:"fn";s:37:"plugins/linking/link_target_blank.php";}s:12:"linkdatabase";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:30:"UseMod compatible LinkDataBase";s:11:"description";s:27:"is loved by all web spiders";s:8:"priority";s:5:"extra";s:5:"hooks";s:13:"page, handler";s:4:"type";s:4:"page";s:2:"fn";s:32:"plugins/linking/linkdatabase.php";}s:12:"linkexcerpts";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:16:"excerpt tooltips";s:11:"description";s:16:"for linked pages";s:8:"priority";s:5:"bonus";s:5:"hooks";s:19:"handler, link_final";s:4:"type";s:9:"intercept";s:2:"fn";s:32:"plugins/linking/linkexcerpts.php";}s:12:"new_nofollow";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:34:"fromat_prepare_linking, link_final";s:4:"type";s:4:"link";s:5:"title";s:16:"new rel=nofollow";s:11:"description";s:58:"sets the rel="NOFOLLOW" attribute only on fresh hyperlinks";s:8:"priority";s:4:"rare";s:2:"fn";s:32:"plugins/linking/new_nofollow.php";}s:6:"plural";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:6:"plural";s:11:"description";s:43:"initiates a fuzzy page name matching (slow)";s:8:"priority";s:5:"bonus";s:5:"hooks";s:37:"format_prepare_linking, handler, page";s:4:"type";s:9:"intercept";s:2:"fn";s:26:"plugins/linking/plural.php";}s:13:"selfbacklinks";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:12:"SelfBackLink";s:5:"hooks";s:22:"format_prepare_linking";s:4:"type";s:9:"transform";s:11:"description";s:77:"any occourence of the current page name will point to the links/ list instead";s:8:"priority";s:5:"bonus";s:2:"fn";s:33:"plugins/linking/selfbacklinks.php";}s:12:"selfmetawiki";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:20:"SelfLink to MetaWiki";s:5:"hooks";s:22:"format_prepare_linking";s:4:"type";s:9:"transform";s:11:"description";s:64:"any SelfLink on the current page will be redirected to MetaWiki:";s:8:"priority";s:5:"bonus";s:2:"fn";s:32:"plugins/linking/selfmetawiki.php";}s:10:"selfsearch";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:10:"SelfSearch";s:8:"priority";s:5:"bonus";s:5:"hooks";s:22:"format_prepare_linking";s:4:"type";s:9:"transform";s:11:"description";s:49:"any SelfLink of a page will trigger a PowerSearch";s:2:"fn";s:30:"plugins/linking/selfsearch.php";}s:9:"shortwiki";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:5:"title";s:9:"ShortWiki";s:11:"description";s:45:"adds a markup extension to render "User|Name"";s:8:"priority";s:10:"deprecated";s:2:"fn";s:29:"plugins/linking/shortwiki.php";}s:7:"targets";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:10:"interxhtml";s:4:"type";s:4:"link";s:5:"title";s:11:"LinkTargets";s:11:"description";s:39:"allows to use target: settings in links";s:8:"priority";s:5:"bonus";s:2:"fn";s:27:"plugins/linking/targets.php";}s:3:"tcn";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:19:"LanguageNegotiation";s:11:"description";s:78:"selects the correct page if multiple variants exist (PageName.en, PageName.fr)";s:8:"priority";s:5:"bonus";s:5:"hooks";s:19:"handler, view_final";s:4:"type";s:9:"intercept";s:6:"config";s:77:" - EWIKI_DEFAULT_LANG="en" - EWIKI_AUTO_CHOOSE=1 - EWIKI_UP_FORCE_LANG="lang"";s:2:"fn";s:23:"plugins/linking/tcn.php";}s:8:"titlefix";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"title";s:13:"TitleSwapping";s:11:"description";s:39:"allows to use wrong [page|title] syntax";s:8:"priority";s:10:"deprecated";s:5:"hooks";s:13:"link_notfound";s:4:"type";s:4:"link";s:2:"fn";s:28:"plugins/linking/titlefix.php";}s:3:"xfn";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:10:"interxhtml";s:4:"type";s:4:"link";s:5:"title";s:3:"XFN";s:11:"description";s:69:"the [http://gmpg.org/xfn/] XHTML Friends Network spec leverages HTML4";s:8:"priority";s:5:"bonus";s:2:"fn";s:23:"plugins/linking/xfn.php";}s:13:"zero_pagerank";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"hypertext";s:5:"hooks";s:8:"link_url";s:4:"type";s:4:"link";s:6:"config";s:86:" - ZERO_PAGERANK="http://www.google.com/url?sa=D&q=" - EWIKI_PAGE_BANNED="BannedLinks"";s:5:"title";s:12:"ZeroPagerank";s:11:"description";s:49:"filter all BannedLinks through a page rank killer";s:8:"priority";s:4:"rare";s:2:"fn";s:33:"plugins/linking/zero_pagerank.php";}s:9:"1emphasis";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:15:"OneCharEmphasis";s:11:"description";s:33:"allows to use *bold* and /italic/";s:8:"priority";s:4:"rare";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:2:"fn";s:28:"plugins/markup/1emphasis.php";}s:4:"abbr";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:13:"abbreviations";s:11:"description";s:100:"are hosted in table or definition lists on dedicated pages, and then become tooltips everywhere else";s:8:"priority";s:5:"extra";s:5:"hooks";s:24:"format_final, page_final";s:4:"type";s:6:"mangle";s:2:"fn";s:23:"plugins/markup/abbr.php";}s:8:"asciitbl";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:14:"AsciiArtTables";s:11:"description";s:15:"are rarely used";s:8:"priority";s:4:"rare";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:2:"fn";s:27:"plugins/markup/asciitbl.php";}s:6:"bbcode";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:6:"BBcode";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:11:"description";s:60:"converts the "bulletin board code" to the easier Wiki syntax";s:8:"priority";s:10:"deprecated";s:2:"fn";s:25:"plugins/markup/bbcode.php";}s:9:"braceabbr";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:5:"title";s:9:"BraceAbbr";s:11:"description";s:63:"provides markup for using the "ABC (explanation)" syntax";s:8:"priority";s:5:"bonus";s:2:"fn";s:28:"plugins/markup/braceabbr.php";}s:10:"complextbl";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"hooks";s:12:"format_table";s:4:"type";s:9:"transform";s:5:"title";s:10:"complextbl";s:6:"author";s:32:"Hans B. Pufal ";s:8:"priority";s:10:"deprecated";s:2:"fn";s:29:"plugins/markup/complextbl.php";}s:3:"css";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:19:"general CSS support";s:11:"description";s:54:"allows to inject style commands into pages (@@ syntax)";s:8:"priority";s:11:"recommended";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:6:"config";s:149:" - EWIKI_CSS_CLASSPREP="" // "wiki-" for example - EWIKI_CSS_LOWER=0 // classnames to lowercase - EWIKI_CSS_FIX=0 // allow only correct classnames";s:2:"fn";s:22:"plugins/markup/css.php";}s:12:"css_singleat";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:8:"priority";s:5:"bonus";s:5:"hooks";s:11:"format_line";s:4:"type";s:9:"transform";s:5:"title";s:12:"css_singleat";s:11:"description";s:58:"allows to use @CLASSNAME to create a
            ";s:6:"author";s:14:"Andy Fundinger";s:2:"fn";s:31:"plugins/markup/css_singleat.php";}s:15:"definitionlinks";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"hooks";s:12:"format_final";s:4:"type";s:9:"transform";s:5:"title";s:15:"DefinitionLinks";s:11:"description";s:92:"turns definition list titles into anchors and links all occourences of them on the same page";s:8:"priority";s:4:"rare";s:2:"fn";s:34:"plugins/markup/definitionlinks.php";}s:19:"fix_source_mangling";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:28:"fixed/faster source mangling";s:11:"description";s:37:"occasionally enhances a few functions";s:8:"priority";s:5:"never";s:5:"hooks";s:41:"singleblock_fmt_src, format_source, block";s:4:"type";s:9:"transform";s:2:"fn";s:38:"plugins/markup/fix_source_mangling.php";}s:9:"footnotes";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:9:"FootNotes";s:11:"description";s:32:"shouldn't be necessary in a Wiki";s:8:"priority";s:5:"bonus";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:2:"fn";s:28:"plugins/markup/footnotes.php";}s:9:"htmltable";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:18:"HTML-syntax Tables";s:11:"description";s:28:"are useful for larger tables";s:8:"priority";s:4:"rare";s:5:"hooks";s:12:"format_block";s:4:"type";s:9:"transform";s:2:"fn";s:28:"plugins/markup/htmltable.php";}s:4:"miki";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:4:"miki";s:11:"description";s:57:"these definitions fake some of the markup found in »miki«";s:4:"type";s:4:"data";s:8:"priority";s:10:"deprecated";s:2:"fn";s:23:"plugins/markup/miki.php";}s:12:"naturallists";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:13:"natural lists";s:11:"description";s:40:"can start with '1.' or '7)' instead of #";s:8:"priority";s:5:"bonus";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:2:"fn";s:31:"plugins/markup/naturallists.php";}s:7:"phpwiki";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:11:"PhpWiki-1.2";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:11:"description";s:54:"converts the PhpWiki [[NoLink] to ErfurtWiki ![NoLink]";s:8:"priority";s:10:"deprecated";s:2:"fn";s:26:"plugins/markup/phpwiki.php";}s:14:"rendering_null";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"hooks";s:6:"render";s:4:"type";s:7:"special";s:5:"title";s:14:"rendering_null";s:11:"description";s:72:"replaces the wiki rendering core with almost nothing (to use plain HTML)";s:8:"priority";s:5:"never";s:2:"fn";s:33:"plugins/markup/rendering_null.php";}s:10:"rescuehtml";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:15:"basic html tags";s:11:"description";s:22:"could be used in pages";s:8:"priority";s:4:"rare";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:2:"fn";s:29:"plugins/markup/rescuehtml.php";}s:6:"sfwiki";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:6:"SfWiki";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:11:"description";s:53:"tries to emulate some of the markup found in »sfWiki«";s:8:"priority";s:10:"deprecated";s:2:"fn";s:25:"plugins/markup/sfwiki.php";}s:7:"smilies";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:7:"Smilies";s:11:"description";s:87:"are automatically replaced with images; you must install the graphic package separately";s:5:"hooks";s:12:"format_final";s:4:"type";s:9:"transform";s:6:"config";s:67:" - SMILIES_DIR="./img/smilies/" - SMILIES_BASE_HREF="/img/smilies/"";s:8:"priority";s:4:"rare";s:2:"fn";s:26:"plugins/markup/smilies.php";}s:13:"table_colspan";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"hooks";s:12:"format_final";s:4:"type";s:9:"transform";s:5:"title";s:13:"table_colspan";s:11:"description";s:24:"table row merging syntax";s:8:"priority";s:4:"rare";s:2:"fn";s:32:"plugins/markup/table_colspan.php";}s:13:"table_rowspan";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:13:"table rowspan";s:11:"description";s:19:"to join table cells";s:8:"priority";s:4:"rare";s:5:"hooks";s:12:"format_final";s:4:"type";s:9:"transform";s:2:"fn";s:32:"plugins/markup/table_rowspan.php";}s:3:"tex";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"hooks";s:12:"format_block";s:4:"type";s:9:"transform";s:6:"config";s:142:" - MIMETEX_BIN="mimetex" - MIMETEX_DIR="/home/www/user28494/htdocs/ewiki/var/mimetex/" - MIMETEX_PATH="/ewiki/var/mimetex/" - MIMETEX_INLINE=0";s:5:"title";s:3:"tex";s:11:"description";s:52:"provides ... tags for embedding formulars";s:8:"priority";s:5:"bonus";s:2:"fn";s:22:"plugins/markup/tex.php";}s:9:"timestamp";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"hooks";s:9:"edit_save";s:4:"type";s:9:"intercept";s:5:"title";s:9:"timestamp";s:11:"description";s:0:"";s:2:"fn";s:28:"plugins/markup/timestamp.php";}s:13:"update_format";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"hooks";s:24:"action, edit_form_append";s:4:"type";s:6:"action";s:5:"title";s:13:"update_format";s:11:"description";s:65:"Converts/Fixes misused markup to correct format (meaning of ! for";s:8:"priority";s:4:"rare";s:2:"fn";s:32:"plugins/markup/update_format.php";}s:6:"usemod";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:6:"markup";s:5:"title";s:6:"UseMod";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:11:"description";s:58:"Emulates UseMode like headlines (but others use this too).";s:8:"priority";s:4:"rare";s:2:"fn";s:25:"plugins/markup/usemod.php";}s:13:"block_chinese";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"meta";s:5:"hooks";s:19:"handler, view_final";s:4:"type";s:9:"intercept";s:5:"title";s:12:"BlockChinese";s:11:"description";s:63:"blocks any contribution that contains chinese characters (spam)";s:8:"priority";s:4:"rare";s:2:"fn";s:30:"plugins/meta/block_chinese.php";}s:17:"builtincategories";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"meta";s:5:"title";s:17:"BuiltinCategories";s:11:"description";s:21:"must be tweaked first";s:8:"priority";s:4:"rare";s:5:"hooks";s:27:"edit_form_append, edit_save";s:4:"type";s:6:"mangle";s:6:"config";s:36:" - EWIKI_BULTINCAT_METAID="category"";s:2:"fn";s:34:"plugins/meta/builtincategories.php";}s:7:"f_title";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"meta";s:5:"title";s:16:"PageTitleSetting";s:11:"description";s:59:"allows to override the displayed page title: with meta info";s:8:"priority";s:5:"bonus";s:5:"hooks";s:7:"handler";s:4:"type";s:9:"intercept";s:2:"fn";s:24:"plugins/meta/f_title.php";}s:4:"meta";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:4:"meta";s:5:"title";s:21:"core MetaData support";s:11:"description";s:57:"adds a small meta data input box below the page edit/ box";s:8:"priority";s:5:"extra";s:5:"hooks";s:27:"edit_form_append, edit_save";s:4:"type";s:6:"mangle";s:2:"fn";s:21:"plugins/meta/meta.php";}s:8:"calendar";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"title";s:8:"Calendar";s:11:"description";s:29:"can be attached to every page";s:8:"priority";s:5:"extra";s:5:"hooks";s:12:"page, action";s:4:"type";s:4:"page";s:6:"config";s:108:" - EWIKI_PAGE_CALENDAR="PageCalendar" - EWIKI_PAGE_YEAR_CALENDAR="PageYearCalendar" - EWIKI_CALENDAR_WIDTH=4";s:2:"fn";s:27:"plugins/module/calendar.php";}s:15:"collectuserdata";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"hooks";s:9:"delegator";s:4:"type";s:7:"special";s:5:"title";s:15:"collectuserdata";s:11:"description";s:78:"a handler that displays a request for user data rather than the requested page";s:8:"priority";s:5:"bonus";s:2:"fn";s:34:"plugins/module/collectuserdata.php";}s:9:"downloads";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"title";s:9:"downloads";s:11:"description";s:42:"expands file uploading to individual pages";s:8:"priority";s:5:"bonus";s:5:"hooks";s:12:"page, action";s:4:"type";s:4:"page";s:6:"config";s:173:" - EWIKI_UPLOAD_MAXSIZE=2*1024*1024 - EWIKI_PAGE_UPLOAD="FileUpload" - EWIKI_PAGE_DOWNLOAD="FileDownload" - EWIKI_ACTION_ATTACHMENTS="attachments" // define to 0 to disable";s:2:"fn";s:28:"plugins/module/downloads.php";}s:9:"fset_blog";a:7:{s:3:"api";s:5:"ewiki";s:4:"type";s:7:"virtual";s:8:"category";s:9:"extension";s:5:"title";s:16:"Blog feature set";s:8:"priority";s:4:"rare";s:11:"description";s:42:"loads all required blogging/weblog plugins";s:2:"fn";s:28:"plugins/module/fset_blog.php";}s:4:"tour";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"title";s:4:"tour";s:11:"description";s:74:"allows users to get a quick wiki overview, using interlinked page previews";s:8:"priority";s:5:"extra";s:5:"hooks";s:6:"action";s:4:"type";s:6:"action";s:2:"fn";s:23:"plugins/module/tour.php";}s:12:"uservars_gui";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:9:"extension";s:5:"hooks";s:4:"page";s:4:"type";s:4:"page";s:5:"title";s:12:"UserVars GUI";s:11:"description";s:28:"interfaces to user variables";s:8:"priority";s:5:"bonus";s:2:"fn";s:31:"plugins/module/uservars_gui.php";}s:8:"mpi+cdml";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:5:"title";s:8:"mpi+cdml";s:11:"description";s:70:"adds the "CDML"-Syntax (as found in ProWiki) to the mpi_ plugin system";s:8:"priority";s:10:"deprecated";s:2:"fn";s:24:"plugins/mpi/mpi+cdml.php";}s:8:"mpi+moin";a:8:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:13:"format_source";s:4:"type";s:9:"transform";s:5:"title";s:8:"mpi+moin";s:11:"description";s:69:"MoinMoin-syntax for mpi-plugin activation - may interfer with linking";s:8:"priority";s:10:"deprecated";s:2:"fn";s:24:"plugins/mpi/mpi+moin.php";}s:3:"mpi";a:9:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"title";s:26:"mpi - markup plugins (API)";s:11:"description";s:135:"can be run from individual pages to embed dynamic content, the various plugins are loaded on demand (except for monsterwikis of course)";s:8:"priority";s:11:"recommended";s:5:"hooks";s:35:"format_source, action, format_block";s:4:"type";s:6:"action";s:6:"config";s:56:" - EWIKI_MPI_DEMANDLOAD=1 // load mpi plugins as needed";s:2:"fn";s:19:"plugins/mpi/mpi.php";}s:14:"mpi_addcomment";a:4:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"title";s:10:"AddComment";s:2:"fn";s:30:"plugins/mpi/mpi_addcomment.php";}s:11:"mpi_addlink";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:3:"mpi";s:4:"type";s:3:"mpi";s:5:"title";s:7:"AddLink";s:11:"description";s:11:"view ";s:2:"fn";s:27:"plugins/mpi/mpi_addlink.php";}s:13:"mpi_backlinks";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:3:"mpi";s:4:"type";s:3:"mpi";s:5:"title";s:9:"BackLinks";s:11:"description";s:64:"This mpi can insert a list of pages referencing the current one.";s:2:"fn";s:29:"plugins/mpi/mpi_backlinks.php";}s:12:"mpi_backtree";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:3:"mpi";s:4:"type";s:3:"mpi";s:5:"title";s:8:"BackTree";s:11:"description";s:66:"This mpi provides a tree of page backlinks from the current or any";s:2:"fn";s:28:"plugins/mpi/mpi_backtree.php";}s:8:"mpi_blog";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:3:"mpi";s:4:"type";s:3:"mpi";s:5:"title";s:4:"Blog";s:11:"description";s:90:"Description: prints out a wiki-news style summary of blog entries for the current page.";s:2:"fn";s:24:"plugins/mpi/mpi_blog.php";}s:13:"mpi_bugreport";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:3:"mpi";s:4:"type";s:3:"mpi";s:5:"title";s:9:"BugReport";s:11:"description";s:68:"Allows users to submit a bug report, automatically creates a new bug";s:2:"fn";s:29:"plugins/mpi/mpi_bugreport.php";}s:18:"mpi_bugreportstate";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:3:"mpi";s:4:"type";s:3:"mpi";s:5:"title";s:14:"BugReportState";s:11:"description";s:62:"Belongs to mpi_bugreports; provides bug status change buttons.";s:2:"fn";s:34:"plugins/mpi/mpi_bugreportstate.php";}s:9:"mpi_embed";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:3:"mpi";s:4:"type";s:3:"mpi";s:5:"title";s:5:"Embed";s:11:"description";s:65:"This allows to embed a dynamic page, like the PowerSearch plugin,";s:2:"fn";s:25:"plugins/mpi/mpi_embed.php";}s:12:"mpi_fallback";a:6:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:27:"mpi, format_prepare_linking";s:4:"type";s:9:"transform";s:5:"title";s:8:"FallBack";s:2:"fn";s:28:"plugins/mpi/mpi_fallback.php";}s:14:"mpi_farinclude";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:3:"mpi";s:4:"type";s:3:"mpi";s:5:"title";s:10:"FarInclude";s:11:"description";s:68:"A plugin call like ";s:2:"fn";s:30:"plugins/mpi/mpi_farinclude.php";}s:12:"mpi_honeypot";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:3:"mpi";s:4:"type";s:3:"mpi";s:5:"title";s:8:"HoneyPot";s:11:"description";s:38:"put this onto your "BannedLinks" page:";s:2:"fn";s:28:"plugins/mpi/mpi_honeypot.php";}s:15:"mpi_inlineframe";a:7:{s:3:"api";s:5:"ewiki";s:8:"category";s:3:"mpi";s:5:"hooks";s:3:"mpi";s:4:"type";s:3:"mpi";s:5:"title";s:11:"InlineFrame";s:11:"description";s:67:"Inserts an "; -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_insert.meta b/mods/wiki/plugins/mpi/mpi_insert.meta deleted file mode 100644 index 75bf6a701..000000000 --- a/mods/wiki/plugins/mpi/mpi_insert.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi -type: mpi -config: - EWIKI_MPI_INSERT_TBL=1 -title: Insert -description: This mpi allows you to insert another wikipage into the current diff --git a/mods/wiki/plugins/mpi/mpi_insert.php b/mods/wiki/plugins/mpi/mpi_insert.php deleted file mode 100644 index cffe5555b..000000000 --- a/mods/wiki/plugins/mpi/mpi_insert.php +++ /dev/null @@ -1,85 +0,0 @@ -. You can also temporarily - change some rendering parameters, by supplying them as optional - parameters: - - - The table=0 parameter would disable the optional table+border - around the inserted page: - - - Please note, that the inserted page will be requested through - an "sub-request" with ewiki_page(), thus usually incorporating - all settings from the main page. - - As additional extension, you can have a split view (vertical) with - multiple pages: - -*/ - - # you can disable the
      generation, if you style pages via CSS -define("EWIKI_MPI_INSERT_TBL", 1); - - -$ewiki_plugins["mpi"]["insert"] = "ewiki_mpi_insert"; -$ewiki_config["mpi_insert"] = array( - "table" => EWIKI_MPI_INSERT_TBL, -); - - -function ewiki_mpi_insert($action="html", $args, &$iii, &$s) { - - global $ewiki_config; - - #-- save environment - $save = array( - "id", "config", "title", "ring", "author", - ); - unset($prevG); - $prevG = array(); - foreach ($save as $name) { - $prevG["$name"] = $GLOBALS["ewiki_$name"]; - } - - #-- use any params as _config settings - $args = $args + $ewiki_config["mpi_insert"]; - foreach ($args as $set=>$val) { - if ($set != "_") { - $ewiki_config[$set] = $val; - } - } - - #-- render requested page, through sub-request - $o = array(); - $o[] = ewiki_page($args["id"]); - for ($n=1; $n<=10; $n++) { - if ($id = $args[$n]) { - $o[] = ewiki_page($id); - } - } - - #-- reset env - foreach ($save as $name) { - $GLOBALS["ewiki_$name"] = $prevG[$name]; - } - - #-- mk table around output - $on = count($o); - if ($args["table"] || ($on >= 2)) { - $o = implode("\n' . "\n"; - } - $o .= "
      ", $o); - $o = '' - // . '' . str_repeat('', $on) . '' - . '
      ' . $o . '
      '; - } - else { - $o = implode("\n

      \n", $o); - } - $o = '
      ' . $o . '
      '; - - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_localsitemap.meta b/mods/wiki/plugins/mpi/mpi_localsitemap.meta deleted file mode 100644 index 2f621b0c9..000000000 --- a/mods/wiki/plugins/mpi/mpi_localsitemap.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi -type: mpi -title: LocalSitemap -description: This mpi provides a tree of page backlinks from the current or any diff --git a/mods/wiki/plugins/mpi/mpi_localsitemap.php b/mods/wiki/plugins/mpi/mpi_localsitemap.php deleted file mode 100644 index eb4869e5d..000000000 --- a/mods/wiki/plugins/mpi/mpi_localsitemap.php +++ /dev/null @@ -1,53 +0,0 @@ - - - - You shouldn't use depths greater than 3, else database walking would - take a while, and the result would be uglily long. -*/ - -$ewiki_plugins["mpi"]["localsitemap"] = "mpi2_localsitemap"; - - -function mpi2_localsitemap($action, $args, &$iii, &$s) { - - ($depth = $args["depth"]) or ($depth = 2); - if ($depth > 5) { - $depth = 5; - } - ($id = $args["page"]) or ($id = $GLOBALS["ewiki_id"]); - - $src = mpi2_localsitemap_revbl($id, "", $depth); - - - #-- throw output into _format() kernel buffer - if ($src) { - $c = &$iii[$s["in"]]; - $c[0] = $src; - $c[1] = 0x00FF; - $c[2] = "core"; - } - return($src); -} - - -function mpi2_localsitemap_revbl($id, $li, $depth) { - $src = ""; - $li .= "*"; - if ($depth--) { - if ($refs = ewiki_get_links($id)) { - foreach ($refs as $id) { - $src .= "$li [$id]\n"; - $src .= mpi2_localsitemap_revbl($id, $li, $depth); - } - } - } - return($src); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_multimedia.meta b/mods/wiki/plugins/mpi/mpi_multimedia.meta deleted file mode 100644 index 4b214ff2a..000000000 --- a/mods/wiki/plugins/mpi/mpi_multimedia.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi -type: mpi -title: MultiMedia -description: this mpi allows to embed multimedia files using following syntax: diff --git a/mods/wiki/plugins/mpi/mpi_multimedia.php b/mods/wiki/plugins/mpi/mpi_multimedia.php deleted file mode 100644 index e4dfc7b6f..000000000 --- a/mods/wiki/plugins/mpi/mpi_multimedia.php +++ /dev/null @@ -1,54 +0,0 @@ - - or - -*/ - - -$ewiki_plugins["mpi"]["multimedia"] = "ewiki_mpi_multimedia"; - - -function ewiki_mpi_multimedia($action="html", $args, &$iii, &$s) { - - switch ($action) { - case "doc": return("The multimedia plugin allows to reference multimedia objects which are no plain images (like videos, flash, applets)."); - case "desc": return("reference multimedia files"); - - default: - $a_url = array("href", 0, "url", "src"); - $a_std = array("width", "height", "type"); - $a_forb = array_merge(array("_"), $a_url, $a_std); - - #-- href - foreach ($a_url as $i) { - if ($href = $args[$i]) { - break; - } } - - #-- tag, std args - $o .= ' args - foreach ($args as $i=>$v) { - if (!in_array($i, $a_forb)) { - $o .= ''; - } - } - $o .= "Your browser cannot view this multimedia object."; -## $o .= ''; - $o .= ""; - } - - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_phpwiki.meta b/mods/wiki/plugins/mpi/mpi_phpwiki.meta deleted file mode 100644 index 51abe6787..000000000 --- a/mods/wiki/plugins/mpi/mpi_phpwiki.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi -type: mpi -title: PhpWiki -description: fake PhpWiki plugins diff --git a/mods/wiki/plugins/mpi/mpi_phpwiki.php b/mods/wiki/plugins/mpi/mpi_phpwiki.php deleted file mode 100644 index f7a9003af..000000000 --- a/mods/wiki/plugins/mpi/mpi_phpwiki.php +++ /dev/null @@ -1,56 +0,0 @@ -get()) { - if ($uu = strtok($row["author"], "(")) { - $authors[trim($uu)] = 1; - } - } - $authors = array_keys($authors); - natcasesort($authors); - - foreach ($authors as $a) { - $o .= "· " . ewiki_link_regex_callback(array($a)) . "
      \n"; - } - return($o); -} - - - - -#-- mimics the phpwiki "AllPages" plugin -------------------------------- -function ewiki_format_mpi_phpwiki_allpages($action, &$args, &$iii, &$s) { - if ($action=="html") { - return(ewiki_page_index(0,0,0,$args)); - } -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_redirectlinks.meta b/mods/wiki/plugins/mpi/mpi_redirectlinks.meta deleted file mode 100644 index 9aadcd5c0..000000000 --- a/mods/wiki/plugins/mpi/mpi_redirectlinks.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi, format_prepare_linking -type: transform -title: RedirectLinks diff --git a/mods/wiki/plugins/mpi/mpi_redirectlinks.php b/mods/wiki/plugins/mpi/mpi_redirectlinks.php deleted file mode 100644 index 24f624f75..000000000 --- a/mods/wiki/plugins/mpi/mpi_redirectlinks.php +++ /dev/null @@ -1,31 +0,0 @@ - - - will make ALL WikiWords of the current page link to the according - pages on another Wiki (see intermap), see also FallBack plugin -*/ - - -$ewiki_plugins["mpi"]["redirectlinks"] = "ewiki_mpi_redirectlinks"; -$ewiki_plugins["format_prepare_linking"][] = "ewiki_redirect_links_iw"; - - -function ewiki_mpi_redirectlinks($action, $args, &$s, &$iii) { - global $ewiki_config; - if (($to = $args["to"]) || ($to = $args[0])) { - $ewiki_config["links_redirect_iw"] = ewiki_array($ewiki_config["interwiki"], $to); - } -} - -function ewiki_redirect_links_iw(&$src) { - global $ewiki_config, $ewiki_links; - foreach ($ewiki_links as $i=>$v) { - if (!strpos($v, "://") && !strpos($i, ":")) { - $ewiki_links[$i] = $ewiki_config["links_redirect_iw"] . urlencode($i); - } - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_registerspam.meta b/mods/wiki/plugins/mpi/mpi_registerspam.meta deleted file mode 100644 index 5034c3ccb..000000000 --- a/mods/wiki/plugins/mpi/mpi_registerspam.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi -type: mpi -title: RegisterSpam -description: This MpiPlugin should be called from the BannedLinks or BlockedLinks diff --git a/mods/wiki/plugins/mpi/mpi_registerspam.php b/mods/wiki/plugins/mpi/mpi_registerspam.php deleted file mode 100644 index 16cb4e9ef..000000000 --- a/mods/wiki/plugins/mpi/mpi_registerspam.php +++ /dev/null @@ -1,64 +0,0 @@ - -
      - - -END; - } - else { - - #-- scan for links - $text = $_REQUEST["add_spam"]; - ewiki_scan_wikiwords($text, $uu); - $ls = array(); - foreach ($uu as $href=>$uu) { - if ($l = strpos($href, "://")) { - // filter out redundant pattern parts - $href = substr($href, $l + 3); - if (strpos($href, "www.")===0) { - $href = substr($href, 4); - } - $href = trim($href, "/"); - $ls[] = strtok($href, " "); - } - } - - #-- reduce - $ls = array_unique($ls); - $data = ewiki_db::GET($ewiki_id); - foreach (explode("\n", trim($data["refs"])) as $href) { - if (in_array($href, $ls)) { - unset($ls[array_search($href, $ls)]); - } - } - - #-- add to current page - if ($ls) { - $inj = "* [" . implode("], [", $ls) . "]\n"; - $data["content"] = preg_replace("/(^[-*#])/m", "$inj$1", $data["content"], 1); - ewiki_db::UPDATE($data); - $data["version"]++; - ewiki_db::WRITE($data); - return "\n
      new links added as patterns here (please go back and reload page to see it)
      \n"; - } - else { - return "\n
      no new links found, please add the patterns by hand then
      \n"; - } - } -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_removedlinks.meta b/mods/wiki/plugins/mpi/mpi_removedlinks.meta deleted file mode 100644 index 100a9421c..000000000 --- a/mods/wiki/plugins/mpi/mpi_removedlinks.meta +++ /dev/null @@ -1,5 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi -type: mpi -title: RemovedLinks diff --git a/mods/wiki/plugins/mpi/mpi_removedlinks.php b/mods/wiki/plugins/mpi/mpi_removedlinks.php deleted file mode 100644 index 977f8b7b2..000000000 --- a/mods/wiki/plugins/mpi/mpi_removedlinks.php +++ /dev/null @@ -1,38 +0,0 @@ - summarizes the page/url links that have - been removed from the current page during its edit history -*/ - - -$ewiki_plugins["mpi"]["backlinks"] = "ewiki_mpi_removedlinks"; - -function ewiki_mpi_removedlinks($action, &$args, &$iii, &$s) { - - ($id = $args["id"]) - or ($id = $args["page"]) - or ($id = $GLOBALS["ewiki_id"]); - - $data = ewiki_db::GET($id); - $ver = $cdata["version"]; - $clinks = explode("\n", trim($data["refs"])); - - $rm = array(); - - while ((--$ver) >= 1) { - $data = ewiki_db::GET($id, $ver); - $refs = explode("\n", trim($data["refs"])); - - $rm = $rm + array_diff($refs, $clinks, $rm); - } - - if ($rm) { - return(ewiki_list_pages($rm, 0)); - } - else { - return(" "); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_settitle.meta b/mods/wiki/plugins/mpi/mpi_settitle.meta deleted file mode 100644 index fa76a0a32..000000000 --- a/mods/wiki/plugins/mpi/mpi_settitle.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi -type: mpi -title: SetTitle -description: Use to define the currently diff --git a/mods/wiki/plugins/mpi/mpi_settitle.php b/mods/wiki/plugins/mpi/mpi_settitle.php deleted file mode 100644 index cad823eff..000000000 --- a/mods/wiki/plugins/mpi/mpi_settitle.php +++ /dev/null @@ -1,25 +0,0 @@ - to define the currently - shown pages' title to something different. -*/ - -$ewiki_plugins["mpi"]["settitle"] = "ewiki_mpi_settitle"; - - -function ewiki_mpi_settitle($action, &$args, &$iii, &$s) { - - global $ewiki_title; - - if ($args[1]) { - $ewiki_title = $args["_"]; - } - elseif ($args["id"]) { - $ewiki_title = $args["id"]; - } - return(""); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_sparsetable.meta b/mods/wiki/plugins/mpi/mpi_sparsetable.meta deleted file mode 100644 index ff75460cc..000000000 --- a/mods/wiki/plugins/mpi/mpi_sparsetable.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi -type: mpi -title: SparseTable -description: SparseTable allows you to build up a table in a data oriented diff --git a/mods/wiki/plugins/mpi/mpi_sparsetable.php b/mods/wiki/plugins/mpi/mpi_sparsetable.php deleted file mode 100644 index 878147a4f..000000000 --- a/mods/wiki/plugins/mpi/mpi_sparsetable.php +++ /dev/null @@ -1,100 +0,0 @@ - - - You could also assign a list of rows="..." instead of columns= names. - In both cases you separate the individual row/column entries with an - empty line, and use one of the specified identifiers and a "=" sign or - ":" colon to fill the table cells with data. - The row/column identifiers itself won't be printed and should therefore - be choosen like variables. The first block of assignments then was - typically used to make appropriate headings. - - (This plugin resembles a feature as seen in ProWiki, or at least - tries to. You could get the ProWiki CDML syntax with an mpi framework - extension plugin.) -*/ - - -$ewiki_plugins["mpi"]["sparsetable"] = "ewiki_mpi_sparsetable"; -function ewiki_mpi_sparsetable($action, $args, &$iii, &$s) { - - $SEP = "|"; - $o = ""; - $i = array(); - $t = array(); - - #-- column/row names - $use_rows = isset($args["rows"]); - if ($use_rows) { - $i = $args["rows"]; - } - else { - $i = $args["columns"]; - } - $ind = preg_split("/\s*[:;,|]\s*/", strtolower(trim($i))); - if (!$ind) { - return("Note: use rows= or columns= for SparseTable"); - } - $ind = array_flip($ind); - $empty_line = array(); - for ($n=0; $n \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_survey.meta b/mods/wiki/plugins/mpi/mpi_survey.meta deleted file mode 100644 index 6d5c12fcb..000000000 --- a/mods/wiki/plugins/mpi/mpi_survey.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi, view_stat -type: mpi -title: Survey -description: This mpi allows for polls/surveys, whose results are stored into diff --git a/mods/wiki/plugins/mpi/mpi_survey.php b/mods/wiki/plugins/mpi/mpi_survey.php deleted file mode 100644 index 1acfcdae5..000000000 --- a/mods/wiki/plugins/mpi/mpi_survey.php +++ /dev/null @@ -1,152 +0,0 @@ - - - Except for the data= setting, the named parameters are free-form and - only associate the text to an internal (named hash) entry. - - If you later want to make a poll read-only, you could use: - (this is just - a pagename, that __looks__ like a filename). -*/ - - -define("EWIKI_UP_SURVEY", "_voting4"); - - -$ewiki_plugins["mpi"]["survey"] = "ewiki_mpi_survey"; -$ewiki_plugins["view_stat"][] = "ewiki_show_survey"; - -function ewiki_mpi_survey($action, &$args, &$iii, &$s) -{ - global $ewiki_id, $ewiki_plugins; - $o = ""; - - #-- load data page - if (! ($df = $args["data"])) { - return; - } - unset($args["data"]); - unset($args["_"]); - unset($args[""]); - $data = ewiki_db::GET($df); - if (!$data["version"]) { - $data = ewiki_new_data($df, EWIKI_DB_F_BINARY); - $data["version"]--; - } - if ($data["flags"] != EWIKI_DB_F_BINARY) { - return; - } - $survey = unserialize($data["content"]); - - #-- operation - $vote = @$_REQUEST[EWIKI_UP_SURVEY]; - if ($vote == "$") { - $action = "show"; - } - - if ($action=="html") - { - #-- show entries - if (!$vote) { - $o = "\n" - . '
      ' - . '' - . "\n"; - foreach ($args as $name=>$text) { - if (!$name || !$text || ($name=="data")) { continue; } - $o .= ' ' . $text . "
      \n"; - } - $o .= ''; - $o .= "\n
      \n

      \n"; - $o .= '"$")).'">show results
      '; - } - - #-- store an entry - if ($vote) { - $survey[$vote]++; - $data["content"] = serialize($survey); - $data["version"]++; - $data["lastmodified"] = time(); - $data["author"] = ewiki_author(); - ewiki_db::WRITE($data); - - #-- show it - $action = "show"; - } - } - - if ($action=="show") - { - $o .= $ewiki_plugins["view_stat"][0]($survey, $args); - } - return($o); -} - - -function ewiki_show_survey($count, $text) { - - $o = ""; - $char = "*"; // char for result bars ( alt text or
      content) - $clen = 60; // max len of above - $px = 6; // pixel size of each $char, for CSS - $colors = array( - "#ff8888", "#88ee88", "#9999ff", "#ffbb33", "#eeee66", - "#dd99dd", "#555555", "#dddddd", -// "poll1.png", "poll2.png", "poll3.png", "poll4.png", "poll5.png", - ); - - $all = 0; - $max = 0; - foreach ($text as $name=>$uu) { - $all += $count[$name]; - $max = max($max, $count[$name]); - } - - $i = 0; - if ($max && $all) { - $o .= "\n"; - foreach ($text as $name=>$title) { - - #-- calc - $n = 0 + $count[$name]; // number of votes - $n_percent = ((int) (1000*$n/$all))/10; - $bar_chars = (int)($clen * ($n/$max)); // num of chars in bar - $bar_width = $n_c * $px; // pixel width of bar - $bar_str = "[" . str_repeat($char, $bar_chars) . "]"; - - #-- visualization - $color = $colors[$i]; - if ($color{0} == "#") { - $bar = "
      " . $bar_str . "
      \n"; - } - else { - $bar = "
      \"$bar_str\"
      "; - } - $i += 1; - $i %= count($colors); - - #-- print - $o .= "$title
      \n"; - $o .= "$n votes, $n_percent%
      \n"; - $o .= $bar; - $o .= "
      \n\n"; - - } - } - - return($o); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_syndicate.meta b/mods/wiki/plugins/mpi/mpi_syndicate.meta deleted file mode 100644 index 16753f51e..000000000 --- a/mods/wiki/plugins/mpi/mpi_syndicate.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi -type: mpi -title: Syndicate -description: Allows to embed a RSS feed into a page. It retrieves and decodes the diff --git a/mods/wiki/plugins/mpi/mpi_syndicate.php b/mods/wiki/plugins/mpi/mpi_syndicate.php deleted file mode 100644 index 840f45fe5..000000000 --- a/mods/wiki/plugins/mpi/mpi_syndicate.php +++ /dev/null @@ -1,37 +0,0 @@ - - - @depends: http, http_cache, xml, feed, feedparse -*/ - - -$ewiki_plugins["mpi"]["syndicate"] = "ewiki_mpi_syndicate"; - -function ewiki_mpi_syndicate($action, &$args, &$iii, &$s) { - global $ewiki_id; - - #-- params - ($url = $args["url"]) or ($args = $args["_"]); - ($cut = $args["limit"]) or ($cut = $args["cut"]) or ($cut = 10); - - #-- fetch - list($channel, $item) = ewiki_feed_get($url); - - #-- insert as html into current page - if ($channel) { - $o = "".htmlentities($channel[title]) . "
      \n"; - $item = array_slice($item, 0, $cut); - foreach ($item as $dat) { - $dat = array_map("htmlentities", $dat); - $o .= "$dat[title] $dat[description]
      \n"; - } - return($o); - } -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_tableeditor.meta b/mods/wiki/plugins/mpi/mpi_tableeditor.meta deleted file mode 100644 index 30342db2b..000000000 --- a/mods/wiki/plugins/mpi/mpi_tableeditor.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi -type: mpi -title: TableEditor -description: fancy inlinie editing of tables diff --git a/mods/wiki/plugins/mpi/mpi_tableeditor.php b/mods/wiki/plugins/mpi/mpi_tableeditor.php deleted file mode 100644 index 36b0be01b..000000000 --- a/mods/wiki/plugins/mpi/mpi_tableeditor.php +++ /dev/null @@ -1,160 +0,0 @@ - - - Will render the table as usual, but provide a [TableEditor] button, - which rerenders the table cells with lots of "; - } - $o .= '
      ' . implode('', $t[$row]) . '
      \n"; - } - - #-- reconvert into WikiMarkup, and insert into $iii - else { - #-- insert form at current position - $o .= '
      '; - $in = $s["in"]; - $iii[$in][0] = "WILL BE REPLACED with \$o..."; - - #-- mk table markup, insert into $iii - $src = "\n\n"; - foreach ($t as $row) { - $src .= "$SEP " . implode(" $SEP ", $row) . " $SEP\n"; - } - $src .= "\n"; - $iii = array_merge( - array_slice($iii, 0, $in+1), - array(array($src, 0x137F, "core")), - array_slice($iii, $in+1) - ); - - // the following return($o); will insert the
      into - // the current input buffer $iii[$in][0] later - } - - $o .= "
      \n"; - return($o); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/mpi_wikiscript.meta b/mods/wiki/plugins/mpi/mpi_wikiscript.meta deleted file mode 100644 index 05eb532db..000000000 --- a/mods/wiki/plugins/mpi/mpi_wikiscript.meta +++ /dev/null @@ -1,6 +0,0 @@ -api: ewiki -category: mpi -hooks: mpi -type: mpi -title: WikiScript -description: safe server-side scripting diff --git a/mods/wiki/plugins/mpi/off/mpi_brainfuck.php b/mods/wiki/plugins/mpi/off/mpi_brainfuck.php deleted file mode 100644 index 9b7f539fd..000000000 --- a/mods/wiki/plugins/mpi/off/mpi_brainfuck.php +++ /dev/null @@ -1,150 +0,0 @@ - increment pointer into data array - < decrement the data pointer - + increment the byte at the pointer - - decrement the data byte - . output the byte at the pointer - , input a byte, store it into the data array - [ starts a code block, only run if current data byte is zero - ] loop back to the opening bracket - - You simply write: - ++++++++++[-<+++++++>]<.+>+++++++[-<++++>]<.++>++ - +++[-<+>]<..+++.------>+++++++++[-<-------->]<. - ?> - Or - - - You must first create a symlink in the mpi/ main directory to - here, else this can't be used (disabled because it could slow - down wiki sites). -*/ - - -$ewiki_plugins["mpi"]["brainfuck"] = "ewiki_mpi_brainfuck"; -function ewiki_mpi_brainfuck($action, $args, &$iii, &$s) -{ - global $ewiki_id; - - if ($action == "input") { - return('
      ' - .' ' - .'' - .'
      ' - ); - } - else { - $input = ""; - foreach ($_REQUEST as $i=>$str) { - if (strlen($i)==1) { - $input .= $str; - } - } - return(bf_exec($args["_"], $input)); - } -} - - -function bf_exec(&$code, $in) -{ - $out = ""; - $data[0] = 0; - $p = 0; - $in_len = strlen($in); - $in_p = 0; - $code_len = strlen($code); - $pc = 0; - - while ($pc < $code_len) { - switch ($c=$code{$pc}) { - - case ">": // increment data pointer - $p++; - if ($p >= count($data)) { - $data[$p] = 0; - } - break; - - case "<": // decrement data pointer - if ($p) { - $p--; - } - break; - - case "+": // inc data byte - $data[$p]++; - break; - - case "-": // dec data byte - $data[$p]--; - break; - - case ".": - $out .= chr($data[$p]); - break; - - case ",": - if ($in_p < $in_len) { - $data[$p] = ord($in[$in_p++]); - } - else { - $data[$p] = 0; - } - break; - - case "[": // skip loop, if data byte is zero - if ($data[$p] == 0) { - $s = 1; - while ($s) { - $c = $code[++$pc]; - if ($c == "[") { - $s++; - } - elseif ($c == "]") { - $s--; - } - } - } - break; - - case "]": // repeat - $s = 1; - while ($s) { - $c = $code[--$pc]; - if ($c == "[") { - $s--; - } - elseif ($c == "]") { - $s++; - } - } - $pc--; - break; - - case "\n": - case "\r": - case "\f": - case "\t": - case " ": - break; - - default: - $out .= " (PARSING ERROR '$c' at position #$pc)"; - return($out); - break; - } - - $pc++; - } - - return($out); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/mpi/off/mpi_sqlquery.php b/mods/wiki/plugins/mpi/off/mpi_sqlquery.php deleted file mode 100644 index 87ebc5a8a..000000000 --- a/mods/wiki/plugins/mpi/off/mpi_sqlquery.php +++ /dev/null @@ -1,67 +0,0 @@ - - What will yield a table dump of the selected result sets. - - You must first enable this plugin - create a symlink into the - parent dir (it isn't found here in the off/ subdir). -*/ - -$ewiki_plugins["mpi"]["sqlquery"] = "ewiki_mpi_sqlquery"; - - -function ewiki_mpi_sqlquery($action, &$args, &$iii, &$s) { - - #-- select PHP db funcs - if (function_exists("anydb_query")) { - $SQL_QUERY = "anydb_query"; - $SQL_FETCH = "anydb_fetch_array"; - } - else { - $SQL_QUERY = "mysql_query"; - $SQL_FETCH = "mysql_fetch_array"; - } - - #-- query - if ($query = $args["_"]) { - - #-- security check - if (!preg_match('/^\s*(SELECT|SHOW)\s+/i', $query, $uu)) { - return("SQL query rejected"); - } - - $result = $SQL_QUERY($query); - if (!$result) { - return("failed SQL query"); - } - - #-- fetch data - $r = array(); - while($row = $SQL_FETCH($result)) { - foreach ($row as $i=>$d) { - if (is_int($i)) { - unset($row[$i]); - } - } - $r[] = $row; - } - - #-- output - $o .= ''; - $o .= ''."\n"; - $alt = 0; - foreach ($r as $row) { - $alt = ($alt++) % 2; - $add = $alt ? ' class="alternate"' : ''; - $o .= "" . implode("",$row) . ''."\n"; - } - $o .= "
      ' . implode('',array_keys($r[0])) . '
      \n"; - - return($o); - } - - return(mysql_error()); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/notify.meta b/mods/wiki/plugins/notify.meta deleted file mode 100644 index cc97537bd..000000000 --- a/mods/wiki/plugins/notify.meta +++ /dev/null @@ -1,8 +0,0 @@ -api: ewiki -type: transform -hooks: edit_hook, format_source -funcs: ewiki_notify_edit_hook, ewiki_notify_links, ewiki_format_remove_notify -title: Notifications -description: the invisible markup [notify:you@there.net] will trigger mails on editing -priority: standard -category: feature diff --git a/mods/wiki/plugins/notify.php b/mods/wiki/plugins/notify.php deleted file mode 100644 index b3f118159..000000000 --- a/mods/wiki/plugins/notify.php +++ /dev/null @@ -1,254 +0,0 @@ -$stat) { - if (strpos($add, "@") && strpos($add, ".")) { - $mailto[] = str_replace("notify:", "", $add); - } - } - } - - if (!count($mailto)) { - return(false); - } - - #-- generate diff - $diff = ""; - if (EWIKI_NOTIFY_WITH_DIFF && (DIRECTORY_SEPARATOR=="/")) { - - #-- save page versions temporarily as files - $fn1 = EWIKI_TMP."/ewiki.tmp.notify.diff.".md5($data["content"]); - $fn2 = EWIKI_TMP."/ewiki.tmp.notify.diff.".md5($_REQUEST["content"]); - $f = fopen($fn1, "w"); - fwrite($f, $data["content"]); - fclose($f); - $f = fopen($fn2, "w"); - fwrite($f, $_REQUEST["content"]); - fclose($f); - #-- set mtime of the old one (GNU diff will report it) - touch($fn1, $data["lastmodified"]); - - #-- get diff output, rm temp files - $diff_exe = EWIKI_NOTIFY_DIFF_EXE; - $diff_params = EWIKI_NOTIFY_DIFF_PARAMS; - if ($f = popen("$diff_exe $diff_params $fn1 $fn2 2>&1 ", "r")) { - - $diff .= fread($f, 16<<10); - pclose($f); - - $diff_failed = !strlen($diff) - || (strpos($diff, "Files ") === 0); - - #-- do not [notify:] if changes were minimal - if ((!$diff_failed) && (strlen($diff) < EWIKI_NOTIFY_WITH_DIFF)) { -#echo("WikiNotice: no notify, because too few changes (" .strlen($diff)." byte)\n"); - $ret_err = 1; - } - - $diff = "\n\n-----------------------------------------------------------------------------\n\n" - . $diff; - } - else { - $diff = ""; -#echo("WikiWarning: diff failed in notify module\n"); - } - - unlink($fn1); - unlink($fn2); - - if ($ret_err) { - return(false); - } - } - - #-- separate addresses into (TLD) groups - $mailto_lang = array( - ); - foreach ($mailto as $m) { - - $lang = ""; - - #-- remove lang selection trailer - $m = strtok($m, ","); - if ($uu = strtok(",")) { - $lang = $uu; - } - $m = strtok($m, ";"); - if ($uu = strtok(";")) { - $lang = $uu; - } - - #-- else use TLD as language code - if (empty($lang)) { - $r = strrpos($m, "."); - $lang = substr($m, $r+1); - } - $lang = trim($lang); - - #-- address mangling - $m = trim($m); - if (substr($m, 0, 4) == "icq:") { - $m = substr($m, 4) . "@pager.icq.com"; - } - - $mailto_lang[$lang][] = $m; - } - - #-- go thru email address groups - foreach ($mailto_lang as $lang=>$a_mailto) { - - $pref_langs = array( - "$lang", "en" - ) + (array)$ewiki_t["languages"]; - - ($server = $_SERVER["HTTP_HOST"]) or - ($server = $_SERVER["SERVER_NAME"]); - $s_4 = "http".($_SERVER['HTTPS'] == "on" ? 's':'')."://" . $server . $_SERVER["REQUEST_URI"]; - $link = str_replace("edit/$id", "$id", $s_4); - $difflink = str_replace("edit/$id", "diff/$id", $s_4); - - $m_text = ewiki_t("NOTIFY_BODY", array( - "id" => $id, - "link" => $link, - "diff_link" => $difflink, - "edit_link" => $s_4, - "server_admin" => $_SERVER["SERVER_ADMIN"], - "server" => $server, - "wiki_title" => EWIKI_PAGE_INDEX, - ), $pref_langs); - $m_text .= $diff; - - $m_from = EWIKI_NOTIFY_SENDER."@$server"; - $m_subject = ewiki_t("NOTIFY_SUBJECT", array( - "id" => $id, - ), $pref_langs); - - $m_to = implode(", ", $a_mailto); - - mail($m_to, $m_subject, $m_text, "From: \"$s_2\" <$m_from>\nX-Mailer: ErfurtWiki/".EWIKI_VERSION); - - } -} - - - -function ewiki_notify_links(&$source, $strip=1) { - $links = array(); - $l = 0; - if (strlen($source) > 10) - while (($l = @strpos($source, "[notify:", $l)) !== false) { - $r = strpos($source, "]", $l); - $n = strpos($source, "\n", $l); - if ($r && (!$n || ($r<$n))) { - $str = substr($source, $l, $r + 1 - $l); - if (!strpos("\n", $str)) { - $links[] = trim(substr($str, 8, -1)); - if ($strip) { - $source = substr($source, 0, $l) . substr($source, $r + 1); - } - } - } - $l++; - } - return($links); -} - - - -function ewiki_format_remove_notify(&$source) { - ewiki_notify_links($source, 1); -} - - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/old/alias.meta b/mods/wiki/plugins/old/alias.meta deleted file mode 100644 index dccb23dfa..000000000 --- a/mods/wiki/plugins/old/alias.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: old -hooks: alias, format_source, page -type: page -title: alias -description: maps PageAliases to existing WikiPages -priority: deprecated diff --git a/mods/wiki/plugins/old/alias.php b/mods/wiki/plugins/old/alias.php deleted file mode 100644 index 12fd03bec..000000000 --- a/mods/wiki/plugins/old/alias.php +++ /dev/null @@ -1,40 +0,0 @@ - "ErfurtWiki", - "WikiInfo" => "AboutPlugins", - "PageAlias" => "RealName", -// ... -); - - -$ewiki_plugins["format_source"] = "ewiki_page_aliases"; - - -function ewiki_page_aliases(&$src) { - global $ewiki_links, $ewiki_plugins; - $ewiki_links = array_merge( - $ewiki_links, - $ewiki_plugins["alias"] - ); -} - -foreach ($ewiki_plugins["alias"] as $page=>$uu) { - $ewiki_plugins["page"][$page] = "ewiki_page_alias"; -} - -function ewiki_page_alias($id, $data, $action) { - global $ewiki_plugins; - return(ewiki_page($ewiki_plugins["alias"][$id])); -} - - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/old/markup_code.meta b/mods/wiki/plugins/old/markup_code.meta deleted file mode 100644 index c17116d29..000000000 --- a/mods/wiki/plugins/old/markup_code.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: old -hooks: render -type: special -title: markup_code -description: another workaround plugin providing ... and
      ...
      -priority: deprecated diff --git a/mods/wiki/plugins/old/markup_code.php b/mods/wiki/plugins/old/markup_code.php deleted file mode 100644 index 4dbf16ef4..000000000 --- a/mods/wiki/plugins/old/markup_code.php +++ /dev/null @@ -1,51 +0,0 @@ -... and - ... escapes for the current rendering kernel. -*/ - - -$ewiki_plugins["render"][0] = "ewiki_format_pre_code"; - - -function ewiki_format_pre_code($wsrc, $sl=1, $hl=EWIKI_ALLOW_HTML, $sh=0) { - - $html = ""; - - $loop = 20; - while (preg_match("#^(.*?\n)?<(code>|php>|\?php|\?)(.+?)\n(#s", $wsrc, $uu) && ($loop--)) { - - $rend = &$uu[1]; - $code = &$uu[3]; - $wsrc = substr($wsrc, strlen($uu[0])); - - $html .= ewiki_format($rend, $sl,$hl,$sh); - $html .= "
      ".
      -               ewiki_format_pre_code_escape($code, $uu[2]!="code>") .
      -               "\n
      "; - - } - - if (strlen($wsrc)) { - $html .= ewiki_format($wsrc, $sl,$hl,$sh); - } - - return($html); -} - -function ewiki_format_pre_code_escape($html, $highl) { - - $html = trim($html, "\n"); - - if ($highl) { - ob_start(); - $html = highlight_string($html); - $html = ob_get_contents(); - ob_end_clean(); - } - - return($html); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/old/markup_html.meta b/mods/wiki/plugins/old/markup_html.meta deleted file mode 100644 index 0294ddc17..000000000 --- a/mods/wiki/plugins/old/markup_html.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: old -hooks: format_source -type: transform -title: markup_html -description: reenables support for HTML with the dash | escaping syntax at line start -priority: deprecated diff --git a/mods/wiki/plugins/old/markup_html.php b/mods/wiki/plugins/old/markup_html.php deleted file mode 100644 index 8f3d82f4f..000000000 --- a/mods/wiki/plugins/old/markup_html.php +++ /dev/null @@ -1,17 +0,0 @@ - usage, then use this plugin to keep compatible for a while. - Nowadays, you enclose blocks or fragments into or - even blocks (the latter still allows WikiLinks and markup). -*/ - - -$ewiki_plugins["format_source"][] = "ewiki_fsrc_old_html"; - -function ewiki_fsrc_old_html(&$src) { - $src = preg_replace('/^\|(.+(\n\|.+)*\n)/me', '"" . str_replace("\n|", "\n", stripslashes("\\1")) . ""', $src); -} - -?> \ No newline at end of file diff --git a/mods/wiki/plugins/old/markup_paragraphs.meta b/mods/wiki/plugins/old/markup_paragraphs.meta deleted file mode 100644 index 7c30cbe34..000000000 --- a/mods/wiki/plugins/old/markup_paragraphs.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: old -hooks: format_source -type: transform -title: markup_paragraphs -description: this plugin makes ewiki mimic the (more text paragraph oriented) ... -priority: deprecated diff --git a/mods/wiki/plugins/old/markup_paragraphs.php b/mods/wiki/plugins/old/markup_paragraphs.php deleted file mode 100644 index 56d93b181..000000000 --- a/mods/wiki/plugins/old/markup_paragraphs.php +++ /dev/null @@ -1,25 +0,0 @@ - \ No newline at end of file diff --git a/mods/wiki/plugins/page/README.meta b/mods/wiki/plugins/page/README.meta deleted file mode 100644 index b46bf7d81..000000000 --- a/mods/wiki/plugins/page/README.meta +++ /dev/null @@ -1,7 +0,0 @@ -api: ewiki -category: page -hooks: page -type: page -title: README -description: splits up the README and hyperlinks headlines -priority: never diff --git a/mods/wiki/plugins/page/README.php b/mods/wiki/plugins/page/README.php deleted file mode 100644 index 3c51b270a..000000000 --- a/mods/wiki/plugins/page/README.php +++ /dev/null @@ -1,191 +0,0 @@ -"); - $line = ""; - $lines = array(); - $strip_n = -1; - while (!feof($r) && (!strstr($line, $UNDERLINE))) { - $last = $line; - $line = fgets($r, 4096); - if ($strip_n == -1) { - preg_match("/^([ ]+)/", $line, $uu); - $strip_n = strlen($uu[1]); - } - if ($strip_n) { - $line = preg_replace("/^[ ]{{$strip_n}}/", "", $line); - } - $lines[] = $line; - } - $str_next = $last; - - array_pop($lines); - array_pop($lines); - $src = rtrim(implode("", $lines)); $lines = ""; - - #-- transformation -# $src = str_replace("[", "![", $src); - if (preg_match_all('/^\s+(EWIKI_[^\s]+)/m', $src, $uu) - && (count($uu[1])>10) || - preg_match_all('/^[ ]+([^\n]+)\n\s\s\s------+/m', $src, $uu) - && (count($uu[1])>7) - ) - { - - $src = preg_replace('/^[ ]+(EWIKI_[^\s]+)/m', - ' $1#[$1":"]', $src); - $src = preg_replace('/^[ ]+([^\n]+)\n\s\s\s(------+)/m', - "\n $1#[$1\"\"]\n $2", $src); - foreach ($uu[1] as $anchor) { - $pre .= "- [#$anchor \"$anchor\"]\n"; - } - $src = $pre."\n".$src; - } - - $end = "\n